Compatible Image .createGraphics() broken?

Abuse’s code:


/********************* START Car Image Loading and Generation *****************/
         BufferedImage carImage = ImageIO.read(getClass().getResource(STRING_CAR_FILENAME)); //load the car Image
         BufferedImage [] carFrames = new BufferedImage[CAR_ROTATIONS];
         for(int i = 0;i < CAR_ROTATIONS;i++)
         {
            carFrames[i] = gc.createCompatibleImage(CAR_SIZE,CAR_SIZE,Transparency.BITMASK);
            Graphics2D cfg2d = carFrames[i].createGraphics();
            cfg2d.rotate(((Math.PI*2)*i)/CAR_ROTATIONS, CAR_SIZE/2,CAR_SIZE/2);
            cfg2d.drawImage(carImage,(CAR_SIZE-CAR_WIDTH)/2,(CAR_SIZE-CAR_HEIGHT)/2 ,null);
         }
/********************* END Car Image Loading and Generation *******************/

I tried to do a very similar thing, producing source code:


protected Image loadImage( String filename, GraphicsConfiguration gc )
      {
            long sTime = System.currentTimeMillis();
            
            BufferedImage loadedImage = null;
            try
            {
                  loadedImage = ImageIO.read(  getClass().getResource( filename ) );
            }
            catch( Exception e )
            {
                  System.out.println( "Exception loading image: "+filename+", e = "+e );
            }
            BufferedImage img = gc.createCompatibleImage( loadedImage.getWidth(), loadedImage.getHeight(), Transparency.BITMASK );
            //BufferedImage img = gc.createCompatibleImage( loadedImage.getWidth(), loadedImage.getHeight(), Transparency.OPAQUE );
            
            Graphics2D g = img.createGraphics();
            g.drawImage( loadedImage, loadedImage.getWidth(), loadedImage.getHeight(), null );
            
            //return img;
            return loadedImage;
      }

…but, if you swap the commenting on the last two lines, so that it returns the Compatible Image, which you have drawn the loadedImage onto, you get a blank image.

If you set the transparency to OPAQUE, you get a black image of the same dimenstions as the source.

The way I’m getting the gc is to actually call a wrapper for the above method:


protected Image loadImage( String filename )
      {
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gd = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            System.out.println( "ge = "+ge+", gd = "+gd+", gc = "+gc );
            return loadImage( filename, gc );
      }

…which seems pretty sensible to me?

But none of this works on linux nor windows for me. So, what the heck am I doing wrong? I’m not getting null devices or anything, no exceptions, just no image! Here’s complete brief source for a tiny Swing app that shows the problem; comment / uncomment the return statements as described above, and you’ll see the application either display your “test.gif” or not.


import net.tmachine.common.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.io.*;

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

public class ImageTest extends JComponent
{
      public static void main( String[] args )
      {
            JFrame jf = new JFrame();
            jf.getContentPane().add( new ImageTest() );
            jf.setSize( 400, 400 );
            jf.setVisible( true );
      }
      
      Image i;
      public ImageTest()
      {
            i = loadImage( "test.gif" );
      }
      
      public void paintComponent( Graphics g )
      {
            g.drawImage( i, 0, 0, null );
      }
      
      protected Image loadImage( String filename )
      {
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gd = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gd.getDefaultConfiguration();
            System.out.println( "ge = "+ge+", gd = "+gd+", gc = "+gc );
            return loadImage( filename, gc );
      }
      
      protected Image loadImage( String filename, GraphicsConfiguration gc )
      {
            long sTime = System.currentTimeMillis();
            
            BufferedImage loadedImage = null;
            try
            {
                  loadedImage = ImageIO.read(  getClass().getResource( filename ) );
            }
            catch( Exception e )
            {
                  System.out.println( "Exception loading image: "+filename+", e = "+e );
            }
            BufferedImage img = gc.createCompatibleImage( loadedImage.getWidth(), loadedImage.getHeight(), Transparency.BITMASK );
            //BufferedImage img = gc.createCompatibleImage( loadedImage.getWidth(), loadedImage.getHeight(), Transparency.OPAQUE );
            
            Graphics2D g = img.createGraphics();
            g.drawImage( loadedImage, loadedImage.getWidth(), loadedImage.getHeight(), null );
            
            //return img;
            return loadedImage;
      }
}

Hey I actually know the answer for this one!
I just wrote a loader like this last week.

drawImage(image,0,0,null)

You need to have the location you are drawing to set to 0,0 the upper left corner of the image. Yours was drawing outside this image size.

[quote]Hey I actually know the answer for this one!
I just wrote a loader like this last week.

drawImage(image,0,0,null)

You need to have the location you are drawing to set to 0,0 the upper left corner of the image. Yours was drawing outside this image size.
[/quote]
Doh, doh, doh, doh ,doh, doh, doh!

<fx: bangs head against table>

hehe
I figured that would be your responce :wink:

Hey I did something just as stupid. As I was writing mine I passed it a string like filename.png, and of course my image was a jpg. It was throwing a null pointer exception and I never filled in the catch block so it took me some time to realize what was going on :slight_smile:

[quote]hehe
I figured that would be your responce :wink:

Hey I did something just as stupid. As I was writing mine I passed it a string like filename.png, and of course my image was a jpg. It was throwing a null pointer exception and I never filled in the catch block so it took me some time to realize what was going on :slight_smile:
[/quote]
Yeah, well, I’d looked over the code 5 or 6 times, reduce it to a test case (rewriting it with different method calls), and shown it to a couple of people, but none of us could spot the problem.

I can only guess that we were all thinking “that’s drawing the Image at 1:1 scaling” rather than “that’s drawing the image at location x,y”.