4893408: JPEGReader throws IllegalArgException when setting the destination to BYTE_GRAY
Reviewed-by: igor, prr
This commit is contained in:
parent
f3d01961f8
commit
8e2b3cf306
@ -215,17 +215,21 @@ public class JPEG {
|
||||
public static class JCS {
|
||||
public static final ColorSpace sRGB =
|
||||
ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
||||
public static final ColorSpace YCC;
|
||||
|
||||
static {
|
||||
ColorSpace cs = null;
|
||||
try {
|
||||
cs = ColorSpace.getInstance(ColorSpace.CS_PYCC);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// PYCC.pf may not always be installed
|
||||
} finally {
|
||||
YCC = cs;
|
||||
private static ColorSpace YCC = null;
|
||||
private static boolean yccInited = false;
|
||||
|
||||
public static ColorSpace getYCC() {
|
||||
if (!yccInited) {
|
||||
try {
|
||||
YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// PYCC.pf may not always be installed
|
||||
} finally {
|
||||
yccInited = true;
|
||||
}
|
||||
}
|
||||
return YCC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import sun.java2d.Disposer;
|
||||
import sun.java2d.DisposerRecord;
|
||||
@ -215,51 +216,6 @@ public class JPEGImageReader extends ImageReader {
|
||||
/** The DisposerRecord that handles the actual disposal of this reader. */
|
||||
private DisposerRecord disposerRecord;
|
||||
|
||||
/**
|
||||
* Maintain an array of the default image types corresponding to the
|
||||
* various supported IJG colorspace codes.
|
||||
*/
|
||||
private static final ImageTypeSpecifier [] defaultTypes =
|
||||
new ImageTypeSpecifier [JPEG.NUM_JCS_CODES];
|
||||
|
||||
static {
|
||||
defaultTypes[JPEG.JCS_GRAYSCALE] =
|
||||
ImageTypeSpecifier.createFromBufferedImageType
|
||||
(BufferedImage.TYPE_BYTE_GRAY);
|
||||
defaultTypes[JPEG.JCS_RGB] =
|
||||
ImageTypeSpecifier.createInterleaved
|
||||
(JPEG.JCS.sRGB,
|
||||
JPEG.bOffsRGB,
|
||||
DataBuffer.TYPE_BYTE,
|
||||
false,
|
||||
false);
|
||||
defaultTypes[JPEG.JCS_RGBA] =
|
||||
ImageTypeSpecifier.createPacked
|
||||
(JPEG.JCS.sRGB,
|
||||
0xff000000,
|
||||
0x00ff0000,
|
||||
0x0000ff00,
|
||||
0x000000ff,
|
||||
DataBuffer.TYPE_INT,
|
||||
false);
|
||||
if (JPEG.JCS.YCC != null) {
|
||||
defaultTypes[JPEG.JCS_YCC] =
|
||||
ImageTypeSpecifier.createInterleaved
|
||||
(JPEG.JCS.YCC,
|
||||
JPEG.bandOffsets[2],
|
||||
DataBuffer.TYPE_BYTE,
|
||||
false,
|
||||
false);
|
||||
defaultTypes[JPEG.JCS_YCCA] =
|
||||
ImageTypeSpecifier.createInterleaved
|
||||
(JPEG.JCS.YCC,
|
||||
JPEG.bandOffsets[3],
|
||||
DataBuffer.TYPE_BYTE,
|
||||
true,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets up static C structures. */
|
||||
private static native void initReaderIDs(Class iisClass,
|
||||
Class qTableClass,
|
||||
@ -706,11 +662,11 @@ public class JPEGImageReader extends ImageReader {
|
||||
* Return an ImageTypeSpecifier corresponding to the given
|
||||
* color space code, or null if the color space is unsupported.
|
||||
*/
|
||||
private ImageTypeSpecifier getImageType(int code) {
|
||||
ImageTypeSpecifier ret = null;
|
||||
private ImageTypeProducer getImageType(int code) {
|
||||
ImageTypeProducer ret = null;
|
||||
|
||||
if ((code > 0) && (code < JPEG.NUM_JCS_CODES)) {
|
||||
ret = defaultTypes[code];
|
||||
ret = ImageTypeProducer.getTypeProducer(code);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -724,7 +680,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
|
||||
// Returns null if it can't be represented
|
||||
return getImageType(colorSpaceCode);
|
||||
return getImageType(colorSpaceCode).getType();
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
}
|
||||
@ -758,13 +714,13 @@ public class JPEGImageReader extends ImageReader {
|
||||
|
||||
// Get the raw ITS, if there is one. Note that this
|
||||
// won't always be the same as the default.
|
||||
ImageTypeSpecifier raw = getImageType(colorSpaceCode);
|
||||
ImageTypeProducer raw = getImageType(colorSpaceCode);
|
||||
|
||||
// Given the encoded colorspace, build a list of ITS's
|
||||
// representing outputs you could handle starting
|
||||
// with the default.
|
||||
|
||||
ArrayList list = new ArrayList(1);
|
||||
ArrayList<ImageTypeProducer> list = new ArrayList<ImageTypeProducer>(1);
|
||||
|
||||
switch (colorSpaceCode) {
|
||||
case JPEG.JCS_GRAYSCALE:
|
||||
@ -774,9 +730,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
case JPEG.JCS_RGB:
|
||||
list.add(raw);
|
||||
list.add(getImageType(JPEG.JCS_GRAYSCALE));
|
||||
if (JPEG.JCS.YCC != null) {
|
||||
list.add(getImageType(JPEG.JCS_YCC));
|
||||
}
|
||||
list.add(getImageType(JPEG.JCS_YCC));
|
||||
break;
|
||||
case JPEG.JCS_RGBA:
|
||||
list.add(raw);
|
||||
@ -801,19 +755,21 @@ public class JPEGImageReader extends ImageReader {
|
||||
list.add(getImageType(JPEG.JCS_RGB));
|
||||
|
||||
if (iccCS != null) {
|
||||
list.add(ImageTypeSpecifier.createInterleaved
|
||||
list.add(new ImageTypeProducer() {
|
||||
protected ImageTypeSpecifier produce() {
|
||||
return ImageTypeSpecifier.createInterleaved
|
||||
(iccCS,
|
||||
JPEG.bOffsRGB, // Assume it's for RGB
|
||||
DataBuffer.TYPE_BYTE,
|
||||
false,
|
||||
false));
|
||||
false);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
list.add(getImageType(JPEG.JCS_GRAYSCALE));
|
||||
if (JPEG.JCS.YCC != null) { // Might be null if PYCC.pf not installed
|
||||
list.add(getImageType(JPEG.JCS_YCC));
|
||||
}
|
||||
list.add(getImageType(JPEG.JCS_YCC));
|
||||
break;
|
||||
case JPEG.JCS_YCbCrA: // Default is to convert to RGBA
|
||||
// As there is no YCbCr ColorSpace, we can't support
|
||||
@ -822,7 +778,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
break;
|
||||
}
|
||||
|
||||
return list.iterator();
|
||||
return new ImageTypeIterator(list.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -872,6 +828,10 @@ public class JPEGImageReader extends ImageReader {
|
||||
if (csType == ColorSpace.TYPE_RGB) { // We want RGB
|
||||
// IJG can do this for us more efficiently
|
||||
setOutColorSpace(structPointer, JPEG.JCS_RGB);
|
||||
// Update java state according to changes
|
||||
// in the native part of decoder.
|
||||
outColorSpaceCode = JPEG.JCS_RGB;
|
||||
numComponents = 3;
|
||||
} else if (csType != ColorSpace.TYPE_GRAY) {
|
||||
throw new IIOException("Incompatible color conversion");
|
||||
}
|
||||
@ -881,6 +841,10 @@ public class JPEGImageReader extends ImageReader {
|
||||
if (colorSpaceCode == JPEG.JCS_YCbCr) {
|
||||
// If the jpeg space is YCbCr, IJG can do it
|
||||
setOutColorSpace(structPointer, JPEG.JCS_GRAYSCALE);
|
||||
// Update java state according to changes
|
||||
// in the native part of decoder.
|
||||
outColorSpaceCode = JPEG.JCS_GRAYSCALE;
|
||||
numComponents = 1;
|
||||
}
|
||||
} else if ((iccCS != null) &&
|
||||
(cm.getNumComponents() == numComponents) &&
|
||||
@ -906,20 +870,26 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
break;
|
||||
case JPEG.JCS_YCC:
|
||||
if (JPEG.JCS.YCC == null) { // We can't do YCC at all
|
||||
throw new IIOException("Incompatible color conversion");
|
||||
}
|
||||
if ((cs != JPEG.JCS.YCC) &&
|
||||
(cm.getNumComponents() == numComponents)) {
|
||||
convert = new ColorConvertOp(JPEG.JCS.YCC, cs, null);
|
||||
{
|
||||
ColorSpace YCC = JPEG.JCS.getYCC();
|
||||
if (YCC == null) { // We can't do YCC at all
|
||||
throw new IIOException("Incompatible color conversion");
|
||||
}
|
||||
if ((cs != YCC) &&
|
||||
(cm.getNumComponents() == numComponents)) {
|
||||
convert = new ColorConvertOp(YCC, cs, null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JPEG.JCS_YCCA:
|
||||
// No conversions available; image must be YCCA
|
||||
if ((JPEG.JCS.YCC == null) || // We can't do YCC at all
|
||||
(cs != JPEG.JCS.YCC) ||
|
||||
(cm.getNumComponents() != numComponents)) {
|
||||
throw new IIOException("Incompatible color conversion");
|
||||
{
|
||||
ColorSpace YCC = JPEG.JCS.getYCC();
|
||||
// No conversions available; image must be YCCA
|
||||
if ((YCC == null) || // We can't do YCC at all
|
||||
(cs != YCC) ||
|
||||
(cm.getNumComponents() != numComponents)) {
|
||||
throw new IIOException("Incompatible color conversion");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1554,3 +1524,140 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal helper class that wraps producer's iterator
|
||||
* and extracts specifier instances on demand.
|
||||
*/
|
||||
class ImageTypeIterator implements Iterator<ImageTypeSpecifier> {
|
||||
private Iterator<ImageTypeProducer> producers;
|
||||
private ImageTypeSpecifier theNext = null;
|
||||
|
||||
public ImageTypeIterator(Iterator<ImageTypeProducer> producers) {
|
||||
this.producers = producers;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
if (theNext != null) {
|
||||
return true;
|
||||
}
|
||||
if (!producers.hasNext()) {
|
||||
return false;
|
||||
}
|
||||
do {
|
||||
theNext = producers.next().getType();
|
||||
} while (theNext == null && producers.hasNext());
|
||||
|
||||
return (theNext != null);
|
||||
}
|
||||
|
||||
public ImageTypeSpecifier next() {
|
||||
if (theNext != null || hasNext()) {
|
||||
ImageTypeSpecifier t = theNext;
|
||||
theNext = null;
|
||||
return t;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
producers.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal helper class that provides means for deferred creation
|
||||
* of ImageTypeSpecifier instance required to describe available
|
||||
* destination types.
|
||||
*
|
||||
* This implementation only supports standard
|
||||
* jpeg color spaces (defined by corresponding JCS color space code).
|
||||
*
|
||||
* To support other color spaces one can override produce() method to
|
||||
* return custom instance of ImageTypeSpecifier.
|
||||
*/
|
||||
class ImageTypeProducer {
|
||||
|
||||
private ImageTypeSpecifier type = null;
|
||||
boolean failed = false;
|
||||
private int csCode;
|
||||
|
||||
public ImageTypeProducer(int csCode) {
|
||||
this.csCode = csCode;
|
||||
}
|
||||
|
||||
public ImageTypeProducer() {
|
||||
csCode = -1; // undefined
|
||||
}
|
||||
|
||||
public synchronized ImageTypeSpecifier getType() {
|
||||
if (!failed && type == null) {
|
||||
try {
|
||||
type = produce();
|
||||
} catch (Throwable e) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static final ImageTypeProducer [] defaultTypes =
|
||||
new ImageTypeProducer [JPEG.NUM_JCS_CODES];
|
||||
|
||||
public synchronized static ImageTypeProducer getTypeProducer(int csCode) {
|
||||
if (csCode < 0 || csCode >= JPEG.NUM_JCS_CODES) {
|
||||
return null;
|
||||
}
|
||||
if (defaultTypes[csCode] == null) {
|
||||
defaultTypes[csCode] = new ImageTypeProducer(csCode);
|
||||
}
|
||||
return defaultTypes[csCode];
|
||||
}
|
||||
|
||||
protected ImageTypeSpecifier produce() {
|
||||
switch (csCode) {
|
||||
case JPEG.JCS_GRAYSCALE:
|
||||
return ImageTypeSpecifier.createFromBufferedImageType
|
||||
(BufferedImage.TYPE_BYTE_GRAY);
|
||||
case JPEG.JCS_RGB:
|
||||
return ImageTypeSpecifier.createInterleaved(JPEG.JCS.sRGB,
|
||||
JPEG.bOffsRGB,
|
||||
DataBuffer.TYPE_BYTE,
|
||||
false,
|
||||
false);
|
||||
case JPEG.JCS_RGBA:
|
||||
return ImageTypeSpecifier.createPacked(JPEG.JCS.sRGB,
|
||||
0xff000000,
|
||||
0x00ff0000,
|
||||
0x0000ff00,
|
||||
0x000000ff,
|
||||
DataBuffer.TYPE_INT,
|
||||
false);
|
||||
case JPEG.JCS_YCC:
|
||||
if (JPEG.JCS.getYCC() != null) {
|
||||
return ImageTypeSpecifier.createInterleaved(
|
||||
JPEG.JCS.getYCC(),
|
||||
JPEG.bandOffsets[2],
|
||||
DataBuffer.TYPE_BYTE,
|
||||
false,
|
||||
false);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
case JPEG.JCS_YCCA:
|
||||
if (JPEG.JCS.getYCC() != null) {
|
||||
return ImageTypeSpecifier.createInterleaved(
|
||||
JPEG.JCS.getYCC(),
|
||||
JPEG.bandOffsets[3],
|
||||
DataBuffer.TYPE_BYTE,
|
||||
true,
|
||||
false);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -812,7 +812,7 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
if (!alpha) {
|
||||
if (jfif != null) {
|
||||
convertTosRGB = true;
|
||||
@ -1494,7 +1494,7 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
if (alpha) {
|
||||
retval = JPEG.JCS_YCCA;
|
||||
} else {
|
||||
@ -1533,7 +1533,7 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
if (alpha) {
|
||||
retval = JPEG.JCS_YCCA;
|
||||
} else {
|
||||
@ -1579,7 +1579,7 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
if (alpha) {
|
||||
retval = JPEG.JCS_YCCA;
|
||||
} else {
|
||||
|
@ -490,7 +490,7 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable {
|
||||
}
|
||||
break;
|
||||
case ColorSpace.TYPE_3CLR:
|
||||
if (cs == JPEG.JCS.YCC) {
|
||||
if (cs == JPEG.JCS.getYCC()) {
|
||||
wantJFIF = false;
|
||||
componentIDs[0] = (byte) 'Y';
|
||||
componentIDs[1] = (byte) 'C';
|
||||
|
@ -863,11 +863,16 @@ public class ICC_Profile implements Serializable {
|
||||
case ColorSpace.CS_PYCC:
|
||||
synchronized(ICC_Profile.class) {
|
||||
if (PYCCprofile == null) {
|
||||
ProfileDeferralInfo pInfo =
|
||||
new ProfileDeferralInfo("PYCC.pf",
|
||||
ColorSpace.TYPE_3CLR, 3,
|
||||
CLASS_DISPLAY);
|
||||
PYCCprofile = getDeferredInstance(pInfo);
|
||||
if (getProfileFile("PYCC.pf") != null) {
|
||||
ProfileDeferralInfo pInfo =
|
||||
new ProfileDeferralInfo("PYCC.pf",
|
||||
ColorSpace.TYPE_3CLR, 3,
|
||||
CLASS_DISPLAY);
|
||||
PYCCprofile = getDeferredInstance(pInfo);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't load standard profile: PYCC.pf");
|
||||
}
|
||||
}
|
||||
thisProfile = PYCCprofile;
|
||||
}
|
||||
@ -1783,17 +1788,33 @@ public class ICC_Profile implements Serializable {
|
||||
return (FileInputStream)java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
return privilegedOpenProfile(fileName);
|
||||
File f = privilegedGetProfileFile(fileName);
|
||||
if (f != null) {
|
||||
try {
|
||||
return new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static File getProfileFile(final String fileName) {
|
||||
return (File)java.security.AccessController.doPrivileged(
|
||||
new java.security.PrivilegedAction() {
|
||||
public Object run() {
|
||||
return privilegedGetProfileFile(fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* this version is called from doPrivileged in privilegedOpenProfile.
|
||||
* the whole method is privileged!
|
||||
* this version is called from doPrivileged in openProfile
|
||||
* or getProfileFile, so the whole method is privileged!
|
||||
*/
|
||||
private static FileInputStream privilegedOpenProfile(String fileName) {
|
||||
FileInputStream fis = null;
|
||||
|
||||
private static File privilegedGetProfileFile(String fileName) {
|
||||
String path, dir, fullPath;
|
||||
|
||||
File f = new File(fileName); /* try absolute file name */
|
||||
@ -1830,12 +1851,9 @@ public class ICC_Profile implements Serializable {
|
||||
}
|
||||
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
fis = new FileInputStream(f);
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
return f;
|
||||
}
|
||||
return fis;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1783,7 +1783,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
|
||||
struct jpeg_source_mgr *src;
|
||||
JSAMPROW scanLinePtr;
|
||||
JSAMPROW scanLinePtr = NULL;
|
||||
jint bands[MAX_BANDS];
|
||||
int i, j;
|
||||
jint *body;
|
||||
@ -1819,7 +1819,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
cinfo = (j_decompress_ptr) data->jpegObj;
|
||||
|
||||
if ((numBands < 1) || (numBands > cinfo->num_components) ||
|
||||
if ((numBands < 1) ||
|
||||
(sourceXStart < 0) || (sourceXStart >= (jint)cinfo->image_width) ||
|
||||
(sourceYStart < 0) || (sourceYStart >= (jint)cinfo->image_height) ||
|
||||
(sourceWidth < 1) || (sourceWidth > (jint)cinfo->image_width) ||
|
||||
@ -1877,16 +1877,6 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
return data->abortFlag; // We already threw an out of memory exception
|
||||
}
|
||||
|
||||
// Allocate a 1-scanline buffer
|
||||
scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->num_components);
|
||||
if (scanLinePtr == NULL) {
|
||||
RELEASE_ARRAYS(env, data, src->next_input_byte);
|
||||
JNU_ThrowByName( env,
|
||||
"java/lang/OutOfMemoryError",
|
||||
"Reading JPEG Stream");
|
||||
return data->abortFlag;
|
||||
}
|
||||
|
||||
/* Establish the setjmp return context for sun_jpeg_error_exit to use. */
|
||||
jerr = (sun_jpeg_error_ptr) cinfo->err;
|
||||
|
||||
@ -1900,7 +1890,10 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
buffer);
|
||||
JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
|
||||
}
|
||||
free(scanLinePtr);
|
||||
if (scanLinePtr != NULL) {
|
||||
free(scanLinePtr);
|
||||
scanLinePtr = NULL;
|
||||
}
|
||||
return data->abortFlag;
|
||||
}
|
||||
|
||||
@ -1938,6 +1931,23 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
jpeg_start_decompress(cinfo);
|
||||
|
||||
if (numBands != cinfo->output_components) {
|
||||
JNU_ThrowByName(env, "javax/imageio/IIOException",
|
||||
"Invalid argument to native readImage");
|
||||
return data->abortFlag;
|
||||
}
|
||||
|
||||
|
||||
// Allocate a 1-scanline buffer
|
||||
scanLinePtr = (JSAMPROW)malloc(cinfo->image_width*cinfo->output_components);
|
||||
if (scanLinePtr == NULL) {
|
||||
RELEASE_ARRAYS(env, data, src->next_input_byte);
|
||||
JNU_ThrowByName( env,
|
||||
"java/lang/OutOfMemoryError",
|
||||
"Reading JPEG Stream");
|
||||
return data->abortFlag;
|
||||
}
|
||||
|
||||
// loop over progressive passes
|
||||
done = FALSE;
|
||||
while (!done) {
|
||||
@ -1965,9 +1975,9 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
|
||||
scanlineLimit = sourceYStart+sourceHeight;
|
||||
pixelLimit = scanLinePtr
|
||||
+(sourceXStart+sourceWidth)*cinfo->num_components;
|
||||
+(sourceXStart+sourceWidth)*cinfo->output_components;
|
||||
|
||||
pixelStride = stepX*cinfo->num_components;
|
||||
pixelStride = stepX*cinfo->output_components;
|
||||
targetLine = 0;
|
||||
|
||||
while ((data->abortFlag == JNI_FALSE)
|
||||
@ -1982,12 +1992,12 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImage
|
||||
// Optimization: The component bands are ordered sequentially,
|
||||
// so we can simply use memcpy() to copy the intermediate
|
||||
// scanline buffer into the raster.
|
||||
in = scanLinePtr + (sourceXStart * cinfo->num_components);
|
||||
in = scanLinePtr + (sourceXStart * cinfo->output_components);
|
||||
if (pixelLimit > in) {
|
||||
memcpy(out, in, pixelLimit - in);
|
||||
}
|
||||
} else {
|
||||
for (in = scanLinePtr+sourceXStart*cinfo->num_components;
|
||||
for (in = scanLinePtr+sourceXStart*cinfo->output_components;
|
||||
in < pixelLimit;
|
||||
in += pixelStride) {
|
||||
for (i = 0; i < numBands; i++) {
|
||||
|
179
jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
Normal file
179
jdk/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4893408
|
||||
*
|
||||
* @summary Test verifies that Image I/O jpeg reader correctly handles
|
||||
* destination types if number of color components in destination
|
||||
* differs from number of color components in the jpeg image.
|
||||
* Particularly, it verifies reading YCbCr image as a grayscaled
|
||||
* and reading grayscaled jpeg as a RGB.
|
||||
*
|
||||
* @run main ReadAsGrayTest
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
|
||||
import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY;
|
||||
import static java.awt.color.ColorSpace.TYPE_GRAY;
|
||||
import static java.awt.color.ColorSpace.CS_sRGB;
|
||||
|
||||
public class ReadAsGrayTest {
|
||||
static Color[] colors = new Color[] {
|
||||
Color.white, Color.red, Color.green,
|
||||
Color.blue, Color.black };
|
||||
|
||||
static final int dx = 50;
|
||||
static final int h = 100;
|
||||
|
||||
static ColorSpace sRGB = ColorSpace.getInstance(CS_sRGB);
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("Type TYPE_BYTE_GRAY");
|
||||
doTest(TYPE_BYTE_GRAY);
|
||||
|
||||
System.out.println("Type TYPE_3BYTE_BGR");
|
||||
doTest(TYPE_3BYTE_BGR);
|
||||
|
||||
System.out.println("Test PASSED.");
|
||||
}
|
||||
|
||||
private static void doTest(int type) throws IOException {
|
||||
BufferedImage src = createTestImage(type);
|
||||
|
||||
File f = new File("test.jpg");
|
||||
|
||||
if (!ImageIO.write(src, "jpg", f)) {
|
||||
throw new RuntimeException("Failed to write test image.");
|
||||
}
|
||||
|
||||
ImageInputStream iis = ImageIO.createImageInputStream(f);
|
||||
ImageReader reader = ImageIO.getImageReaders(iis).next();
|
||||
reader.setInput(iis);
|
||||
|
||||
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
|
||||
ImageTypeSpecifier srgb = null;
|
||||
ImageTypeSpecifier gray = null;
|
||||
// look for gray and srgb types
|
||||
while ((srgb == null || gray == null) && types.hasNext()) {
|
||||
ImageTypeSpecifier t = types.next();
|
||||
if (t.getColorModel().getColorSpace().getType() == TYPE_GRAY) {
|
||||
gray = t;
|
||||
}
|
||||
if (t.getColorModel().getColorSpace() == sRGB) {
|
||||
srgb = t;
|
||||
}
|
||||
}
|
||||
if (gray == null) {
|
||||
throw new RuntimeException("No gray type available.");
|
||||
}
|
||||
if (srgb == null) {
|
||||
throw new RuntimeException("No srgb type available.");
|
||||
}
|
||||
|
||||
System.out.println("Read as GRAY...");
|
||||
testType(reader, gray, src);
|
||||
|
||||
System.out.println("Read as sRGB...");
|
||||
testType(reader, srgb, src);
|
||||
}
|
||||
|
||||
private static void testType(ImageReader reader,
|
||||
ImageTypeSpecifier t,
|
||||
BufferedImage src)
|
||||
throws IOException
|
||||
{
|
||||
ImageReadParam p = reader.getDefaultReadParam();
|
||||
p.setDestinationType(t);
|
||||
BufferedImage dst = reader.read(0, p);
|
||||
|
||||
verify(src, dst, t);
|
||||
}
|
||||
|
||||
private static void verify(BufferedImage src,
|
||||
BufferedImage dst,
|
||||
ImageTypeSpecifier type)
|
||||
{
|
||||
BufferedImage test =
|
||||
type.createBufferedImage(src.getWidth(), src.getHeight());
|
||||
Graphics2D g = test.createGraphics();
|
||||
g.drawImage(src, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
int x = i * dx + dx / 2;
|
||||
int y = h / 2;
|
||||
|
||||
Color c_test = new Color(test.getRGB(x, y));
|
||||
Color c_dst = new Color(dst.getRGB(x, y));
|
||||
|
||||
if (!compareWithTolerance(c_test, c_dst, 0.01f)) {
|
||||
String msg = String.format("Invalid color: %x instead of %x",
|
||||
c_dst.getRGB(), c_test.getRGB());
|
||||
throw new RuntimeException("Test failed: " + msg);
|
||||
}
|
||||
}
|
||||
System.out.println("Verified.");
|
||||
}
|
||||
|
||||
private static boolean compareWithTolerance(Color a, Color b, float delta) {
|
||||
float[] a_rgb = new float[3];
|
||||
a_rgb = a.getRGBColorComponents(a_rgb);
|
||||
float[] b_rgb = new float[3];
|
||||
b_rgb = b.getRGBColorComponents(b_rgb);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (Math.abs(a_rgb[i] - b_rgb[i]) > delta) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BufferedImage createTestImage(int type) {
|
||||
BufferedImage img = new BufferedImage(dx * colors.length, h, type);
|
||||
|
||||
Graphics2D g = img.createGraphics();
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
g.setColor(colors[i]);
|
||||
g.fillRect(i * dx, 0, dx, h);
|
||||
}
|
||||
g.dispose();
|
||||
|
||||
return img;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user