合并两个图像

发布于 2024-08-22 13:23:04 字数 444 浏览 4 评论 0原文

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

有人可以帮助我吗? 谢谢!

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

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

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.

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 Java does not do what I need because it does not handle well with the two images having transparency - it modifies first picture transparency.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏末 2024-08-29 13:23:04

只需创建一个具有透明度的新 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"));

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:

Image plus overlay

Sample code (images are called 'image.png' and '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"));
紧拥背影 2024-08-29 13:23:04

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

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

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);
        }
    }
黎歌 2024-08-29 13:23:04

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

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.

笑,眼淚并存 2024-08-29 13:23:04

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

因此,如果您想要的只是将一个绘制在另一个之上,那非常简单。只需抓取基本图像的 Graphics 对象并将另一个对象绘制到其上即可。

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

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.

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.

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文