JDK-4696285 : AffineTransformOp on 4-component color model throws ImagingOpException
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_98
  • CPU: x86
  • Submitted: 2002-06-03
  • Updated: 2014-03-18
Description
Name: jk109818			Date: 06/03/2002


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)


FULL OPERATING SYSTEM VERSION :
Windows 98 [Version 4.10.2222]

A DESCRIPTION OF THE PROBLEM :
Trying to use AffineImageOp on 4-component color models
throws an java.awt.image.ImagingOpException: Unable to
transform src image because ImigingLib returns a null
for the transformed image.

The sample code shows a simple change to a ColorModel
based on a 1- or 3-component ColorSpace works fine.

Java 2D has 1- and 3-component (sRGB) color spaces,
but no 4-component, so perhaps there wasn't a test case.
The source code below contains a 4-component color space
(for CMYK) for use in this test, and the same error happens
with 4-component color spaces built from ICC color spaces
built from profile data with
ICC_Profile.getInstance(InputStream s).

There are a number of other outstanding bugs related to
AffineTransformOp, such as that is throws an exception on
transformation matrices with shearing, so it would nice if
it and ImagingLib could receive some attention for Java 1.4.1.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run source code.
2.
3.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected scaled image; actual results in exception.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
[native ImagingLib returns null, triggering...]
java.awt.image.ImagingOpException: Unable to transform src image
		at java.awt.image.AffineTransformOp.filter(AffineTransformOp.java:262)
		at AOP4Test.testAOP(AOP4Test.java:41)
		at AOP4Test.main(AOP4Test.java:50)

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.image.*;
import java.awt.geom.*;
import java.awt.color.ColorSpace;



/**
	AffineTransformOp on 4-component color space image throws:

	java.awt.image.ImagingOpException: Unable to transform src image
		at java.awt.image.AffineTransformOp.filter(AffineTransformOp.java:262)
		at AOP4Test.testAOP(AOP4Test.java:41)
		at AOP4Test.main(AOP4Test.java:50)
*/
public class AOP4Test {
  static void testAOP() {
	// TRY DIFFERENT COLOR MODELS by uncommenting others
	ColorModel cm;
	// 4-components => BOOM!
	cm = new ComponentColorModel(ColorSpaceCMYK.getInstance(), false, true,
Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
	// 3-component OK
	//cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false,
true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
	// 1-component OK
	//cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), false,
true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);

	// create image
	int w = 200, h=300;
	int ncomp = cm.getNumComponents();
	int[] offs = new int[ncomp]; for (int i=0; i<ncomp; i++) offs[i]=i;
	DataBufferByte db = new DataBufferByte(w * ncomp * h);
	WritableRaster r = Raster.createInterleavedRaster(db, w,h, w*ncomp, ncomp, offs,
null);
	BufferedImage img = new BufferedImage(cm, r, false, new java.util.Hashtable());

	// transform
	AffineTransform at = new AffineTransform(2.0,0.0, 0.0,2.0, 0.0,0.0);    // simple
scaling
	AffineTransformOp aop = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);

	img = aop.filter(img, null);

	// if no exception above, report success
	System.out.println(w+"x"+h+" scale to "+img.getWidth()+"x"+img.getHeight());
  }


  public static void main(String[] args) {
	try {
		testAOP();
	} catch (Exception e) {
		e.printStackTrace();
		System.out.println(e);
	}
  }
}


/** CMYK ColorSpace by Thomas A. Phelps */
class ColorSpaceCMYK extends ColorSpace {
  static final ColorSpace RGB = getInstance(ColorSpace.CS_sRGB);
  static ColorSpaceCMYK instance_ = null;

  private ColorSpaceCMYK() { super(TYPE_CMYK, 4); }
  public static ColorSpaceCMYK getInstance() {
	if (instance_==null) instance_ = new ColorSpaceCMYK();
	return instance_;
  }


  public float[] fromCIEXYZ(float[] colorvalue) {
	return fromRGB(RGB.fromCIEXYZ(colorvalue));
  }

  public float[] toCIEXYZ(float[] colorvalue) {
	return RGB.toCIEXYZ(toRGB(colorvalue));
  }

  /** Black generation and undercolor removal hardcoded to maximum.  See PDF Ref
1.4, page 377. */
  public float[] fromRGB(float[] rgbvalue) {
	float[] out = new float[4];
	float c = 1.0f - rgbvalue[0];   // c = 1-r
	float m = 1.0f - rgbvalue[1];   // m = 1-g
	float y = 1.0f - rgbvalue[2];   // y = 1-b
	float k = Math.min(Math.min(c,m), y);

	out[0]=c-k; out[1]=m-k; out[2]=y-k; out[3]=k;

	return out;
  }

  public float[] toRGB(float[] colorvalue) {
	// following PDF Ref 1.4, page 380
	float[] out = new float[3];
	float k = colorvalue[3];
	out[0] = 1.0f - Math.min(1.0f, colorvalue[0] + k);
	out[1] = 1.0f - Math.min(1.0f, colorvalue[1] + k);
	out[2] = 1.0f - Math.min(1.0f, colorvalue[2] + k);
	return out;
  }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Translate samples to 3-component color space.  This is hairy
in general, but perhaps in the particular case it's needed
it is not so bad.
(Review ID: 148119) 
======================================================================
###@###.### 10/5/04 21:42 GMT

Comments
Please re-open if - if fix is in progress or on the plan to fix soon - if this is a P3 (file as P3, not P4)
18-03-2014