aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hgtags1
-rw-r--r--src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java17
-rw-r--r--src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java15
-rw-r--r--src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java24
-rw-r--r--src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java261
-rw-r--r--src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java8
-rw-r--r--src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java2
-rw-r--r--src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java16
-rw-r--r--src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java44
-rw-r--r--src/share/classes/java/awt/Font.java13
-rw-r--r--src/share/classes/java/awt/GraphicsEnvironment.java5
-rw-r--r--src/share/classes/java/awt/color/ICC_Profile.java48
-rw-r--r--src/share/classes/javax/imageio/ImageIO.java14
-rw-r--r--src/share/classes/sun/font/TrueTypeFont.java52
-rw-r--r--src/share/classes/sun/java2d/pisces/PiscesCache.java2
-rw-r--r--src/share/native/sun/awt/image/jpeg/imageioJPEG.c44
-rw-r--r--test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java120
-rw-r--r--test/javax/imageio/CachePremissionsTest/rw.policy5
-rw-r--r--test/javax/imageio/CachePremissionsTest/rwd.policy5
-rw-r--r--test/javax/imageio/CachePremissionsTest/w.policy5
-rw-r--r--test/javax/imageio/plugins/bmp/TopDownTest.java142
-rw-r--r--test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java179
-rw-r--r--test/javax/imageio/plugins/wbmp/CanDecodeTest.java131
-rw-r--r--test/sun/pisces/ScaleTest.java58
24 files changed, 1053 insertions, 158 deletions
diff --git a/.hgtags b/.hgtags
index f1ddffab9..78053b178 100644
--- a/.hgtags
+++ b/.hgtags
@@ -37,3 +37,4 @@ d5a1223e961891564de25c39fba6f2442d0fb045 jdk7-b57
0c3ef2d612a47667829eb17a192decef23f1c536 jdk7-b60
f72c0dc047b9b2e797beee68ae0b50decb1f020d jdk7-b61
12e11fab9a839a9666a996a8f9a02fd8fa03aab6 jdk7-b62
+2ed6ed6b5bfc7dd724925b90dbb31223df59c25d jdk7-b63
diff --git a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java
index d70f8f031..1b0d08643 100644
--- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java
+++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriter.java
@@ -506,6 +506,19 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
writeFileHeader(fileSize, offset);
+ /* According to MSDN description, the top-down image layout
+ * is allowed only if compression type is BI_RGB or BI_BITFIELDS.
+ * Images with any other compression type must be wrote in the
+ * bottom-up layout.
+ */
+ if (compressionType == BMPConstants.BI_RGB ||
+ compressionType == BMPConstants.BI_BITFIELDS)
+ {
+ isTopDown = bmpParam.isTopDown();
+ } else {
+ isTopDown = false;
+ }
+
writeInfoHeader(headerSize, bitsPerPixel);
// compression
@@ -588,8 +601,6 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
return;
}
- isTopDown = bmpParam.isTopDown();
-
int maxBandOffset = bandOffsets[0];
for (int i = 1; i < bandOffsets.length; i++)
if (bandOffsets[i] > maxBandOffset)
@@ -1299,7 +1310,7 @@ public class BMPImageWriter extends ImageWriter implements BMPConstants {
stream.writeInt(w);
// height
- stream.writeInt(h);
+ stream.writeInt(isTopDown ? -h : h);
// number of planes
stream.writeShort(1);
diff --git a/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java b/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java
index 1f0068c20..36865df60 100644
--- a/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java
+++ b/src/share/classes/com/sun/imageio/plugins/common/ReaderUtil.java
@@ -27,6 +27,8 @@ package com.sun.imageio.plugins.common;
import java.awt.Point;
import java.awt.Rectangle;
+import java.io.IOException;
+import javax.imageio.stream.ImageInputStream;
/**
* This class contains utility methods that may be useful to ImageReader
@@ -198,4 +200,17 @@ public class ReaderUtil {
vals, 1);
return vals;
}
+
+ public static int readMultiByteInteger(ImageInputStream iis)
+ throws IOException
+ {
+ int value = iis.readByte();
+ int result = value & 0x7f;
+ while((value & 0x80) == 0x80) {
+ result <<= 7;
+ value = iis.readByte();
+ result |= (value & 0x7f);
+ }
+ return result;
+ }
}
diff --git a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java
index 3ed5c5083..6957bec6a 100644
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java
@@ -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;
}
}
diff --git a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
index faf826154..e9a4b8ac5 100644
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
@@ -41,6 +41,7 @@ import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.awt.color.ICC_ColorSpace;
+import java.awt.color.CMMException;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
@@ -53,6 +54,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 +217,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,
@@ -673,6 +630,17 @@ public class JPEGImageReader extends ImageReader {
!java.util.Arrays.equals(oldData, newData))
{
iccCS = new ICC_ColorSpace(newProfile);
+ // verify new color space
+ try {
+ float[] colors = iccCS.fromRGB(new float[] {1f, 0f, 0f});
+ } catch (CMMException e) {
+ /*
+ * Embedded profile seems to be corrupted.
+ * Ignore this profile.
+ */
+ iccCS = null;
+ warningOccurred(WARNING_IGNORE_INVALID_ICC);
+ }
}
}
@@ -706,11 +674,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 +692,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 +726,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 +742,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 +767,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 +790,7 @@ public class JPEGImageReader extends ImageReader {
break;
}
- return list.iterator();
+ return new ImageTypeIterator(list.iterator());
}
/**
@@ -872,6 +840,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 +853,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 +882,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 +1536,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;
+ }
+ }
+}
diff --git a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java
index 9c585047f..1c4b5bc1b 100644
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java
@@ -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 {
diff --git a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java
index 044f7d632..c7a628c9f 100644
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java
@@ -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';
diff --git a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java
index e8da025b3..707a54192 100644
--- a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java
+++ b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReader.java
@@ -45,6 +45,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import com.sun.imageio.plugins.common.I18N;
+import com.sun.imageio.plugins.common.ReaderUtil;
/** This class is the Java Image IO plugin reader for WBMP images.
* It may subsample the image, clip the image,
@@ -141,11 +142,11 @@ public class WBMPImageReader extends ImageReader {
metadata.wbmpType = wbmpType;
// Read image width
- width = readMultiByteInteger();
+ width = ReaderUtil.readMultiByteInteger(iis);
metadata.width = width;
// Read image height
- height = readMultiByteInteger();
+ height = ReaderUtil.readMultiByteInteger(iis);
metadata.height = height;
gotHeader = true;
@@ -311,17 +312,6 @@ public class WBMPImageReader extends ImageReader {
gotHeader = false;
}
- private int readMultiByteInteger() throws IOException {
- int value = iis.readByte();
- int result = value & 0x7f;
- while((value & 0x80) == 0x80) {
- result <<= 7;
- value = iis.readByte();
- result |= (value & 0x7f);
- }
- return result;
- }
-
/*
* This method verifies that given byte is valid wbmp type marker.
* At the moment only 0x0 marker is described by wbmp spec.
diff --git a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java
index 2d882ab6b..cb4f3bce2 100644
--- a/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java
+++ b/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java
@@ -33,9 +33,13 @@ import javax.imageio.spi.ServiceRegistry;
import java.io.IOException;
import javax.imageio.ImageReader;
import javax.imageio.IIOException;
+import com.sun.imageio.plugins.common.ReaderUtil;
public class WBMPImageReaderSpi extends ImageReaderSpi {
+ private static final int MAX_WBMP_WIDTH = 1024;
+ private static final int MAX_WBMP_HEIGHT = 768;
+
private static String [] writerSpiNames =
{"com.sun.imageio.plugins.wbmp.WBMPImageWriterSpi"};
private static String[] formatNames = {"wbmp", "WBMP"};
@@ -79,16 +83,44 @@ public class WBMPImageReaderSpi extends ImageReaderSpi {
}
ImageInputStream stream = (ImageInputStream)source;
- byte[] b = new byte[3];
stream.mark();
- stream.readFully(b);
+ int type = stream.readByte(); // TypeField
+ int fixHeaderField = stream.readByte();
+ // check WBMP "header"
+ if (type != 0 || fixHeaderField != 0) {
+ // while WBMP reader does not support ext WBMP headers
+ stream.reset();
+ return false;
+ }
+
+ int width = ReaderUtil.readMultiByteInteger(stream);
+ int height = ReaderUtil.readMultiByteInteger(stream);
+ // check image dimension
+ if (width <= 0 || height <= 0) {
+ stream.reset();
+ return false;
+ }
+
+ long dataLength = stream.length();
+ if (dataLength == -1) {
+ // We can't verify that amount of data in the stream
+ // corresponds to image dimension because we do not know
+ // the length of the data stream.
+ // Assuming that wbmp image are used for mobile devices,
+ // let's introduce an upper limit for image dimension.
+ // In case if exact amount of raster data is unknown,
+ // let's reject images with dimension above the limit.
+ stream.reset();
+ return (width < MAX_WBMP_WIDTH) && (height < MAX_WBMP_HEIGHT);
+ }
+
+ dataLength -= stream.getStreamPosition();
stream.reset();
- return ((b[0] == (byte)0) && // TypeField == 0
- b[1] == 0 && // FixHeaderField == 0xxx00000; not support ext header
- ((b[2] & 0x8f) != 0 || (b[2] & 0x7f) != 0)); // First width byte
- //XXX: b[2] & 0x8f) != 0 for the bug in Sony Ericsson encoder.
+ long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1);
+
+ return (dataLength == scanSize * height);
}
public ImageReader createReaderInstance(Object extension)
diff --git a/src/share/classes/java/awt/Font.java b/src/share/classes/java/awt/Font.java
index f73e0e90c..977731434 100644
--- a/src/share/classes/java/awt/Font.java
+++ b/src/share/classes/java/awt/Font.java
@@ -445,18 +445,19 @@ public class Font implements java.io.Serializable
*/
private AttributeValues getAttributeValues() {
if (values == null) {
- values = new AttributeValues();
- values.setFamily(name);
- values.setSize(pointSize); // expects the float value.
+ AttributeValues valuesTmp = new AttributeValues();
+ valuesTmp.setFamily(name);
+ valuesTmp.setSize(pointSize); // expects the float value.
if ((style & BOLD) != 0) {
- values.setWeight(2); // WEIGHT_BOLD
+ valuesTmp.setWeight(2); // WEIGHT_BOLD
}
if ((style & ITALIC) != 0) {
- values.setPosture(.2f); // POSTURE_OBLIQUE
+ valuesTmp.setPosture(.2f); // POSTURE_OBLIQUE
}
- values.defineAll(PRIMARY_MASK); // for streaming compatibility
+ valuesTmp.defineAll(PRIMARY_MASK); // for streaming compatibility
+ values = valuesTmp;
}
return values;
diff --git a/src/share/classes/java/awt/GraphicsEnvironment.java b/src/share/classes/java/awt/GraphicsEnvironment.java
index cf1852e2f..d77b2f22b 100644
--- a/src/share/classes/java/awt/GraphicsEnvironment.java
+++ b/src/share/classes/java/awt/GraphicsEnvironment.java
@@ -79,8 +79,9 @@ public abstract class GraphicsEnvironment {
try {
// long t0 = System.currentTimeMillis();
- localEnv =
- (GraphicsEnvironment) Class.forName(nm).newInstance();
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ Class geCls = Class.forName(nm, true, cl);
+ localEnv = (GraphicsEnvironment)geCls.newInstance();
// long t1 = System.currentTimeMillis();
// System.out.println("GE creation took " + (t1-t0)+ "ms.");
if (isHeadless()) {
diff --git a/src/share/classes/java/awt/color/ICC_Profile.java b/src/share/classes/java/awt/color/ICC_Profile.java
index 705d2560e..ef685f435 100644
--- a/src/share/classes/java/awt/color/ICC_Profile.java
+++ b/src/share/classes/java/awt/color/ICC_Profile.java
@@ -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;
}
diff --git a/src/share/classes/javax/imageio/ImageIO.java b/src/share/classes/javax/imageio/ImageIO.java
index 77f2a6b65..51b5eaeb8 100644
--- a/src/share/classes/javax/imageio/ImageIO.java
+++ b/src/share/classes/javax/imageio/ImageIO.java
@@ -28,6 +28,7 @@ package javax.imageio;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
+import java.io.FilePermission;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -195,13 +196,22 @@ public final class ImageIO {
} else {
cachepath = getTempDir();
- if (cachepath == null) {
+ if (cachepath == null || cachepath.isEmpty()) {
getCacheInfo().setHasPermission(Boolean.FALSE);
return false;
}
}
- security.checkWrite(cachepath);
+ // we have to check whether we can read, write,
+ // and delete cache files.
+ // So, compose cache file path and check it.
+ String filepath = cachepath;
+ if (!filepath.endsWith(File.separator)) {
+ filepath += File.separator;
+ }
+ filepath += "*";
+
+ security.checkPermission(new FilePermission(filepath, "read, write, delete"));
}
} catch (SecurityException e) {
getCacheInfo().setHasPermission(Boolean.FALSE);
diff --git a/src/share/classes/sun/font/TrueTypeFont.java b/src/share/classes/sun/font/TrueTypeFont.java
index 7a87e81a0..01893d655 100644
--- a/src/share/classes/sun/font/TrueTypeFont.java
+++ b/src/share/classes/sun/font/TrueTypeFont.java
@@ -160,6 +160,13 @@ public class TrueTypeFont extends FileFont {
private boolean supportsJA;
private boolean supportsCJK;
+ /* These are for faster access to the name of the font as
+ * typically exposed via API to applications.
+ */
+ private Locale nameLocale;
+ private String localeFamilyName;
+ private String localeFullName;
+
/**
* - does basic verification of the file
* - reads the header table for this font (within a collection)
@@ -1092,6 +1099,10 @@ public class TrueTypeFont extends FileFont {
* greater than 32767, so read and store those as ints
*/
int stringPtr = sbuffer.get() & 0xffff;
+
+ nameLocale = sun.awt.SunToolkit.getStartupLocale();
+ short nameLocaleID = FontManager.getLCIDFromLocale(nameLocale);
+
for (int i=0; i<numRecords; i++) {
short platformID = sbuffer.get();
if (platformID != MS_PLATFORM_ID) {
@@ -1103,15 +1114,24 @@ public class TrueTypeFont extends FileFont {
short nameID = sbuffer.get();
int nameLen = ((int) sbuffer.get()) & 0xffff;
int namePtr = (((int) sbuffer.get()) & 0xffff) + stringPtr;
-
+ String tmpName = null;
switch (nameID) {
case FAMILY_NAME_ID:
- if (familyName == null || langID == ENGLISH_LOCALE_ID) {
+ if (familyName == null || langID == ENGLISH_LOCALE_ID ||
+ langID == nameLocaleID)
+ {
buffer.position(namePtr);
buffer.get(name, 0, nameLen);
- familyName = makeString(name, nameLen, encodingID);
+ tmpName = makeString(name, nameLen, encodingID);
+
+ if (familyName == null || langID == ENGLISH_LOCALE_ID){
+ familyName = tmpName;
+ }
+ if (langID == nameLocaleID) {
+ localeFamilyName = tmpName;
+ }
}
/*
for (int ii=0;ii<nameLen;ii++) {
@@ -1129,15 +1149,29 @@ public class TrueTypeFont extends FileFont {
case FULL_NAME_ID:
- if (fullName == null || langID == ENGLISH_LOCALE_ID) {
+ if (fullName == null || langID == ENGLISH_LOCALE_ID ||
+ langID == nameLocaleID)
+ {
buffer.position(namePtr);
buffer.get(name, 0, nameLen);
- fullName = makeString(name, nameLen, encodingID);
+ tmpName = makeString(name, nameLen, encodingID);
+
+ if (fullName == null || langID == ENGLISH_LOCALE_ID) {
+ fullName = tmpName;
+ }
+ if (langID == nameLocaleID) {
+ localeFullName = tmpName;
+ }
}
break;
-
}
}
+ if (localeFamilyName == null) {
+ localeFamilyName = familyName;
+ }
+ if (localeFullName == null) {
+ localeFullName = fullName;
+ }
}
}
@@ -1220,6 +1254,8 @@ public class TrueTypeFont extends FileFont {
public String getFontName(Locale locale) {
if (locale == null) {
return fullName;
+ } else if (locale.equals(nameLocale) && localeFullName != null) {
+ return localeFullName;
} else {
short localeID = FontManager.getLCIDFromLocale(locale);
String name = lookupName(localeID, FULL_NAME_ID);
@@ -1234,11 +1270,13 @@ public class TrueTypeFont extends FileFont {
public String getFamilyName(Locale locale) {
if (locale == null) {
return familyName;
+ } else if (locale.equals(nameLocale) && localeFamilyName != null) {
+ return localeFamilyName;
} else {
short localeID = FontManager.getLCIDFromLocale(locale);
String name = lookupName(localeID, FAMILY_NAME_ID);
if (name == null) {
- return familyName;
+ return familyName;
} else {
return name;
}
diff --git a/src/share/classes/sun/java2d/pisces/PiscesCache.java b/src/share/classes/sun/java2d/pisces/PiscesCache.java
index ce62e0dab..05e20fdfc 100644
--- a/src/share/classes/sun/java2d/pisces/PiscesCache.java
+++ b/src/share/classes/sun/java2d/pisces/PiscesCache.java
@@ -96,7 +96,7 @@ public final class PiscesCache {
bboxX1 = x1+1;
} else {
if (bboxX0 > x0) bboxX0 = x0;
- if (bboxX1 < x1) bboxX1 = x1;
+ if (bboxX1 < x1 + 1) bboxX1 = x1 + 1;
while (bboxY1++ < y) {
reallocRowInfo(alphaRows+1);
minTouched[alphaRows] = 0;
diff --git a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
index 0a99c3fdb..7d39c61e0 100644
--- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
+++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c
@@ -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++) {
diff --git a/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java b/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java
new file mode 100644
index 000000000..4aa3a3064
--- /dev/null
+++ b/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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 6684104
+ * @summary Test verifies that ImageIO checks all permissions required for
+ * the file cache usage:
+ *
+ * no policy file: No security restrictions.
+ * Expected result: ImageIO creates file-cached stream.
+ *
+ * w.policy: the case when we have read and write permissions
+ * for java.io.temp directory but have only write permission
+ * for a temp file.
+ * Expected result: ImageIO create a memory-cached stream
+ * image output stream.
+ *
+ * rw.policy: the case when we have read and write permissions
+ * for java.io.temp directory but have only read and write
+ * permission for a temp cache file.
+ * Expected result: ImageIO creates a memory-cached stream
+ * because temporary cache file can not be deleted.
+ *
+ * rwd.policy: the case when we have read and write permissions
+ * for java.io.temp directory and have all required permissions
+ * (read, write, and delete) for a temporary cache file.
+ * Expected result: ImageIO creates file-cached stream.
+ *
+ * -Djava.security.debug=access can be used to verify file permissions.
+ *
+ * @run main CachePermissionsTest true
+ * @run main/othervm/policy=w.policy CachePermissionsTest false
+ * @run main/othervm/policy=rw.policy CachePermissionsTest false
+ * @run main/othervm/policy=rwd.policy CachePermissionsTest true
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import javax.imageio.stream.ImageOutputStream;
+
+import javax.imageio.ImageIO;
+
+
+public class CachePermissionsTest {
+ public static void main(String[] args) {
+ boolean isFileCacheExpected =
+ Boolean.valueOf(args[0]).booleanValue();
+ System.out.println("Is file cache expected: " + isFileCacheExpected);
+
+ ImageIO.setUseCache(true);
+
+ System.out.println("java.io.tmpdir is " + System.getProperty("java.io.tmpdir"));
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
+
+ boolean isFileCache = ios.isCachedFile();
+ System.out.println("Is file cache used: " + isFileCache);
+
+ if (isFileCache !=isFileCacheExpected) {
+ System.out.println("WARNING: file chace usage is not as expected!");
+ }
+
+ System.out.println("Verify data writing...");
+ for (int i = 0; i < 8192; i++) {
+ ios.writeInt(i);
+ }
+
+ System.out.println("Verify data reading...");
+ ios.seek(0L);
+
+ for (int i = 0; i < 8192; i++) {
+ int j = ios.readInt();
+ if (i != j) {
+ throw new RuntimeException("Wrong data in the stream " + j + " instead of " + i);
+ }
+ }
+
+ System.out.println("Verify stream closing...");
+ ios.close();
+ } catch (IOException e) {
+ /*
+ * Something went wrong?
+ */
+ throw new RuntimeException("Test FAILED.", e);
+ } catch (SecurityException e) {
+ /*
+ * We do not expect security execptions here:
+ * we there are any security restrition, ImageIO
+ * should swith to memory-cached streams, instead
+ * of using file cache.
+ */
+ throw new RuntimeException("Test FAILED.", e);
+ }
+ }
+}
diff --git a/test/javax/imageio/CachePremissionsTest/rw.policy b/test/javax/imageio/CachePremissionsTest/rw.policy
new file mode 100644
index 000000000..003c85b57
--- /dev/null
+++ b/test/javax/imageio/CachePremissionsTest/rw.policy
@@ -0,0 +1,5 @@
+grant {
+ permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "java.io.tmpdir", "read";
+ permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write";
+};
diff --git a/test/javax/imageio/CachePremissionsTest/rwd.policy b/test/javax/imageio/CachePremissionsTest/rwd.policy
new file mode 100644
index 000000000..f4d1f90a3
--- /dev/null
+++ b/test/javax/imageio/CachePremissionsTest/rwd.policy
@@ -0,0 +1,5 @@
+grant {
+ permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "java.io.tmpdir", "read";
+ permission java.io.FilePermission "${java.io.tmpdir}${/}*", "read, write, delete";
+};
diff --git a/test/javax/imageio/CachePremissionsTest/w.policy b/test/javax/imageio/CachePremissionsTest/w.policy
new file mode 100644
index 000000000..ff354e961
--- /dev/null
+++ b/test/javax/imageio/CachePremissionsTest/w.policy
@@ -0,0 +1,5 @@
+grant {
+ permission java.util.PropertyPermission "test.classes", "read";
+ permission java.util.PropertyPermission "java.io.tmpdir", "read";
+ permission java.io.FilePermission "${java.io.tmpdir}${/}*", "write";
+};
diff --git a/test/javax/imageio/plugins/bmp/TopDownTest.java b/test/javax/imageio/plugins/bmp/TopDownTest.java
new file mode 100644
index 000000000..0163dae59
--- /dev/null
+++ b/test/javax/imageio/plugins/bmp/TopDownTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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 6296893
+ * @summary Test verifies that the isTopDown flag does not cause
+ * a writing of bmp image in wrong scanline layout.
+ * @run main TopDownTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+import java.awt.image.IndexColorModel;
+import java.io.File;
+import java.io.IOException;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.plugins.bmp.BMPImageWriteParam;
+import javax.imageio.stream.ImageOutputStream;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+
+public class TopDownTest {
+
+ public static void main(String[] args) throws IOException {
+ BufferedImage src = createTestImage(24);
+
+ writeWithCompression(src, "BI_BITFIELDS");
+
+ writeWithCompression(src, "BI_RGB");
+
+ src = createTestImage(8);
+ writeWithCompression(src, "BI_RLE8");
+
+ src = createTestImage(4);
+ writeWithCompression(src, "BI_RLE4");
+
+ }
+
+ private static void writeWithCompression(BufferedImage src,
+ String compression) throws IOException
+ {
+ System.out.println("Compression: " + compression);
+ ImageWriter writer = ImageIO.getImageWritersByFormatName("BMP").next();
+ if (writer == null) {
+ throw new RuntimeException("Test failed: no bmp writer available");
+ }
+ File fout = File.createTempFile(compression + "_", ".bmp",
+ new File("."));
+
+ ImageOutputStream ios = ImageIO.createImageOutputStream(fout);
+ writer.setOutput(ios);
+
+ BMPImageWriteParam param = (BMPImageWriteParam)
+ writer.getDefaultWriteParam();
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionType(compression);
+ param.setTopDown(true);
+ writer.write(null, new IIOImage(src, null, null), param);
+ writer.dispose();
+ ios.flush();
+ ios.close();
+
+ BufferedImage dst = ImageIO.read(fout);
+
+ verify(dst);
+ }
+
+ private static void verify(BufferedImage dst) {
+ int top_rgb = dst.getRGB(50, 25);
+ System.out.printf("top_rgb: %x\n", top_rgb);
+ int bot_rgb = dst.getRGB(50, 75);
+ System.out.printf("bot_rgb: %x\n", bot_rgb);
+
+ // expect to see blue color on the top of image
+ if (top_rgb != 0xff0000ff) {
+ throw new RuntimeException("Invaid top color: " +
+ Integer.toHexString(bot_rgb));
+ }
+ if (bot_rgb != 0xffff0000) {
+ throw new RuntimeException("Invalid bottom color: " +
+ Integer.toHexString(bot_rgb));
+ }
+ }
+
+ private static BufferedImage createTestImage(int bpp) {
+
+ BufferedImage img = null;
+ switch (bpp) {
+ case 8:
+ img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED);
+ break;
+ case 4: {
+ byte[] r = new byte[16];
+ byte[] g = new byte[16];
+ byte[] b = new byte[16];
+
+ r[1] = (byte)0xff;
+ b[0] = (byte)0xff;
+
+ IndexColorModel icm = new IndexColorModel(4, 16, r, g, b);
+ img = new BufferedImage(100, 100, TYPE_BYTE_INDEXED, icm);
+ }
+ break;
+ case 24:
+ default:
+ img = new BufferedImage(100, 100, TYPE_INT_RGB);
+ }
+ Graphics g = img.createGraphics();
+ g.setColor(Color.blue);
+ g.fillRect(0, 0, 100, 50);
+ g.setColor(Color.red);
+ g.fillRect(0, 50, 100, 50);
+ g.dispose();
+ return img;
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java b/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
new file mode 100644
index 000000000..b57256777
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/ReadAsGrayTest.java
@@ -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;
+ }
+}
diff --git a/test/javax/imageio/plugins/wbmp/CanDecodeTest.java b/test/javax/imageio/plugins/wbmp/CanDecodeTest.java
new file mode 100644
index 000000000..adaecdce4
--- /dev/null
+++ b/test/javax/imageio/plugins/wbmp/CanDecodeTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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 5101862
+ * @summary Test verifies that SPI of WBMP image reader
+ * does not claims to be able to decode QT movies,
+ * tga images, or ico files.
+ * @run main CanDecodeTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Vector;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.ImageInputStream;
+
+public class CanDecodeTest {
+
+ public static void main(String[] args) throws IOException {
+ ImageReader r =
+ ImageIO.getImageReadersByFormatName("WBMP").next();
+ ImageReaderSpi spi = r.getOriginatingProvider();
+
+ Vector<TestCase> tests = getTestCases();
+ for (TestCase t : tests) {
+ t.doTest(spi);
+ }
+ System.out.println("Test passed.");
+ }
+
+ private static Vector<TestCase> getTestCases() {
+ Vector<TestCase> v = new Vector<TestCase>(4);
+ v.add(new TestCase("wbmp", new byte[]{(byte) 0x00, (byte) 0x00,
+ (byte) 0x60, (byte) 0x14}, 244, true));
+ v.add(new TestCase("mov", new byte[]{(byte) 0x00, (byte) 0x00,
+ (byte) 0x07, (byte) 0xb5, (byte) 0x6d}, 82397, false));
+ v.add(new TestCase("tga", new byte[]{(byte) 0x00, (byte) 0x00,
+ (byte) 0x0a, (byte) 0x00}, 39693, false));
+ v.add(new TestCase("ico", new byte[]{(byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0x00}, 1078, false));
+ return v;
+ }
+
+ private static class TestCase {
+
+ private String title;
+ private byte[] header;
+ private int dataLength;
+ private boolean canDecode;
+
+ public TestCase(String title, byte[] header,
+ int dataLength, boolean canDecode) {
+ this.title = title;
+ this.dataLength = dataLength;
+ this.header = header.clone();
+ this.canDecode = canDecode;
+
+ }
+
+ public void doTest(ImageReaderSpi spi) throws IOException {
+ System.out.println("Test for " + title +
+ (canDecode ? " (can decode)" : " (can't decode)"));
+ System.out.print("As a stream...");
+ ImageInputStream iis =
+ ImageIO.createImageInputStream(getDataStream());
+
+ if (spi.canDecodeInput(iis) != canDecode) {
+ throw new RuntimeException("Test failed: wrong decideion " +
+ "for stream data");
+ }
+ System.out.println("OK");
+
+ System.out.print("As a file...");
+ iis = ImageIO.createImageInputStream(getDataFile());
+ if (spi.canDecodeInput(iis) != canDecode) {
+ throw new RuntimeException("Test failed: wrong decideion " +
+ "for file data");
+ }
+ System.out.println("OK");
+ }
+
+ private byte[] getData() {
+ byte[] data = new byte[dataLength];
+ Arrays.fill(data, (byte) 0);
+ System.arraycopy(header, 0, data, 0, header.length);
+
+ return data;
+ }
+ public InputStream getDataStream() {
+ return new ByteArrayInputStream(getData());
+ }
+
+ public File getDataFile() throws IOException {
+ File f = File.createTempFile("wbmp_", "." + title, new File("."));
+ FileOutputStream fos = new FileOutputStream(f);
+ fos.write(getData());
+ fos.flush();
+ fos.close();
+
+ return f;
+ }
+ }
+}
diff --git a/test/sun/pisces/ScaleTest.java b/test/sun/pisces/ScaleTest.java
new file mode 100644
index 000000000..bef16e28b
--- /dev/null
+++ b/test/sun/pisces/ScaleTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+import java.awt.*;
+import java.awt.geom.Ellipse2D;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import javax.imageio.ImageIO;
+
+
+public class ScaleTest {
+ public static void main(String[] args) throws Exception {
+ BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = image.createGraphics();
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setPaint(Color.WHITE);
+ g.fill(new Rectangle(image.getWidth(), image.getHeight()));
+ g.scale(.9, .9);
+ g.setPaint(Color.BLACK);
+ g.setStroke(new BasicStroke(0.5f));
+ g.draw(new Ellipse2D.Double(25, 25, 150, 150));
+
+ // To visually check it
+ //ImageIO.write(image, "PNG", new File(args[0]));
+
+ boolean nonWhitePixelFound = false;
+ for (int x = 100; x < 200; ++x) {
+ if (image.getRGB(x, 90) != Color.WHITE.getRGB()) {
+ nonWhitePixelFound = true;
+ break;
+ }
+ }
+ if (!nonWhitePixelFound) {
+ throw new RuntimeException("A circle is rendered like a 'C' shape.");
+ }
+ }
+}