JFrame 绘制带有 alpha 通道的动画 gif 图像

Posted

技术标签:

【中文标题】JFrame 绘制带有 alpha 通道的动画 gif 图像【英文标题】:JFrame drawing an animated gif image with an alpha channel 【发布时间】:2014-11-22 12:24:42 【问题描述】:

我正在尝试在 JFrame 上绘制动画 gif 图像。目前,我就是这样做的:

public class JImageComponent extends JComponent 

    private static final long serialVersionUID = -6926323540532721196L;

    private final Image image;

    public JImageComponent(Image image) 
        this.image = image;
    

    public JImageComponent(byte[] data) 
        this(Toolkit.getDefaultToolkit().createImage(data));
    

    @Override
    protected void paintComponent(Graphics graphics) 
        super.paintComponent(graphics);
        final int centerX = getWidth() / 2 - image.getWidth(this) / 2;
        final int centerY = getHeight() / 2 - image.getHeight(this) / 2;
        graphics.drawImage(image, centerX, centerY, this);
    


这很好,但是(因为边缘有阴影)如果我设置了背景颜色,它会显示出令人讨厌的白色边缘。我想我知道是什么原因造成的,这是因为 Image 类没有使用 alpha 通道。我不知道如何使图像使用 32 位颜色模型,使用 8 个最高有效位作为 alpha 值。任何帮助表示赞赏!谢谢。

编辑:当我尝试使用 ImageIO 和 BufferedImage 时,它​​没有动画。显然这是因为它没有更新 ImageObserver

编辑:这是有背景时图像的样子:http://puu.sh/bQ5sZ.png 我不想要那个白边,它应该看起来像这样:http://puu.sh/bQ5Ya.png。就像我之前说的,我知道为什么会这样;我需要 Image 类来使用 RGBA 而不是 RBG。

【问题讨论】:

请编辑您的问题以包含一个 complete example 来展示您描述的问题。在你的complete example中,通过URL访问图片,如图here 我添加了更多关于我的意思的信息。我想我只需要让它使用 RGBA 而不是 RGB,但我认为这是不可能的...... 【参考方案1】:

我根本无法使用您的 cade 来绘制图像。按原样,您的类为组件的宽度和高度返回 1。

    覆盖 getWidthgetHeight 以返回图像的大小。 不要打电话给super.paintComponent() - 在这种情况下它是多余的。 drawImage 接收图像的最左侧、最顶部坐标,因此您可以简单地用 0、0 调用它。

这段代码为我绘制了 alpha 通道:

public class JImageComponent extends JComponent 

   private static final long serialVersionUID = -6926323540532721196L;

   private final Image image;

   public JImageComponent(Image image) 
       this.image = image;
   

   public JImageComponent(byte[] data) 
       this(Toolkit.getDefaultToolkit().createImage(data));
   

   @Override
   protected void paintComponent(Graphics graphics) 
       graphics.drawImage(image, 0, 0, null);
   

   @Override
   public int getWidth() 
        return image.getWidth(null);
    

    @Override
    public int getHeight() 
        return image.getHeight(null);
    

编辑:

我之前的代码仍然为您的图像显示白色背景,所以我挖了一个小勺子并迭代每个像素:

public class JImageComponent extends JComponent 

    private static final long serialVersionUID = -6926323540532721196L;

    private final Image image;

    public JImageComponent(Image image) 
        this.image = image;
    

    public JImageComponent(byte[] data) 
        this(Toolkit.getDefaultToolkit().createImage(data));
    

    @Override
    protected void paintComponent(Graphics graphics) 
        Graphics2D g2 = (Graphics2D) graphics.create();
        int[] pixels = new int[image.getWidth(null)*image.getHeight(null)];
        PixelGrabber pg = 
                new PixelGrabber(image, 0, 0, image.getWidth(null), image.getHeight(null), pixels, 0, image.getWidth(null));
        try 
            pg.grabPixels();
         catch (InterruptedException e) 
            System.err.println("interrupted waiting for pixels!");
            return;
        
        if ((pg.getStatus() & ImageObserver.ABORT) != 0) 
            System.err.println("image fetch aborted or errored");
            return;
        

        for (int i = 0 ; i < image.getWidth(null) ; i++) 
            for (int j = 0 ; j < image.getHeight(null) ; j++) 
                handlesinglepixel(i, j, pixels[j * image.getWidth(null) + i], g2);  
            
        
    

    @Override
    public int getWidth() 
        return image.getWidth(null);
    

    @Override
    public int getHeight() 
        return image.getHeight(null);
    

    public void handlesinglepixel(int x, int y, int pixel, Graphics2D g2d) 
        int alpha = (pixel >> 24) & 0xff;
        int red   = (pixel >> 16) & 0xff;
        int green = (pixel >>  8) & 0xff;
        int blue  = (pixel      ) & 0xff;

        Color color = new Color(red,green,blue);
        g2d.setColor(color);
        System.out.println("Alpha value is " + (float)(alpha/255));
        g2d.setComposite(AlphaComposite.SrcAtop.derive((float)(alpha/255)));
        g2d.drawRect(x, y, 1, 1);
    

这会为每个像素打印一个1.0 alpha 值,所以我猜你的图像有问题...

【讨论】:

它的绘图对我来说很好。我使用 HTTP GET 方法从我的服务器获取图像,然后只是缓冲来自 InputStream 的数据并将字节数组传递给 JImageComponent 构造函数。你能给我看一张它为你工作的图片吗? 哦,哇,我真的很笨。我在白色背景上查看图像,所以颜色混合得很好。您是正确的,每个像素的 alpha 值都是 1...我应该在发布之前自己完成此操作。我道歉。

以上是关于JFrame 绘制带有 alpha 通道的动画 gif 图像的主要内容,如果未能解决你的问题,请参考以下文章

在 Win32 中显示带 alpha 通道的 32 位图像

ffmpeg 使用过滤器分割 RGB 和 Alpha 通道

OpenCV - 如何检测带有 alpha 通道的标记

带有 Alpha 通道的 OpenCV getRectSubPix

alpha通道与混合技术

带有 alpha 通道部分的透明 PNG 显示带有丑陋的边框