1.5 'AffineTrans. rotation screwing up colors' bug

ok, after several requests to convert this 4K Game.( http://www.pkl.net/~rsc/4KShooter/4KShooter.jar)
So it doesn’t use the Windows only Experimental alpha trans.
I decided to do it. It was only 10mins work… and I ended up with this (note the lack of a cool blur effect ;P):-

http://www.pkl.net/~rsc/4KShooter/4KShooterSE.jar

and it runs perfectly on 1.4.2_03

I then tried it on the 1.5beta… and its bugged :-/

It seems that rotation AffineTransforms are screwing up the ColorModel of the destination image.

The source image is a managed Image (BITMASK),
The destination Image is a managed image (BITMASK).
When the rotation angle is anything but 0, the palette gets screwed up.

the sourcecode is available here (though I have to warn you its size optimised code :P):-

http://www.pkl.net/~rsc/4KShooter/A.java

To summarise, im doing this :-


//load the image
BufferedImage loadedImage = ImageIO.read(getClass().getResource(STRING_SHIPS_FILENAME));

//copy a portion of it into a smaller image
(objectImages[0][0] = gc.createCompatibleImage(IMAGE_WIDTH,IMAGE_HEIGHT, Transparency.BITMASK))
.createGraphics().drawImage(loadedImage,(IMAGE_WIDTH-SHIP_WIDTH)/2,(IMAGE_HEIGHT-SHIP_HEIGHT)/2,null);

//rotate the smaller image X times (pre-calc of rotation frames)
BufferedImage src = objectImages[0][0];
for(int i =0;i < NUM_ROTATIONS;i++)
{
   (g = (objectImages[0][i] = gc.createCompatibleImage(IMAGE_WIDTH,IMAGE_HEIGHT,Transparency.BITMASK)).createGraphics())
   .rotate(i*ANGLE_INC,IMAGE_WIDTH/2,IMAGE_HEIGHT/2);
   g.drawImage(src,0,0,null);
}

ok, i’ve made a testcase demonstrating the bug.

As I said, this bug is not present in 1.4.2_03, it only appears in 1.5beta1.

I’ve only tested it on WinXP, but i’d wager it appears in on all Windows platforms…

Executable Jar (also containing sourcecode) :-
http://www.pkl.net/~rsc/4KShooter/TestCase.jar

and the sourcecode and image seperately :-

http://www.pkl.net/~rsc/4KShooter/TestCase.java

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
public class TestCase extends Frame implements Runnable
{
   
   static final int IMAGE_WIDTH = 32, IMAGE_HEIGHT = 32;
   static final int SHIP_WIDTH = 21, SHIP_HEIGHT = 25;

   static final int NUM_ROTATIONS = 90;
   static final float ANGLE_INC = (float)((Math.PI*2d) / NUM_ROTATIONS);
   
   static final String STRING_SHIPS_FILENAME = "image.gif";
   
   static final int SCREEN_WIDTH = 400,SCREEN_HEIGHT = 300;
   
   BufferedImage loadedImage;
   
   BufferedImage [] objectImages = new BufferedImage[NUM_ROTATIONS];
   
   public TestCase() throws Exception
   {
      super("ManagedImage/AffineTransform bug");
      
      setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
      show();
      GraphicsConfiguration gc = getGraphicsConfiguration();
      
      //load the image
      loadedImage = ImageIO.read(getClass().getResource(STRING_SHIPS_FILENAME));

      //copy it into the centre of the 1st element of the array
      BufferedImage src = gc.createCompatibleImage(IMAGE_WIDTH,IMAGE_HEIGHT, Transparency.BITMASK);
      {
         Graphics2D g = src.createGraphics();
         g.drawImage(loadedImage,(IMAGE_WIDTH-SHIP_WIDTH)/2,(IMAGE_HEIGHT-SHIP_HEIGHT)/2,null);
      }
         
      for(int i =0;i < NUM_ROTATIONS;i++)
      {
         //create rotations
         objectImages[i] = gc.createCompatibleImage(IMAGE_WIDTH,IMAGE_HEIGHT,Transparency.BITMASK);
         Graphics2D g = objectImages[i].createGraphics();
         g.rotate(i*ANGLE_INC,IMAGE_WIDTH/2,IMAGE_HEIGHT/2); //combined, saved 1byte
         g.drawImage(src,0,0,null);
      }
         
      createBufferStrategy(2);
      enableEvents(AWTEvent.WINDOW_EVENT_MASK);
      
      Thread me = new Thread(this);
      me.start();
   }
   
   boolean running = true;
   
   public void processWindowEvent(WindowEvent we)
   {
      if(we.getID()==WindowEvent.WINDOW_CLOSING)
      {
         running = false;
      }
   }
   
   public void run()
   {
      int angle = 80;
      while(running)
      {
         BufferStrategy bs = getBufferStrategy();
         Graphics g = bs.getDrawGraphics();
         g.setColor(Color.black);
         g.fillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
         g.drawImage(objectImages[angle],40,40,null);
         g.setColor(Color.white);
         g.drawString(String.valueOf(angle*4),50,90);
         bs.show();
         
         
         angle=(angle+1)%NUM_ROTATIONS;
         try
         {
            Thread.sleep(50);
         }
         catch(Exception e)
         {
         }
      }
      dispose();
   }
   
   
   public static void main(String [] args)
   {
      try
      {
         new TestCase();
      }
      catch(Exception e)
      {
         System.out.println("Something went wrong");
      }
   }
}

Did you report this to Sun? Post the bug# when it is available. Then others might vote for it.

[quote]Did you report this to Sun? Post the bug# when it is available. Then others might vote for it.
[/quote]
yeah, reported it.
Posted here as well, cos generally you get a faster response :wink:

wow!
I take that back, got a response in less than 12hours!

bug ID 4994576

http://developer.java.sun.com/developer/bugParade/bugs/4994576.html

I doubt it’ll need any votes for it to get fixed though, it is kinda core functionality :stuck_out_tongue:

I think the Sun folks are going all out to get 1.5 ready for release.