Hợp nhất hai hình ảnh


84

Tôi cần hợp nhất hai hình ảnh (BufferedImage) trong Java. Sẽ không có vấn đề gì nếu không có sự minh bạch. Hình ảnh cơ sở đã có một số trong suốt. Tôi muốn giữ nguyên trạng này và áp dụng "mặt nạ" cho nó, hình ảnh thứ hai. Hình ảnh thứ hai này không có pixel mờ đục, trên thực tế nó gần như hoàn toàn trong suốt, chỉ có một số pixel ít trong suốt hơn để tạo ra một số loại "hiệu ứng ánh sáng", giống như một phản xạ. Chi tiết quan trọng: Tôi không muốn thực hiện việc này trên màn hình, với đồ họa, tôi cần lấy BufferedImage với kết quả hợp nhất.

Ai giúp tôi với? Cảm ơn!

CHI TIẾT: Hợp nhất hai hình ảnh để duy trì độ trong suốt. Đây là điều tôi cần làm.

Lưu ý: Mặt nạ alpha Set BufferedImage trong Java này không làm những gì tôi cần vì nó không xử lý tốt với hai hình ảnh có độ trong suốt - nó sửa đổi độ trong suốt của hình ảnh đầu tiên.

Câu trả lời:


179

Chỉ cần tạo một BufferedImage mới với độ trong suốt, sau đó sơn hai hình ảnh khác (với toàn bộ hoặc bán trong suốt) lên đó. Đây là cách nó sẽ trông như thế nào:

Hình ảnh cộng với lớp phủ

Mã mẫu (hình ảnh được gọi là 'image.png' và 'overlay.png'):

File path = ... // base path of the images

// load source images
BufferedImage image = ImageIO.read(new File(path, "image.png"));
BufferedImage overlay = ImageIO.read(new File(path, "overlay.png"));

// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);

g.dispose();

// Save as new image
ImageIO.write(combined, "PNG", new File(path, "combined.png"));

Có cách nào để có hình thứ hai ở tâm của hình thứ nhất?
Ahmed

6
Bạn không nên gọi g.dispose (); cuối cùng?
m-szalik

Xin chào, tôi đã làm theo cách tiếp cận này và chỉ lưu hình ảnh thứ hai chứ không lưu hình ảnh đầu tiên ... Mọi sự trợ giúp ở đây sẽ được đánh giá cao ..
TP_JAVA 23/04

@Peter Hình ảnh chuyển sang màu xám khi tôi đặt tệp kết hợp thành tệp jpeg. Vui lòng giúp đỡ
Mohammed shebin

3

Tôi không thể cho bạn một câu trả lời cụ thể, nhưng java.awt.AlphaComposite ở đây là bạn của bạn. Bạn sẽ kiểm soát tuyệt đối cách bạn muốn hai hình ảnh hợp nhất. Tuy nhiên, nó không đơn giản để sử dụng - trước tiên bạn cần học một chút lý thuyết đồ họa.


3

Nếu không biết thêm về hiệu ứng mà bạn đang cố gắng đạt được, tôi sẽ chỉ ra rằng bạn cũng có thể vẽ ngay vào BufferedImage. Vì vậy, bất cứ điều gì bạn có thể làm trên màn hình, bạn có thể làm ngay trên chính hình ảnh đó.

Vì vậy, nếu tất cả những gì bạn muốn là một cái được vẽ lên trên cái kia, điều đó thực sự dễ dàng. Chỉ cần lấy đối tượng Graphics cho hình ảnh cơ sở và vẽ cái kia lên nó.

Một lần nữa, tùy thuộc vào hiệu ứng chính xác mà bạn đang thực hiện có thể không hiệu quả. Chi tiết hơn sẽ cho phép trợ giúp tốt hơn. Ví dụ: đây là công việc cho AlphaComposite như người trả lời khác đề cập hay ImageOp tùy chỉnh (hoặc một số kết hợp của ImageOps hiện có).


1

hợp nhất bất kỳ loại tệp nào theo chiều dọc.

void mergeFiles(List<String> files, String fileName) {
        int heightTotal = 0;
        int maxWidth = 100;

        List<BufferedImage> images = new ArrayList<>();
        try {
            for (String file : files) {
                BufferedImage image = ImageIO.read(new File(file));
                images.add(image);
            }


        for (BufferedImage bufferedImage : images) {
            heightTotal += bufferedImage.getHeight();
            if (bufferedImage.getWidth() > maxWidth) {
                maxWidth = bufferedImage.getWidth();
            }
        }


        int heightCurr = 0;
        BufferedImage concatImage = new BufferedImage(maxWidth, heightTotal, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = concatImage.createGraphics();
        for (BufferedImage bufferedImage : images) {
            g2d.drawImage(bufferedImage, 0, heightCurr, null);
            heightCurr += bufferedImage.getHeight();
        }

        File compressedImageFile = new File(fileName);
        OutputStream outputStream = new FileOutputStream(compressedImageFile);

        float imageQuality = 0.7f;
        Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("jpeg");

        if (!imageWriters.hasNext())
            throw new IllegalStateException("Writers Not Found!!");

        ImageWriter imageWriter = imageWriters.next();
        ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(outputStream);
        imageWriter.setOutput(imageOutputStream);

        ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();

        //Set the compress quality metrics
        imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        imageWriteParam.setCompressionQuality(imageQuality);

        //Created image
        imageWriter.write(null, new IIOImage(concatImage, null, null), imageWriteParam);

        // close all streams
        outputStream.close();
        imageOutputStream.close();
        imageWriter.dispose();
        log.info(" Files Merged");
        } catch (IOException e) {
            log.error("Error while merging files :::"+e);
            throw new RuntimeException(e);
        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.