0

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.

  • Please edit your question to include a [complete example](http://stackoverflow.com/help/mcve) that exhibits the problem you describe. In your [complete example](http://stackoverflow.com/help/mcve), access the image via `URL`, as shown [here](http://stackoverflow.com/a/10862262/230513) – trashgod Sep 27 '14 at 17:50
  • I've added some more information about what I mean. I guess I just need to make it use RGBA instead of RGB but i don't think that's possible... – user3746721 Sep 27 '14 at 18:03

1 Answers1

1

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

Elist
  • 5,313
  • 3
  • 35
  • 73
  • The drawing of it is fine for me. I was using HTTP GET method to get images from my server and then just buffered the data from the InputStream and passed the byte array to the JImageComponent constructor. Can you show me an image of it working for you, please? – user3746721 Sep 27 '14 at 19:27
  • Oh wow, I feel really dumb. I was viewing the image on a white background so the colours blended fine. You're correct the alpha value is 1 for every pixel... I should have done this myself before posting. I apologise. – user3746721 Sep 27 '14 at 19:32