Java 合并两个图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2318020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:03:23  来源:igfitidea点击:

Merging two images

javaimage-processingtransparencyalpha

提问by GuilhermeA

I need to merge two images (BufferedImage) in Java. It wouldn't be a problem if there was no transparency. The base image already has some transparency. I want to keep this as it is and apply a "mask" to it, the second image. This second image has no opaque pixels, in fact it's almost completely transparent, just has some less transparent pixels to give some sort of "light effect", like a reflex. Important detail: I don't want to do this on screen, with graphics, I need to obtain a BufferedImage with the resultant merge.

我需要在 Java 中合并两个图像 (BufferedImage)。如果没有透明度,这将不是问题。基本图像已经具有一些透明度。我想保持原样并对其应用“蒙版”,即第二张图片。第二张图像没有不透明的像素,实际上它几乎是完全透明的,只是有一些不太透明的像素来提供某种“光效”,比如反射。重要细节:我不想在屏幕上执行此操作,对于图形,我需要通过结果合并获取 BufferedImage。

Can anyone help me? Thanks!

谁能帮我?谢谢!

DETAILS: Merge two images maintaining transparency. This is what I need to do.

细节:合并两个图像保持透明度。这是我需要做的。

Note: this Set BufferedImage alpha mask in Javadoes not do what I need because it does not handle well with the two images having transparency - it modifies first picture transparency.

注意:Java中的这个Set BufferedImage alpha mask不能满足我的需求,因为它不能很好地处理具有透明度的两个图像 - 它修改了第一张图片的透明度。

采纳答案by Peter Walser

Just create a new BufferedImage with transparency, then paint the other two images (with full or semi-transparency) on it. This is how it will look like:

只需创建一个具有透明度的新 BufferedImage,然后在其上绘制其他两个图像(完全或半透明)。这是它的样子:

Image plus overlay

图像加叠加

Sample code (images are called 'image.png' and 'overlay.png'):

示例代码(图像称为“image.png”和“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"));

回答by Steve McLeod

I can't give you a specific answer, but java.awt.AlphaComposite here is your friend. You'll get absolute control over how you want the two images to merge. However it is not straightforward to use - you need to learn a bit of graphics theory first.

我不能给你一个具体的答案,但这里的 java.awt.AlphaComposite 是你的朋友。您将完全控制您希望如何合并两个图像。然而,它使用起来并不简单——你需要先学习一些图形理论。

回答by PSpeed

Without knowing more about the effect you are trying to achieve, I'll just point out that you can also draw right onto a BufferedImage. So anything you could do on screen you can do right on the image itself.

在不了解您想要达到的效果的情况下,我只想指出您也可以直接绘制到 BufferedImage 上。因此,您可以在屏幕上执行的任何操作都可以直接在图像上执行。

So if all you want is one drawn on top of the other, that's really easy. Just grab the Graphics object for the base image and draw the other onto it.

因此,如果您想要的只是将一个绘制在另一个之上,那真的很容易。只需抓取基本图像的 Graphics 对象并将另一个对象绘制到它上面。

Again, depending on the exact effect you are going for that may not work. More detail would allow better help. For example, is this a job for AlphaComposite as the other responder mentions or a custom ImageOp (or some combination of existing ImageOps).

同样,根据您想要的确切效果,这可能不起作用。更多细节将提供更好的帮助。例如,这是其他响应者提到的 AlphaComposite 的工作还是自定义 ImageOp(或现有 ImageOps 的某种组合)。

回答by Kumar Abhishek

merge any type of file vertically.

垂直合并任何类型的文件。

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);
        }
    }