JDK-6357449 : Illegitimate parts drawn outside of transformed black+transparent images
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-12-01
  • Updated: 2010-04-02
  • Resolved: 2005-12-01
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)
---and----
java version "1.4.2_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]
Caldera Linux

A DESCRIPTION OF THE PROBLEM :
Illegitimate parts outside of certain images are drawn when using method Graphics2D.drawImage(Image,AffineTransform,ImageObserver).
The problem occurs with transformed BufferedImages having an IndexColorModel with black and transparent color.
Scaled and translated images tend to have black hair-lines around their upper quarter (especially for fractional AffineTransforms).
Rotated BufferedImages have a black filled rectangle drawn "behind" their upper quarter.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the source code below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No parts outside the image areas should be drawn.
Only the 3 "X"-shaped images should appear.

ACTUAL -
Additional spurious parts just outside the images are drawn.
1st image: Black hair-line appears at right edge of upper quarter.
2nd image: Black hair-lines appear at left and top edge of upper quarter.
3rd image: Black filled rectangle appears "behind" upper quarter.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import javax.swing.*;

public class ImageComponent extends JComponent {
  public static void main(String args[]) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(new ImageComponent());
    frame.setSize(800, 400);
    frame.setVisible(true);
  }

  Image image;

  ImageComponent() {
    // build 16x16 image, 1 bit/pixel, black "X" on transparent background
    byte data[] = {
      (byte)0x7F, (byte)0xFE, (byte)0xBF, (byte)0xFD,
      (byte)0xDF, (byte)0xFB, (byte)0xEF, (byte)0xF7,
      (byte)0xF7, (byte)0xEF, (byte)0xFB, (byte)0xDF,
      (byte)0xFD, (byte)0xBF, (byte)0xFE, (byte)0x7F,
      (byte)0xFE, (byte)0x7F, (byte)0xFD, (byte)0xBF,
      (byte)0xFB, (byte)0xDF, (byte)0xF7, (byte)0xEF,
      (byte)0xEF, (byte)0xF7, (byte)0xDF, (byte)0xFB,
      (byte)0xBF, (byte)0xFD, (byte)0x7F, (byte)0xFE
    };
    WritableRaster raster = Raster.createPackedRaster(
        new DataBufferByte(data, data.length), 16, 16, 1, null);
    ColorModel colorModel = new IndexColorModel(1, 2,
        new int[] { 0xFF000000, 0 },  // [0]=black, [1]=transparent
        0, true, -1, DataBuffer.TYPE_BYTE);
    image = new BufferedImage(colorModel, raster, false, null);
  }

  protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g.create();
    g2.scale(10, 10);
    g2.translate(5, 5);
    g2.drawImage(image,
        AffineTransform.getScaleInstance(1.02, 1.02), this);
    g2.translate(25, 0);
    g2.drawImage(image,
        AffineTransform.getTranslateInstance(-0.02, -0.02), this);
    g2.translate(30, 0);
    g2.drawImage(image,
        AffineTransform.getRotateInstance(Math.toRadians(30)), this);
    g2.dispose();
  }
}
---------- END SOURCE ----------

Comments
EVALUATION This was fixed by the new image transformation pipelines introduced in Mustang (see bug 5051527).
01-12-2005