89

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

谁能帮我?谢谢!

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

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

4

4 回答 4

195

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

图像加叠加

示例代码(图像称为“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"));
于 2010-02-23T15:21:48.433 回答
4

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

于 2010-02-23T12:43:49.243 回答
4

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

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

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

于 2010-02-23T12:54:54.527 回答
3

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

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);
        }
    }
于 2020-02-18T13:19:15.993 回答