简体   繁体   中英

JFrame drawing an animated gif image with an alpha channel

I'm trying to draw an animated gif image on a JFrame. At the moment, this is how I'm doing it:

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

}

This is fine, however, (because there's shading on the edge) if i have a background colour set, it shows a nasty white edge. I think i know what's causing this, it's because of the the Image class does not utilise an alpha channel. I don't know how to make the image use a 32-bit colour model using the 8 most significant bits as the alpha value. Any help is appreciated! Thanks.

Edit: when I tried using a ImageIO and a BufferedImage, it didn't animate. Apparently this is because it doesn't update the ImageObserver

Edit: This is what the image looks like when there's a background: http://puu.sh/bQ5sZ.png I don't want that white edge, it should look like this: http://puu.sh/bQ5Ya.png . Like i said previously, i know why it's happening; I need the Image class to use RGBA not RBG.

I couldn't use your cade to draw an image at all. Your class, as is, returns 1 for both the width and height of the component.

  1. Override getWidth and getHeight to return the size of the image.
  2. Don't call super.paintComponent() - it's redundant in this case.
  3. drawImage receives the left-most, top-most coordinate of the image, so you can simply call it with 0, 0.

This code draws alpha channel right for me:

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

EDIT:

My previous code still showed a white background for your image, so I dig a little dipper and iterate each pixel:

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

This prints a 1.0 alpha value for every pixel, so I guess there's a problem with your image...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM