resizing png vs gif

hi!
I’m facing a strange bug with resize/scale ops using Java Graphics2D. I have a small Display objects that paints a background image and adds the desired picture over with transparency. I load the display with a specified size, well this works perfectly. But if I resize the component I should have a scaled picture displayed. That works well for the background but the picture over it simply disapears when it is scaled down and reappears as the scaling comes bigger. I use a Gif format as a background and the picture logo over it is a Png, both with transparent backgrounds.

Gif’s seem to accept the scale transform in real time while the png’s don’t. Is this a know issue with the Java Graphics?
See the paintComponent method:

 /** overriden to draw the image on the component graphics
     * @param g1 the Graphics instance*/
    public void paintComponent(Graphics g1) {
        Graphics2D g = (Graphics2D)g1;
        originalBox = new Rectangle(0, 0, display.getWidth(this), display.getHeight(this));
        Rectangle box = this.tx.createTransformedShape(new Rectangle(0, 0, getWidth(), getHeight())).getBounds();
        AffineTransform resizeTX = AffineTransform.getScaleInstance(box.width/originalBox.width, box.height/originalBox.height);
        g.setClip(box);
        g.setBackground(background);
        g.clearRect(box.x, box.y, box.width, box.height);
        Composite cps = g.getComposite();
        AffineTransform tx = AffineTransform.getScaleInstance(box.width/bgImg.getWidth(this), box.height/bgImg.getWidth(this));
        mt.addImage(bgImg, bgImg.hashCode(), box.width, box.height);
        mt.addImage(display, hashCode(), box.width, box.height);
        try {
            mt.waitForAll();
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.33f));
            g.drawImage(bgImg, tx, this);
            g.setComposite(cps);
            g.drawImage(display, resizeTX, this);
            super.paintComponent(g);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

I have never experienced a PNG vs GIF problem in Java.

I ran your code on my computer and have a few suggestions:

  1. Call super.paintComponent() first.
    On a Mac, if you call it last it will write over everything you just drew. :slight_smile: If I call it first, then it acts as your background.
    (I don’t think you need to call it at all if you’re effectively covering up the whole panel anyway.)

  2. When you say “box.width/originalBox.width”… this is a very deceptive line. They’re both integers. So what do you get if you divide 90/100? 0. But if you divide 90.0/100.0, then you get .9. So you need to convert them to floats or doubles:
    ((double)box.width)/((double)originalBox.width)

This could, in some cases, make some images disappear.

  1. Unless your image pointers are constantly changing, don’t use a MediaTracker in the paintComponent method to wait for each image to load. Instead, when you create pointers to the images, wait for them there. Then you’ll only wait once.

I adopted your code to this stand-alone example and played with it on my Mac. There’s a checkbox at the top of the window that demonstrates the difference between integer division and floating-point division:

import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.event.*;

public class ImageTest extends JPanel {
	JCheckBox floatingPrecision = new JCheckBox("Floating-Point Precision");
	
	public static void main(String[] args) {
		JFrame f = new JFrame();
		ImageTest t = new ImageTest();
		f.getContentPane().add(t.floatingPrecision,BorderLayout.NORTH);
		f.getContentPane().add(t);
		f.pack();
		f.show();
	}
	
	BufferedImage bi1 = new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
	BufferedImage bi2 = new BufferedImage(bi1.getWidth(),bi1.getHeight(),bi1.getType());
	public ImageTest() {
		floatingPrecision.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				repaint();
			}
		});
		
		setPreferredSize(new Dimension(bi1.getWidth(),bi1.getHeight()));
		Graphics2D g2 = bi1.createGraphics();
		g2.setColor(Color.red);
		Polygon polygon = new Polygon();
		polygon.addPoint(bi1.getWidth(),0);
		polygon.addPoint(bi1.getWidth(),bi1.getHeight());
		polygon.addPoint(0,bi1.getHeight());
		g2.fill(polygon);
		g2.dispose();
		
		g2 = bi2.createGraphics();
		Ellipse2D e = new Ellipse2D.Float(0,0,bi1.getWidth(),bi1.getHeight());
		g2.setColor(Color.blue);
		g2.fill(e);
		g2.dispose();
	}
	/** overriden to draw the image on the component graphics
	 * @param g1 the Graphics instance*/
	public void paintComponent(Graphics g1) {
		Image display = bi1;
		Rectangle originalBox;
		Color background = Color.lightGray;
		Image bgImg = bi2;
		super.paintComponent(g1);
		
		Graphics2D g = (Graphics2D)g1;
		originalBox = new Rectangle(0, 0, display.getWidth(this), display.getHeight(this));
		Rectangle box = new Rectangle(0,0,getWidth(),getHeight()); //this.tx.createTransformedShape(new Rectangle(0, 0, getWidth(), getHeight())).getBounds();
		AffineTransform resizeTX;
		if(!floatingPrecision.isSelected()) {
			resizeTX = AffineTransform.getScaleInstance(box.width/originalBox.width, box.height/originalBox.height);
		} else {
			double sx = ((double)box.width)/((double)originalBox.width);
			double sy = ((double)box.height)/((double)originalBox.height);
			resizeTX = AffineTransform.getScaleInstance(sx,sy);
		}
		g.setClip(box);
		g.setBackground(background);
		g.clearRect(box.x, box.y, box.width, box.height);
		Composite cps = g.getComposite();
		AffineTransform tx;
		if(!floatingPrecision.isSelected()) {
			tx = AffineTransform.getScaleInstance(box.width/bgImg.getWidth(this), box.height/bgImg.getWidth(this));
		} else {
			double sx = ((double)box.width)/((double)bgImg.getWidth(this));
			double sy = ((double)box.height)/((double)bgImg.getHeight(this));
			tx = AffineTransform.getScaleInstance(sx,sy);
		}
		g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.33f));
		g.drawImage(bgImg, tx, this);
		g.setComposite(cps);
		g.drawImage(display, resizeTX, this);
	}
}

Does this help? If not, can you give me some more pointers to better reproduce your problem?

well this is a classical mistake… :smiley: Thanks a lot for the fix I’ll debug soon.