java背景透明

发布于 2024-10-20 01:25:26 字数 2101 浏览 6 评论 0原文

我有一个 gif 图像,其中仅包含彩色形状和透明背景。

我想用我想要的颜色替换形状的颜色(这个 gif 的调色板只有 2 种颜色:在我的例子中是透明和白色)。

我创建了一个过滤器,可以正确地将白色替换为红色(这是一个测试)。

但是,我的方法 imageToBufferedImage 遇到了问题,它删除了透明度并将其替换为黑色(不知道为什么)。

所以到目前为止我所做的是:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.imageio.ImageIO;

public class TestPNG {
    
    public static void main(String[] args) throws Exception {

        File in = new File("bg.gif");
        BufferedImage source = ImageIO.read(in);
        int color = source.getRGB(0, 0);

        Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

        BufferedImage transparent = imageToBufferedImage(image);

        File out = new File("bg2.gif");
        ImageIO.write(transparent, "gif", out);

    }

    private static BufferedImage imageToBufferedImage(Image image) {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        //g2.setBackground(Color.blue);
        g2.clearRect(0, 0, 200, 40);
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
        return bufferedImage;
    }

    public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
        ImageFilter filter = new RGBImageFilter() {
                public final int filterRGB(int x, int y, int rgb) {
                        if (rgb == search.getRGB()) {
                            return replace.getRGB();
                        } else {
                            return rgb;
                        }
                }
        };
        ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
        return Toolkit.getDefaultToolkit().createImage(ip);
    }

}

I have a gif image which contains only a colored shape, and a transparent background.

I would like to replace the shape's color by the one I want (the color pallet for this gif is only 2 colors: transparent and white in my case).

I've created a filter which correctly replace white with red (this is a test).

However I'm encountering an issue with my method imageToBufferedImage, it removes the transparency and replace it with black (don't know why).

So what I've done so far is this:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.imageio.ImageIO;

public class TestPNG {
    
    public static void main(String[] args) throws Exception {

        File in = new File("bg.gif");
        BufferedImage source = ImageIO.read(in);
        int color = source.getRGB(0, 0);

        Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

        BufferedImage transparent = imageToBufferedImage(image);

        File out = new File("bg2.gif");
        ImageIO.write(transparent, "gif", out);

    }

    private static BufferedImage imageToBufferedImage(Image image) {
        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bufferedImage.createGraphics();
        //g2.setBackground(Color.blue);
        g2.clearRect(0, 0, 200, 40);
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
        return bufferedImage;
    }

    public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
        ImageFilter filter = new RGBImageFilter() {
                public final int filterRGB(int x, int y, int rgb) {
                        if (rgb == search.getRGB()) {
                            return replace.getRGB();
                        } else {
                            return rgb;
                        }
                }
        };
        ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
        return Toolkit.getDefaultToolkit().createImage(ip);
    }

}

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

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

发布评论

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

评论(5

清浅ˋ旧时光 2024-10-27 01:25:26

您的代码中有 3 个问题:

1)替换

Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

Image image = makeColorTransparent(source, color, new Color(255, 0, 0));

和 ,

public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
...
if (rgb == search.getRGB()) {
...
}

因为

public static Image makeColorTransparent(BufferedImage im, final int search, final Color replace) {
...
if (rgb == search) {
...
}

由于某种原因, source.getRGB(0, 0) 忽略 alpha 值,它变成白色 ((255, 255, 255, 0) 变成 (255, 255, 255, 255))

2) 不能使用 int color = source.getRGB(0, 0),因为它使用第一个像素的颜色(透明) 。您应该使用一些其他代码(例如在控制台中询问颜色)来找出要存储在 int color 中的像素颜色

3) 您正在清除 BufferedImage bufferedImage 的颜色在 imageToBufferedImage(...) 中使用 Color.BLACK (默认)。将 //g2.setBackground(Color.blue); 替换为 g2.setBackground(new Color(0, 0, 0, 0)); 或删除 g2.clearRect(...);

There are 3 problems in your code:

1) Replace

Image image = makeColorTransparent(source, new Color(color), new Color(255, 0, 0));

with

Image image = makeColorTransparent(source, color, new Color(255, 0, 0));

and

public static Image makeColorTransparent(BufferedImage im, final Color search, final Color replace) {
...
if (rgb == search.getRGB()) {
...
}

with

public static Image makeColorTransparent(BufferedImage im, final int search, final Color replace) {
...
if (rgb == search) {
...
}

BECAUSE for some reason, the source.getRGB(0, 0) ignores alpha value and it becomes white ((255, 255, 255, 0) becomes (255, 255, 255, 255))

2) You can't use int color = source.getRGB(0, 0), because it uses the color of first pixel (transparent). You should use some other code (like asking for the color in console) to find out what pixel's color to store in int color

3) You are clearing the color of BufferedImage bufferedImage in imageToBufferedImage(...) with Color.BLACK (default). Replace //g2.setBackground(Color.blue); with g2.setBackground(new Color(0, 0, 0, 0)); or remove the g2.clearRect(...);

寂寞清仓 2024-10-27 01:25:26

确定您的图像支持 Alpha 通道吗?
尝试先将非黑色全尺寸矩形绘制到 bufferedImage 中?

Sure your image supports an alpha channel?
Tried drawing a non-black full size rectangle into bufferedImage first?

神魇的王 2024-10-27 01:25:26

得到

    g2.drawImage(image, 0, 0, null);

您可以从该方法的 Javadoc 中

图像中的透明像素不会影响已有的任何像素。

由于您清除了图像并用背景颜色填充了它,因此像素已经是黑色的,因此它们保持黑色。

尝试一下。

g2.setBackground(new Color(0, 0, 0, 0) );
g2.clearRect(0, 0, 200, 40);

在绘制图像之前

You have this:

    g2.drawImage(image, 0, 0, null);

From the Javadoc for this method:

Transparent pixels in the image do not affect whatever pixels are already there.

Since you cleared your image, filling it with the background colour, the pixels are already black so they stay black.

Try

g2.setBackground(new Color(0, 0, 0, 0) );
g2.clearRect(0, 0, 200, 40);

before painting your image.

丶视觉 2024-10-27 01:25:26

只是猜测:

a) 也许您不需要 clearRect(...) 方法。

b)也许你可以使用类似的东西:

g2.setColor(new Color(0, 0, 0, 0));
g2.fillRect(...);

Just guessing:

a) Maybe you don't need the clearRect(...) method.

b) Maybe you can use something like:

g2.setColor(new Color(0, 0, 0, 0));
g2.fillRect(...);
要走就滚别墨迹 2024-10-27 01:25:26

您可以使用合成来清除像素。您不能只在其他像素或任何垃圾上绘制透明像素。 Porter-Duff 规则很明确,执行任何操作都会导致像素根据复合规则进行混合。所以只要改变一下,规则就会清除像素。

问题是大多数解决方案都试图使用规则来诱使图像最终获得您想要的像素。稍微改变一下规则,一切都会变得更容易。

Composite composite = g.getComposite();

g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g.fillRect(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight());

g.setComposite(composite);

这将清除图形对象的当前像素。然后再画回你想要的东西。我的示例恢复了之前的合成,因为您会惊讶地发现这些东西变得奇怪的频率如此之高,这样您就可以获得清除的像素,并且可以重新开始,而无需更改图形上下文的任何内容。

You clear out the pixels with the use of a composite. You can't just paint transparent pixels over other pixels or any of that trash. The Porter-Duff rules are clear, doing any of that will cause pixels to mix according to the composite rule. So just change, the rule clear the pixels.

The problem is most of the solutions are trying to coax the image into getting the pixels you want at the end, using the rule. Change the rule for a second and everything gets way easier.

Composite composite = g.getComposite();

g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g.fillRect(0, 0, bufferedimage.getWidth(), bufferedimage.getHeight());

g.setComposite(composite);

That will clear a graphics object of the current pixels. Then just paint back on what you want. My example restored the previous composite as you'll be surprised how often that stuff goes weird, this way you just get cleared pixels and can start over without changing anything with the graphics context.

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