feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
public class BMPCompressionTypes {
private static final String[] compressionTypeNames =
{"BI_RGB", "BI_RLE8", "BI_RLE4", "BI_BITFIELDS", "BI_JPEG", "BI_PNG"};
static int getType(String typeString) {
for (int i = 0; i < compressionTypeNames.length; i++)
if (compressionTypeNames[i].equals(typeString))
return i;
return 0;
}
static String getName(int type) {
return compressionTypeNames[type];
}
public static String[] getCompressionTypes() {
return compressionTypeNames.clone();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
public interface BMPConstants {
// bmp versions
static final String VERSION_2 = "BMP v. 2.x";
static final String VERSION_3 = "BMP v. 3.x";
static final String VERSION_3_NT = "BMP v. 3.x NT";
static final String VERSION_4 = "BMP v. 4.x";
static final String VERSION_5 = "BMP v. 5.x";
// Color space types
static final int LCS_CALIBRATED_RGB = 0;
static final int LCS_sRGB = 1;
static final int LCS_WINDOWS_COLOR_SPACE = 2;
static final int PROFILE_LINKED = 3;
static final int PROFILE_EMBEDDED = 4;
// Compression Types
static final int BI_RGB = 0;
static final int BI_RLE8 = 1;
static final int BI_RLE4 = 2;
static final int BI_BITFIELDS = 3;
static final int BI_JPEG = 4;
static final int BI_PNG = 5;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
import java.util.Locale;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ServiceRegistry;
import java.io.IOException;
import javax.imageio.ImageReader;
import javax.imageio.IIOException;
public class BMPImageReaderSpi extends ImageReaderSpi {
private static String [] writerSpiNames =
{"com.sun.imageio.plugins.bmp.BMPImageWriterSpi"};
private static String[] formatNames = {"bmp", "BMP"};
private static String[] entensions = {"bmp"};
private static String[] mimeType = {"image/bmp"};
private boolean registered = false;
public BMPImageReaderSpi() {
super("Oracle Corporation",
"1.0",
formatNames,
entensions,
mimeType,
"com.sun.imageio.plugins.bmp.BMPImageReader",
new Class[] { ImageInputStream.class },
writerSpiNames,
false,
null, null, null, null,
true,
BMPMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.bmp.BMPMetadataFormat",
null, null);
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
registered = true;
}
public String getDescription(Locale locale) {
return "Standard BMP Image Reader";
}
public boolean canDecodeInput(Object source) throws IOException {
if (!(source instanceof ImageInputStream)) {
return false;
}
ImageInputStream stream = (ImageInputStream)source;
byte[] b = new byte[2];
stream.mark();
stream.readFully(b);
stream.reset();
return (b[0] == 0x42) && (b[1] == 0x4d);
}
public ImageReader createReaderInstance(Object extension)
throws IIOException {
return new BMPImageReader(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.ImageWriter;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.IIOException;
import java.util.Locale;
import javax.imageio.plugins.bmp.BMPImageWriteParam;
public class BMPImageWriterSpi extends ImageWriterSpi {
private static String [] readerSpiNames =
{"com.sun.imageio.plugins.bmp.BMPImageReaderSpi"};
private static String[] formatNames = {"bmp", "BMP"};
private static String[] entensions = {"bmp"};
private static String[] mimeType = {"image/bmp"};
private boolean registered = false;
public BMPImageWriterSpi() {
super("Oracle Corporation",
"1.0",
formatNames,
entensions,
mimeType,
"com.sun.imageio.plugins.bmp.BMPImageWriter",
new Class[] { ImageOutputStream.class },
readerSpiNames,
false,
null, null, null, null,
true,
BMPMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.bmp.BMPMetadataFormat",
null, null);
}
public String getDescription(Locale locale) {
return "Standard BMP Image Writer";
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
registered = true;
}
public boolean canEncodeImage(ImageTypeSpecifier type) {
int dataType= type.getSampleModel().getDataType();
if (dataType < DataBuffer.TYPE_BYTE || dataType > DataBuffer.TYPE_INT)
return false;
SampleModel sm = type.getSampleModel();
int numBands = sm.getNumBands();
if (!(numBands == 1 || numBands == 3))
return false;
if (numBands == 1 && dataType != DataBuffer.TYPE_BYTE)
return false;
if (dataType > DataBuffer.TYPE_BYTE &&
!(sm instanceof SinglePixelPackedSampleModel))
return false;
return true;
}
public ImageWriter createWriterInstance(Object extension)
throws IIOException {
return new BMPImageWriter(this);
}
}

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
import com.sun.imageio.plugins.common.I18N;
import com.sun.imageio.plugins.common.ImageUtil;
public class BMPMetadata extends IIOMetadata implements BMPConstants {
public static final String nativeMetadataFormatName =
"javax_imageio_bmp_1.0";
// Fields for Image Descriptor
public String bmpVersion;
public int width ;
public int height;
public short bitsPerPixel;
public int compression;
public int imageSize;
// Fields for PixelsPerMeter
public int xPixelsPerMeter;
public int yPixelsPerMeter;
public int colorsUsed;
public int colorsImportant;
// Fields for BI_BITFIELDS compression(Mask)
public int redMask;
public int greenMask;
public int blueMask;
public int alphaMask;
public int colorSpace;
// Fields for CIE XYZ for the LCS_CALIBRATED_RGB color space
public double redX;
public double redY;
public double redZ;
public double greenX;
public double greenY;
public double greenZ;
public double blueX;
public double blueY;
public double blueZ;
// Fields for Gamma values for the LCS_CALIBRATED_RGB color space
public int gammaRed;
public int gammaGreen;
public int gammaBlue;
public int intent;
// Fields for the Palette and Entries
public byte[] palette = null;
public int paletteSize;
public int red;
public int green;
public int blue;
// Fields from CommentExtension
// List of byte[]
public List comments = null; // new ArrayList();
public BMPMetadata() {
super(true,
nativeMetadataFormatName,
"com.sun.imageio.plugins.bmp.BMPMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException(I18N.getString("BMPMetadata0"));
}
}
private String toISO8859(byte[] data) {
try {
return new String(data, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
return "";
}
}
private Node getNativeTree() {
IIOMetadataNode root =
new IIOMetadataNode(nativeMetadataFormatName);
addChildNode(root, "BMPVersion", bmpVersion);
addChildNode(root, "Width", new Integer(width));
addChildNode(root, "Height", new Integer(height));
addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel));
addChildNode(root, "Compression", new Integer(compression));
addChildNode(root, "ImageSize", new Integer(imageSize));
IIOMetadataNode node = addChildNode(root, "PixelsPerMeter", null);
addChildNode(node, "X", new Integer(xPixelsPerMeter));
addChildNode(node, "Y", new Integer(yPixelsPerMeter));
addChildNode(root, "ColorsUsed", new Integer(colorsUsed));
addChildNode(root, "ColorsImportant", new Integer(colorsImportant));
int version = 0;
for (int i = 0; i < bmpVersion.length(); i++)
if (Character.isDigit(bmpVersion.charAt(i)))
version = bmpVersion.charAt(i) -'0';
if (version >= 4) {
node = addChildNode(root, "Mask", null);
addChildNode(node, "Red", new Integer(redMask));
addChildNode(node, "Green", new Integer(greenMask));
addChildNode(node, "Blue", new Integer(blueMask));
addChildNode(node, "Alpha", new Integer(alphaMask));
addChildNode(root, "ColorSpaceType", new Integer(colorSpace));
node = addChildNode(root, "CIEXYZEndPoints", null);
addXYZPoints(node, "Red", redX, redY, redZ);
addXYZPoints(node, "Green", greenX, greenY, greenZ);
addXYZPoints(node, "Blue", blueX, blueY, blueZ);
node = addChildNode(root, "Intent", new Integer(intent));
}
// Palette
if ((palette != null) && (paletteSize > 0)) {
node = addChildNode(root, "Palette", null);
int numComps = palette.length / paletteSize;
for (int i = 0, j = 0; i < paletteSize; i++) {
IIOMetadataNode entry =
addChildNode(node, "PaletteEntry", null);
red = palette[j++] & 0xff;
green = palette[j++] & 0xff;
blue = palette[j++] & 0xff;
addChildNode(entry, "Red", new Byte((byte)red));
addChildNode(entry, "Green", new Byte((byte)green));
addChildNode(entry, "Blue", new Byte((byte)blue));
if (numComps == 4)
addChildNode(entry, "Alpha",
new Byte((byte)(palette[j++] & 0xff)));
}
}
return root;
}
// Standard tree node methods
protected IIOMetadataNode getStandardChromaNode() {
if ((palette != null) && (paletteSize > 0)) {
IIOMetadataNode node = new IIOMetadataNode("Chroma");
IIOMetadataNode subNode = new IIOMetadataNode("Palette");
int numComps = palette.length / paletteSize;
subNode.setAttribute("value", "" + numComps);
for (int i = 0, j = 0; i < paletteSize; i++) {
IIOMetadataNode subNode1 = new IIOMetadataNode("PaletteEntry");
subNode1.setAttribute("index", ""+i);
subNode1.setAttribute("red", "" + palette[j++]);
subNode1.setAttribute("green", "" + palette[j++]);
subNode1.setAttribute("blue", "" + palette[j++]);
if (numComps == 4 && palette[j] != 0)
subNode1.setAttribute("alpha", "" + palette[j++]);
subNode.appendChild(subNode1);
}
node.appendChild(subNode);
return node;
}
return null;
}
protected IIOMetadataNode getStandardCompressionNode() {
IIOMetadataNode node = new IIOMetadataNode("Compression");
// CompressionTypeName
IIOMetadataNode subNode = new IIOMetadataNode("CompressionTypeName");
subNode.setAttribute("value", BMPCompressionTypes.getName(compression));
node.appendChild(subNode);
return node;
}
protected IIOMetadataNode getStandardDataNode() {
IIOMetadataNode node = new IIOMetadataNode("Data");
String bits = "";
if (bitsPerPixel == 24)
bits = "8 8 8 ";
else if (bitsPerPixel == 16 || bitsPerPixel == 32) {
bits = "" + countBits(redMask) + " " + countBits(greenMask) +
countBits(blueMask) + "" + countBits(alphaMask);
}
IIOMetadataNode subNode = new IIOMetadataNode("BitsPerSample");
subNode.setAttribute("value", bits);
node.appendChild(subNode);
return node;
}
protected IIOMetadataNode getStandardDimensionNode() {
if (yPixelsPerMeter > 0.0F && xPixelsPerMeter > 0.0F) {
IIOMetadataNode node = new IIOMetadataNode("Dimension");
float ratio = yPixelsPerMeter / xPixelsPerMeter;
IIOMetadataNode subNode = new IIOMetadataNode("PixelAspectRatio");
subNode.setAttribute("value", "" + ratio);
node.appendChild(subNode);
subNode = new IIOMetadataNode("HorizontalPhysicalPixelSpacing");
subNode.setAttribute("value", "" + (1 / xPixelsPerMeter * 1000));
node.appendChild(subNode);
subNode = new IIOMetadataNode("VerticalPhysicalPixelSpacing");
subNode.setAttribute("value", "" + (1 / yPixelsPerMeter * 1000));
node.appendChild(subNode);
return node;
}
return null;
}
public void setFromTree(String formatName, Node root) {
throw new IllegalStateException(I18N.getString("BMPMetadata1"));
}
public void mergeTree(String formatName, Node root) {
throw new IllegalStateException(I18N.getString("BMPMetadata1"));
}
public void reset() {
throw new IllegalStateException(I18N.getString("BMPMetadata1"));
}
private String countBits(int num) {
int count = 0;
while(num > 0) {
if ((num & 1) == 1)
count++;
num >>>= 1;
}
return count == 0 ? "" : "" + count;
}
private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) {
IIOMetadataNode node = addChildNode(root, name, null);
addChildNode(node, "X", new Double(x));
addChildNode(node, "Y", new Double(y));
addChildNode(node, "Z", new Double(z));
}
private IIOMetadataNode addChildNode(IIOMetadataNode root,
String name,
Object object) {
IIOMetadataNode child = new IIOMetadataNode(name);
if (object != null) {
child.setUserObject(object);
child.setNodeValue(ImageUtil.convertObjectToString(object));
}
root.appendChild(child);
return child;
}
}

View File

@@ -0,0 +1,208 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
import java.util.Arrays;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class BMPMetadataFormat extends IIOMetadataFormatImpl {
private static IIOMetadataFormat instance = null;
private BMPMetadataFormat() {
super(BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_SOME);
// root -> ImageDescriptor
addElement("ImageDescriptor",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ImageDescriptor", "bmpVersion",
DATATYPE_STRING, true, null);
addAttribute("ImageDescriptor", "width",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("ImageDescriptor", "height",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("ImageDescriptor", "bitsPerPixel",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("ImageDescriptor", "compression",
DATATYPE_INTEGER, false, null);
addAttribute("ImageDescriptor", "imageSize",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addElement("PixelsPerMeter",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("PixelsPerMeter", "X",
DATATYPE_INTEGER, false, null,
"1", "65535", true, true);
addAttribute("PixelsPerMeter", "Y",
DATATYPE_INTEGER, false, null,
"1", "65535", true, true);
addElement("ColorsUsed",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ColorsUsed", "value",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addElement("ColorsImportant",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ColorsImportant", "value",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addElement("BI_BITFIELDS_Mask",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("BI_BITFIELDS_Mask", "red",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addAttribute("BI_BITFIELDS_Mask", "green",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addAttribute("BI_BITFIELDS_Mask", "blue",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addElement("ColorSpace",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ColorSpace", "value",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addElement("LCS_CALIBRATED_RGB",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
/// Should the max value be 1.7976931348623157e+308 ?
addAttribute("LCS_CALIBRATED_RGB", "redX",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "redY",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "redZ",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "greenX",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "greenY",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "greenZ",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "blueX",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "blueY",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB", "blueZ",
DATATYPE_DOUBLE, false, null,
"0", "65535", true, true);
addElement("LCS_CALIBRATED_RGB_GAMMA",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("LCS_CALIBRATED_RGB_GAMMA","red",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB_GAMMA","green",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addAttribute("LCS_CALIBRATED_RGB_GAMMA","blue",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
addElement("Intent",
BMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("Intent", "value",
DATATYPE_INTEGER, false, null,
"0", "65535", true, true);
// root -> Palette
addElement("Palette",
BMPMetadata.nativeMetadataFormatName,
2, 256);
addAttribute("Palette", "sizeOfPalette",
DATATYPE_INTEGER, true, null);
addBooleanAttribute("Palette", "sortFlag",
false, false);
// root -> Palette -> PaletteEntry
addElement("PaletteEntry", "Palette",
CHILD_POLICY_EMPTY);
addAttribute("PaletteEntry", "index",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("PaletteEntry", "red",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("PaletteEntry", "green",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("PaletteEntry", "blue",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
// root -> CommentExtensions
addElement("CommentExtensions",
BMPMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> CommentExtensions -> CommentExtension
addElement("CommentExtension", "CommentExtensions",
CHILD_POLICY_EMPTY);
addAttribute("CommentExtension", "value",
DATATYPE_STRING, true, null);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
public static synchronized IIOMetadataFormat getInstance() {
if (instance == null) {
instance = new BMPMetadataFormat();
}
return instance;
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.bmp;
import java.util.ListResourceBundle;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class BMPMetadataFormatResources extends ListResourceBundle {
public BMPMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description
{ "BMPVersion", "BMP version string" },
{ "Width", "The width of the image" },
{ "Height","The height of the image" },
{ "BitsPerPixel", "" },
{ "PixelsPerMeter", "Resolution in pixels per unit distance" },
{ "X", "Pixels Per Meter along X" },
{ "Y", "Pixels Per Meter along Y" },
{ "ColorsUsed",
"Number of color indexes in the color table actually used" },
{ "ColorsImportant",
"Number of color indexes considered important for display" },
{ "Mask",
"Color masks; present for BI_BITFIELDS compression only"},
{ "Intent", "Rendering intent" },
{ "Palette", "The color palette" },
{ "Red", "Red Mask/Color Palette" },
{ "Green", "Green Mask/Color Palette/Gamma" },
{ "Blue", "Blue Mask/Color Palette/Gamma" },
{ "Alpha", "Alpha Mask/Color Palette/Gamma" },
{ "ColorSpaceType", "Color Space Type" },
{ "X", "The X coordinate of a point in XYZ color space" },
{ "Y", "The Y coordinate of a point in XYZ color space" },
{ "Z", "The Z coordinate of a point in XYZ color space" },
};
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import javax.imageio.stream.ImageOutputStream;
/*
* Came from GIFEncoder initially.
* Modified - to allow for output compressed data without the block counts
* which breakup the compressed data stream for GIF.
*/
public class BitFile {
ImageOutputStream output;
byte buffer[];
int index;
int bitsLeft; // bits left at current index that are avail.
/** note this also indicates gif format BITFile. **/
boolean blocks = false;
/*
* @param output destination for output data
* @param blocks GIF LZW requires block counts for output data
*/
public BitFile(ImageOutputStream output, boolean blocks) {
this.output = output;
this.blocks = blocks;
buffer = new byte[256];
index = 0;
bitsLeft = 8;
}
public void flush() throws IOException {
int numBytes = index + (bitsLeft == 8 ? 0 : 1);
if (numBytes > 0) {
if (blocks) {
output.write(numBytes);
}
output.write(buffer, 0, numBytes);
buffer[0] = 0;
index = 0;
bitsLeft = 8;
}
}
public void writeBits(int bits, int numbits) throws IOException {
int bitsWritten = 0;
int numBytes = 255; // gif block count
do {
// This handles the GIF block count stuff
if ((index == 254 && bitsLeft == 0) || index > 254) {
if (blocks) {
output.write(numBytes);
}
output.write(buffer, 0, numBytes);
buffer[0] = 0;
index = 0;
bitsLeft = 8;
}
if (numbits <= bitsLeft) { // bits contents fit in current index byte
if (blocks) { // GIF
buffer[index] |= (bits & ((1 << numbits) - 1)) << (8 - bitsLeft);
bitsWritten += numbits;
bitsLeft -= numbits;
numbits = 0;
} else {
buffer[index] |= (bits & ((1 << numbits) - 1)) << (bitsLeft - numbits);
bitsWritten += numbits;
bitsLeft -= numbits;
numbits = 0;
}
} else { // bits overflow from current byte to next.
if (blocks) { // GIF
// if bits > space left in current byte then the lowest order bits
// of code are taken and put in current byte and rest put in next.
buffer[index] |= (bits & ((1 << bitsLeft) - 1)) << (8 - bitsLeft);
bitsWritten += bitsLeft;
bits >>= bitsLeft;
numbits -= bitsLeft;
buffer[++index] = 0;
bitsLeft = 8;
} else {
// if bits > space left in current byte then the highest order bits
// of code are taken and put in current byte and rest put in next.
// at highest order bit location !!
int topbits = (bits >>> (numbits - bitsLeft)) & ((1 << bitsLeft) - 1);
buffer[index] |= topbits;
numbits -= bitsLeft; // ok this many bits gone off the top
bitsWritten += bitsLeft;
buffer[++index] = 0; // next index
bitsLeft = 8;
}
}
} while (numbits != 0);
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.color.ColorSpace;
/**
* A dummy <code>ColorSpace</code> to enable <code>ColorModel</code>
* for image data which do not have an innate color representation.
*/
public class BogusColorSpace extends ColorSpace {
/**
* Return the type given the number of components.
*
* @param numComponents The number of components in the
* <code>ColorSpace</code>.
* @exception IllegalArgumentException if <code>numComponents</code>
* is less than 1.
*/
private static int getType(int numComponents) {
if(numComponents < 1) {
throw new IllegalArgumentException("numComponents < 1!");
}
int type;
switch(numComponents) {
case 1:
type = ColorSpace.TYPE_GRAY;
break;
default:
// Based on the constant definitions TYPE_2CLR=12 through
// TYPE_FCLR=25. This will return unknown types for
// numComponents > 15.
type = numComponents + 10;
}
return type;
}
/**
* Constructs a bogus <code>ColorSpace</code>.
*
* @param numComponents The number of components in the
* <code>ColorSpace</code>.
* @exception IllegalArgumentException if <code>numComponents</code>
* is less than 1.
*/
public BogusColorSpace(int numComponents) {
super(getType(numComponents), numComponents);
}
//
// The following methods simply copy the input array to the
// output array while otherwise attempting to adhere to the
// specified behavior of the methods vis-a-vis exceptions.
//
public float[] toRGB(float[] colorvalue) {
if(colorvalue.length < getNumComponents()) {
throw new ArrayIndexOutOfBoundsException
("colorvalue.length < getNumComponents()");
}
float[] rgbvalue = new float[3];
System.arraycopy(colorvalue, 0, rgbvalue, 0,
Math.min(3, getNumComponents()));
return colorvalue;
}
public float[] fromRGB(float[] rgbvalue) {
if(rgbvalue.length < 3) {
throw new ArrayIndexOutOfBoundsException
("rgbvalue.length < 3");
}
float[] colorvalue = new float[getNumComponents()];
System.arraycopy(rgbvalue, 0, colorvalue, 0,
Math.min(3, colorvalue.length));
return rgbvalue;
}
public float[] toCIEXYZ(float[] colorvalue) {
if(colorvalue.length < getNumComponents()) {
throw new ArrayIndexOutOfBoundsException
("colorvalue.length < getNumComponents()");
}
float[] xyzvalue = new float[3];
System.arraycopy(colorvalue, 0, xyzvalue, 0,
Math.min(3, getNumComponents()));
return colorvalue;
}
public float[] fromCIEXYZ(float[] xyzvalue) {
if(xyzvalue.length < 3) {
throw new ArrayIndexOutOfBoundsException
("xyzvalue.length < 3");
}
float[] colorvalue = new float[getNumComponents()];
System.arraycopy(xyzvalue, 0, colorvalue, 0,
Math.min(3, colorvalue.length));
return xyzvalue;
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
public final class I18N extends I18NImpl {
private final static String resource_name = "iio-plugin.properties";
public static String getString(String key) {
return getString("com.sun.imageio.plugins.common.I18N", resource_name, key);
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.InputStream;
import java.util.PropertyResourceBundle;
import java.net.URL;
/**
* Class to simplify use of internationalization message strings.
* Property files are constructed in terms of content as for JAI with
* one "key=value" pair per line. All such files however have the same
* name "properties". The resource extractor resolves the extraction of
* the file from the jar as the package name is included automatically.
*
* <p>Extenders need only provide a static method
* <code>getString(String)</code> which calls the static method in this
* class with the name of the invoking class and returns a
* <code>String</code>.
*/
public class I18NImpl {
/**
* Returns the message string with the specified key from the
* "properties" file in the package containing the class with
* the specified name.
*/
protected static final String getString(String className, String resource_name, String key) {
PropertyResourceBundle bundle = null;
try {
InputStream stream =
Class.forName(className).getResourceAsStream(resource_name);
bundle = new PropertyResourceBundle(stream);
} catch(Throwable e) {
throw new RuntimeException(e); // Chain the exception.
}
return (String)bundle.handleGetObject(key);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.stream.ImageInputStream;
public class InputStreamAdapter extends InputStream {
ImageInputStream stream;
public InputStreamAdapter(ImageInputStream stream) {
super();
this.stream = stream;
}
public int read() throws IOException {
return stream.read();
}
public int read(byte b[], int off, int len) throws IOException {
return stream.read(b, off, len);
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import java.io.PrintStream;
import javax.imageio.stream.ImageOutputStream;
/*
* Modified from original LZWCompressor to change interface to passing a
* buffer of data to be compressed.
*/
public class LZWCompressor {
/** base underlying code size of data being compressed 8 for TIFF, 1 to 8 for GIF **/
int codeSize;
/** reserved clear code based on code size **/
int clearCode;
/** reserved end of data code based on code size **/
int endOfInfo;
/** current number bits output for each code **/
int numBits;
/** limit at which current number of bits code size has to be increased **/
int limit;
/** the prefix code which represents the predecessor string to current input point **/
short prefix;
/** output destination for bit codes **/
BitFile bf;
/** general purpose LZW string table **/
LZWStringTable lzss;
/** modify the limits of the code values in LZW encoding due to TIFF bug / feature **/
boolean tiffFudge;
/**
* @param out destination for compressed data
* @param codeSize the initial code size for the LZW compressor
* @param TIFF flag indicating that TIFF lzw fudge needs to be applied
* @exception IOException if underlying output stream error
**/
public LZWCompressor(ImageOutputStream out, int codeSize, boolean TIFF)
throws IOException
{
bf = new BitFile(out, !TIFF); // set flag for GIF as NOT tiff
this.codeSize = codeSize;
tiffFudge = TIFF;
clearCode = 1 << codeSize;
endOfInfo = clearCode + 1;
numBits = codeSize + 1;
limit = (1 << numBits) - 1;
if (tiffFudge) {
--limit;
}
prefix = (short)0xFFFF;
lzss = new LZWStringTable();
lzss.clearTable(codeSize);
bf.writeBits(clearCode, numBits);
}
/**
* @param buf data to be compressed to output stream
* @exception IOException if underlying output stream error
**/
public void compress(byte[] buf, int offset, int length)
throws IOException
{
int idx;
byte c;
short index;
int maxOffset = offset + length;
for (idx = offset; idx < maxOffset; ++idx) {
c = buf[idx];
if ((index = lzss.findCharString(prefix, c)) != -1) {
prefix = index;
} else {
bf.writeBits(prefix, numBits);
if (lzss.addCharString(prefix, c) > limit) {
if (numBits == 12) {
bf.writeBits(clearCode, numBits);
lzss.clearTable(codeSize);
numBits = codeSize + 1;
} else {
++numBits;
}
limit = (1 << numBits) - 1;
if (tiffFudge) {
--limit;
}
}
prefix = (short)((short)c & 0xFF);
}
}
}
/*
* Indicate to compressor that no more data to go so write out
* any remaining buffered data.
*
* @exception IOException if underlying output stream error
*/
public void flush() throws IOException {
if (prefix != -1) {
bf.writeBits(prefix, numBits);
}
bf.writeBits(endOfInfo, numBits);
bf.flush();
}
public void dump(PrintStream out) {
lzss.dump(out);
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.PrintStream;
/**
* General purpose LZW String Table.
* Extracted from GIFEncoder by Adam Doppelt
* Comments added by Robin Luiten
* <code>expandCode</code> added by Robin Luiten
* The strLen table to give quick access to the lenght of an expanded
* code for use by the <code>expandCode</code> method added by Robin.
**/
public class LZWStringTable {
/** codesize + Reserved Codes */
private final static int RES_CODES = 2;
private final static short HASH_FREE = (short)0xFFFF;
private final static short NEXT_FIRST = (short)0xFFFF;
private final static int MAXBITS = 12;
private final static int MAXSTR = (1 << MAXBITS);
private final static short HASHSIZE = 9973;
private final static short HASHSTEP = 2039;
byte[] strChr; // after predecessor character
short[] strNxt; // predecessor string
short[] strHsh; // hash table to find predecessor + char pairs
short numStrings; // next code if adding new prestring + char
/*
* each entry corresponds to a code and contains the length of data
* that the code expands to when decoded.
*/
int[] strLen;
/*
* Constructor allocate memory for string store data
*/
public LZWStringTable() {
strChr = new byte[MAXSTR];
strNxt = new short[MAXSTR];
strLen = new int[MAXSTR];
strHsh = new short[HASHSIZE];
}
/*
* @param index value of -1 indicates no predecessor [used in initialisation]
* @param b the byte [character] to add to the string store which follows
* the predecessor string specified the index.
* @return 0xFFFF if no space in table left for addition of predecesor
* index and byte b. Else return the code allocated for combination index + b.
*/
public int addCharString(short index, byte b) {
int hshidx;
if (numStrings >= MAXSTR) { // if used up all codes
return 0xFFFF;
}
hshidx = hash(index, b);
while (strHsh[hshidx] != HASH_FREE) {
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}
strHsh[hshidx] = numStrings;
strChr[numStrings] = b;
if (index == HASH_FREE) {
strNxt[numStrings] = NEXT_FIRST;
strLen[numStrings] = 1;
} else {
strNxt[numStrings] = index;
strLen[numStrings] = strLen[index] + 1;
}
return numStrings++; // return the code and inc for next code
}
/*
* @param index index to prefix string
* @param b the character that follws the index prefix
* @return b if param index is HASH_FREE. Else return the code
* for this prefix and byte successor
*/
public short findCharString(short index, byte b) {
int hshidx, nxtidx;
if (index == HASH_FREE) {
return (short)(b & 0xFF); // Rob fixed used to sign extend
}
hshidx = hash(index, b);
while ((nxtidx = strHsh[hshidx]) != HASH_FREE) { // search
if (strNxt[nxtidx] == index && strChr[nxtidx] == b) {
return (short)nxtidx;
}
hshidx = (hshidx + HASHSTEP) % HASHSIZE;
}
return (short)0xFFFF;
}
/*
* @param codesize the size of code to be preallocated for the
* string store.
*/
public void clearTable(int codesize) {
numStrings = 0;
for (int q = 0; q < HASHSIZE; q++) {
strHsh[q] = HASH_FREE;
}
int w = (1 << codesize) + RES_CODES;
for (int q = 0; q < w; q++) {
addCharString((short)0xFFFF, (byte)q); // init with no prefix
}
}
static public int hash(short index, byte lastbyte) {
return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
}
/*
* If expanded data doesn't fit into array only what will fit is written
* to buf and the return value indicates how much of the expanded code has
* been written to the buf. The next call to expandCode() should be with
* the same code and have the skip parameter set the negated value of the
* previous return. Succesive negative return values should be negated and
* added together for next skip parameter value with same code.
*
* @param buf buffer to place expanded data into
* @param offset offset to place expanded data
* @param code the code to expand to the byte array it represents.
* PRECONDITION This code must already be in the LZSS
* @param skipHead is the number of bytes at the start of the expanded code to
* be skipped before data is written to buf. It is possible that skipHead is
* equal to codeLen.
* @return the length of data expanded into buf. If the expanded code is longer
* than space left in buf then the value returned is a negative number which when
* negated is equal to the number of bytes that were used of the code being expanded.
* This negative value also indicates the buffer is full.
*/
public int expandCode(byte[] buf, int offset, short code, int skipHead) {
if (offset == -2) {
if (skipHead == 1) {
skipHead = 0;
}
}
if (code == (short)0xFFFF || // just in case
skipHead == strLen[code]) // DONE no more unpacked
{
return 0;
}
int expandLen; // how much data we are actually expanding
int codeLen = strLen[code] - skipHead; // length of expanded code left
int bufSpace = buf.length - offset; // how much space left
if (bufSpace > codeLen) {
expandLen = codeLen; // only got this many to unpack
} else {
expandLen = bufSpace;
}
int skipTail = codeLen - expandLen; // only > 0 if codeLen > bufSpace [left overs]
int idx = offset + expandLen; // initialise to exclusive end address of buffer area
// NOTE: data unpacks in reverse direction and we are placing the
// unpacked data directly into the array in the correct location.
while ((idx > offset) && (code != (short)0xFFFF)) {
if (--skipTail < 0) { // skip required of expanded data
buf[--idx] = strChr[code];
}
code = strNxt[code]; // to predecessor code
}
if (codeLen > expandLen) {
return -expandLen; // indicate what part of codeLen used
} else {
return expandLen; // indicate length of dat unpacked
}
}
public void dump(PrintStream out) {
int i;
for (i = 258; i < numStrings; ++i) {
out.println(" strNxt[" + i + "] = " + strNxt[i]
+ " strChr " + Integer.toHexString(strChr[i] & 0xFF)
+ " strLen " + Integer.toHexString(strLen[i]));
}
}
}

View File

@@ -0,0 +1,486 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.Color;
import javax.imageio.ImageTypeSpecifier;
/**
* This class implements the octree quantization method
* as it is described in the "Graphics Gems"
* (ISBN 0-12-286166-3, Chapter 4, pages 297-293)
*/
public class PaletteBuilder {
/**
* maximum of tree depth
*/
protected static final int MAXLEVEL = 8;
protected RenderedImage src;
protected ColorModel srcColorModel;
protected Raster srcRaster;
protected int requiredSize;
protected ColorNode root;
protected int numNodes;
protected int maxNodes;
protected int currLevel;
protected int currSize;
protected ColorNode[] reduceList;
protected ColorNode[] palette;
protected int transparency;
protected ColorNode transColor;
/**
* Creates an image representing given image
* <code>src</code> using <code>IndexColorModel</code>.
*
* Lossless conversion is not always possible (e.g. if number
* of colors in the given image exceeds maximum palette size).
* Result image then is an approximation constructed by octree
* quantization method.
*
* @exception IllegalArgumentException if <code>src</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>src</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexColorModel
*
* @see canCreatePalette
*
*/
public static RenderedImage createIndexedImage(RenderedImage src) {
PaletteBuilder pb = new PaletteBuilder(src);
pb.buildPalette();
return pb.getIndexedImage();
}
/**
* Creates an palette representing colors from given image
* <code>img</code>. If number of colors in the given image exceeds
* maximum palette size closest colors would be merged.
*
* @exception IllegalArgumentException if <code>img</code> is
* <code>null</code>.
*
* @exception UnsupportedOperationException if implemented method
* is unable to create approximation of <code>img</code>
* and <code>canCreatePalette</code> returns <code>false</code>.
*
* @see createIndexedImage
*
* @see canCreatePalette
*
*/
public static IndexColorModel createIndexColorModel(RenderedImage img) {
PaletteBuilder pb = new PaletteBuilder(img);
pb.buildPalette();
return pb.getIndexColorModel();
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given image type.
*
* @param type an instance of <code>ImageTypeSpecifier</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>type</code>
* is <code>null</code>.
*/
public static boolean canCreatePalette(ImageTypeSpecifier type) {
if (type == null) {
throw new IllegalArgumentException("type == null");
}
return true;
}
/**
* Returns <code>true</code> if PaletteBuilder is able to create
* palette for given rendered image.
*
* @param image an instance of <code>RenderedImage</code> to be
* indexed.
*
* @return <code>true</code> if the <code>PaletteBuilder</code>
* is likely to be able to create palette for this image type.
*
* @exception IllegalArgumentException if <code>image</code>
* is <code>null</code>.
*/
public static boolean canCreatePalette(RenderedImage image) {
if (image == null) {
throw new IllegalArgumentException("image == null");
}
ImageTypeSpecifier type = new ImageTypeSpecifier(image);
return canCreatePalette(type);
}
protected RenderedImage getIndexedImage() {
IndexColorModel icm = getIndexColorModel();
BufferedImage dst =
new BufferedImage(src.getWidth(), src.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED, icm);
WritableRaster wr = dst.getRaster();
for (int y =0; y < dst.getHeight(); y++) {
for (int x = 0; x < dst.getWidth(); x++) {
Color aColor = getSrcColor(x,y);
wr.setSample(x, y, 0, findColorIndex(root, aColor));
}
}
return dst;
}
protected PaletteBuilder(RenderedImage src) {
this(src, 256);
}
protected PaletteBuilder(RenderedImage src, int size) {
this.src = src;
this.srcColorModel = src.getColorModel();
this.srcRaster = src.getData();
this.transparency =
srcColorModel.getTransparency();
this.requiredSize = size;
}
private Color getSrcColor(int x, int y) {
int argb = srcColorModel.getRGB(srcRaster.getDataElements(x, y, null));
return new Color(argb, transparency != Transparency.OPAQUE);
}
protected int findColorIndex(ColorNode aNode, Color aColor) {
if (transparency != Transparency.OPAQUE &&
aColor.getAlpha() != 0xff)
{
return 0; // default transparnt pixel
}
if (aNode.isLeaf) {
return aNode.paletteIndex;
} else {
int childIndex = getBranchIndex(aColor, aNode.level);
return findColorIndex(aNode.children[childIndex], aColor);
}
}
protected void buildPalette() {
reduceList = new ColorNode[MAXLEVEL + 1];
for (int i = 0; i < reduceList.length; i++) {
reduceList[i] = null;
}
numNodes = 0;
maxNodes = 0;
root = null;
currSize = 0;
currLevel = MAXLEVEL;
/*
from the book
*/
int w = src.getWidth();
int h = src.getHeight();
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color aColor = getSrcColor(w - x - 1, h - y - 1);
/*
* If transparency of given image is not opaque we assume all
* colors with alpha less than 1.0 as fully transparent.
*/
if (transparency != Transparency.OPAQUE &&
aColor.getAlpha() != 0xff)
{
if (transColor == null) {
this.requiredSize --; // one slot for transparent color
transColor = new ColorNode();
transColor.isLeaf = true;
}
transColor = insertNode(transColor, aColor, 0);
} else {
root = insertNode(root, aColor, 0);
}
if (currSize > requiredSize) {
reduceTree();
}
}
}
}
protected ColorNode insertNode(ColorNode aNode, Color aColor, int aLevel) {
if (aNode == null) {
aNode = new ColorNode();
numNodes++;
if (numNodes > maxNodes) {
maxNodes = numNodes;
}
aNode.level = aLevel;
aNode.isLeaf = (aLevel > MAXLEVEL);
if (aNode.isLeaf) {
currSize++;
}
}
aNode.colorCount++;
aNode.red += aColor.getRed();
aNode.green += aColor.getGreen();
aNode.blue += aColor.getBlue();
if (!aNode.isLeaf) {
int branchIndex = getBranchIndex(aColor, aLevel);
if (aNode.children[branchIndex] == null) {
aNode.childCount++;
if (aNode.childCount == 2) {
aNode.nextReducible = reduceList[aLevel];
reduceList[aLevel] = aNode;
}
}
aNode.children[branchIndex] =
insertNode(aNode.children[branchIndex], aColor, aLevel + 1);
}
return aNode;
}
protected IndexColorModel getIndexColorModel() {
int size = currSize;
if (transColor != null) {
size ++; // we need place for transparent color;
}
byte[] red = new byte[size];
byte[] green = new byte[size];
byte[] blue = new byte[size];
int index = 0;
palette = new ColorNode[size];
if (transColor != null) {
index ++;
}
if (root != null) {
findPaletteEntry(root, index, red, green, blue);
}
IndexColorModel icm = null;
if (transColor != null) {
icm = new IndexColorModel(8, size, red, green, blue, 0);
} else {
icm = new IndexColorModel(8, currSize, red, green, blue);
}
return icm;
}
protected int findPaletteEntry(ColorNode aNode, int index,
byte[] red, byte[] green, byte[] blue)
{
if (aNode.isLeaf) {
red[index] = (byte)(aNode.red/aNode.colorCount);
green[index] = (byte)(aNode.green/aNode.colorCount);
blue[index] = (byte)(aNode.blue/aNode.colorCount);
aNode.paletteIndex = index;
palette[index] = aNode;
index++;
} else {
for (int i = 0; i < 8; i++) {
if (aNode.children[i] != null) {
index = findPaletteEntry(aNode.children[i], index,
red, green, blue);
}
}
}
return index;
}
protected int getBranchIndex(Color aColor, int aLevel) {
if (aLevel > MAXLEVEL || aLevel < 0) {
throw new IllegalArgumentException("Invalid octree node depth: " +
aLevel);
}
int shift = MAXLEVEL - aLevel;
int red_index = 0x1 & ((0xff & aColor.getRed()) >> shift);
int green_index = 0x1 & ((0xff & aColor.getGreen()) >> shift);
int blue_index = 0x1 & ((0xff & aColor.getBlue()) >> shift);
int index = (red_index << 2) | (green_index << 1) | blue_index;
return index;
}
protected void reduceTree() {
int level = reduceList.length - 1;
while (reduceList[level] == null && level >= 0) {
level--;
}
ColorNode thisNode = reduceList[level];
if (thisNode == null) {
// nothing to reduce
return;
}
// look for element with lower color count
ColorNode pList = thisNode;
int minColorCount = pList.colorCount;
int cnt = 1;
while (pList.nextReducible != null) {
if (minColorCount > pList.nextReducible.colorCount) {
thisNode = pList;
minColorCount = pList.colorCount;
}
pList = pList.nextReducible;
cnt++;
}
// save pointer to first reducible node
// NB: current color count for node could be changed in future
if (thisNode == reduceList[level]) {
reduceList[level] = thisNode.nextReducible;
} else {
pList = thisNode.nextReducible; // we need to process it
thisNode.nextReducible = pList.nextReducible;
thisNode = pList;
}
if (thisNode.isLeaf) {
return;
}
// reduce node
int leafChildCount = thisNode.getLeafChildCount();
thisNode.isLeaf = true;
currSize -= (leafChildCount - 1);
int aDepth = thisNode.level;
for (int i = 0; i < 8; i++) {
thisNode.children[i] = freeTree(thisNode.children[i]);
}
thisNode.childCount = 0;
}
protected ColorNode freeTree(ColorNode aNode) {
if (aNode == null) {
return null;
}
for (int i = 0; i < 8; i++) {
aNode.children[i] = freeTree(aNode.children[i]);
}
numNodes--;
return null;
}
/**
* The node of color tree.
*/
protected class ColorNode {
public boolean isLeaf;
public int childCount;
ColorNode[] children;
public int colorCount;
public long red;
public long blue;
public long green;
public int paletteIndex;
public int level;
ColorNode nextReducible;
public ColorNode() {
isLeaf = false;
level = 0;
childCount = 0;
children = new ColorNode[8];
for (int i = 0; i < 8; i++) {
children[i] = null;
}
colorCount = 0;
red = green = blue = 0;
paletteIndex = 0;
}
public int getLeafChildCount() {
if (isLeaf) {
return 0;
}
int cnt = 0;
for (int i = 0; i < children.length; i++) {
if (children[i] != null) {
if (children[i].isLeaf) {
cnt ++;
} else {
cnt += children[i].getLeafChildCount();
}
}
}
return cnt;
}
public int getRGB() {
int r = (int)red/colorCount;
int g = (int)green/colorCount;
int b = (int)blue/colorCount;
int c = 0xff << 24 | (0xff&r) << 16 | (0xff&g) << 8 | (0xff&b);
return c;
}
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import javax.imageio.stream.ImageInputStream;
/**
* This class contains utility methods that may be useful to ImageReader
* plugins. Ideally these methods would be in the ImageReader base class
* so that all subclasses could benefit from them, but that would be an
* addition to the existing API, and it is not yet clear whether these methods
* are universally useful, so for now we will leave them here.
*/
public class ReaderUtil {
// Helper for computeUpdatedPixels method
private static void computeUpdatedPixels(int sourceOffset,
int sourceExtent,
int destinationOffset,
int dstMin,
int dstMax,
int sourceSubsampling,
int passStart,
int passExtent,
int passPeriod,
int[] vals,
int offset)
{
// We need to satisfy the congruences:
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling
//
// src - passStart == 0 (mod passPeriod)
// src - sourceOffset == 0 (mod sourceSubsampling)
//
// subject to the inequalities:
//
// src >= passStart
// src < passStart + passExtent
// src >= sourceOffset
// src < sourceOffset + sourceExtent
// dst >= dstMin
// dst <= dstmax
//
// where
//
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling
//
// For now we use a brute-force approach although we could
// attempt to analyze the congruences. If passPeriod and
// sourceSubsamling are relatively prime, the period will be
// their product. If they share a common factor, either the
// period will be equal to the larger value, or the sequences
// will be completely disjoint, depending on the relationship
// between passStart and sourceOffset. Since we only have to do this
// twice per image (once each for X and Y), it seems cheap enough
// to do it the straightforward way.
boolean gotPixel = false;
int firstDst = -1;
int secondDst = -1;
int lastDst = -1;
for (int i = 0; i < passExtent; i++) {
int src = passStart + i*passPeriod;
if (src < sourceOffset) {
continue;
}
if ((src - sourceOffset) % sourceSubsampling != 0) {
continue;
}
if (src >= sourceOffset + sourceExtent) {
break;
}
int dst = destinationOffset +
(src - sourceOffset)/sourceSubsampling;
if (dst < dstMin) {
continue;
}
if (dst > dstMax) {
break;
}
if (!gotPixel) {
firstDst = dst; // Record smallest valid pixel
gotPixel = true;
} else if (secondDst == -1) {
secondDst = dst; // Record second smallest valid pixel
}
lastDst = dst; // Record largest valid pixel
}
vals[offset] = firstDst;
// If we never saw a valid pixel, set width to 0
if (!gotPixel) {
vals[offset + 2] = 0;
} else {
vals[offset + 2] = lastDst - firstDst + 1;
}
// The period is given by the difference of any two adjacent pixels
vals[offset + 4] = Math.max(secondDst - firstDst, 1);
}
/**
* A utility method that computes the exact set of destination
* pixels that will be written during a particular decoding pass.
* The intent is to simplify the work done by readers in combining
* the source region, source subsampling, and destination offset
* information obtained from the <code>ImageReadParam</code> with
* the offsets and periods of a progressive or interlaced decoding
* pass.
*
* @param sourceRegion a <code>Rectangle</code> containing the
* source region being read, offset by the source subsampling
* offsets, and clipped against the source bounds, as returned by
* the <code>getSourceRegion</code> method.
* @param destinationOffset a <code>Point</code> containing the
* coordinates of the upper-left pixel to be written in the
* destination.
* @param dstMinX the smallest X coordinate (inclusive) of the
* destination <code>Raster</code>.
* @param dstMinY the smallest Y coordinate (inclusive) of the
* destination <code>Raster</code>.
* @param dstMaxX the largest X coordinate (inclusive) of the destination
* <code>Raster</code>.
* @param dstMaxY the largest Y coordinate (inclusive) of the destination
* <code>Raster</code>.
* @param sourceXSubsampling the X subsampling factor.
* @param sourceYSubsampling the Y subsampling factor.
* @param passXStart the smallest source X coordinate (inclusive)
* of the current progressive pass.
* @param passYStart the smallest source Y coordinate (inclusive)
* of the current progressive pass.
* @param passWidth the width in pixels of the current progressive
* pass.
* @param passHeight the height in pixels of the current progressive
* pass.
* @param passPeriodX the X period (horizontal spacing between
* pixels) of the current progressive pass.
* @param passPeriodY the Y period (vertical spacing between
* pixels) of the current progressive pass.
*
* @return an array of 6 <code>int</code>s containing the
* destination min X, min Y, width, height, X period and Y period
* of the region that will be updated.
*/
public static int[] computeUpdatedPixels(Rectangle sourceRegion,
Point destinationOffset,
int dstMinX,
int dstMinY,
int dstMaxX,
int dstMaxY,
int sourceXSubsampling,
int sourceYSubsampling,
int passXStart,
int passYStart,
int passWidth,
int passHeight,
int passPeriodX,
int passPeriodY)
{
int[] vals = new int[6];
computeUpdatedPixels(sourceRegion.x, sourceRegion.width,
destinationOffset.x,
dstMinX, dstMaxX, sourceXSubsampling,
passXStart, passWidth, passPeriodX,
vals, 0);
computeUpdatedPixels(sourceRegion.y, sourceRegion.height,
destinationOffset.y,
dstMinY, dstMaxY, sourceYSubsampling,
passYStart, passHeight, passPeriodY,
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;
}
/**
* An utility method to allocate and initialize a byte array
* step by step with pre-defined limit, instead of allocating
* a large array up-front based on the length derived from
* an image header.
*
* @param iis a {@code ImageInputStream} to decode data and store
* it in byte array.
* @param length the size of data to decode
*
* @return array of size length when decode succeeeds
*
* @throws IOException if decoding of stream fails
*/
public static byte[] staggeredReadByteStream(ImageInputStream iis,
int length) throws IOException {
final int UNIT_SIZE = 1024000;
byte[] decodedData;
if (length < UNIT_SIZE) {
decodedData = new byte[length];
iis.readFully(decodedData, 0, length);
} else {
int bytesToRead = length;
int bytesRead = 0;
List<byte[]> bufs = new ArrayList<>();
while (bytesToRead != 0) {
int sz = Math.min(bytesToRead, UNIT_SIZE);
byte[] unit = new byte[sz];
iis.readFully(unit, 0, sz);
bufs.add(unit);
bytesRead += sz;
bytesToRead -= sz;
}
decodedData = new byte[bytesRead];
int copiedBytes = 0;
for (byte[] ba : bufs) {
System.arraycopy(ba, 0, decodedData, copiedBytes, ba.length);
copiedBytes += ba.length;
}
}
return decodedData;
}
}

View File

@@ -0,0 +1,499 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class StandardMetadataFormat extends IIOMetadataFormatImpl {
// Utility method for nodes with a single attribute named "value"
private void addSingleAttributeElement(String elementName,
String parentName,
int dataType) {
addElement(elementName, parentName, CHILD_POLICY_EMPTY);
addAttribute(elementName, "value", dataType, true, null);
}
public StandardMetadataFormat() {
super(standardMetadataFormatName, CHILD_POLICY_SOME);
List values;
// root -> Chroma
addElement("Chroma", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Chroma -> ColorSpaceType
addElement("ColorSpaceType", "Chroma",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("XYZ");
values.add("Lab");
values.add("Luv");
values.add("YCbCr");
values.add("Yxy");
values.add("YCCK");
values.add("PhotoYCC");
values.add("RGB");
values.add("GRAY");
values.add("HSV");
values.add("HLS");
values.add("CMYK");
values.add("CMY");
values.add("2CLR");
values.add("3CLR");
values.add("4CLR");
values.add("5CLR");
values.add("6CLR");
values.add("7CLR");
values.add("8CLR");
values.add("9CLR");
values.add("ACLR");
values.add("BCLR");
values.add("CCLR");
values.add("DCLR");
values.add("ECLR");
values.add("FCLR");
addAttribute("ColorSpaceType",
"name",
DATATYPE_STRING,
true,
null,
values);
// root -> Chroma -> NumChannels
addElement("NumChannels", "Chroma",
CHILD_POLICY_EMPTY);
addAttribute("NumChannels", "value",
DATATYPE_INTEGER,
true,
0, Integer.MAX_VALUE);
// root -> Chroma -> Gamma
addElement("Gamma", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("Gamma", "value",
DATATYPE_FLOAT, true, null);
// root -> Chroma -> BlackIsZero
addElement("BlackIsZero", "Chroma", CHILD_POLICY_EMPTY);
addBooleanAttribute("BlackIsZero", "value", true, true);
// root -> Chroma -> Palette
addElement("Palette", "Chroma", 0, Integer.MAX_VALUE);
// root -> Chroma -> PaletteEntry
addElement("PaletteEntry", "Palette", CHILD_POLICY_EMPTY);
addAttribute("PaletteEntry", "index", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "red", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "green", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "blue", DATATYPE_INTEGER,
true, null);
addAttribute("PaletteEntry", "alpha", DATATYPE_INTEGER,
false, "255");
// root -> Chroma -> BackgroundIndex
addElement("BackgroundIndex", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("BackgroundIndex", "value", DATATYPE_INTEGER,
true, null);
// root -> Chroma -> BackgroundColor
addElement("BackgroundColor", "Chroma", CHILD_POLICY_EMPTY);
addAttribute("BackgroundColor", "red", DATATYPE_INTEGER,
true, null);
addAttribute("BackgroundColor", "green", DATATYPE_INTEGER,
true, null);
addAttribute("BackgroundColor", "blue", DATATYPE_INTEGER,
true, null);
// root -> Compression
addElement("Compression", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Compression -> CompressionTypeName
addSingleAttributeElement("CompressionTypeName",
"Compression",
DATATYPE_STRING);
// root -> Compression -> Lossless
addElement("Lossless", "Compression", CHILD_POLICY_EMPTY);
addBooleanAttribute("Lossless", "value", true, true);
// root -> Compression -> NumProgressiveScans
addSingleAttributeElement("NumProgressiveScans",
"Compression",
DATATYPE_INTEGER);
// root -> Compression -> BitRate
addSingleAttributeElement("BitRate",
"Compression",
DATATYPE_FLOAT);
// root -> Data
addElement("Data", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Data -> PlanarConfiguration
addElement("PlanarConfiguration", "Data", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("PixelInterleaved");
values.add("PlaneInterleaved");
values.add("LineInterleaved");
values.add("TileInterleaved");
addAttribute("PlanarConfiguration", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Data -> SampleFormat
addElement("SampleFormat", "Data", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("SignedIntegral");
values.add("UnsignedIntegral");
values.add("Real");
values.add("Index");
addAttribute("SampleFormat", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Data -> BitsPerSample
addElement("BitsPerSample", "Data",
CHILD_POLICY_EMPTY);
addAttribute("BitsPerSample", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Data -> SignificantBitsPerSample
addElement("SignificantBitsPerSample", "Data", CHILD_POLICY_EMPTY);
addAttribute("SignificantBitsPerSample", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Data -> SampleMSB
addElement("SampleMSB", "Data",
CHILD_POLICY_EMPTY);
addAttribute("SampleMSB", "value",
DATATYPE_INTEGER,
true,
1, Integer.MAX_VALUE);
// root -> Dimension
addElement("Dimension", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Dimension -> PixelAspectRatio
addSingleAttributeElement("PixelAspectRatio",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> ImageOrientation
addElement("ImageOrientation", "Dimension",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("Normal");
values.add("Rotate90");
values.add("Rotate180");
values.add("Rotate270");
values.add("FlipH");
values.add("FlipV");
values.add("FlipHRotate90");
values.add("FlipVRotate90");
addAttribute("ImageOrientation", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Dimension -> HorizontalPixelSize
addSingleAttributeElement("HorizontalPixelSize",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPixelSize
addSingleAttributeElement("VerticalPixelSize",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPhysicalPixelSpacing
addSingleAttributeElement("HorizontalPhysicalPixelSpacing",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPhysicalPixelSpacing
addSingleAttributeElement("VerticalPhysicalPixelSpacing",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPosition
addSingleAttributeElement("HorizontalPosition",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> VerticalPosition
addSingleAttributeElement("VerticalPosition",
"Dimension",
DATATYPE_FLOAT);
// root -> Dimension -> HorizontalPixelOffset
addSingleAttributeElement("HorizontalPixelOffset",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> VerticalPixelOffset
addSingleAttributeElement("VerticalPixelOffset",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> HorizontalScreenSize
addSingleAttributeElement("HorizontalScreenSize",
"Dimension",
DATATYPE_INTEGER);
// root -> Dimension -> VerticalScreenSize
addSingleAttributeElement("VerticalScreenSize",
"Dimension",
DATATYPE_INTEGER);
// root -> Document
addElement("Document", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Document -> FormatVersion
addElement("FormatVersion", "Document",
CHILD_POLICY_EMPTY);
addAttribute("FormatVersion", "value",
DATATYPE_STRING,
true,
null);
// root -> Document -> SubimageInterpretation
addElement("SubimageInterpretation", "Document",
CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("Standalone");
values.add("SinglePage");
values.add("FullResolution");
values.add("ReducedResolution");
values.add("PyramidLayer");
values.add("Preview");
values.add("VolumeSlice");
values.add("ObjectView");
values.add("Panorama");
values.add("AnimationFrame");
values.add("TransparencyMask");
values.add("CompositingLayer");
values.add("SpectralSlice");
values.add("Unknown");
addAttribute("SubimageInterpretation", "value",
DATATYPE_STRING,
true,
null,
values);
// root -> Document -> ImageCreationTime
addElement("ImageCreationTime", "Document",
CHILD_POLICY_EMPTY);
addAttribute("ImageCreationTime", "year",
DATATYPE_INTEGER,
true,
null);
addAttribute("ImageCreationTime", "month",
DATATYPE_INTEGER,
true,
null,
"1", "12", true, true);
addAttribute("ImageCreationTime", "day",
DATATYPE_INTEGER,
true,
null,
"1", "31", true, true);
addAttribute("ImageCreationTime", "hour",
DATATYPE_INTEGER,
false,
"0",
"0", "23", true, true);
addAttribute("ImageCreationTime", "minute",
DATATYPE_INTEGER,
false,
"0",
"0", "59", true, true);
// second = 60 denotes leap second
addAttribute("ImageCreationTime", "second",
DATATYPE_INTEGER,
false,
"0",
"0", "60", true, true);
// root -> Document -> ImageModificationTime
addElement("ImageModificationTime", "Document",
CHILD_POLICY_EMPTY);
addAttribute("ImageModificationTime", "year",
DATATYPE_INTEGER,
true,
null);
addAttribute("ImageModificationTime", "month",
DATATYPE_INTEGER,
true,
null,
"1", "12", true, true);
addAttribute("ImageModificationTime", "day",
DATATYPE_INTEGER,
true,
null,
"1", "31", true, true);
addAttribute("ImageModificationTime", "hour",
DATATYPE_INTEGER,
false,
"0",
"0", "23", true, true);
addAttribute("ImageModificationTime", "minute",
DATATYPE_INTEGER,
false,
"0",
"0", "59", true, true);
// second = 60 denotes leap second
addAttribute("ImageModificationTime", "second",
DATATYPE_INTEGER,
false,
"0",
"0", "60", true, true);
// root -> Text
addElement("Text", standardMetadataFormatName,
0, Integer.MAX_VALUE);
// root -> Text -> TextEntry
addElement("TextEntry", "Text", CHILD_POLICY_EMPTY);
addAttribute("TextEntry", "keyword",
DATATYPE_STRING,
false,
null);
addAttribute("TextEntry", "value",
DATATYPE_STRING,
true,
null);
addAttribute("TextEntry", "language",
DATATYPE_STRING,
false,
null);
addAttribute("TextEntry", "encoding",
DATATYPE_STRING,
false,
null);
values = new ArrayList();
values.add("none");
values.add("lzw");
values.add("zip");
values.add("bzip");
values.add("other");
addAttribute("TextEntry", "compression",
DATATYPE_STRING,
false,
"none",
values);
// root -> Transparency
addElement("Transparency", standardMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Transparency -> Alpha
addElement("Alpha", "Transparency", CHILD_POLICY_EMPTY);
values = new ArrayList();
values.add("none");
values.add("premultiplied");
values.add("nonpremultiplied");
addAttribute("Alpha", "value",
DATATYPE_STRING,
false,
"none",
values);
// root -> Transparency -> TransparentIndex
addSingleAttributeElement("TransparentIndex", "Transparency",
DATATYPE_INTEGER);
// root -> Transparency -> TransparentColor
addElement("TransparentColor", "Transparency",
CHILD_POLICY_EMPTY);
addAttribute("TransparentColor", "value",
DATATYPE_INTEGER,
true,
0, Integer.MAX_VALUE);
// root -> Transparency -> TileTransparencies
addElement("TileTransparencies", "Transparency",
0, Integer.MAX_VALUE);
// root -> Transparency -> TileTransparencies -> TransparentTile
addElement("TransparentTile", "TileTransparencies",
CHILD_POLICY_EMPTY);
addAttribute("TransparentTile", "x",
DATATYPE_INTEGER,
true,
null);
addAttribute("TransparentTile", "y",
DATATYPE_INTEGER,
true,
null);
// root -> Transparency -> TileOpacities
addElement("TileOpacities", "Transparency",
0, Integer.MAX_VALUE);
// root -> Transparency -> TileOpacities -> OpaqueTile
addElement("OpaqueTile", "TileOpacities",
CHILD_POLICY_EMPTY);
addAttribute("OpaqueTile", "x",
DATATYPE_INTEGER,
true,
null);
addAttribute("OpaqueTile", "y",
DATATYPE_INTEGER,
true,
null);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.util.ListResourceBundle;
public class StandardMetadataFormatResources extends ListResourceBundle {
public StandardMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description, or
// Node name + "/" + AttributeName, followed by description
{ "Chroma", "Chroma (color) information" },
{ "ColorSpaceType", "The raw color space of the image" },
{ "NumChannels",
"The number of channels in the raw image, including alpha" },
{ "Gamma", "The image gamma" },
{ "BlackIsZero",
"True if smaller values represent darker shades"},
{ "Palette", "Palette-color information" },
{ "PaletteEntry", "A palette entry" },
{ "PaletteEntry/index", "The index of the palette entry" },
{ "PaletteEntry/red", "The red value for the palette entry" },
{ "PaletteEntry/green", "The green value for the palette entry" },
{ "PaletteEntry/blue", "The blue value for the palette entry" },
{ "PaletteEntry/alpha", "The alpha value for the palette entry" },
{ "BackgroundIndex", "A palette index to be used as a background" },
{ "BackgroundColor", "An RGB triple to be used as a background" },
{ "BackgroundColor/red", "The red background value" },
{ "BackgroundColor/green", "The green background value" },
{ "BackgroundColor/blue", "The blue background value" },
{ "Compression", "Compression information" },
{ "CompressionTypeName", "The name of the compression scheme in use" },
{ "Lossless",
"True if the compression scheme is lossless" },
{ "BitRate", "The estimated bit rate of the compression scheme" },
{ "NumProgressiveScans",
"The number of progressive scans used in the image encoding"},
{ "Data", "Information on the image layout" },
{ "PlanarConfiguration",
"The organization of image samples in the stream" },
{ "SampleFormat", "The numeric format of image samples" },
{ "BitsPerSample", "The number of bits per sample"},
{ "BitsPerSample/value",
"A list of integers, one per channel" },
{ "SignificantBitsPerSample",
"The number of significant bits per sample"},
{ "SignificantBitsPerSample/value",
"A list of integers, one per channel" },
{ "SampleMSB",
"The position of the most significant bit of each sample"},
{ "SampleMSB/value",
"A list of integers, one per channel" },
{ "Dimension", "Dimension information" },
{ "PixelAspectRatio", "The width of a pixel divided by its height" },
{ "ImageOrientation", "The desired orientation of the image in terms of flips and counter-clockwise rotations" },
{ "HorizontalPixelSize",
"The width of a pixel, in millimeters, as it should be rendered on media" },
{ "VerticalPixelSize",
"The height of a pixel, in millimeters, as it should be rendered on media" },
{ "HorizontalPhysicalPixelSpacing",
"The horizontal distance in the subject of the image, in millimeters, represented by one pixel at the center of the image" },
{ "VerticalPhysicalPixelSpacing",
"The vertical distance in the subject of the image, in millimeters, represented by one pixel at the center of the image" },
{ "HorizontalPosition",
"The horizontal position, in millimeters, where the image should be rendered on media " },
{ "VerticalPosition",
"The vertical position, in millimeters, where the image should be rendered on media " },
{ "HorizontalPixelOffset",
"The horizontal position, in pixels, where the image should be rendered onto a raster display" },
{ "VerticalPixelOffset",
"The vertical position, in pixels, where the image should be rendered onto a raster display" },
{ "HorizontalScreenSize",
"The width, in pixels, of the raster display into which the image should be rendered" },
{ "VerticalScreenSize",
"The height, in pixels, of the raster display into which the image should be rendered" },
{ "Document", "Document information" },
{ "FormatVersion",
"The version of the format used by the stream" },
{ "SubimageInterpretation",
"The interpretation of this image in relation to the other images stored in the same stream" },
{ "ImageCreationTime", "The time of image creation" },
{ "ImageCreationTime/year",
"The full year (e.g., 1967, not 67)" },
{ "ImageCreationTime/month",
"The month, with January = 1" },
{ "ImageCreationTime/day",
"The day of the month" },
{ "ImageCreationTime/hour",
"The hour from 0 to 23" },
{ "ImageCreationTime/minute",
"The minute from 0 to 59" },
{ "ImageCreationTime/second",
"The second from 0 to 60 (60 = leap second)" },
{ "ImageModificationTime", "The time of the last image modification" },
{ "ImageModificationTime/year",
"The full year (e.g., 1967, not 67)" },
{ "ImageModificationTime/month",
"The month, with January = 1" },
{ "ImageModificationTime/day",
"The day of the month" },
{ "ImageModificationTime/hour",
"The hour from 0 to 23" },
{ "ImageModificationTime/minute",
"The minute from 0 to 59" },
{ "ImageModificationTime/second",
"The second from 0 to 60 (60 = leap second)" },
{ "Text", "Text information" },
{ "TextEntry", "A text entry"},
{ "TextEntry/keyword", "A keyword associated with the text entry" },
{ "TextEntry/value", "the text entry" },
{ "TextEntry/language", "The language of the text" },
{ "TextEntry/encoding", "The encoding of the text" },
{ "TextEntry/compression", "The method used to compress the text" },
{ "Transparency", "Transparency information" },
{ "Alpha", "The type of alpha information contained in the image" },
{ "TransparentIndex", "A palette index to be treated as transparent" },
{ "TransparentColor", "An RGB color to be treated as transparent" },
{ "TransparentColor/red",
"The red channel of the transparent color" },
{ "TransparentColor/green",
"The green channel of the transparent color" },
{ "TransparentColor/blue",
"The blue channel of the transparent color" },
{ "TileTransparencies", "A list of completely transparent tiles" },
{ "TransparentTile", "The index of a completely transparent tile" },
{ "TransparentTile/x", "The tile's X index" },
{ "TransparentTile/y", "The tile's Y index" },
{ "TileOpacities", "A list of completely opaque tiles" },
{ "OpaqueTile", "The index of a completely opaque tile" },
{ "OpaqueTile/x", "The tile's X index" },
{ "OpaqueTile/y", "The tile's Y index" },
};
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.common;
import java.io.IOException;
import javax.imageio.stream.ImageInputStreamImpl;
import javax.imageio.stream.ImageInputStream;
public final class SubImageInputStream extends ImageInputStreamImpl {
ImageInputStream stream;
long startingPos;
int startingLength;
int length;
public SubImageInputStream(ImageInputStream stream, int length)
throws IOException {
this.stream = stream;
this.startingPos = stream.getStreamPosition();
this.startingLength = this.length = length;
}
public int read() throws IOException {
if (length == 0) { // Local EOF
return -1;
} else {
--length;
return stream.read();
}
}
public int read(byte[] b, int off, int len) throws IOException {
if (length == 0) { // Local EOF
return -1;
}
len = Math.min(len, length);
int bytes = stream.read(b, off, len);
length -= bytes;
return bytes;
}
public long length() {
return startingLength;
}
public void seek(long pos) throws IOException {
stream.seek(pos - startingPos);
streamPos = pos;
}
protected void finalize() throws Throwable {
// Empty finalizer (for improved performance; no need to call
// super.finalize() in this case)
}
}

View File

@@ -0,0 +1,446 @@
/*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
public class GIFImageMetadata extends GIFMetadata {
// package scope
static final String
nativeMetadataFormatName = "javax_imageio_gif_image_1.0";
static final String[] disposalMethodNames = {
"none",
"doNotDispose",
"restoreToBackgroundColor",
"restoreToPrevious",
"undefinedDisposalMethod4",
"undefinedDisposalMethod5",
"undefinedDisposalMethod6",
"undefinedDisposalMethod7"
};
// Fields from Image Descriptor
public int imageLeftPosition;
public int imageTopPosition;
public int imageWidth;
public int imageHeight;
public boolean interlaceFlag = false;
public boolean sortFlag = false;
public byte[] localColorTable = null;
// Fields from Graphic Control Extension
public int disposalMethod = 0;
public boolean userInputFlag = false;
public boolean transparentColorFlag = false;
public int delayTime = 0;
public int transparentColorIndex = 0;
// Fields from Plain Text Extension
public boolean hasPlainTextExtension = false;
public int textGridLeft;
public int textGridTop;
public int textGridWidth;
public int textGridHeight;
public int characterCellWidth;
public int characterCellHeight;
public int textForegroundColor;
public int textBackgroundColor;
public byte[] text;
// Fields from ApplicationExtension
// List of byte[]
public List applicationIDs = null; // new ArrayList();
// List of byte[]
public List authenticationCodes = null; // new ArrayList();
// List of byte[]
public List applicationData = null; // new ArrayList();
// Fields from CommentExtension
// List of byte[]
public List comments = null; // new ArrayList();
protected GIFImageMetadata(boolean standardMetadataFormatSupported,
String nativeMetadataFormatName,
String nativeMetadataFormatClassName,
String[] extraMetadataFormatNames,
String[] extraMetadataFormatClassNames)
{
super(standardMetadataFormatSupported,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
extraMetadataFormatNames,
extraMetadataFormatClassNames);
}
public GIFImageMetadata() {
this(true,
nativeMetadataFormatName,
"com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
private String toISO8859(byte[] data) {
try {
return new String(data, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
return "";
}
}
private Node getNativeTree() {
IIOMetadataNode node; // scratch node
IIOMetadataNode root =
new IIOMetadataNode(nativeMetadataFormatName);
// Image descriptor
node = new IIOMetadataNode("ImageDescriptor");
node.setAttribute("imageLeftPosition",
Integer.toString(imageLeftPosition));
node.setAttribute("imageTopPosition",
Integer.toString(imageTopPosition));
node.setAttribute("imageWidth", Integer.toString(imageWidth));
node.setAttribute("imageHeight", Integer.toString(imageHeight));
node.setAttribute("interlaceFlag",
interlaceFlag ? "TRUE" : "FALSE");
root.appendChild(node);
// Local color table
if (localColorTable != null) {
node = new IIOMetadataNode("LocalColorTable");
int numEntries = localColorTable.length/3;
node.setAttribute("sizeOfLocalColorTable",
Integer.toString(numEntries));
node.setAttribute("sortFlag",
sortFlag ? "TRUE" : "FALSE");
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("ColorTableEntry");
entry.setAttribute("index", Integer.toString(i));
int r = localColorTable[3*i] & 0xff;
int g = localColorTable[3*i + 1] & 0xff;
int b = localColorTable[3*i + 2] & 0xff;
entry.setAttribute("red", Integer.toString(r));
entry.setAttribute("green", Integer.toString(g));
entry.setAttribute("blue", Integer.toString(b));
node.appendChild(entry);
}
root.appendChild(node);
}
// Graphic control extension
node = new IIOMetadataNode("GraphicControlExtension");
node.setAttribute("disposalMethod",
disposalMethodNames[disposalMethod]);
node.setAttribute("userInputFlag",
userInputFlag ? "TRUE" : "FALSE");
node.setAttribute("transparentColorFlag",
transparentColorFlag ? "TRUE" : "FALSE");
node.setAttribute("delayTime",
Integer.toString(delayTime));
node.setAttribute("transparentColorIndex",
Integer.toString(transparentColorIndex));
root.appendChild(node);
if (hasPlainTextExtension) {
node = new IIOMetadataNode("PlainTextExtension");
node.setAttribute("textGridLeft",
Integer.toString(textGridLeft));
node.setAttribute("textGridTop",
Integer.toString(textGridTop));
node.setAttribute("textGridWidth",
Integer.toString(textGridWidth));
node.setAttribute("textGridHeight",
Integer.toString(textGridHeight));
node.setAttribute("characterCellWidth",
Integer.toString(characterCellWidth));
node.setAttribute("characterCellHeight",
Integer.toString(characterCellHeight));
node.setAttribute("textForegroundColor",
Integer.toString(textForegroundColor));
node.setAttribute("textBackgroundColor",
Integer.toString(textBackgroundColor));
node.setAttribute("text", toISO8859(text));
root.appendChild(node);
}
// Application extensions
int numAppExtensions = applicationIDs == null ?
0 : applicationIDs.size();
if (numAppExtensions > 0) {
node = new IIOMetadataNode("ApplicationExtensions");
for (int i = 0; i < numAppExtensions; i++) {
IIOMetadataNode appExtNode =
new IIOMetadataNode("ApplicationExtension");
byte[] applicationID = (byte[])applicationIDs.get(i);
appExtNode.setAttribute("applicationID",
toISO8859(applicationID));
byte[] authenticationCode = (byte[])authenticationCodes.get(i);
appExtNode.setAttribute("authenticationCode",
toISO8859(authenticationCode));
byte[] appData = (byte[])applicationData.get(i);
appExtNode.setUserObject((byte[])appData.clone());
node.appendChild(appExtNode);
}
root.appendChild(node);
}
// Comment extensions
int numComments = comments == null ? 0 : comments.size();
if (numComments > 0) {
node = new IIOMetadataNode("CommentExtensions");
for (int i = 0; i < numComments; i++) {
IIOMetadataNode commentNode =
new IIOMetadataNode("CommentExtension");
byte[] comment = (byte[])comments.get(i);
commentNode.setAttribute("value", toISO8859(comment));
node.appendChild(commentNode);
}
root.appendChild(node);
}
return root;
}
public IIOMetadataNode getStandardChromaNode() {
IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("ColorSpaceType");
node.setAttribute("name", "RGB");
chroma_node.appendChild(node);
node = new IIOMetadataNode("NumChannels");
node.setAttribute("value", transparentColorFlag ? "4" : "3");
chroma_node.appendChild(node);
// Gamma not in format
node = new IIOMetadataNode("BlackIsZero");
node.setAttribute("value", "TRUE");
chroma_node.appendChild(node);
if (localColorTable != null) {
node = new IIOMetadataNode("Palette");
int numEntries = localColorTable.length/3;
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("PaletteEntry");
entry.setAttribute("index", Integer.toString(i));
entry.setAttribute("red",
Integer.toString(localColorTable[3*i] & 0xff));
entry.setAttribute("green",
Integer.toString(localColorTable[3*i + 1] & 0xff));
entry.setAttribute("blue",
Integer.toString(localColorTable[3*i + 2] & 0xff));
node.appendChild(entry);
}
chroma_node.appendChild(node);
}
// BackgroundIndex not in image
// BackgroundColor not in format
return chroma_node;
}
public IIOMetadataNode getStandardCompressionNode() {
IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("CompressionTypeName");
node.setAttribute("value", "lzw");
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", "TRUE");
compression_node.appendChild(node);
node = new IIOMetadataNode("NumProgressiveScans");
node.setAttribute("value", interlaceFlag ? "4" : "1");
compression_node.appendChild(node);
// BitRate not in format
return compression_node;
}
public IIOMetadataNode getStandardDataNode() {
IIOMetadataNode data_node = new IIOMetadataNode("Data");
IIOMetadataNode node = null; // scratch node
// PlanarConfiguration not in format
node = new IIOMetadataNode("SampleFormat");
node.setAttribute("value", "Index");
data_node.appendChild(node);
// BitsPerSample not in image
// SignificantBitsPerSample not in format
// SampleMSB not in format
return data_node;
}
public IIOMetadataNode getStandardDimensionNode() {
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
IIOMetadataNode node = null; // scratch node
// PixelAspectRatio not in image
node = new IIOMetadataNode("ImageOrientation");
node.setAttribute("value", "Normal");
dimension_node.appendChild(node);
// HorizontalPixelSize not in format
// VerticalPixelSize not in format
// HorizontalPhysicalPixelSpacing not in format
// VerticalPhysicalPixelSpacing not in format
// HorizontalPosition not in format
// VerticalPosition not in format
node = new IIOMetadataNode("HorizontalPixelOffset");
node.setAttribute("value", Integer.toString(imageLeftPosition));
dimension_node.appendChild(node);
node = new IIOMetadataNode("VerticalPixelOffset");
node.setAttribute("value", Integer.toString(imageTopPosition));
dimension_node.appendChild(node);
// HorizontalScreenSize not in image
// VerticalScreenSize not in image
return dimension_node;
}
// Document not in image
public IIOMetadataNode getStandardTextNode() {
if (comments == null) {
return null;
}
Iterator commentIter = comments.iterator();
if (!commentIter.hasNext()) {
return null;
}
IIOMetadataNode text_node = new IIOMetadataNode("Text");
IIOMetadataNode node = null; // scratch node
while (commentIter.hasNext()) {
byte[] comment = (byte[])commentIter.next();
String s = null;
try {
s = new String(comment, "ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Encoding ISO-8859-1 unknown!");
}
node = new IIOMetadataNode("TextEntry");
node.setAttribute("value", s);
node.setAttribute("encoding", "ISO-8859-1");
node.setAttribute("compression", "none");
text_node.appendChild(node);
}
return text_node;
}
public IIOMetadataNode getStandardTransparencyNode() {
if (!transparentColorFlag) {
return null;
}
IIOMetadataNode transparency_node =
new IIOMetadataNode("Transparency");
IIOMetadataNode node = null; // scratch node
// Alpha not in format
node = new IIOMetadataNode("TransparentIndex");
node.setAttribute("value",
Integer.toString(transparentColorIndex));
transparency_node.appendChild(node);
// TransparentColor not in format
// TileTransparencies not in format
// TileOpacities not in format
return transparency_node;
}
public void setFromTree(String formatName, Node root)
throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeNativeTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeStandardTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
public void reset() {
throw new IllegalStateException("Metadata is read-only!");
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.util.Arrays;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class GIFImageMetadataFormat extends IIOMetadataFormatImpl {
private static IIOMetadataFormat instance = null;
private GIFImageMetadataFormat() {
super(GIFImageMetadata.nativeMetadataFormatName,
CHILD_POLICY_SOME);
// root -> ImageDescriptor
addElement("ImageDescriptor",
GIFImageMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ImageDescriptor", "imageLeftPosition",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("ImageDescriptor", "imageTopPosition",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("ImageDescriptor", "imageWidth",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("ImageDescriptor", "imageHeight",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addBooleanAttribute("ImageDescriptor", "interlaceFlag",
false, false);
// root -> LocalColorTable
addElement("LocalColorTable",
GIFImageMetadata.nativeMetadataFormatName,
2, 256);
addAttribute("LocalColorTable", "sizeOfLocalColorTable",
DATATYPE_INTEGER, true, null,
Arrays.asList(GIFStreamMetadata.colorTableSizes));
addBooleanAttribute("LocalColorTable", "sortFlag",
false, false);
// root -> LocalColorTable -> ColorTableEntry
addElement("ColorTableEntry", "LocalColorTable",
CHILD_POLICY_EMPTY);
addAttribute("ColorTableEntry", "index",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "red",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "green",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "blue",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
// root -> GraphicControlExtension
addElement("GraphicControlExtension",
GIFImageMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("GraphicControlExtension", "disposalMethod",
DATATYPE_STRING, true, null,
Arrays.asList(GIFImageMetadata.disposalMethodNames));
addBooleanAttribute("GraphicControlExtension", "userInputFlag",
false, false);
addBooleanAttribute("GraphicControlExtension", "transparentColorFlag",
false, false);
addAttribute("GraphicControlExtension", "delayTime",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("GraphicControlExtension", "transparentColorIndex",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
// root -> PlainTextExtension
addElement("PlainTextExtension",
GIFImageMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("PlainTextExtension", "textGridLeft",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("PlainTextExtension", "textGridTop",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("PlainTextExtension", "textGridWidth",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("PlainTextExtension", "textGridHeight",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("PlainTextExtension", "characterCellWidth",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("PlainTextExtension", "characterCellHeight",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("PlainTextExtension", "textForegroundColor",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("PlainTextExtension", "textBackgroundColor",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
// root -> ApplicationExtensions
addElement("ApplicationExtensions",
GIFImageMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> ApplicationExtensions -> ApplicationExtension
addElement("ApplicationExtension", "ApplicationExtensions",
CHILD_POLICY_EMPTY);
addAttribute("ApplicationExtension", "applicationID",
DATATYPE_STRING, true, null);
addAttribute("ApplicationExtension", "authenticationCode",
DATATYPE_STRING, true, null);
addObjectValue("ApplicationExtension", byte.class,
0, Integer.MAX_VALUE);
// root -> CommentExtensions
addElement("CommentExtensions",
GIFImageMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> CommentExtensions -> CommentExtension
addElement("CommentExtension", "CommentExtensions",
CHILD_POLICY_EMPTY);
addAttribute("CommentExtension", "value",
DATATYPE_STRING, true, null);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
public static synchronized IIOMetadataFormat getInstance() {
if (instance == null) {
instance = new GIFImageMetadataFormat();
}
return instance;
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.util.ListResourceBundle;
public class GIFImageMetadataFormatResources extends ListResourceBundle {
public GIFImageMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description
{ "ImageDescriptor", "The image descriptor" },
{ "LocalColorTable", "The local color table" },
{ "ColorTableEntry", "A local color table entry" },
{ "GraphicControlExtension", "A graphic control extension" },
{ "PlainTextExtension", "A plain text (text grid) extension" },
{ "ApplicationExtensions", "A set of application extensions" },
{ "ApplicationExtension", "An application extension" },
{ "CommentExtensions", "A set of comments" },
{ "CommentExtension", "A comment" },
// Node name + "/" + AttributeName, followed by description
{ "ImageDescriptor/imageLeftPosition",
"The X offset of the image relative to the screen origin" },
{ "ImageDescriptor/imageTopPosition",
"The Y offset of the image relative to the screen origin" },
{ "ImageDescriptor/imageWidth",
"The width of the image" },
{ "ImageDescriptor/imageHeight",
"The height of the image" },
{ "ImageDescriptor/interlaceFlag",
"True if the image is stored using interlacing" },
{ "LocalColorTable/sizeOfLocalColorTable",
"The number of entries in the local color table" },
{ "LocalColorTable/sortFlag",
"True if the local color table is sorted by frequency" },
{ "ColorTableEntry/index", "The index of the color table entry" },
{ "ColorTableEntry/red",
"The red value for the color table entry" },
{ "ColorTableEntry/green",
"The green value for the color table entry" },
{ "ColorTableEntry/blue",
"The blue value for the color table entry" },
{ "GraphicControlExtension/disposalMethod",
"The disposal method for this frame" },
{ "GraphicControlExtension/userInputFlag",
"True if the frame should be advanced based on user input" },
{ "GraphicControlExtension/transparentColorFlag",
"True if a transparent color exists" },
{ "GraphicControlExtension/delayTime",
"The time to delay between frames, in hundredths of a second" },
{ "GraphicControlExtension/transparentColorIndex",
"The transparent color, if transparentColorFlag is true" },
{ "PlainTextExtension/textGridLeft",
"The X offset of the text grid" },
{ "PlainTextExtension/textGridTop",
"The Y offset of the text grid" },
{ "PlainTextExtension/textGridWidth",
"The number of columns in the text grid" },
{ "PlainTextExtension/textGridHeight",
"The number of rows in the text grid" },
{ "PlainTextExtension/characterCellWidth",
"The width of a character cell" },
{ "PlainTextExtension/characterCellHeight",
"The height of a character cell" },
{ "PlainTextExtension/textForegroundColor",
"The text foreground color index" },
{ "PlainTextExtension/textBackgroundColor",
"The text background color index" },
{ "ApplicationExtension/applicationID",
"The application ID" },
{ "ApplicationExtension/authenticationCode",
"The authentication code" },
{ "CommentExtension/value", "The comment" },
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.io.IOException;
import java.util.Locale;
import java.util.Iterator;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
public class GIFImageReaderSpi extends ImageReaderSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final String[] names = { "gif", "GIF" };
private static final String[] suffixes = { "gif" };
private static final String[] MIMETypes = { "image/gif" };
private static final String readerClassName =
"com.sun.imageio.plugins.gif.GIFImageReader";
private static final String[] writerSpiNames = {
"com.sun.imageio.plugins.gif.GIFImageWriterSpi"
};
public GIFImageReaderSpi() {
super(vendorName,
version,
names,
suffixes,
MIMETypes,
readerClassName,
new Class[] { ImageInputStream.class },
writerSpiNames,
true,
GIFStreamMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.gif.GIFStreamMetadataFormat",
null, null,
true,
GIFImageMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
null, null
);
}
public String getDescription(Locale locale) {
return "Standard GIF image reader";
}
public boolean canDecodeInput(Object input) throws IOException {
if (!(input instanceof ImageInputStream)) {
return false;
}
ImageInputStream stream = (ImageInputStream)input;
byte[] b = new byte[6];
stream.mark();
stream.readFully(b);
stream.reset();
return b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' &&
(b[4] == '7' || b[4] == '9') && b[5] == 'a';
}
public ImageReader createReaderInstance(Object extension) {
return new GIFImageReader(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.awt.image.ColorModel;
import java.awt.image.SampleModel;
import java.util.Locale;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import com.sun.imageio.plugins.common.PaletteBuilder;
public class GIFImageWriterSpi extends ImageWriterSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final String[] names = { "gif", "GIF" };
private static final String[] suffixes = { "gif" };
private static final String[] MIMETypes = { "image/gif" };
private static final String writerClassName =
"com.sun.imageio.plugins.gif.GIFImageWriter";
private static final String[] readerSpiNames = {
"com.sun.imageio.plugins.gif.GIFImageReaderSpi"
};
public GIFImageWriterSpi() {
super(vendorName,
version,
names,
suffixes,
MIMETypes,
writerClassName,
new Class[] { ImageOutputStream.class },
readerSpiNames,
true,
GIFWritableStreamMetadata.NATIVE_FORMAT_NAME,
"com.sun.imageio.plugins.gif.GIFStreamMetadataFormat",
null, null,
true,
GIFWritableImageMetadata.NATIVE_FORMAT_NAME,
"com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
null, null
);
}
public boolean canEncodeImage(ImageTypeSpecifier type) {
if (type == null) {
throw new IllegalArgumentException("type == null!");
}
SampleModel sm = type.getSampleModel();
ColorModel cm = type.getColorModel();
boolean canEncode = sm.getNumBands() == 1 &&
sm.getSampleSize(0) <= 8 &&
sm.getWidth() <= 65535 &&
sm.getHeight() <= 65535 &&
(cm == null || cm.getComponentSize()[0] <= 8);
if (canEncode) {
return true;
} else {
return PaletteBuilder.canCreatePalette(type);
}
}
public String getDescription(Locale locale) {
return "Standard GIF image writer";
}
public ImageWriter createWriterInstance(Object extension) {
return new GIFImageWriter(this);
}
}

View File

@@ -0,0 +1,317 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
/**
* Class which adds utility DOM element attribute access methods to
* <code>IIOMetadata</code> for subclass use.
*/
abstract class GIFMetadata extends IIOMetadata {
/**
* Represents an undefined value of integer attributes.
*/
static final int UNDEFINED_INTEGER_VALUE = -1;
//
// Note: These attribute methods were shamelessly lifted from
// com.sun.imageio.plugins.png.PNGMetadata and modified.
//
// Shorthand for throwing an IIOInvalidTreeException
protected static void fatal(Node node, String reason)
throws IIOInvalidTreeException {
throw new IIOInvalidTreeException(reason, node);
}
// Get an integer-valued attribute
protected static String getStringAttribute(Node node, String name,
String defaultValue,
boolean required,
String[] range)
throws IIOInvalidTreeException {
Node attr = node.getAttributes().getNamedItem(name);
if (attr == null) {
if (!required) {
return defaultValue;
} else {
fatal(node, "Required attribute " + name + " not present!");
}
}
String value = attr.getNodeValue();
if (range != null) {
if (value == null) {
fatal(node,
"Null value for "+node.getNodeName()+
" attribute "+name+"!");
}
boolean validValue = false;
int len = range.length;
for (int i = 0; i < len; i++) {
if (value.equals(range[i])) {
validValue = true;
break;
}
}
if (!validValue) {
fatal(node,
"Bad value for "+node.getNodeName()+
" attribute "+name+"!");
}
}
return value;
}
// Get an integer-valued attribute
protected static int getIntAttribute(Node node, String name,
int defaultValue, boolean required,
boolean bounded, int min, int max)
throws IIOInvalidTreeException {
String value = getStringAttribute(node, name, null, required, null);
if (value == null || "".equals(value)) {
return defaultValue;
}
int intValue = defaultValue;
try {
intValue = Integer.parseInt(value);
} catch (NumberFormatException e) {
fatal(node,
"Bad value for "+node.getNodeName()+
" attribute "+name+"!");
}
if (bounded && (intValue < min || intValue > max)) {
fatal(node,
"Bad value for "+node.getNodeName()+
" attribute "+name+"!");
}
return intValue;
}
// Get a float-valued attribute
protected static float getFloatAttribute(Node node, String name,
float defaultValue,
boolean required)
throws IIOInvalidTreeException {
String value = getStringAttribute(node, name, null, required, null);
if (value == null) {
return defaultValue;
}
return Float.parseFloat(value);
}
// Get a required integer-valued attribute
protected static int getIntAttribute(Node node, String name,
boolean bounded, int min, int max)
throws IIOInvalidTreeException {
return getIntAttribute(node, name, -1, true, bounded, min, max);
}
// Get a required float-valued attribute
protected static float getFloatAttribute(Node node, String name)
throws IIOInvalidTreeException {
return getFloatAttribute(node, name, -1.0F, true);
}
// Get a boolean-valued attribute
protected static boolean getBooleanAttribute(Node node, String name,
boolean defaultValue,
boolean required)
throws IIOInvalidTreeException {
Node attr = node.getAttributes().getNamedItem(name);
if (attr == null) {
if (!required) {
return defaultValue;
} else {
fatal(node, "Required attribute " + name + " not present!");
}
}
String value = attr.getNodeValue();
// Allow lower case booleans for backward compatibility, #5082756
if (value.equals("TRUE") || value.equals("true")) {
return true;
} else if (value.equals("FALSE") || value.equals("false")) {
return false;
} else {
fatal(node, "Attribute " + name + " must be 'TRUE' or 'FALSE'!");
return false;
}
}
// Get a required boolean-valued attribute
protected static boolean getBooleanAttribute(Node node, String name)
throws IIOInvalidTreeException {
return getBooleanAttribute(node, name, false, true);
}
// Get an enumerated attribute as an index into a String array
protected static int getEnumeratedAttribute(Node node,
String name,
String[] legalNames,
int defaultValue,
boolean required)
throws IIOInvalidTreeException {
Node attr = node.getAttributes().getNamedItem(name);
if (attr == null) {
if (!required) {
return defaultValue;
} else {
fatal(node, "Required attribute " + name + " not present!");
}
}
String value = attr.getNodeValue();
for (int i = 0; i < legalNames.length; i++) {
if(value.equals(legalNames[i])) {
return i;
}
}
fatal(node, "Illegal value for attribute " + name + "!");
return -1;
}
// Get a required enumerated attribute as an index into a String array
protected static int getEnumeratedAttribute(Node node,
String name,
String[] legalNames)
throws IIOInvalidTreeException {
return getEnumeratedAttribute(node, name, legalNames, -1, true);
}
// Get a String-valued attribute
protected static String getAttribute(Node node, String name,
String defaultValue, boolean required)
throws IIOInvalidTreeException {
Node attr = node.getAttributes().getNamedItem(name);
if (attr == null) {
if (!required) {
return defaultValue;
} else {
fatal(node, "Required attribute " + name + " not present!");
}
}
return attr.getNodeValue();
}
// Get a required String-valued attribute
protected static String getAttribute(Node node, String name)
throws IIOInvalidTreeException {
return getAttribute(node, name, null, true);
}
protected GIFMetadata(boolean standardMetadataFormatSupported,
String nativeMetadataFormatName,
String nativeMetadataFormatClassName,
String[] extraMetadataFormatNames,
String[] extraMetadataFormatClassNames) {
super(standardMetadataFormatSupported,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
extraMetadataFormatNames,
extraMetadataFormatClassNames);
}
public void mergeTree(String formatName, Node root)
throws IIOInvalidTreeException {
if (formatName.equals(nativeMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeNativeTree(root);
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeStandardTree(root);
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
protected byte[] getColorTable(Node colorTableNode,
String entryNodeName,
boolean lengthExpected,
int expectedLength)
throws IIOInvalidTreeException {
byte[] red = new byte[256];
byte[] green = new byte[256];
byte[] blue = new byte[256];
int maxIndex = -1;
Node entry = colorTableNode.getFirstChild();
if (entry == null) {
fatal(colorTableNode, "Palette has no entries!");
}
while (entry != null) {
if (!entry.getNodeName().equals(entryNodeName)) {
fatal(colorTableNode,
"Only a "+entryNodeName+" may be a child of a "+
entry.getNodeName()+"!");
}
int index = getIntAttribute(entry, "index", true, 0, 255);
if (index > maxIndex) {
maxIndex = index;
}
red[index] = (byte)getIntAttribute(entry, "red", true, 0, 255);
green[index] = (byte)getIntAttribute(entry, "green", true, 0, 255);
blue[index] = (byte)getIntAttribute(entry, "blue", true, 0, 255);
entry = entry.getNextSibling();
}
int numEntries = maxIndex + 1;
if (lengthExpected && numEntries != expectedLength) {
fatal(colorTableNode, "Unexpected length for palette!");
}
byte[] colorTable = new byte[3*numEntries];
for (int i = 0, j = 0; i < numEntries; i++) {
colorTable[j++] = red[i];
colorTable[j++] = green[i];
colorTable[j++] = blue[i];
}
return colorTable;
}
protected abstract void mergeNativeTree(Node root)
throws IIOInvalidTreeException;
protected abstract void mergeStandardTree(Node root)
throws IIOInvalidTreeException;
}

View File

@@ -0,0 +1,317 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
// TODO - document elimination of globalColorTableFlag
public class GIFStreamMetadata extends GIFMetadata {
// package scope
static final String
nativeMetadataFormatName = "javax_imageio_gif_stream_1.0";
static final String[] versionStrings = { "87a", "89a" };
public String version; // 87a or 89a
public int logicalScreenWidth;
public int logicalScreenHeight;
public int colorResolution; // 1 to 8
public int pixelAspectRatio;
public int backgroundColorIndex; // Valid if globalColorTable != null
public boolean sortFlag; // Valid if globalColorTable != null
static final String[] colorTableSizes = {
"2", "4", "8", "16", "32", "64", "128", "256"
};
// Set global color table flag in header to 0 if null, 1 otherwise
public byte[] globalColorTable = null;
protected GIFStreamMetadata(boolean standardMetadataFormatSupported,
String nativeMetadataFormatName,
String nativeMetadataFormatClassName,
String[] extraMetadataFormatNames,
String[] extraMetadataFormatClassNames)
{
super(standardMetadataFormatSupported,
nativeMetadataFormatName,
nativeMetadataFormatClassName,
extraMetadataFormatNames,
extraMetadataFormatClassNames);
}
public GIFStreamMetadata() {
this(true,
nativeMetadataFormatName,
"com.sun.imageio.plugins.gif.GIFStreamMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
private Node getNativeTree() {
IIOMetadataNode node; // scratch node
IIOMetadataNode root =
new IIOMetadataNode(nativeMetadataFormatName);
node = new IIOMetadataNode("Version");
node.setAttribute("value", version);
root.appendChild(node);
// Image descriptor
node = new IIOMetadataNode("LogicalScreenDescriptor");
/* NB: At the moment we use empty strings to support undefined
* integer values in tree representation.
* We need to add better support for undefined/default values later.
*/
node.setAttribute("logicalScreenWidth",
logicalScreenWidth == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(logicalScreenWidth));
node.setAttribute("logicalScreenHeight",
logicalScreenHeight == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(logicalScreenHeight));
// Stored value plus one
node.setAttribute("colorResolution",
colorResolution == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(colorResolution));
node.setAttribute("pixelAspectRatio",
Integer.toString(pixelAspectRatio));
root.appendChild(node);
if (globalColorTable != null) {
node = new IIOMetadataNode("GlobalColorTable");
int numEntries = globalColorTable.length/3;
node.setAttribute("sizeOfGlobalColorTable",
Integer.toString(numEntries));
node.setAttribute("backgroundColorIndex",
Integer.toString(backgroundColorIndex));
node.setAttribute("sortFlag",
sortFlag ? "TRUE" : "FALSE");
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("ColorTableEntry");
entry.setAttribute("index", Integer.toString(i));
int r = globalColorTable[3*i] & 0xff;
int g = globalColorTable[3*i + 1] & 0xff;
int b = globalColorTable[3*i + 2] & 0xff;
entry.setAttribute("red", Integer.toString(r));
entry.setAttribute("green", Integer.toString(g));
entry.setAttribute("blue", Integer.toString(b));
node.appendChild(entry);
}
root.appendChild(node);
}
return root;
}
public IIOMetadataNode getStandardChromaNode() {
IIOMetadataNode chroma_node = new IIOMetadataNode("Chroma");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("ColorSpaceType");
node.setAttribute("name", "RGB");
chroma_node.appendChild(node);
node = new IIOMetadataNode("BlackIsZero");
node.setAttribute("value", "TRUE");
chroma_node.appendChild(node);
// NumChannels not in stream
// Gamma not in format
if (globalColorTable != null) {
node = new IIOMetadataNode("Palette");
int numEntries = globalColorTable.length/3;
for (int i = 0; i < numEntries; i++) {
IIOMetadataNode entry =
new IIOMetadataNode("PaletteEntry");
entry.setAttribute("index", Integer.toString(i));
entry.setAttribute("red",
Integer.toString(globalColorTable[3*i] & 0xff));
entry.setAttribute("green",
Integer.toString(globalColorTable[3*i + 1] & 0xff));
entry.setAttribute("blue",
Integer.toString(globalColorTable[3*i + 2] & 0xff));
node.appendChild(entry);
}
chroma_node.appendChild(node);
// backgroundColorIndex is valid iff there is a color table
node = new IIOMetadataNode("BackgroundIndex");
node.setAttribute("value", Integer.toString(backgroundColorIndex));
chroma_node.appendChild(node);
}
return chroma_node;
}
public IIOMetadataNode getStandardCompressionNode() {
IIOMetadataNode compression_node = new IIOMetadataNode("Compression");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("CompressionTypeName");
node.setAttribute("value", "lzw");
compression_node.appendChild(node);
node = new IIOMetadataNode("Lossless");
node.setAttribute("value", "TRUE");
compression_node.appendChild(node);
// NumProgressiveScans not in stream
// BitRate not in format
return compression_node;
}
public IIOMetadataNode getStandardDataNode() {
IIOMetadataNode data_node = new IIOMetadataNode("Data");
IIOMetadataNode node = null; // scratch node
// PlanarConfiguration
node = new IIOMetadataNode("SampleFormat");
node.setAttribute("value", "Index");
data_node.appendChild(node);
node = new IIOMetadataNode("BitsPerSample");
node.setAttribute("value",
colorResolution == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(colorResolution));
data_node.appendChild(node);
// SignificantBitsPerSample
// SampleMSB
return data_node;
}
public IIOMetadataNode getStandardDimensionNode() {
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("PixelAspectRatio");
float aspectRatio = 1.0F;
if (pixelAspectRatio != 0) {
aspectRatio = (pixelAspectRatio + 15)/64.0F;
}
node.setAttribute("value", Float.toString(aspectRatio));
dimension_node.appendChild(node);
node = new IIOMetadataNode("ImageOrientation");
node.setAttribute("value", "Normal");
dimension_node.appendChild(node);
// HorizontalPixelSize not in format
// VerticalPixelSize not in format
// HorizontalPhysicalPixelSpacing not in format
// VerticalPhysicalPixelSpacing not in format
// HorizontalPosition not in format
// VerticalPosition not in format
// HorizontalPixelOffset not in stream
// VerticalPixelOffset not in stream
node = new IIOMetadataNode("HorizontalScreenSize");
node.setAttribute("value",
logicalScreenWidth == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(logicalScreenWidth));
dimension_node.appendChild(node);
node = new IIOMetadataNode("VerticalScreenSize");
node.setAttribute("value",
logicalScreenHeight == UNDEFINED_INTEGER_VALUE ?
"" : Integer.toString(logicalScreenHeight));
dimension_node.appendChild(node);
return dimension_node;
}
public IIOMetadataNode getStandardDocumentNode() {
IIOMetadataNode document_node = new IIOMetadataNode("Document");
IIOMetadataNode node = null; // scratch node
node = new IIOMetadataNode("FormatVersion");
node.setAttribute("value", version);
document_node.appendChild(node);
// SubimageInterpretation not in format
// ImageCreationTime not in format
// ImageModificationTime not in format
return document_node;
}
public IIOMetadataNode getStandardTextNode() {
// Not in stream
return null;
}
public IIOMetadataNode getStandardTransparencyNode() {
// Not in stream
return null;
}
public void setFromTree(String formatName, Node root)
throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeNativeTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
protected void mergeStandardTree(Node root) throws IIOInvalidTreeException
{
throw new IllegalStateException("Metadata is read-only!");
}
public void reset() {
throw new IllegalStateException("Metadata is read-only!");
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.util.Arrays;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class GIFStreamMetadataFormat extends IIOMetadataFormatImpl {
private static IIOMetadataFormat instance = null;
private GIFStreamMetadataFormat() {
super(GIFStreamMetadata.nativeMetadataFormatName,
CHILD_POLICY_SOME);
// root -> Version
addElement("Version", GIFStreamMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("Version", "value",
DATATYPE_STRING, true, null,
Arrays.asList(GIFStreamMetadata.versionStrings));
// root -> LogicalScreenDescriptor
addElement("LogicalScreenDescriptor",
GIFStreamMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("LogicalScreenDescriptor", "logicalScreenWidth",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("LogicalScreenDescriptor", "logicalScreenHeight",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
addAttribute("LogicalScreenDescriptor", "colorResolution",
DATATYPE_INTEGER, true, null,
"1", "8", true, true);
addAttribute("LogicalScreenDescriptor", "pixelAspectRatio",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
// root -> GlobalColorTable
addElement("GlobalColorTable",
GIFStreamMetadata.nativeMetadataFormatName,
2, 256);
addAttribute("GlobalColorTable", "sizeOfGlobalColorTable",
DATATYPE_INTEGER, true, null,
Arrays.asList(GIFStreamMetadata.colorTableSizes));
addAttribute("GlobalColorTable", "backgroundColorIndex",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addBooleanAttribute("GlobalColorTable", "sortFlag",
false, false);
// root -> GlobalColorTable -> ColorTableEntry
addElement("ColorTableEntry", "GlobalColorTable",
CHILD_POLICY_EMPTY);
addAttribute("ColorTableEntry", "index",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "red",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "green",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
addAttribute("ColorTableEntry", "blue",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
public static synchronized IIOMetadataFormat getInstance() {
if (instance == null) {
instance = new GIFStreamMetadataFormat();
}
return instance;
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.util.ListResourceBundle;
public class GIFStreamMetadataFormatResources extends ListResourceBundle {
public GIFStreamMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description
{ "Version", "The file version, either 87a or 89a" },
{ "LogicalScreenDescriptor",
"The logical screen descriptor, except for the global color table" },
{ "GlobalColorTable", "The global color table" },
{ "ColorTableEntry", "A global color table entry" },
// Node name + "/" + AttributeName, followed by description
{ "Version/value",
"The version string" },
{ "LogicalScreenDescriptor/logicalScreenWidth",
"The width in pixels of the whole picture" },
{ "LogicalScreenDescriptor/logicalScreenHeight",
"The height in pixels of the whole picture" },
{ "LogicalScreenDescriptor/colorResolution",
"The number of bits of color resolution, beteen 1 and 8" },
{ "LogicalScreenDescriptor/pixelAspectRatio",
"If 0, indicates square pixels, else W/H = (value + 15)/64" },
{ "GlobalColorTable/sizeOfGlobalColorTable",
"The number of entries in the global color table" },
{ "GlobalColorTable/backgroundColorIndex",
"The index of the color table entry to be used as a background" },
{ "GlobalColorTable/sortFlag",
"True if the global color table is sorted by frequency" },
{ "ColorTableEntry/index", "The index of the color table entry" },
{ "ColorTableEntry/red",
"The red value for the color table entry" },
{ "ColorTableEntry/green",
"The green value for the color table entry" },
{ "ColorTableEntry/blue",
"The blue value for the color table entry" },
};
}
}

View File

@@ -0,0 +1,402 @@
/*
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
class GIFWritableImageMetadata extends GIFImageMetadata {
// package scope
static final String
NATIVE_FORMAT_NAME = "javax_imageio_gif_image_1.0";
GIFWritableImageMetadata() {
super(true,
NATIVE_FORMAT_NAME,
"com.sun.imageio.plugins.gif.GIFImageMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return false;
}
public void reset() {
// Fields from Image Descriptor
imageLeftPosition = 0;
imageTopPosition = 0;
imageWidth = 0;
imageHeight = 0;
interlaceFlag = false;
sortFlag = false;
localColorTable = null;
// Fields from Graphic Control Extension
disposalMethod = 0;
userInputFlag = false;
transparentColorFlag = false;
delayTime = 0;
transparentColorIndex = 0;
// Fields from Plain Text Extension
hasPlainTextExtension = false;
textGridLeft = 0;
textGridTop = 0;
textGridWidth = 0;
textGridHeight = 0;
characterCellWidth = 0;
characterCellHeight = 0;
textForegroundColor = 0;
textBackgroundColor = 0;
text = null;
// Fields from ApplicationExtension
applicationIDs = null;
authenticationCodes = null;
applicationData = null;
// Fields from CommentExtension
// List of byte[]
comments = null;
}
private byte[] fromISO8859(String data) {
try {
return data.getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
return "".getBytes();
}
}
protected void mergeNativeTree(Node root) throws IIOInvalidTreeException {
Node node = root;
if (!node.getNodeName().equals(nativeMetadataFormatName)) {
fatal(node, "Root must be " + nativeMetadataFormatName);
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("ImageDescriptor")) {
imageLeftPosition = getIntAttribute(node,
"imageLeftPosition",
-1, true,
true, 0, 65535);
imageTopPosition = getIntAttribute(node,
"imageTopPosition",
-1, true,
true, 0, 65535);
imageWidth = getIntAttribute(node,
"imageWidth",
-1, true,
true, 1, 65535);
imageHeight = getIntAttribute(node,
"imageHeight",
-1, true,
true, 1, 65535);
interlaceFlag = getBooleanAttribute(node, "interlaceFlag",
false, true);
} else if (name.equals("LocalColorTable")) {
int sizeOfLocalColorTable =
getIntAttribute(node, "sizeOfLocalColorTable",
true, 2, 256);
if (sizeOfLocalColorTable != 2 &&
sizeOfLocalColorTable != 4 &&
sizeOfLocalColorTable != 8 &&
sizeOfLocalColorTable != 16 &&
sizeOfLocalColorTable != 32 &&
sizeOfLocalColorTable != 64 &&
sizeOfLocalColorTable != 128 &&
sizeOfLocalColorTable != 256) {
fatal(node,
"Bad value for LocalColorTable attribute sizeOfLocalColorTable!");
}
sortFlag = getBooleanAttribute(node, "sortFlag", false, true);
localColorTable = getColorTable(node, "ColorTableEntry",
true, sizeOfLocalColorTable);
} else if (name.equals("GraphicControlExtension")) {
String disposalMethodName =
getStringAttribute(node, "disposalMethod", null,
true, disposalMethodNames);
disposalMethod = 0;
while(!disposalMethodName.equals(disposalMethodNames[disposalMethod])) {
disposalMethod++;
}
userInputFlag = getBooleanAttribute(node, "userInputFlag",
false, true);
transparentColorFlag =
getBooleanAttribute(node, "transparentColorFlag",
false, true);
delayTime = getIntAttribute(node,
"delayTime",
-1, true,
true, 0, 65535);
transparentColorIndex =
getIntAttribute(node, "transparentColorIndex",
-1, true,
true, 0, 65535);
} else if (name.equals("PlainTextExtension")) {
hasPlainTextExtension = true;
textGridLeft = getIntAttribute(node,
"textGridLeft",
-1, true,
true, 0, 65535);
textGridTop = getIntAttribute(node,
"textGridTop",
-1, true,
true, 0, 65535);
textGridWidth = getIntAttribute(node,
"textGridWidth",
-1, true,
true, 1, 65535);
textGridHeight = getIntAttribute(node,
"textGridHeight",
-1, true,
true, 1, 65535);
characterCellWidth = getIntAttribute(node,
"characterCellWidth",
-1, true,
true, 1, 65535);
characterCellHeight = getIntAttribute(node,
"characterCellHeight",
-1, true,
true, 1, 65535);
textForegroundColor = getIntAttribute(node,
"textForegroundColor",
-1, true,
true, 0, 255);
textBackgroundColor = getIntAttribute(node,
"textBackgroundColor",
-1, true,
true, 0, 255);
// XXX The "text" attribute of the PlainTextExtension element
// is not defined in the GIF image metadata format but it is
// present in the GIFImageMetadata class. Consequently it is
// used here but not required and with a default of "". See
// bug 5082763.
String textString =
getStringAttribute(node, "text", "", false, null);
text = fromISO8859(textString);
} else if (name.equals("ApplicationExtensions")) {
IIOMetadataNode applicationExtension =
(IIOMetadataNode)node.getFirstChild();
if (!applicationExtension.getNodeName().equals("ApplicationExtension")) {
fatal(node,
"Only a ApplicationExtension may be a child of a ApplicationExtensions!");
}
String applicationIDString =
getStringAttribute(applicationExtension, "applicationID",
null, true, null);
String authenticationCodeString =
getStringAttribute(applicationExtension, "authenticationCode",
null, true, null);
Object applicationExtensionData =
applicationExtension.getUserObject();
if (applicationExtensionData == null ||
!(applicationExtensionData instanceof byte[])) {
fatal(applicationExtension,
"Bad user object in ApplicationExtension!");
}
if (applicationIDs == null) {
applicationIDs = new ArrayList();
authenticationCodes = new ArrayList();
applicationData = new ArrayList();
}
applicationIDs.add(fromISO8859(applicationIDString));
authenticationCodes.add(fromISO8859(authenticationCodeString));
applicationData.add(applicationExtensionData);
} else if (name.equals("CommentExtensions")) {
Node commentExtension = node.getFirstChild();
if (commentExtension != null) {
while(commentExtension != null) {
if (!commentExtension.getNodeName().equals("CommentExtension")) {
fatal(node,
"Only a CommentExtension may be a child of a CommentExtensions!");
}
if (comments == null) {
comments = new ArrayList();
}
String comment =
getStringAttribute(commentExtension, "value", null,
true, null);
comments.add(fromISO8859(comment));
commentExtension = commentExtension.getNextSibling();
}
}
} else {
fatal(node, "Unknown child of root node!");
}
node = node.getNextSibling();
}
}
protected void mergeStandardTree(Node root)
throws IIOInvalidTreeException {
Node node = root;
if (!node.getNodeName()
.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
fatal(node, "Root must be " +
IIOMetadataFormatImpl.standardMetadataFormatName);
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("Chroma")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("Palette")) {
localColorTable = getColorTable(childNode,
"PaletteEntry",
false, -1);
break;
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Compression")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("NumProgressiveScans")) {
int numProgressiveScans =
getIntAttribute(childNode, "value", 4, false,
true, 1, Integer.MAX_VALUE);
if (numProgressiveScans > 1) {
interlaceFlag = true;
}
break;
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Dimension")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("HorizontalPixelOffset")) {
imageLeftPosition = getIntAttribute(childNode,
"value",
-1, true,
true, 0, 65535);
} else if (childName.equals("VerticalPixelOffset")) {
imageTopPosition = getIntAttribute(childNode,
"value",
-1, true,
true, 0, 65535);
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Text")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("TextEntry") &&
getAttribute(childNode, "compression",
"none", false).equals("none") &&
Charset.isSupported(getAttribute(childNode,
"encoding",
"ISO-8859-1",
false))) {
String value = getAttribute(childNode, "value");
byte[] comment = fromISO8859(value);
if (comments == null) {
comments = new ArrayList();
}
comments.add(comment);
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Transparency")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("TransparentIndex")) {
transparentColorIndex = getIntAttribute(childNode,
"value",
-1, true,
true, 0, 255);
transparentColorFlag = true;
break;
}
childNode = childNode.getNextSibling();
}
}
node = node.getNextSibling();
}
}
public void setFromTree(String formatName, Node root)
throws IIOInvalidTreeException
{
reset();
mergeTree(formatName, root);
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.gif;
/*
* The source for this class was copied verbatim from the source for
* package com.sun.imageio.plugins.gif.GIFImageMetadata and then modified
* to make the class read-write capable.
*/
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
class GIFWritableStreamMetadata extends GIFStreamMetadata {
// package scope
static final String
NATIVE_FORMAT_NAME = "javax_imageio_gif_stream_1.0";
public GIFWritableStreamMetadata() {
super(true,
NATIVE_FORMAT_NAME,
"com.sun.imageio.plugins.gif.GIFStreamMetadataFormat", // XXX J2SE
null, null);
// initialize metadata fields by default values
reset();
}
public boolean isReadOnly() {
return false;
}
public void mergeTree(String formatName, Node root)
throws IIOInvalidTreeException {
if (formatName.equals(nativeMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeNativeTree(root);
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
if (root == null) {
throw new IllegalArgumentException("root == null!");
}
mergeStandardTree(root);
} else {
throw new IllegalArgumentException("Not a recognized format!");
}
}
public void reset() {
version = null;
logicalScreenWidth = UNDEFINED_INTEGER_VALUE;
logicalScreenHeight = UNDEFINED_INTEGER_VALUE;
colorResolution = UNDEFINED_INTEGER_VALUE;
pixelAspectRatio = 0;
backgroundColorIndex = 0;
sortFlag = false;
globalColorTable = null;
}
protected void mergeNativeTree(Node root) throws IIOInvalidTreeException {
Node node = root;
if (!node.getNodeName().equals(nativeMetadataFormatName)) {
fatal(node, "Root must be " + nativeMetadataFormatName);
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("Version")) {
version = getStringAttribute(node, "value", null,
true, versionStrings);
} else if (name.equals("LogicalScreenDescriptor")) {
/* NB: At the moment we use empty strings to support undefined
* integer values in tree representation.
* We need to add better support for undefined/default values
* later.
*/
logicalScreenWidth = getIntAttribute(node,
"logicalScreenWidth",
UNDEFINED_INTEGER_VALUE,
true,
true, 1, 65535);
logicalScreenHeight = getIntAttribute(node,
"logicalScreenHeight",
UNDEFINED_INTEGER_VALUE,
true,
true, 1, 65535);
colorResolution = getIntAttribute(node,
"colorResolution",
UNDEFINED_INTEGER_VALUE,
true,
true, 1, 8);
pixelAspectRatio = getIntAttribute(node,
"pixelAspectRatio",
0, true,
true, 0, 255);
} else if (name.equals("GlobalColorTable")) {
int sizeOfGlobalColorTable =
getIntAttribute(node, "sizeOfGlobalColorTable",
true, 2, 256);
if (sizeOfGlobalColorTable != 2 &&
sizeOfGlobalColorTable != 4 &&
sizeOfGlobalColorTable != 8 &&
sizeOfGlobalColorTable != 16 &&
sizeOfGlobalColorTable != 32 &&
sizeOfGlobalColorTable != 64 &&
sizeOfGlobalColorTable != 128 &&
sizeOfGlobalColorTable != 256) {
fatal(node,
"Bad value for GlobalColorTable attribute sizeOfGlobalColorTable!");
}
backgroundColorIndex = getIntAttribute(node,
"backgroundColorIndex",
0, true,
true, 0, 255);
sortFlag = getBooleanAttribute(node, "sortFlag", false, true);
globalColorTable = getColorTable(node, "ColorTableEntry",
true, sizeOfGlobalColorTable);
} else {
fatal(node, "Unknown child of root node!");
}
node = node.getNextSibling();
}
}
protected void mergeStandardTree(Node root)
throws IIOInvalidTreeException {
Node node = root;
if (!node.getNodeName()
.equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
fatal(node, "Root must be " +
IIOMetadataFormatImpl.standardMetadataFormatName);
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("Chroma")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("Palette")) {
globalColorTable = getColorTable(childNode,
"PaletteEntry",
false, -1);
} else if (childName.equals("BackgroundIndex")) {
backgroundColorIndex = getIntAttribute(childNode,
"value",
-1, true,
true, 0, 255);
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Data")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("BitsPerSample")) {
colorResolution = getIntAttribute(childNode,
"value",
-1, true,
true, 1, 8);
break;
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Dimension")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("PixelAspectRatio")) {
float aspectRatio = getFloatAttribute(childNode,
"value");
if (aspectRatio == 1.0F) {
pixelAspectRatio = 0;
} else {
int ratio = (int)(aspectRatio*64.0F - 15.0F);
pixelAspectRatio =
Math.max(Math.min(ratio, 255), 0);
}
} else if (childName.equals("HorizontalScreenSize")) {
logicalScreenWidth = getIntAttribute(childNode,
"value",
-1, true,
true, 1, 65535);
} else if (childName.equals("VerticalScreenSize")) {
logicalScreenHeight = getIntAttribute(childNode,
"value",
-1, true,
true, 1, 65535);
}
childNode = childNode.getNextSibling();
}
} else if (name.equals("Document")) {
Node childNode = node.getFirstChild();
while(childNode != null) {
String childName = childNode.getNodeName();
if (childName.equals("FormatVersion")) {
String formatVersion =
getStringAttribute(childNode, "value", null,
true, null);
for (int i = 0; i < versionStrings.length; i++) {
if (formatVersion.equals(versionStrings[i])) {
version = formatVersion;
break;
}
}
break;
}
childNode = childNode.getNextSibling();
}
}
node = node.getNextSibling();
}
}
public void setFromTree(String formatName, Node root)
throws IIOInvalidTreeException
{
reset();
mergeTree(formatName, root);
}
}

View File

@@ -0,0 +1,136 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.IIOException;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.io.IOException;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
/**
* An Adobe APP14 (Application-Specific) marker segment.
*/
class AdobeMarkerSegment extends MarkerSegment {
int version;
int flags0;
int flags1;
int transform;
private static final int ID_SIZE = 5;
AdobeMarkerSegment(int transform) {
super(JPEG.APP14);
version = 101;
flags0 = 0;
flags1 = 0;
this.transform = transform;
}
AdobeMarkerSegment(JPEGBuffer buffer) throws IOException {
super(buffer);
buffer.bufPtr += ID_SIZE; // Skip the id
version = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
version |= buffer.buf[buffer.bufPtr++] & 0xff;
flags0 = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
flags0 |= buffer.buf[buffer.bufPtr++] & 0xff;
flags1 = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
flags1 |= buffer.buf[buffer.bufPtr++] & 0xff;
transform = buffer.buf[buffer.bufPtr++] & 0xff;
buffer.bufAvail -= length;
}
AdobeMarkerSegment(Node node) throws IIOInvalidTreeException {
this(0); // default transform will be changed
updateFromNativeNode(node, true);
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("app14Adobe");
node.setAttribute("version", Integer.toString(version));
node.setAttribute("flags0", Integer.toString(flags0));
node.setAttribute("flags1", Integer.toString(flags1));
node.setAttribute("transform", Integer.toString(transform));
return node;
}
void updateFromNativeNode(Node node, boolean fromScratch)
throws IIOInvalidTreeException {
// Only the transform is required
NamedNodeMap attrs = node.getAttributes();
transform = getAttributeValue(node, attrs, "transform", 0, 2, true);
int count = attrs.getLength();
if (count > 4) {
throw new IIOInvalidTreeException
("Adobe APP14 node cannot have > 4 attributes", node);
}
if (count > 1) {
int value = getAttributeValue(node, attrs, "version",
100, 255, false);
version = (value != -1) ? value : version;
value = getAttributeValue(node, attrs, "flags0", 0, 65535, false);
flags0 = (value != -1) ? value : flags0;
value = getAttributeValue(node, attrs, "flags1", 0, 65535, false);
flags1 = (value != -1) ? value : flags1;
}
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
length = 14;
writeTag(ios);
byte [] id = {0x41, 0x64, 0x6F, 0x62, 0x65};
ios.write(id);
write2bytes(ios, version);
write2bytes(ios, flags0);
write2bytes(ios, flags1);
ios.write(transform);
}
static void writeAdobeSegment(ImageOutputStream ios, int transform)
throws IOException {
(new AdobeMarkerSegment(transform)).write(ios);
}
void print () {
printTag("Adobe APP14");
System.out.print("Version: ");
System.out.println(version);
System.out.print("Flags0: 0x");
System.out.println(Integer.toHexString(flags0));
System.out.print("Flags1: 0x");
System.out.println(Integer.toHexString(flags1));
System.out.print("Transform: ");
System.out.println(transform);
}
}

View File

@@ -0,0 +1,133 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.metadata.IIOInvalidTreeException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.w3c.dom.Node;
/**
* A Comment marker segment. Retains an array of bytes representing the
* comment data as it is read from the stream. If the marker segment is
* constructed from a String, then local default encoding is assumed
* when creating the byte array. If the marker segment is created from
* an <code>IIOMetadataNode</code>, the user object, if present is
* assumed to be a byte array containing the comment data. If there is
* no user object then the comment attribute is used to create the
* byte array, again assuming the default local encoding.
*/
class COMMarkerSegment extends MarkerSegment {
private static final String ENCODING = "ISO-8859-1";
/**
* Constructs a marker segment from the given buffer, which contains
* data from an <code>ImageInputStream</code>. This is used when
* reading metadata from a stream.
*/
COMMarkerSegment(JPEGBuffer buffer) throws IOException {
super(buffer);
loadData(buffer);
}
/**
* Constructs a marker segment from a String. This is used when
* modifying metadata from a non-native tree and when transcoding.
* The default encoding is used to construct the byte array.
*/
COMMarkerSegment(String comment) {
super(JPEG.COM);
data = comment.getBytes(); // Default encoding
}
/**
* Constructs a marker segment from a native tree node. If the node
* is an <code>IIOMetadataNode</code> and contains a user object,
* that object is used rather than the string attribute. If the
* string attribute is used, the default encoding is used.
*/
COMMarkerSegment(Node node) throws IIOInvalidTreeException{
super(JPEG.COM);
if (node instanceof IIOMetadataNode) {
IIOMetadataNode ourNode = (IIOMetadataNode) node;
data = (byte []) ourNode.getUserObject();
}
if (data == null) {
String comment =
node.getAttributes().getNamedItem("comment").getNodeValue();
if (comment != null) {
data = comment.getBytes(); // Default encoding
} else {
throw new IIOInvalidTreeException("Empty comment node!", node);
}
}
}
/**
* Returns the array encoded as a String, using ISO-Latin-1 encoding.
* If an application needs another encoding, the data array must be
* consulted directly.
*/
String getComment() {
try {
return new String (data, ENCODING);
} catch (UnsupportedEncodingException e) {} // Won't happen
return null;
}
/**
* Returns an <code>IIOMetadataNode</code> containing the data array
* as a user object and a string encoded using ISO-8895-1, as an
* attribute.
*/
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("com");
node.setAttribute("comment", getComment());
if (data != null) {
node.setUserObject(data.clone());
}
return node;
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format, directly from the data array.
*/
void write(ImageOutputStream ios) throws IOException {
length = 2 + data.length;
writeTag(ios);
ios.write(data);
}
void print() {
printTag("COM");
System.out.println("<" + getComment() + ">");
}
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
/**
* A DHT (Define Huffman Table) marker segment.
*/
class DHTMarkerSegment extends MarkerSegment {
List tables = new ArrayList();
DHTMarkerSegment(boolean needFour) {
super(JPEG.DHT);
tables.add(new Htable(JPEGHuffmanTable.StdDCLuminance, true, 0));
if (needFour) {
tables.add(new Htable(JPEGHuffmanTable.StdDCChrominance, true, 1));
}
tables.add(new Htable(JPEGHuffmanTable.StdACLuminance, false, 0));
if (needFour) {
tables.add(new Htable(JPEGHuffmanTable.StdACChrominance, false, 1));
}
}
DHTMarkerSegment(JPEGBuffer buffer) throws IOException {
super(buffer);
int count = length;
while (count > 0) {
Htable newGuy = new Htable(buffer);
tables.add(newGuy);
count -= 1 + 16 + newGuy.values.length;
}
buffer.bufAvail -= length;
}
DHTMarkerSegment(JPEGHuffmanTable[] dcTables,
JPEGHuffmanTable[] acTables) {
super(JPEG.DHT);
for (int i = 0; i < dcTables.length; i++) {
tables.add(new Htable(dcTables[i], true, i));
}
for (int i = 0; i < acTables.length; i++) {
tables.add(new Htable(acTables[i], false, i));
}
}
DHTMarkerSegment(Node node) throws IIOInvalidTreeException {
super(JPEG.DHT);
NodeList children = node.getChildNodes();
int size = children.getLength();
if ((size < 1) || (size > 4)) {
throw new IIOInvalidTreeException("Invalid DHT node", node);
}
for (int i = 0; i < size; i++) {
tables.add(new Htable(children.item(i)));
}
}
protected Object clone() {
DHTMarkerSegment newGuy = (DHTMarkerSegment) super.clone();
newGuy.tables = new ArrayList(tables.size());
Iterator iter = tables.iterator();
while (iter.hasNext()) {
Htable table = (Htable) iter.next();
newGuy.tables.add(table.clone());
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("dht");
for (int i= 0; i<tables.size(); i++) {
Htable table = (Htable) tables.get(i);
node.appendChild(table.getNativeNode());
}
return node;
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
// We don't write DHT segments; the IJG library does.
}
void print() {
printTag("DHT");
System.out.println("Num tables: "
+ Integer.toString(tables.size()));
for (int i= 0; i<tables.size(); i++) {
Htable table = (Htable) tables.get(i);
table.print();
}
System.out.println();
}
Htable getHtableFromNode(Node node) throws IIOInvalidTreeException {
return new Htable(node);
}
void addHtable(JPEGHuffmanTable table, boolean isDC, int id) {
tables.add(new Htable(table, isDC, id));
}
/**
* A Huffman table within a DHT marker segment.
*/
class Htable implements Cloneable {
int tableClass; // 0 == DC, 1 == AC
int tableID; // 0 - 4
private static final int NUM_LENGTHS = 16;
// # of codes of each length
short [] numCodes = new short[NUM_LENGTHS];
short [] values;
Htable(JPEGBuffer buffer) {
tableClass = buffer.buf[buffer.bufPtr] >>> 4;
tableID = buffer.buf[buffer.bufPtr++] & 0xf;
for (int i = 0; i < NUM_LENGTHS; i++) {
numCodes[i] = (short) (buffer.buf[buffer.bufPtr++] & 0xff);
}
int numValues = 0;
for (int i = 0; i < NUM_LENGTHS; i++) {
numValues += numCodes[i];
}
values = new short[numValues];
for (int i = 0; i < numValues; i++) {
values[i] = (short) (buffer.buf[buffer.bufPtr++] & 0xff);
}
}
Htable(JPEGHuffmanTable table, boolean isDC, int id) {
tableClass = isDC ? 0 : 1;
tableID = id;
numCodes = table.getLengths();
values = table.getValues();
}
Htable(Node node) throws IIOInvalidTreeException {
if (node.getNodeName().equals("dhtable")) {
NamedNodeMap attrs = node.getAttributes();
int count = attrs.getLength();
if (count != 2) {
throw new IIOInvalidTreeException
("dhtable node must have 2 attributes", node);
}
tableClass = getAttributeValue(node, attrs, "class", 0, 1, true);
tableID = getAttributeValue(node, attrs, "htableId", 0, 3, true);
if (node instanceof IIOMetadataNode) {
IIOMetadataNode ourNode = (IIOMetadataNode) node;
JPEGHuffmanTable table =
(JPEGHuffmanTable) ourNode.getUserObject();
if (table == null) {
throw new IIOInvalidTreeException
("dhtable node must have user object", node);
}
numCodes = table.getLengths();
values = table.getValues();
} else {
throw new IIOInvalidTreeException
("dhtable node must have user object", node);
}
} else {
throw new IIOInvalidTreeException
("Invalid node, expected dqtable", node);
}
}
protected Object clone() {
Htable newGuy = null;
try {
newGuy = (Htable) super.clone();
} catch (CloneNotSupportedException e) {} // won't happen
if (numCodes != null) {
newGuy.numCodes = (short []) numCodes.clone();
}
if (values != null) {
newGuy.values = (short []) values.clone();
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("dhtable");
node.setAttribute("class", Integer.toString(tableClass));
node.setAttribute("htableId", Integer.toString(tableID));
node.setUserObject(new JPEGHuffmanTable(numCodes, values));
return node;
}
void print() {
System.out.println("Huffman Table");
System.out.println("table class: "
+ ((tableClass == 0) ? "DC":"AC"));
System.out.println("table id: " + Integer.toString(tableID));
(new JPEGHuffmanTable(numCodes, values)).toString();
/*
System.out.print("Lengths:");
for (int i=0; i<16; i++) {
System.out.print(" " + Integer.toString(numCodes[i]));
}
int count = 0;
if (values.length > 16) {
System.out.println("\nFirst 16 Values:");
count = 16;
} else {
System.out.println("\nValues:");
count = values.length;
}
for (int i=0; i<count; i++) {
System.out.println(Integer.toString(values[i]&0xff));
}
*/
}
}
}

View File

@@ -0,0 +1,309 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.IIOException;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.plugins.jpeg.JPEGQTable;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
/**
* A DQT (Define Quantization Table) marker segment.
*/
class DQTMarkerSegment extends MarkerSegment {
List tables = new ArrayList(); // Could be 1 to 4
DQTMarkerSegment(float quality, boolean needTwo) {
super(JPEG.DQT);
tables.add(new Qtable(true, quality));
if (needTwo) {
tables.add(new Qtable(false, quality));
}
}
DQTMarkerSegment(JPEGBuffer buffer) throws IOException {
super(buffer);
int count = length;
while (count > 0) {
Qtable newGuy = new Qtable(buffer);
tables.add(newGuy);
count -= newGuy.data.length+1;
}
buffer.bufAvail -= length;
}
DQTMarkerSegment(JPEGQTable[] qtables) {
super(JPEG.DQT);
for (int i = 0; i < qtables.length; i++) {
tables.add(new Qtable(qtables[i], i));
}
}
DQTMarkerSegment(Node node) throws IIOInvalidTreeException {
super(JPEG.DQT);
NodeList children = node.getChildNodes();
int size = children.getLength();
if ((size < 1) || (size > 4)) {
throw new IIOInvalidTreeException("Invalid DQT node", node);
}
for (int i = 0; i < size; i++) {
tables.add(new Qtable(children.item(i)));
}
}
protected Object clone() {
DQTMarkerSegment newGuy = (DQTMarkerSegment) super.clone();
newGuy.tables = new ArrayList(tables.size());
Iterator iter = tables.iterator();
while (iter.hasNext()) {
Qtable table = (Qtable) iter.next();
newGuy.tables.add(table.clone());
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("dqt");
for (int i= 0; i<tables.size(); i++) {
Qtable table = (Qtable) tables.get(i);
node.appendChild(table.getNativeNode());
}
return node;
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
// We don't write DQT segments; the IJG library does.
}
void print() {
printTag("DQT");
System.out.println("Num tables: "
+ Integer.toString(tables.size()));
for (int i= 0; i<tables.size(); i++) {
Qtable table = (Qtable) tables.get(i);
table.print();
}
System.out.println();
}
/**
* Assuming the given table was generated by scaling the "standard"
* visually lossless luminance table, extract the scale factor that
* was used.
*/
Qtable getChromaForLuma(Qtable luma) {
Qtable newGuy = null;
// Determine if the table is all the same values
// if so, use the same table
boolean allSame = true;
for (int i = 1; i < luma.QTABLE_SIZE; i++) {
if (luma.data[i] != luma.data[i-1]) {
allSame = false;
break;
}
}
if (allSame) {
newGuy = (Qtable) luma.clone();
newGuy.tableID = 1;
} else {
// Otherwise, find the largest coefficient less than 255. This is
// the largest value that we know did not clamp on scaling.
int largestPos = 0;
for (int i = 1; i < luma.QTABLE_SIZE; i++) {
if (luma.data[i] > luma.data[largestPos]) {
largestPos = i;
}
}
// Compute the scale factor by dividing it by the value in the
// same position from the "standard" table.
// If the given table was not generated by scaling the standard,
// the resulting table will still be reasonable, as it will reflect
// a comparable scaling of chrominance frequency response of the
// eye.
float scaleFactor = ((float)(luma.data[largestPos]))
/ ((float)(JPEGQTable.K1Div2Luminance.getTable()[largestPos]));
// generate a new table
JPEGQTable jpegTable =
JPEGQTable.K2Div2Chrominance.getScaledInstance(scaleFactor,
true);
newGuy = new Qtable(jpegTable, 1);
}
return newGuy;
}
Qtable getQtableFromNode(Node node) throws IIOInvalidTreeException {
return new Qtable(node);
}
/**
* A quantization table within a DQT marker segment.
*/
class Qtable implements Cloneable {
int elementPrecision;
int tableID;
final int QTABLE_SIZE = 64;
int [] data; // 64 elements, in natural order
/**
* The zigzag-order position of the i'th element
* of a DCT block read in natural order.
*/
private final int [] zigzag = {
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63
};
Qtable(boolean wantLuma, float quality) {
elementPrecision = 0;
JPEGQTable base = null;
if (wantLuma) {
tableID = 0;
base = JPEGQTable.K1Div2Luminance;
} else {
tableID = 1;
base = JPEGQTable.K2Div2Chrominance;
}
if (quality != JPEG.DEFAULT_QUALITY) {
quality = JPEG.convertToLinearQuality(quality);
if (wantLuma) {
base = JPEGQTable.K1Luminance.getScaledInstance
(quality, true);
} else {
base = JPEGQTable.K2Div2Chrominance.getScaledInstance
(quality, true);
}
}
data = base.getTable();
}
Qtable(JPEGBuffer buffer) throws IIOException {
elementPrecision = buffer.buf[buffer.bufPtr] >>> 4;
tableID = buffer.buf[buffer.bufPtr++] & 0xf;
if (elementPrecision != 0) {
// IJG is compiled for 8-bits, so this shouldn't happen
throw new IIOException ("Unsupported element precision");
}
data = new int [QTABLE_SIZE];
// Read from zig-zag order to natural order
for (int i = 0; i < QTABLE_SIZE; i++) {
data[i] = buffer.buf[buffer.bufPtr+zigzag[i]] & 0xff;
}
buffer.bufPtr += QTABLE_SIZE;
}
Qtable(JPEGQTable table, int id) {
elementPrecision = 0;
tableID = id;
data = table.getTable();
}
Qtable(Node node) throws IIOInvalidTreeException {
if (node.getNodeName().equals("dqtable")) {
NamedNodeMap attrs = node.getAttributes();
int count = attrs.getLength();
if ((count < 1) || (count > 2)) {
throw new IIOInvalidTreeException
("dqtable node must have 1 or 2 attributes", node);
}
elementPrecision = 0;
tableID = getAttributeValue(node, attrs, "qtableId", 0, 3, true);
if (node instanceof IIOMetadataNode) {
IIOMetadataNode ourNode = (IIOMetadataNode) node;
JPEGQTable table = (JPEGQTable) ourNode.getUserObject();
if (table == null) {
throw new IIOInvalidTreeException
("dqtable node must have user object", node);
}
data = table.getTable();
} else {
throw new IIOInvalidTreeException
("dqtable node must have user object", node);
}
} else {
throw new IIOInvalidTreeException
("Invalid node, expected dqtable", node);
}
}
protected Object clone() {
Qtable newGuy = null;
try {
newGuy = (Qtable) super.clone();
} catch (CloneNotSupportedException e) {} // won't happen
if (data != null) {
newGuy.data = (int []) data.clone();
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("dqtable");
node.setAttribute("elementPrecision",
Integer.toString(elementPrecision));
node.setAttribute("qtableId",
Integer.toString(tableID));
node.setUserObject(new JPEGQTable(data));
return node;
}
void print() {
System.out.println("Table id: " + Integer.toString(tableID));
System.out.println("Element precision: "
+ Integer.toString(elementPrecision));
(new JPEGQTable(data)).toString();
/*
for (int i = 0; i < 64; i++) {
if (i % 8 == 0) {
System.out.println();
}
System.out.print(" " + Integer.toString(data[i]));
}
System.out.println();
*/
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.io.IOException;
import org.w3c.dom.Node;
/**
* A DRI (Define Restart Interval) marker segment.
*/
class DRIMarkerSegment extends MarkerSegment {
/**
* Restart interval, or 0 if none is specified.
*/
int restartInterval = 0;
DRIMarkerSegment(JPEGBuffer buffer)
throws IOException {
super(buffer);
restartInterval = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
restartInterval |= buffer.buf[buffer.bufPtr++] & 0xff;
buffer.bufAvail -= length;
}
DRIMarkerSegment(Node node) throws IIOInvalidTreeException {
super(JPEG.DRI);
updateFromNativeNode(node, true);
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("dri");
node.setAttribute("interval", Integer.toString(restartInterval));
return node;
}
void updateFromNativeNode(Node node, boolean fromScratch)
throws IIOInvalidTreeException {
restartInterval = getAttributeValue(node, null, "interval",
0, 65535, true);
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
// We don't write DRI segments; the IJG library does.
}
void print() {
printTag("DRI");
System.out.println("Interval: "
+ Integer.toString(restartInterval));
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,368 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.plugins.jpeg.JPEGQTable;
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
import java.awt.image.ColorModel;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
/**
* A class containing JPEG-related constants, definitions, and
* static methods. This class and its constants must be public so that
* <code>JPEGImageWriteParam</code> can see it.
*/
public class JPEG {
// List of all the JPEG markers (pre-JPEG2000)
/** For temporary use in arithmetic coding */
public static final int TEM = 0x01;
// Codes 0x02 - 0xBF are reserved
// SOF markers for Nondifferential Huffman coding
/** Baseline DCT */
public static final int SOF0 = 0xC0;
/** Extended Sequential DCT */
public static final int SOF1 = 0xC1;
/** Progressive DCT */
public static final int SOF2 = 0xC2;
/** Lossless Sequential */
public static final int SOF3 = 0xC3;
/** Define Huffman Tables */
public static final int DHT = 0xC4;
// SOF markers for Differential Huffman coding
/** Differential Sequential DCT */
public static final int SOF5 = 0xC5;
/** Differential Progressive DCT */
public static final int SOF6 = 0xC6;
/** Differential Lossless */
public static final int SOF7 = 0xC7;
/** Reserved for JPEG extensions */
public static final int JPG = 0xC8;
// SOF markers for Nondifferential arithmetic coding
/** Extended Sequential DCT, Arithmetic coding */
public static final int SOF9 = 0xC9;
/** Progressive DCT, Arithmetic coding */
public static final int SOF10 = 0xCA;
/** Lossless Sequential, Arithmetic coding */
public static final int SOF11 = 0xCB;
/** Define Arithmetic conditioning tables */
public static final int DAC = 0xCC;
// SOF markers for Differential arithmetic coding
/** Differential Sequential DCT, Arithmetic coding */
public static final int SOF13 = 0xCD;
/** Differential Progressive DCT, Arithmetic coding */
public static final int SOF14 = 0xCE;
/** Differential Lossless, Arithmetic coding */
public static final int SOF15 = 0xCF;
// Restart Markers
public static final int RST0 = 0xD0;
public static final int RST1 = 0xD1;
public static final int RST2 = 0xD2;
public static final int RST3 = 0xD3;
public static final int RST4 = 0xD4;
public static final int RST5 = 0xD5;
public static final int RST6 = 0xD6;
public static final int RST7 = 0xD7;
/** Number of restart markers */
public static final int RESTART_RANGE = 8;
/** Start of Image */
public static final int SOI = 0xD8;
/** End of Image */
public static final int EOI = 0xD9;
/** Start of Scan */
public static final int SOS = 0xDA;
/** Define Quantisation Tables */
public static final int DQT = 0xDB;
/** Define Number of lines */
public static final int DNL = 0xDC;
/** Define Restart Interval */
public static final int DRI = 0xDD;
/** Define Heirarchical progression */
public static final int DHP = 0xDE;
/** Expand reference image(s) */
public static final int EXP = 0xDF;
// Application markers
/** APP0 used by JFIF */
public static final int APP0 = 0xE0;
public static final int APP1 = 0xE1;
public static final int APP2 = 0xE2;
public static final int APP3 = 0xE3;
public static final int APP4 = 0xE4;
public static final int APP5 = 0xE5;
public static final int APP6 = 0xE6;
public static final int APP7 = 0xE7;
public static final int APP8 = 0xE8;
public static final int APP9 = 0xE9;
public static final int APP10 = 0xEA;
public static final int APP11 = 0xEB;
public static final int APP12 = 0xEC;
public static final int APP13 = 0xED;
/** APP14 used by Adobe */
public static final int APP14 = 0xEE;
public static final int APP15 = 0xEF;
// codes 0xF0 to 0xFD are reserved
/** Comment marker */
public static final int COM = 0xFE;
// JFIF Resolution units
/** The X and Y units simply indicate the aspect ratio of the pixels. */
public static final int DENSITY_UNIT_ASPECT_RATIO = 0;
/** Pixel density is in pixels per inch. */
public static final int DENSITY_UNIT_DOTS_INCH = 1;
/** Pixel density is in pixels per centemeter. */
public static final int DENSITY_UNIT_DOTS_CM = 2;
/** The max known value for DENSITY_UNIT */
public static final int NUM_DENSITY_UNIT = 3;
// Adobe transform values
public static final int ADOBE_IMPOSSIBLE = -1;
public static final int ADOBE_UNKNOWN = 0;
public static final int ADOBE_YCC = 1;
public static final int ADOBE_YCCK = 2;
// Spi initialization stuff
public static final String vendor = "Oracle Corporation";
public static final String version = "0.5";
// Names of the formats we can read or write
static final String [] names = {"JPEG", "jpeg", "JPG", "jpg"};
static final String [] suffixes = {"jpg", "jpeg"};
static final String [] MIMETypes = {"image/jpeg"};
public static final String nativeImageMetadataFormatName =
"javax_imageio_jpeg_image_1.0";
public static final String nativeImageMetadataFormatClassName =
"com.sun.imageio.plugins.jpeg.JPEGImageMetadataFormat";
public static final String nativeStreamMetadataFormatName =
"javax_imageio_jpeg_stream_1.0";
public static final String nativeStreamMetadataFormatClassName =
"com.sun.imageio.plugins.jpeg.JPEGStreamMetadataFormat";
// IJG Color codes.
public static final int JCS_UNKNOWN = 0; // error/unspecified
public static final int JCS_GRAYSCALE = 1; // monochrome
public static final int JCS_RGB = 2; // red/green/blue
public static final int JCS_YCbCr = 3; // Y/Cb/Cr (also known as YUV)
public static final int JCS_CMYK = 4; // C/M/Y/K
public static final int JCS_YCC = 5; // PhotoYCC
public static final int JCS_RGBA = 6; // RGB-Alpha
public static final int JCS_YCbCrA = 7; // Y/Cb/Cr/Alpha
// 8 and 9 were old "Legacy" codes which the old code never identified
// on reading anyway. Support for writing them is being dropped, too.
public static final int JCS_YCCA = 10; // PhotoYCC-Alpha
public static final int JCS_YCCK = 11; // Y/Cb/Cr/K
public static final int NUM_JCS_CODES = JCS_YCCK+1;
/** IJG can handle up to 4-channel JPEGs */
static final int [] [] bandOffsets = {{0},
{0, 1},
{0, 1, 2},
{0, 1, 2, 3}};
static final int [] bOffsRGB = { 2, 1, 0 };
/* These are kept in the inner class to avoid static initialization
* of the CMM class until someone actually needs it.
* (e.g. do not init CMM on the request for jpeg mime types)
*/
public static class JCS {
public static final ColorSpace sRGB =
ColorSpace.getInstance(ColorSpace.CS_sRGB);
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;
}
}
// Default value for ImageWriteParam
public static final float DEFAULT_QUALITY = 0.75F;
/**
* Returns <code>true</code> if the given <code>ColorSpace</code>
* object is an instance of ICC_ColorSpace but is not one of the
* standard <code>ColorSpaces</code> returned by
* <code>ColorSpace.getInstance()</code>.
*/
static boolean isNonStandardICC(ColorSpace cs) {
boolean retval = false;
if ((cs instanceof ICC_ColorSpace)
&& (!cs.isCS_sRGB())
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_GRAY)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_PYCC)))
) {
retval = true;
}
return retval;
}
/**
* Returns <code>true</code> if the given imageType can be used
* in a JFIF file. If <code>input</code> is true, then the
* image type is considered before colorspace conversion.
*/
static boolean isJFIFcompliant(ImageTypeSpecifier imageType,
boolean input) {
ColorModel cm = imageType.getColorModel();
// Can't have alpha
if (cm.hasAlpha()) {
return false;
}
// Gray is OK, always
int numComponents = imageType.getNumComponents();
if (numComponents == 1) {
return true;
}
// If it isn't gray, it must have 3 channels
if (numComponents != 3) {
return false;
}
if (input) {
// Must be RGB
if (cm.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
return true;
}
} else {
// Must be YCbCr
if (cm.getColorSpace().getType() == ColorSpace.TYPE_YCbCr) {
return true;
}
}
return false;
}
/**
* Given an image type, return the Adobe transform corresponding to
* that type, or ADOBE_IMPOSSIBLE if the image type is incompatible
* with an Adobe marker segment. If <code>input</code> is true, then
* the image type is considered before colorspace conversion.
*/
static int transformForType(ImageTypeSpecifier imageType, boolean input) {
int retval = ADOBE_IMPOSSIBLE;
ColorModel cm = imageType.getColorModel();
switch (cm.getColorSpace().getType()) {
case ColorSpace.TYPE_GRAY:
retval = ADOBE_UNKNOWN;
break;
case ColorSpace.TYPE_RGB:
retval = input ? ADOBE_YCC : ADOBE_UNKNOWN;
break;
case ColorSpace.TYPE_YCbCr:
retval = ADOBE_YCC;
break;
case ColorSpace.TYPE_CMYK:
retval = input ? ADOBE_YCCK : ADOBE_IMPOSSIBLE;
}
return retval;
}
/**
* Converts an ImageWriteParam (i.e. IJG) non-linear quality value
* to a float suitable for passing to JPEGQTable.getScaledInstance().
*/
static float convertToLinearQuality(float quality) {
// The following is converted from the IJG code.
if (quality <= 0.0F) {
quality = 0.01F;
}
if (quality > 1.00F) {
quality = 1.00F;
}
if (quality < 0.5F) {
quality = 0.5F / quality;
} else {
quality = 2.0F - (quality * 2.0F);
}
return quality;
}
/**
* Return an array of default, visually lossless quantization tables.
*/
static JPEGQTable [] getDefaultQTables() {
JPEGQTable [] qTables = new JPEGQTable[2];
qTables[0] = JPEGQTable.K1Div2Luminance;
qTables[1] = JPEGQTable.K2Div2Chrominance;
return qTables;
}
/**
* Return an array of default Huffman tables.
*/
static JPEGHuffmanTable [] getDefaultHuffmanTables(boolean wantDC) {
JPEGHuffmanTable [] tables = new JPEGHuffmanTable[2];
if (wantDC) {
tables[0] = JPEGHuffmanTable.StdDCLuminance;
tables[1] = JPEGHuffmanTable.StdDCChrominance;
} else {
tables[0] = JPEGHuffmanTable.StdACLuminance;
tables[1] = JPEGHuffmanTable.StdACChrominance;
}
return tables;
}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.IIOException;
import java.io.IOException;
/**
* A class wrapping a buffer and its state. For efficiency,
* the members are made visible to other classes in this package.
*/
class JPEGBuffer {
private boolean debug = false;
/**
* The size of the buffer. This is large enough to hold all
* known marker segments (other than thumbnails and icc profiles)
*/
final int BUFFER_SIZE = 4096;
/**
* The actual buffer.
*/
byte [] buf;
/**
* The number of bytes available for reading from the buffer.
* Anytime data is read from the buffer, this should be updated.
*/
int bufAvail;
/**
* A pointer to the next available byte in the buffer. This is
* used to read data from the buffer and must be updated to
* move through the buffer.
*/
int bufPtr;
/**
* The ImageInputStream buffered.
*/
ImageInputStream iis;
JPEGBuffer (ImageInputStream iis) {
buf = new byte[BUFFER_SIZE];
bufAvail = 0;
bufPtr = 0;
this.iis = iis;
}
/**
* Ensures that there are at least <code>count</code> bytes available
* in the buffer, loading more data and moving any remaining
* bytes to the front. A count of 0 means to just fill the buffer.
* If the count is larger than the buffer size, just fills the buffer.
* If the end of the stream is encountered before a non-0 count can
* be satisfied, an <code>IIOException</code> is thrown with the
* message "Image Format Error".
*/
void loadBuf(int count) throws IOException {
if (debug) {
System.out.print("loadbuf called with ");
System.out.print("count " + count + ", ");
System.out.println("bufAvail " + bufAvail + ", ");
}
if (count != 0) {
if (bufAvail >= count) { // have enough
return;
}
} else {
if (bufAvail == BUFFER_SIZE) { // already full
return;
}
}
// First copy any remaining bytes down to the beginning
if ((bufAvail > 0) && (bufAvail < BUFFER_SIZE)) {
System.arraycopy(buf, bufPtr, buf, 0, bufAvail);
}
// Now fill the rest of the buffer
int ret = iis.read(buf, bufAvail, buf.length - bufAvail);
if (debug) {
System.out.println("iis.read returned " + ret);
}
if (ret != -1) {
bufAvail += ret;
}
bufPtr = 0;
int minimum = Math.min(BUFFER_SIZE, count);
if (bufAvail < minimum) {
throw new IIOException ("Image Format Error");
}
}
/**
* Fills the data array from the stream, starting with
* the buffer and then reading directly from the stream
* if necessary. The buffer is left in an appropriate
* state. If the end of the stream is encountered, an
* <code>IIOException</code> is thrown with the
* message "Image Format Error".
*/
void readData(byte [] data) throws IOException {
int count = data.length;
// First see what's left in the buffer.
if (bufAvail >= count) { // It's enough
System.arraycopy(buf, bufPtr, data, 0, count);
bufAvail -= count;
bufPtr += count;
return;
}
int offset = 0;
if (bufAvail > 0) { // Some there, but not enough
System.arraycopy(buf, bufPtr, data, 0, bufAvail);
offset = bufAvail;
count -= bufAvail;
bufAvail = 0;
bufPtr = 0;
}
// Now read the rest directly from the stream
if (iis.read(data, offset, count) != count) {
throw new IIOException ("Image format Error");
}
}
/**
* Skips <code>count</code> bytes, leaving the buffer
* in an appropriate state. If the end of the stream is
* encountered, an <code>IIOException</code> is thrown with the
* message "Image Format Error".
*/
void skipData(int count) throws IOException {
// First see what's left in the buffer.
if (bufAvail >= count) { // It's enough
bufAvail -= count;
bufPtr += count;
return;
}
if (bufAvail > 0) { // Some there, but not enough
count -= bufAvail;
bufAvail = 0;
bufPtr = 0;
}
// Now read the rest directly from the stream
if (iis.skipBytes(count) != count) {
throw new IIOException ("Image format Error");
}
}
/**
* Push back the remaining contents of the buffer by
* repositioning the input stream.
*/
void pushBack() throws IOException {
iis.seek(iis.getStreamPosition()-bufAvail);
bufAvail = 0;
bufPtr = 0;
}
/**
* Return the stream position corresponding to the next
* available byte in the buffer.
*/
long getStreamPosition() throws IOException {
return (iis.getStreamPosition()-bufAvail);
}
/**
* Scan the buffer until the next 0xff byte, reloading
* the buffer as necessary. The buffer position is left
* pointing to the first non-0xff byte after a run of
* 0xff bytes. If the end of the stream is encountered,
* an EOI marker is inserted into the buffer and <code>true</code>
* is returned. Otherwise returns <code>false</code>.
*/
boolean scanForFF(JPEGImageReader reader) throws IOException {
boolean retval = false;
boolean foundFF = false;
while (foundFF == false) {
while (bufAvail > 0) {
if ((buf[bufPtr++] & 0xff) == 0xff) {
bufAvail--;
foundFF = true;
break; // out of inner while
}
bufAvail--;
}
// Reload the buffer and keep going
loadBuf(0);
// Skip any remaining pad bytes
if (foundFF == true) {
while ((bufAvail > 0) && (buf[bufPtr] & 0xff) == 0xff) {
bufPtr++; // Only if it still is 0xff
bufAvail--;
}
}
if (bufAvail == 0) { // Premature EOF
// send out a warning, but treat it as EOI
//reader.warningOccurred(JPEGImageReader.WARNING_NO_EOI);
retval = true;
buf[0] = (byte)JPEG.EOI;
bufAvail = 1;
bufPtr = 0;
foundFF = true;
}
}
return retval;
}
/**
* Prints the contents of the buffer, in hex.
* @param count the number of bytes to print,
* starting at the current available byte.
*/
void print(int count) {
System.out.print("buffer has ");
System.out.print(bufAvail);
System.out.println(" bytes available");
if (bufAvail < count) {
count = bufAvail;
}
for (int ptr = bufPtr; count > 0; count--) {
int val = (int)buf[ptr++] & 0xff;
System.out.print(" " + Integer.toHexString(val));
}
System.out.println();
}
}

View File

@@ -0,0 +1,366 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.ImageTypeSpecifier;
import java.awt.color.ICC_Profile;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.util.List;
import java.util.ArrayList;
public class JPEGImageMetadataFormat extends JPEGMetadataFormat {
private static JPEGImageMetadataFormat theInstance = null;
private JPEGImageMetadataFormat() {
super(JPEG.nativeImageMetadataFormatName,
CHILD_POLICY_ALL);
addElement("JPEGvariety",
JPEG.nativeImageMetadataFormatName,
CHILD_POLICY_CHOICE);
addElement("markerSequence",
JPEG.nativeImageMetadataFormatName,
CHILD_POLICY_SEQUENCE);
addElement("app0JFIF", "JPEGvariety", CHILD_POLICY_SOME);
addStreamElements("markerSequence");
addElement("app14Adobe", "markerSequence", CHILD_POLICY_EMPTY);
addElement("sof", "markerSequence", 1, 4);
addElement("sos", "markerSequence", 1, 4);
addElement("JFXX", "app0JFIF", 1, Integer.MAX_VALUE);
addElement("app0JFXX", "JFXX", CHILD_POLICY_CHOICE);
addElement("app2ICC", "app0JFIF", CHILD_POLICY_EMPTY);
addAttribute("app0JFIF",
"majorVersion",
DATATYPE_INTEGER,
false,
"1",
"0", "255",
true, true);
addAttribute("app0JFIF",
"minorVersion",
DATATYPE_INTEGER,
false,
"2",
"0", "255",
true, true);
List resUnits = new ArrayList();
resUnits.add("0");
resUnits.add("1");
resUnits.add("2");
addAttribute("app0JFIF",
"resUnits",
DATATYPE_INTEGER,
false,
"0",
resUnits);
addAttribute("app0JFIF",
"Xdensity",
DATATYPE_INTEGER,
false,
"1",
"1", "65535",
true, true);
addAttribute("app0JFIF",
"Ydensity",
DATATYPE_INTEGER,
false,
"1",
"1", "65535",
true, true);
addAttribute("app0JFIF",
"thumbWidth",
DATATYPE_INTEGER,
false,
"0",
"0", "255",
true, true);
addAttribute("app0JFIF",
"thumbHeight",
DATATYPE_INTEGER,
false,
"0",
"0", "255",
true, true);
addElement("JFIFthumbJPEG", "app0JFXX", CHILD_POLICY_SOME);
addElement("JFIFthumbPalette", "app0JFXX", CHILD_POLICY_EMPTY);
addElement("JFIFthumbRGB", "app0JFXX", CHILD_POLICY_EMPTY);
List codes = new ArrayList();
codes.add("16"); // Hex 10
codes.add("17"); // Hex 11
codes.add("19"); // Hex 13
addAttribute("app0JFXX",
"extensionCode",
DATATYPE_INTEGER,
false,
null,
codes);
addChildElement("markerSequence", "JFIFthumbJPEG");
addAttribute("JFIFthumbPalette",
"thumbWidth",
DATATYPE_INTEGER,
false,
null,
"0", "255",
true, true);
addAttribute("JFIFthumbPalette",
"thumbHeight",
DATATYPE_INTEGER,
false,
null,
"0", "255",
true, true);
addAttribute("JFIFthumbRGB",
"thumbWidth",
DATATYPE_INTEGER,
false,
null,
"0", "255",
true, true);
addAttribute("JFIFthumbRGB",
"thumbHeight",
DATATYPE_INTEGER,
false,
null,
"0", "255",
true, true);
addObjectValue("app2ICC", ICC_Profile.class, false, null);
addAttribute("app14Adobe",
"version",
DATATYPE_INTEGER,
false,
"100",
"100", "255",
true, true);
addAttribute("app14Adobe",
"flags0",
DATATYPE_INTEGER,
false,
"0",
"0", "65535",
true, true);
addAttribute("app14Adobe",
"flags1",
DATATYPE_INTEGER,
false,
"0",
"0", "65535",
true, true);
List transforms = new ArrayList();
transforms.add("0");
transforms.add("1");
transforms.add("2");
addAttribute("app14Adobe",
"transform",
DATATYPE_INTEGER,
true,
null,
transforms);
addElement("componentSpec", "sof", CHILD_POLICY_EMPTY);
List procs = new ArrayList();
procs.add("0");
procs.add("1");
procs.add("2");
addAttribute("sof",
"process",
DATATYPE_INTEGER,
false,
null,
procs);
addAttribute("sof",
"samplePrecision",
DATATYPE_INTEGER,
false,
"8");
addAttribute("sof",
"numLines",
DATATYPE_INTEGER,
false,
null,
"0", "65535",
true, true);
addAttribute("sof",
"samplesPerLine",
DATATYPE_INTEGER,
false,
null,
"0", "65535",
true, true);
List comps = new ArrayList();
comps.add("1");
comps.add("2");
comps.add("3");
comps.add("4");
addAttribute("sof",
"numFrameComponents",
DATATYPE_INTEGER,
false,
null,
comps);
addAttribute("componentSpec",
"componentId",
DATATYPE_INTEGER,
true,
null,
"0", "255",
true, true);
addAttribute("componentSpec",
"HsamplingFactor",
DATATYPE_INTEGER,
true,
null,
"1", "255",
true, true);
addAttribute("componentSpec",
"VsamplingFactor",
DATATYPE_INTEGER,
true,
null,
"1", "255",
true, true);
List tabids = new ArrayList();
tabids.add("0");
tabids.add("1");
tabids.add("2");
tabids.add("3");
addAttribute("componentSpec",
"QtableSelector",
DATATYPE_INTEGER,
true,
null,
tabids);
addElement("scanComponentSpec", "sos", CHILD_POLICY_EMPTY);
addAttribute("sos",
"numScanComponents",
DATATYPE_INTEGER,
true,
null,
comps);
addAttribute("sos",
"startSpectralSelection",
DATATYPE_INTEGER,
false,
"0",
"0", "63",
true, true);
addAttribute("sos",
"endSpectralSelection",
DATATYPE_INTEGER,
false,
"63",
"0", "63",
true, true);
addAttribute("sos",
"approxHigh",
DATATYPE_INTEGER,
false,
"0",
"0", "15",
true, true);
addAttribute("sos",
"approxLow",
DATATYPE_INTEGER,
false,
"0",
"0", "15",
true, true);
addAttribute("scanComponentSpec",
"componentSelector",
DATATYPE_INTEGER,
true,
null,
"0", "255",
true, true);
addAttribute("scanComponentSpec",
"dcHuffTable",
DATATYPE_INTEGER,
true,
null,
tabids);
addAttribute("scanComponentSpec",
"acHuffTable",
DATATYPE_INTEGER,
true,
null,
tabids);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
// All images can have these
if (elementName.equals(getRootName())
|| elementName.equals("JPEGvariety")
|| isInSubtree(elementName, "markerSequence")) {
return true;
}
// If it is an element in the app0jfif subtree, just check
// that the image type is JFIF compliant.
if ((isInSubtree(elementName, "app0JFIF"))
&& JPEG.isJFIFcompliant(imageType, true)) {
return true;
}
return false;
}
public static synchronized IIOMetadataFormat getInstance() {
if (theInstance == null) {
theInstance = new JPEGImageMetadataFormat();
}
return theInstance;
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.ListResourceBundle;
public class JPEGImageMetadataFormatResources
extends JPEGMetadataFormatResources {
static final Object[][] imageContents = {
// Node name, followed by description
{ "JPEGvariety", "A node grouping all marker segments specific to the variety of stream being read/written (e.g. JFIF) - may be empty" },
{ "markerSequence", "A node grouping all non-jfif marker segments" },
{ "app0jfif", "A JFIF APP0 marker segment" },
{ "app14Adobe", "An Adobe APP14 marker segment" },
{ "sof", "A Start Of Frame marker segment" },
{ "sos", "A Start Of Scan marker segment" },
{ "app0JFXX", "A JFIF extension marker segment" },
{ "app2ICC", "An ICC profile APP2 marker segment" },
{ "JFIFthumbJPEG",
"A JFIF thumbnail in JPEG format (no JFIF segments permitted)" },
{ "JFIFthumbPalette", "A JFIF thumbnail as an RGB indexed image" },
{ "JFIFthumbRGB", "A JFIF thumbnail as an RGB image" },
{ "componentSpec", "A component specification for a frame" },
{ "scanComponentSpec", "A component specification for a scan" },
// Node name + "/" + AttributeName, followed by description
{ "app0JFIF/majorVersion",
"The major JFIF version number" },
{ "app0JFIF/minorVersion",
"The minor JFIF version number" },
{ "app0JFIF/resUnits",
"The resolution units for Xdensity and Ydensity "
+ "(0 = no units, just aspect ratio; 1 = dots/inch; 2 = dots/cm)" },
{ "app0JFIF/Xdensity",
"The horizontal density or aspect ratio numerator" },
{ "app0JFIF/Ydensity",
"The vertical density or aspect ratio denominator" },
{ "app0JFIF/thumbWidth",
"The width of the thumbnail, or 0 if there isn't one" },
{ "app0JFIF/thumbHeight",
"The height of the thumbnail, or 0 if there isn't one" },
{ "app0JFXX/extensionCode",
"The JFXX extension code identifying thumbnail type: "
+ "(16 = JPEG, 17 = indexed, 19 = RGB" },
{ "JFIFthumbPalette/thumbWidth",
"The width of the thumbnail" },
{ "JFIFthumbPalette/thumbHeight",
"The height of the thumbnail" },
{ "JFIFthumbRGB/thumbWidth",
"The width of the thumbnail" },
{ "JFIFthumbRGB/thumbHeight",
"The height of the thumbnail" },
{ "app14Adobe/version",
"The version of Adobe APP14 marker segment" },
{ "app14Adobe/flags0",
"The flags0 variable of an APP14 marker segment" },
{ "app14Adobe/flags1",
"The flags1 variable of an APP14 marker segment" },
{ "app14Adobe/transform",
"The color transform applied to the image "
+ "(0 = Unknown, 1 = YCbCr, 2 = YCCK)" },
{ "sof/process",
"The JPEG process (0 = Baseline sequential, "
+ "1 = Extended sequential, 2 = Progressive)" },
{ "sof/samplePrecision",
"The number of bits per sample" },
{ "sof/numLines",
"The number of lines in the image" },
{ "sof/samplesPerLine",
"The number of samples per line" },
{ "sof/numFrameComponents",
"The number of components in the image" },
{ "componentSpec/componentId",
"The id for this component" },
{ "componentSpec/HsamplingFactor",
"The horizontal sampling factor for this component" },
{ "componentSpec/VsamplingFactor",
"The vertical sampling factor for this component" },
{ "componentSpec/QtableSelector",
"The quantization table to use for this component" },
{ "sos/numScanComponents",
"The number of components in the scan" },
{ "sos/startSpectralSelection",
"The first spectral band included in this scan" },
{ "sos/endSpectralSelection",
"The last spectral band included in this scan" },
{ "sos/approxHigh",
"The highest bit position included in this scan" },
{ "sos/approxLow",
"The lowest bit position included in this scan" },
{ "scanComponentSpec/componentSelector",
"The id of this component" },
{ "scanComponentSpec/dcHuffTable",
"The huffman table to use for encoding DC coefficients" },
{ "scanComponentSpec/acHuffTable",
"The huffman table to use for encoding AC coefficients" }
};
public JPEGImageMetadataFormatResources() {}
protected Object[][] getContents() {
// return a copy of the combined commonContents and imageContents;
// in theory we want a deep clone of the combined arrays,
// but since it only contains (immutable) Strings, this shallow
// copy is sufficient
Object[][] combinedContents =
new Object[commonContents.length + imageContents.length][2];
int combined = 0;
for (int i = 0; i < commonContents.length; i++, combined++) {
combinedContents[combined][0] = commonContents[i][0];
combinedContents[combined][1] = commonContents[i][1];
}
for (int i = 0; i < imageContents.length; i++, combined++) {
combinedContents[combined][0] = imageContents[i][0];
combinedContents[combined][1] = imageContents[i][1];
}
return combinedContents;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.ListResourceBundle;
public class JPEGImageReaderResources extends ListResourceBundle {
public JPEGImageReaderResources() {}
protected Object[][] getContents() {
return new Object[][] {
{Integer.toString(JPEGImageReader.WARNING_NO_EOI),
"Truncated File - Missing EOI marker"},
{Integer.toString(JPEGImageReader.WARNING_NO_JFIF_IN_THUMB),
"JFIF markers not allowed in JFIF JPEG thumbnail; ignored"},
{Integer.toString(JPEGImageReader.WARNING_IGNORE_INVALID_ICC),
"Embedded color profile is invalid; ignored"}
};
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.Locale;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.spi.IIORegistry;
import javax.imageio.spi.ServiceRegistry;
import java.io.IOException;
import javax.imageio.ImageReader;
import javax.imageio.IIOException;
public class JPEGImageReaderSpi extends ImageReaderSpi {
private static String [] writerSpiNames =
{"com.sun.imageio.plugins.jpeg.JPEGImageWriterSpi"};
public JPEGImageReaderSpi() {
super(JPEG.vendor,
JPEG.version,
JPEG.names,
JPEG.suffixes,
JPEG.MIMETypes,
"com.sun.imageio.plugins.jpeg.JPEGImageReader",
new Class[] { ImageInputStream.class },
writerSpiNames,
true,
JPEG.nativeStreamMetadataFormatName,
JPEG.nativeStreamMetadataFormatClassName,
null, null,
true,
JPEG.nativeImageMetadataFormatName,
JPEG.nativeImageMetadataFormatClassName,
null, null
);
}
public String getDescription(Locale locale) {
return "Standard JPEG Image Reader";
}
public boolean canDecodeInput(Object source) throws IOException {
if (!(source instanceof ImageInputStream)) {
return false;
}
ImageInputStream iis = (ImageInputStream) source;
iis.mark();
// If the first two bytes are a JPEG SOI marker, it's probably
// a JPEG file. If they aren't, it definitely isn't a JPEG file.
int byte1 = iis.read();
int byte2 = iis.read();
iis.reset();
if ((byte1 == 0xFF) && (byte2 == JPEG.SOI)) {
return true;
}
return false;
}
public ImageReader createReaderInstance(Object extension)
throws IIOException {
return new JPEGImageReader(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.ListResourceBundle;
public class JPEGImageWriterResources extends ListResourceBundle {
public JPEGImageWriterResources() {}
protected Object[][] getContents() {
return new Object[][] {
{Integer.toString(JPEGImageWriter.WARNING_DEST_IGNORED),
"Only Rasters or band subsets may be written with a destination type. "
+ "Destination type ignored."},
{Integer.toString(JPEGImageWriter.WARNING_STREAM_METADATA_IGNORED),
"Stream metadata ignored on write"},
{Integer.toString(JPEGImageWriter.WARNING_DEST_METADATA_COMP_MISMATCH),
"Metadata component ids incompatible with destination type. "
+ "Metadata modified."},
{Integer.toString(JPEGImageWriter.WARNING_DEST_METADATA_JFIF_MISMATCH),
"Metadata JFIF settings incompatible with destination type. "
+ "Metadata modified."},
{Integer.toString(JPEGImageWriter.WARNING_DEST_METADATA_ADOBE_MISMATCH),
"Metadata Adobe settings incompatible with destination type. "
+ "Metadata modified."},
{Integer.toString(JPEGImageWriter.WARNING_IMAGE_METADATA_JFIF_MISMATCH),
"Metadata JFIF settings incompatible with image type. "
+ "Metadata modified."},
{Integer.toString(JPEGImageWriter.WARNING_IMAGE_METADATA_ADOBE_MISMATCH),
"Metadata Adobe settings incompatible with image type. "
+ "Metadata modified."},
{Integer.toString(JPEGImageWriter.WARNING_METADATA_NOT_JPEG_FOR_RASTER),
"Metadata must be JPEGMetadata when writing a Raster. "
+ "Metadata ignored."},
{Integer.toString(JPEGImageWriter.WARNING_NO_BANDS_ON_INDEXED),
"Band subset not allowed for an IndexColorModel image. "
+ "Band subset ignored."},
{Integer.toString(JPEGImageWriter.WARNING_ILLEGAL_THUMBNAIL),
"Thumbnails must be simple (possibly index) RGB or grayscale. "
+ "Incompatible thumbnail ignored."},
{Integer.toString(JPEGImageWriter.WARNING_IGNORING_THUMBS ),
"Thumbnails ignored for non-JFIF-compatible image."},
{Integer.toString(JPEGImageWriter.WARNING_FORCING_JFIF ),
"Thumbnails require JFIF marker segment. "
+ "Missing node added to metadata."},
{Integer.toString(JPEGImageWriter.WARNING_THUMB_CLIPPED ),
"Thumbnail clipped."},
{Integer.toString(JPEGImageWriter.WARNING_METADATA_ADJUSTED_FOR_THUMB ),
"Metadata adjusted (made JFIF-compatible) for thumbnail."},
{Integer.toString(JPEGImageWriter.WARNING_NO_RGB_THUMB_AS_INDEXED ),
"RGB thumbnail can't be written as indexed. Written as RGB"},
{Integer.toString(JPEGImageWriter.WARNING_NO_GRAY_THUMB_AS_INDEXED),
"Grayscale thumbnail can't be written as indexed. Written as JPEG"},
};
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.ImageWriter;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.IIOException;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.SampleModel;
import java.util.Locale;
public class JPEGImageWriterSpi extends ImageWriterSpi {
private static String [] readerSpiNames =
{"com.sun.imageio.plugins.jpeg.JPEGImageReaderSpi"};
public JPEGImageWriterSpi() {
super(JPEG.vendor,
JPEG.version,
JPEG.names,
JPEG.suffixes,
JPEG.MIMETypes,
"com.sun.imageio.plugins.jpeg.JPEGImageWriter",
new Class[] { ImageOutputStream.class },
readerSpiNames,
true,
JPEG.nativeStreamMetadataFormatName,
JPEG.nativeStreamMetadataFormatClassName,
null, null,
true,
JPEG.nativeImageMetadataFormatName,
JPEG.nativeImageMetadataFormatClassName,
null, null
);
}
public String getDescription(Locale locale) {
return "Standard JPEG Image Writer";
}
public boolean isFormatLossless() {
return false;
}
public boolean canEncodeImage(ImageTypeSpecifier type) {
SampleModel sampleModel = type.getSampleModel();
// Find the maximum bit depth across all channels
int[] sampleSize = sampleModel.getSampleSize();
int bitDepth = sampleSize[0];
for (int i = 1; i < sampleSize.length; i++) {
if (sampleSize[i] > bitDepth) {
bitDepth = sampleSize[i];
}
}
// 4450894: Ensure bitDepth is between 1 and 8
if (bitDepth < 1 || bitDepth > 8) {
return false;
}
return true;
}
public ImageWriter createWriterInstance(Object extension)
throws IIOException {
return new JPEGImageWriter(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.plugins.jpeg.JPEGQTable;
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
import java.util.List;
import java.util.ArrayList;
abstract class JPEGMetadataFormat extends IIOMetadataFormatImpl {
// 2-byte length reduces max to 65533
private static final int MAX_JPEG_DATA_SIZE = 65533;
String resourceBaseName = this.getClass().getName() + "Resources";
JPEGMetadataFormat(String formatName, int childPolicy) {
super(formatName, childPolicy);
setResourceBaseName(resourceBaseName);
}
// Format shared between image and stream formats
void addStreamElements(String parentName) {
addElement("dqt", parentName, 1, 4);
addElement("dqtable", "dqt", CHILD_POLICY_EMPTY);
addAttribute("dqtable",
"elementPrecision",
DATATYPE_INTEGER,
false,
"0");
List tabids = new ArrayList();
tabids.add("0");
tabids.add("1");
tabids.add("2");
tabids.add("3");
addAttribute("dqtable",
"qtableId",
DATATYPE_INTEGER,
true,
null,
tabids);
addObjectValue("dqtable",
JPEGQTable.class,
true,
null);
addElement("dht", parentName, 1, 4);
addElement("dhtable", "dht", CHILD_POLICY_EMPTY);
List classes = new ArrayList();
classes.add("0");
classes.add("1");
addAttribute("dhtable",
"class",
DATATYPE_INTEGER,
true,
null,
classes);
addAttribute("dhtable",
"htableId",
DATATYPE_INTEGER,
true,
null,
tabids);
addObjectValue("dhtable",
JPEGHuffmanTable.class,
true,
null);
addElement("dri", parentName, CHILD_POLICY_EMPTY);
addAttribute("dri",
"interval",
DATATYPE_INTEGER,
true,
null,
"0", "65535",
true, true);
addElement("com", parentName, CHILD_POLICY_EMPTY);
addAttribute("com",
"comment",
DATATYPE_STRING,
false,
null);
addObjectValue("com", byte[].class, 1, MAX_JPEG_DATA_SIZE);
addElement("unknown", parentName, CHILD_POLICY_EMPTY);
addAttribute("unknown",
"MarkerTag",
DATATYPE_INTEGER,
true,
null,
"0", "255",
true, true);
addObjectValue("unknown", byte[].class, 1, MAX_JPEG_DATA_SIZE);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
// Just check if it appears in the format
if (isInSubtree(elementName, getRootName())){
return true;
}
return false;
}
/**
* Returns <code>true</code> if the named element occurs in the
* subtree of the format starting with the node named by
* <code>subtreeName</code>, including the node
* itself. <code>subtreeName</code> may be any node in
* the format. If it is not, an
* <code>IllegalArgumentException</code> is thrown.
*/
protected boolean isInSubtree(String elementName,
String subtreeName) {
if (elementName.equals(subtreeName)) {
return true;
}
String [] children = getChildNames(elementName);
for (int i=0; i < children.length; i++) {
if (isInSubtree(elementName, children[i])) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.ListResourceBundle;
abstract class JPEGMetadataFormatResources
extends ListResourceBundle {
static final Object[][] commonContents = {
// Node name, followed by description
{ "dqt", "A Define Quantization Table(s) marker segment" },
{ "dqtable", "A single quantization table" },
{ "dht", "A Define Huffman Table(s) marker segment" },
{ "dhtable", "A single Huffman table" },
{ "dri", "A Define Restart Interval marker segment" },
{ "com", "A Comment marker segment. The user object contains "
+ "the actual bytes."},
{ "unknown", "An unrecognized marker segment. The user object "
+ "contains the data not including length." },
// Node name + "/" + AttributeName, followed by description
{ "dqtable/elementPrecision",
"The number of bits in each table element (0 = 8, 1 = 16)" },
{ "dgtable/qtableId",
"The table id" },
{ "dhtable/class",
"Indicates whether this is a DC (0) or an AC (1) table" },
{ "dhtable/htableId",
"The table id" },
{ "dri/interval",
"The restart interval in MCUs" },
{ "com/comment",
"The comment as a string (used only if user object is null)" },
{ "unknown/MarkerTag",
"The tag identifying this marker segment" }
};
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class JPEGStreamMetadataFormat extends JPEGMetadataFormat {
private static JPEGStreamMetadataFormat theInstance = null;
private JPEGStreamMetadataFormat() {
super(JPEG.nativeStreamMetadataFormatName,
CHILD_POLICY_SEQUENCE);
addStreamElements(getRootName());
}
public static synchronized IIOMetadataFormat getInstance() {
if (theInstance == null) {
theInstance = new JPEGStreamMetadataFormat();
}
return theInstance;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import java.util.ListResourceBundle;
public class JPEGStreamMetadataFormatResources
extends JPEGMetadataFormatResources {
public JPEGStreamMetadataFormatResources() {}
protected Object[][] getContents() {
// return a copy of commonContents; in theory we want a deep clone
// of commonContents, but since it only contains (immutable) Strings,
// this shallow copy is sufficient
Object[][] commonCopy = new Object[commonContents.length][2];
for (int i = 0; i < commonContents.length; i++) {
commonCopy[i][0] = commonContents[i][0];
commonCopy[i][1] = commonContents[i][1];
}
return commonCopy;
}
}

View File

@@ -0,0 +1,229 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.IIOException;
import java.io.IOException;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
/**
* All metadata is stored in MarkerSegments. Marker segments
* that we know about are stored in subclasses of this
* basic class, which used for unrecognized APPn marker
* segments. XXX break out UnknownMarkerSegment as a subclass
* and make this abstract, avoiding unused data field.
*/
class MarkerSegment implements Cloneable {
protected static final int LENGTH_SIZE = 2; // length is 2 bytes
int tag; // See JPEG.java
int length; /* Sometimes needed by subclasses; doesn't include
itself. Meaningful only if constructed from a stream */
byte [] data = null; // Raw segment data, used for unrecognized segments
boolean unknown = false; // Set to true if the tag is not recognized
/**
* Constructor for creating <code>MarkerSegment</code>s by reading
* from an <code>ImageInputStream</code>.
*/
MarkerSegment(JPEGBuffer buffer) throws IOException {
buffer.loadBuf(3); // tag plus length
tag = buffer.buf[buffer.bufPtr++] & 0xff;
length = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
length |= buffer.buf[buffer.bufPtr++] & 0xff;
length -= 2; // JPEG length includes itself, we don't
if (length < 0) {
throw new IIOException("Invalid segment length: " + length);
}
buffer.bufAvail -= 3;
// Now that we know the true length, ensure that we've got it,
// or at least a bufferful if length is too big.
buffer.loadBuf(length);
}
/**
* Constructor used when creating segments other than by
* reading them from a stream.
*/
MarkerSegment(int tag) {
this.tag = tag;
length = 0;
}
/**
* Construct a MarkerSegment from an "unknown" DOM Node.
*/
MarkerSegment(Node node) throws IIOInvalidTreeException {
// The type of node should have been verified already.
// get the attribute and assign it to the tag
tag = getAttributeValue(node,
null,
"MarkerTag",
0, 255,
true);
length = 0;
// get the user object and clone it to the data
if (node instanceof IIOMetadataNode) {
IIOMetadataNode iioNode = (IIOMetadataNode) node;
try {
data = (byte []) iioNode.getUserObject();
} catch (Exception e) {
IIOInvalidTreeException newGuy =
new IIOInvalidTreeException
("Can't get User Object", node);
newGuy.initCause(e);
throw newGuy;
}
} else {
throw new IIOInvalidTreeException
("Node must have User Object", node);
}
}
/**
* Deep copy of data array.
*/
protected Object clone() {
MarkerSegment newGuy = null;
try {
newGuy = (MarkerSegment) super.clone();
} catch (CloneNotSupportedException e) {} // won't happen
if (this.data != null) {
newGuy.data = (byte[]) data.clone();
}
return newGuy;
}
/**
* We have determined that we don't know the type, so load
* the data using the length parameter.
*/
void loadData(JPEGBuffer buffer) throws IOException {
data = new byte[length];
buffer.readData(data);
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("unknown");
node.setAttribute("MarkerTag", Integer.toString(tag));
node.setUserObject(data);
return node;
}
static int getAttributeValue(Node node,
NamedNodeMap attrs,
String name,
int min,
int max,
boolean required)
throws IIOInvalidTreeException {
if (attrs == null) {
attrs = node.getAttributes();
}
String valueString = attrs.getNamedItem(name).getNodeValue();
int value = -1;
if (valueString == null) {
if (required) {
throw new IIOInvalidTreeException
(name + " attribute not found", node);
}
} else {
value = Integer.parseInt(valueString);
if ((value < min) || (value > max)) {
throw new IIOInvalidTreeException
(name + " attribute out of range", node);
}
}
return value;
}
/**
* Writes the marker, tag, and length. Note that length
* should be verified by the caller as a correct JPEG
* length, i.e it includes itself.
*/
void writeTag(ImageOutputStream ios) throws IOException {
ios.write(0xff);
ios.write(tag);
write2bytes(ios, length);
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
length = 2 + ((data != null) ? data.length : 0);
writeTag(ios);
if (data != null) {
ios.write(data);
}
}
static void write2bytes(ImageOutputStream ios,
int value) throws IOException {
ios.write((value >> 8) & 0xff);
ios.write(value & 0xff);
}
void printTag(String prefix) {
System.out.println(prefix + " marker segment - marker = 0x"
+ Integer.toHexString(tag));
System.out.println("length: " + length);
}
void print() {
printTag("Unknown");
if (length > 10) {
System.out.print("First 5 bytes:");
for (int i=0;i<5;i++) {
System.out.print(" Ox"
+ Integer.toHexString((int)data[i]));
}
System.out.print("\nLast 5 bytes:");
for (int i=data.length-5;i<data.length;i++) {
System.out.print(" Ox"
+ Integer.toHexString((int)data[i]));
}
} else {
System.out.print("Data:");
for (int i=0;i<data.length;i++) {
System.out.print(" Ox"
+ Integer.toHexString((int)data[i]));
}
}
System.out.println();
}
}

View File

@@ -0,0 +1,284 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
//import javax.imageio.IIOException;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.io.IOException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
/**
* An SOF (Start Of Frame) marker segment.
*/
class SOFMarkerSegment extends MarkerSegment {
int samplePrecision;
int numLines;
int samplesPerLine;
ComponentSpec [] componentSpecs; // Array size is num components
SOFMarkerSegment(boolean wantProg,
boolean wantExtended,
boolean willSubsample,
byte[] componentIDs,
int numComponents) {
super(wantProg ? JPEG.SOF2
: wantExtended ? JPEG.SOF1
: JPEG.SOF0);
samplePrecision = 8;
numLines = 0;
samplesPerLine = 0;
componentSpecs = new ComponentSpec[numComponents];
for(int i = 0; i < numComponents; i++) {
int factor = 1;
int qsel = 0;
if (willSubsample) {
factor = 2;
if ((i == 1) || (i == 2)) {
factor = 1;
qsel = 1;
}
}
componentSpecs[i] = new ComponentSpec(componentIDs[i], factor, qsel);
}
}
SOFMarkerSegment(JPEGBuffer buffer) throws IOException{
super(buffer);
samplePrecision = buffer.buf[buffer.bufPtr++];
numLines = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
numLines |= buffer.buf[buffer.bufPtr++] & 0xff;
samplesPerLine = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
samplesPerLine |= buffer.buf[buffer.bufPtr++] & 0xff;
int numComponents = buffer.buf[buffer.bufPtr++] & 0xff;
componentSpecs = new ComponentSpec [numComponents];
for (int i = 0; i < numComponents; i++) {
componentSpecs[i] = new ComponentSpec(buffer);
}
buffer.bufAvail -= length;
}
SOFMarkerSegment(Node node) throws IIOInvalidTreeException {
// All attributes are optional, so setup defaults first
super(JPEG.SOF0);
samplePrecision = 8;
numLines = 0;
samplesPerLine = 0;
updateFromNativeNode(node, true);
}
protected Object clone() {
SOFMarkerSegment newGuy = (SOFMarkerSegment) super.clone();
if (componentSpecs != null) {
newGuy.componentSpecs = (ComponentSpec []) componentSpecs.clone();
for (int i = 0; i < componentSpecs.length; i++) {
newGuy.componentSpecs[i] =
(ComponentSpec) componentSpecs[i].clone();
}
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("sof");
node.setAttribute("process", Integer.toString(tag-JPEG.SOF0));
node.setAttribute("samplePrecision",
Integer.toString(samplePrecision));
node.setAttribute("numLines",
Integer.toString(numLines));
node.setAttribute("samplesPerLine",
Integer.toString(samplesPerLine));
node.setAttribute("numFrameComponents",
Integer.toString(componentSpecs.length));
for (int i = 0; i < componentSpecs.length; i++) {
node.appendChild(componentSpecs[i].getNativeNode());
}
return node;
}
void updateFromNativeNode(Node node, boolean fromScratch)
throws IIOInvalidTreeException {
NamedNodeMap attrs = node.getAttributes();
int value = getAttributeValue(node, attrs, "process", 0, 2, false);
tag = (value != -1) ? value+JPEG.SOF0 : tag;
// If samplePrecision is present, it must be 8.
// This just checks. We don't bother to assign the value.
value = getAttributeValue(node, attrs, "samplePrecision", 8, 8, false);
value = getAttributeValue(node, attrs, "numLines", 0, 65535, false);
numLines = (value != -1) ? value : numLines;
value = getAttributeValue(node, attrs, "samplesPerLine", 0, 65535, false);
samplesPerLine = (value != -1) ? value : samplesPerLine;
int numComponents = getAttributeValue(node, attrs, "numFrameComponents",
1, 4, false);
NodeList children = node.getChildNodes();
if (children.getLength() != numComponents) {
throw new IIOInvalidTreeException
("numFrameComponents must match number of children", node);
}
componentSpecs = new ComponentSpec [numComponents];
for (int i = 0; i < numComponents; i++) {
componentSpecs[i] = new ComponentSpec(children.item(i));
}
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
// We don't write SOF segments; the IJG library does.
}
void print () {
printTag("SOF");
System.out.print("Sample precision: ");
System.out.println(samplePrecision);
System.out.print("Number of lines: ");
System.out.println(numLines);
System.out.print("Samples per line: ");
System.out.println(samplesPerLine);
System.out.print("Number of components: ");
System.out.println(componentSpecs.length);
for(int i = 0; i<componentSpecs.length; i++) {
componentSpecs[i].print();
}
}
int getIDencodedCSType () {
for (int i = 0; i < componentSpecs.length; i++) {
if (componentSpecs[i].componentId < 'A') {
return JPEG.JCS_UNKNOWN;
}
}
switch(componentSpecs.length) {
case 3:
if ((componentSpecs[0].componentId == 'R')
&&(componentSpecs[0].componentId == 'G')
&&(componentSpecs[0].componentId == 'B')) {
return JPEG.JCS_RGB;
}
if ((componentSpecs[0].componentId == 'Y')
&&(componentSpecs[0].componentId == 'C')
&&(componentSpecs[0].componentId == 'c')) {
return JPEG.JCS_YCC;
}
break;
case 4:
if ((componentSpecs[0].componentId == 'R')
&&(componentSpecs[0].componentId == 'G')
&&(componentSpecs[0].componentId == 'B')
&&(componentSpecs[0].componentId == 'A')) {
return JPEG.JCS_RGBA;
}
if ((componentSpecs[0].componentId == 'Y')
&&(componentSpecs[0].componentId == 'C')
&&(componentSpecs[0].componentId == 'c')
&&(componentSpecs[0].componentId == 'A')) {
return JPEG.JCS_YCCA;
}
}
return JPEG.JCS_UNKNOWN;
}
ComponentSpec getComponentSpec(byte id, int factor, int qSelector) {
return new ComponentSpec(id, factor, qSelector);
}
/**
* A component spec within an SOF marker segment.
*/
class ComponentSpec implements Cloneable {
int componentId;
int HsamplingFactor;
int VsamplingFactor;
int QtableSelector;
ComponentSpec(byte id, int factor, int qSelector) {
componentId = id;
HsamplingFactor = factor;
VsamplingFactor = factor;
QtableSelector = qSelector;
}
ComponentSpec(JPEGBuffer buffer) {
// Parent already did a loadBuf
componentId = buffer.buf[buffer.bufPtr++];
HsamplingFactor = buffer.buf[buffer.bufPtr] >>> 4;
VsamplingFactor = buffer.buf[buffer.bufPtr++] & 0xf;
QtableSelector = buffer.buf[buffer.bufPtr++];
}
ComponentSpec(Node node) throws IIOInvalidTreeException {
NamedNodeMap attrs = node.getAttributes();
componentId = getAttributeValue(node, attrs, "componentId", 0, 255, true);
HsamplingFactor = getAttributeValue(node, attrs, "HsamplingFactor",
1, 255, true);
VsamplingFactor = getAttributeValue(node, attrs, "VsamplingFactor",
1, 255, true);
QtableSelector = getAttributeValue(node, attrs, "QtableSelector",
0, 3, true);
}
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {} // won't happen
return null;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("componentSpec");
node.setAttribute("componentId",
Integer.toString(componentId));
node.setAttribute("HsamplingFactor",
Integer.toString(HsamplingFactor));
node.setAttribute("VsamplingFactor",
Integer.toString(VsamplingFactor));
node.setAttribute("QtableSelector",
Integer.toString(QtableSelector));
return node;
}
void print () {
System.out.print("Component ID: ");
System.out.println(componentId);
System.out.print("H sampling factor: ");
System.out.println(HsamplingFactor);
System.out.print("V sampling factor: ");
System.out.println(VsamplingFactor);
System.out.print("Q table selector: ");
System.out.println(QtableSelector);
}
}
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright (c) 2001, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.jpeg;
//import javax.imageio.IIOException;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.io.IOException;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
/**
* An SOS (Start Of Scan) marker segment.
*/
class SOSMarkerSegment extends MarkerSegment {
int startSpectralSelection;
int endSpectralSelection;
int approxHigh;
int approxLow;
ScanComponentSpec [] componentSpecs; // Array size is numScanComponents
SOSMarkerSegment(boolean willSubsample,
byte[] componentIDs,
int numComponents) {
super(JPEG.SOS);
startSpectralSelection = 0;
endSpectralSelection = 63;
approxHigh = 0;
approxLow = 0;
componentSpecs = new ScanComponentSpec[numComponents];
for (int i = 0; i < numComponents; i++) {
int tableSel = 0;
if (willSubsample) {
if ((i == 1) || (i == 2)) {
tableSel = 1;
}
}
componentSpecs[i] = new ScanComponentSpec(componentIDs[i],
tableSel);
}
}
SOSMarkerSegment(JPEGBuffer buffer) throws IOException {
super(buffer);
int numComponents = buffer.buf[buffer.bufPtr++];
componentSpecs = new ScanComponentSpec[numComponents];
for (int i = 0; i < numComponents; i++) {
componentSpecs[i] = new ScanComponentSpec(buffer);
}
startSpectralSelection = buffer.buf[buffer.bufPtr++];
endSpectralSelection = buffer.buf[buffer.bufPtr++];
approxHigh = buffer.buf[buffer.bufPtr] >> 4;
approxLow = buffer.buf[buffer.bufPtr++] &0xf;
buffer.bufAvail -= length;
}
SOSMarkerSegment(Node node) throws IIOInvalidTreeException {
super(JPEG.SOS);
startSpectralSelection = 0;
endSpectralSelection = 63;
approxHigh = 0;
approxLow = 0;
updateFromNativeNode(node, true);
}
protected Object clone () {
SOSMarkerSegment newGuy = (SOSMarkerSegment) super.clone();
if (componentSpecs != null) {
newGuy.componentSpecs =
(ScanComponentSpec []) componentSpecs.clone();
for (int i = 0; i < componentSpecs.length; i++) {
newGuy.componentSpecs[i] =
(ScanComponentSpec) componentSpecs[i].clone();
}
}
return newGuy;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("sos");
node.setAttribute("numScanComponents",
Integer.toString(componentSpecs.length));
node.setAttribute("startSpectralSelection",
Integer.toString(startSpectralSelection));
node.setAttribute("endSpectralSelection",
Integer.toString(endSpectralSelection));
node.setAttribute("approxHigh",
Integer.toString(approxHigh));
node.setAttribute("approxLow",
Integer.toString(approxLow));
for (int i = 0; i < componentSpecs.length; i++) {
node.appendChild(componentSpecs[i].getNativeNode());
}
return node;
}
void updateFromNativeNode(Node node, boolean fromScratch)
throws IIOInvalidTreeException {
NamedNodeMap attrs = node.getAttributes();
int numComponents = getAttributeValue(node, attrs, "numScanComponents",
1, 4, true);
int value = getAttributeValue(node, attrs, "startSpectralSelection",
0, 63, false);
startSpectralSelection = (value != -1) ? value : startSpectralSelection;
value = getAttributeValue(node, attrs, "endSpectralSelection",
0, 63, false);
endSpectralSelection = (value != -1) ? value : endSpectralSelection;
value = getAttributeValue(node, attrs, "approxHigh", 0, 15, false);
approxHigh = (value != -1) ? value : approxHigh;
value = getAttributeValue(node, attrs, "approxLow", 0, 15, false);
approxLow = (value != -1) ? value : approxLow;
// Now the children
NodeList children = node.getChildNodes();
if (children.getLength() != numComponents) {
throw new IIOInvalidTreeException
("numScanComponents must match the number of children", node);
}
componentSpecs = new ScanComponentSpec[numComponents];
for (int i = 0; i < numComponents; i++) {
componentSpecs[i] = new ScanComponentSpec(children.item(i));
}
}
/**
* Writes the data for this segment to the stream in
* valid JPEG format.
*/
void write(ImageOutputStream ios) throws IOException {
// We don't write SOS segments; the IJG library does.
}
void print () {
printTag("SOS");
System.out.print("Start spectral selection: ");
System.out.println(startSpectralSelection);
System.out.print("End spectral selection: ");
System.out.println(endSpectralSelection);
System.out.print("Approx high: ");
System.out.println(approxHigh);
System.out.print("Approx low: ");
System.out.println(approxLow);
System.out.print("Num scan components: ");
System.out.println(componentSpecs.length);
for (int i = 0; i< componentSpecs.length; i++) {
componentSpecs[i].print();
}
}
ScanComponentSpec getScanComponentSpec(byte componentSel, int tableSel) {
return new ScanComponentSpec(componentSel, tableSel);
}
/**
* A scan component spec within an SOS marker segment.
*/
class ScanComponentSpec implements Cloneable {
int componentSelector;
int dcHuffTable;
int acHuffTable;
ScanComponentSpec(byte componentSel, int tableSel) {
componentSelector = componentSel;
dcHuffTable = tableSel;
acHuffTable = tableSel;
}
ScanComponentSpec(JPEGBuffer buffer) {
// Parent already loaded the buffer
componentSelector = buffer.buf[buffer.bufPtr++];
dcHuffTable = buffer.buf[buffer.bufPtr] >> 4;
acHuffTable = buffer.buf[buffer.bufPtr++] & 0xf;
}
ScanComponentSpec(Node node) throws IIOInvalidTreeException {
NamedNodeMap attrs = node.getAttributes();
componentSelector = getAttributeValue(node, attrs, "componentSelector",
0, 255, true);
dcHuffTable = getAttributeValue(node, attrs, "dcHuffTable",
0, 3, true);
acHuffTable = getAttributeValue(node, attrs, "acHuffTable",
0, 3, true);
}
protected Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {} // won't happen
return null;
}
IIOMetadataNode getNativeNode() {
IIOMetadataNode node = new IIOMetadataNode("scanComponentSpec");
node.setAttribute("componentSelector",
Integer.toString(componentSelector));
node.setAttribute("dcHuffTable",
Integer.toString(dcHuffTable));
node.setAttribute("acHuffTable",
Integer.toString(acHuffTable));
return node;
}
void print () {
System.out.print("Component Selector: ");
System.out.println(componentSelector);
System.out.print("DC huffman table: ");
System.out.println(dcHuffTable);
System.out.print("AC huffman table: ");
System.out.println(acHuffTable);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.png;
import java.io.IOException;
import java.util.Locale;
import java.util.Iterator;
import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.stream.ImageInputStream;
public class PNGImageReaderSpi extends ImageReaderSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final String[] names = { "png", "PNG" };
private static final String[] suffixes = { "png" };
private static final String[] MIMETypes = { "image/png", "image/x-png" };
private static final String readerClassName =
"com.sun.imageio.plugins.png.PNGImageReader";
private static final String[] writerSpiNames = {
"com.sun.imageio.plugins.png.PNGImageWriterSpi"
};
public PNGImageReaderSpi() {
super(vendorName,
version,
names,
suffixes,
MIMETypes,
readerClassName,
new Class[] { ImageInputStream.class },
writerSpiNames,
false,
null, null,
null, null,
true,
PNGMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.png.PNGMetadataFormat",
null, null
);
}
public String getDescription(Locale locale) {
return "Standard PNG image reader";
}
public boolean canDecodeInput(Object input) throws IOException {
if (!(input instanceof ImageInputStream)) {
return false;
}
ImageInputStream stream = (ImageInputStream)input;
byte[] b = new byte[8];
stream.mark();
stream.readFully(b);
stream.reset();
return (b[0] == (byte)137 &&
b[1] == (byte)80 &&
b[2] == (byte)78 &&
b[3] == (byte)71 &&
b[4] == (byte)13 &&
b[5] == (byte)10 &&
b[6] == (byte)26 &&
b[7] == (byte)10);
}
public ImageReader createReaderInstance(Object extension) {
return new PNGImageReader(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.png;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.SampleModel;
import java.util.Locale;
import javax.imageio.ImageWriter;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
public class PNGImageWriterSpi extends ImageWriterSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final String[] names = { "png", "PNG" };
private static final String[] suffixes = { "png" };
private static final String[] MIMETypes = { "image/png", "image/x-png" };
private static final String writerClassName =
"com.sun.imageio.plugins.png.PNGImageWriter";
private static final String[] readerSpiNames = {
"com.sun.imageio.plugins.png.PNGImageReaderSpi"
};
public PNGImageWriterSpi() {
super(vendorName,
version,
names,
suffixes,
MIMETypes,
writerClassName,
new Class[] { ImageOutputStream.class },
readerSpiNames,
false,
null, null,
null, null,
true,
PNGMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.png.PNGMetadataFormat",
null, null
);
}
public boolean canEncodeImage(ImageTypeSpecifier type) {
SampleModel sampleModel = type.getSampleModel();
ColorModel colorModel = type.getColorModel();
// Find the maximum bit depth across all channels
int[] sampleSize = sampleModel.getSampleSize();
int bitDepth = sampleSize[0];
for (int i = 1; i < sampleSize.length; i++) {
if (sampleSize[i] > bitDepth) {
bitDepth = sampleSize[i];
}
}
// Ensure bitDepth is between 1 and 16
if (bitDepth < 1 || bitDepth > 16) {
return false;
}
// Check number of bands, alpha
int numBands = sampleModel.getNumBands();
if (numBands < 1 || numBands > 4) {
return false;
}
boolean hasAlpha = colorModel.hasAlpha();
// Fix 4464413: PNGTransparency reg-test was failing
// because for IndexColorModels that have alpha,
// numBands == 1 && hasAlpha == true, thus causing
// the check below to fail and return false.
if (colorModel instanceof IndexColorModel) {
return true;
}
if ((numBands == 1 || numBands == 3) && hasAlpha) {
return false;
}
if ((numBands == 2 || numBands == 4) && !hasAlpha) {
return false;
}
return true;
}
public String getDescription(Locale locale) {
return "Standard PNG image writer";
}
public ImageWriter createWriterInstance(Object extension) {
return new PNGImageWriter(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,500 @@
/*
* Copyright (c) 2001, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.png;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListResourceBundle;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class PNGMetadataFormat extends IIOMetadataFormatImpl {
private static IIOMetadataFormat instance = null;
private static String VALUE_0 = "0";
private static String VALUE_1 = "1";
private static String VALUE_12 = "12";
private static String VALUE_23 = "23";
private static String VALUE_31 = "31";
private static String VALUE_59 = "59";
private static String VALUE_60 = "60";
private static String VALUE_255 = "255";
private static String VALUE_MAX_16 = "65535"; // 2^16 - 1
private static String VALUE_MAX_32 = "2147483647"; // 2^32 - 1
private PNGMetadataFormat() {
super(PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_SOME);
// root -> IHDR
addElement("IHDR", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("IHDR", "width",
DATATYPE_INTEGER, true, null,
VALUE_1, VALUE_MAX_32, true, true);
addAttribute("IHDR", "height",
DATATYPE_INTEGER, true, null,
VALUE_1, VALUE_MAX_32, true, true);
addAttribute("IHDR", "bitDepth",
DATATYPE_INTEGER, true, null,
Arrays.asList(PNGMetadata.IHDR_bitDepths));
String[] colorTypes = {
"Grayscale", "RGB", "Palette", "GrayAlpha", "RGBAlpha"
};
addAttribute("IHDR", "colorType",
DATATYPE_STRING, true, null,
Arrays.asList(colorTypes));
addAttribute("IHDR", "compressionMethod",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.IHDR_compressionMethodNames));
addAttribute("IHDR", "filterMethod",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.IHDR_filterMethodNames));
addAttribute("IHDR", "interlaceMethod",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.IHDR_interlaceMethodNames));
// root -> PLTE
addElement("PLTE", PNGMetadata.nativeMetadataFormatName,
1, 256);
// root -> PLTE -> PLTEEntry
addElement("PLTEEntry", "PLTE",
CHILD_POLICY_EMPTY);
addAttribute("PLTEEntry", "index",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("PLTEEntry", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("PLTEEntry", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("PLTEEntry", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> bKGD
addElement("bKGD", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_CHOICE);
// root -> bKGD -> bKGD_Grayscale
addElement("bKGD_Grayscale", "bKGD",
CHILD_POLICY_EMPTY);
addAttribute("bKGD_Grayscale", "gray",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> bKGD -> bKGD_RGB
addElement("bKGD_RGB", "bKGD",
CHILD_POLICY_EMPTY);
addAttribute("bKGD_RGB", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("bKGD_RGB", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("bKGD_RGB", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> bKGD -> bKGD_Palette
addElement("bKGD_Palette", "bKGD",
CHILD_POLICY_EMPTY);
addAttribute("bKGD_Palette", "index",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> cHRM
addElement("cHRM", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("cHRM", "whitePointX",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "whitePointY",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "redX",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "redY",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "greenX",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "greenY",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "blueX",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("cHRM", "blueY",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> gAMA
addElement("gAMA", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("gAMA", "value",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_32, true, true);
// root -> hIST
addElement("hIST", PNGMetadata.nativeMetadataFormatName,
1, 256);
// root -> hISTEntry
addElement("hISTEntry", "hIST",
CHILD_POLICY_EMPTY);
addAttribute("hISTEntry", "index",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("hISTEntry", "value",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> iCCP
addElement("iCCP", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("iCCP", "profileName",
DATATYPE_STRING, true, null);
addAttribute("iCCP", "compressionMethod",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.iCCP_compressionMethodNames));
addObjectValue("iCCP", byte.class, 0, Integer.MAX_VALUE);
// root -> iTXt
addElement("iTXt", PNGMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> iTXt -> iTXtEntry
addElement("iTXtEntry", "iTXt",
CHILD_POLICY_EMPTY);
addAttribute("iTXtEntry", "keyword",
DATATYPE_STRING, true, null);
addBooleanAttribute("iTXtEntry", "compressionFlag",
false, false);
addAttribute("iTXtEntry", "compressionMethod",
DATATYPE_STRING, true, null);
addAttribute("iTXtEntry", "languageTag",
DATATYPE_STRING, true, null);
addAttribute("iTXtEntry", "translatedKeyword",
DATATYPE_STRING, true, null);
addAttribute("iTXtEntry", "text",
DATATYPE_STRING, true, null);
// root -> pHYS
addElement("pHYS", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("pHYS", "pixelsPerUnitXAxis",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_32, true, true);
addAttribute("pHYS", "pixelsPerUnitYAxis",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_32, true, true);
addAttribute("pHYS", "unitSpecifier",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.unitSpecifierNames));
// root -> sBIT
addElement("sBIT", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_CHOICE);
// root -> sBIT -> sBIT_Grayscale
addElement("sBIT_Grayscale", "sBIT",
CHILD_POLICY_EMPTY);
addAttribute("sBIT_Grayscale", "gray",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sBIT -> sBIT_GrayAlpha
addElement("sBIT_GrayAlpha", "sBIT",
CHILD_POLICY_EMPTY);
addAttribute("sBIT_GrayAlpha", "gray",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_GrayAlpha", "alpha",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sBIT -> sBIT_RGB
addElement("sBIT_RGB", "sBIT",
CHILD_POLICY_EMPTY);
addAttribute("sBIT_RGB", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_RGB", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_RGB", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sBIT -> sBIT_RGBAlpha
addElement("sBIT_RGBAlpha", "sBIT",
CHILD_POLICY_EMPTY);
addAttribute("sBIT_RGBAlpha", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_RGBAlpha", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_RGBAlpha", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_RGBAlpha", "alpha",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sBIT -> sBIT_Palette
addElement("sBIT_Palette", "sBIT",
CHILD_POLICY_EMPTY);
addAttribute("sBIT_Palette", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_Palette", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sBIT_Palette", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sPLT
addElement("sPLT", PNGMetadata.nativeMetadataFormatName,
1, 256);
// root -> sPLT -> sPLTEntry
addElement("sPLTEntry", "sPLT",
CHILD_POLICY_EMPTY);
addAttribute("sPLTEntry", "index",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sPLTEntry", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sPLTEntry", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sPLTEntry", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("sPLTEntry", "alpha",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> sRGB
addElement("sRGB", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("sRGB", "renderingIntent",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.renderingIntentNames));
// root -> tEXt
addElement("tEXt", PNGMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> tEXt -> tEXtEntry
addElement("tEXtEntry", "tEXt",
CHILD_POLICY_EMPTY);
addAttribute("tEXtEntry", "keyword",
DATATYPE_STRING, true, null);
addAttribute("tEXtEntry", "value",
DATATYPE_STRING, true, null);
// root -> tIME
addElement("tIME", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("tIME", "year",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("tIME", "month",
DATATYPE_INTEGER, true, null,
VALUE_1, VALUE_12, true, true);
addAttribute("tIME", "day",
DATATYPE_INTEGER, true, null,
VALUE_1, VALUE_31, true, true);
addAttribute("tIME", "hour",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_23, true, true);
addAttribute("tIME", "minute",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_59, true, true);
addAttribute("tIME", "second",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_60, true, true);
// root -> tRNS
addElement("tRNS", PNGMetadata.nativeMetadataFormatName,
CHILD_POLICY_CHOICE);
// root -> tRNS -> tRNS_Grayscale
addElement("tRNS_Grayscale", "tRNS",
CHILD_POLICY_EMPTY);
addAttribute("tRNS_Grayscale", "gray",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> tRNS -> tRNS_RGB
addElement("tRNS_RGB", "tRNS",
CHILD_POLICY_EMPTY);
addAttribute("tRNS_RGB", "red",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("tRNS_RGB", "green",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
addAttribute("tRNS_RGB", "blue",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_MAX_16, true, true);
// root -> tRNS -> tRNS_Palette
addElement("tRNS_Palette", "tRNS",
CHILD_POLICY_EMPTY);
addAttribute("tRNS_Palette", "index",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
addAttribute("tRNS_Palette", "alpha",
DATATYPE_INTEGER, true, null,
VALUE_0, VALUE_255, true, true);
// root -> zTXt
addElement("zTXt", PNGMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> zTXt -> zTXtEntry
addElement("zTXtEntry", "zTXt",
CHILD_POLICY_EMPTY);
addAttribute("zTXtEntry", "keyword",
DATATYPE_STRING, true, null);
addAttribute("zTXtEntry", "compressionMethod",
DATATYPE_STRING, true, null,
Arrays.asList(PNGMetadata.zTXt_compressionMethodNames));
addAttribute("zTXtEntry", "text",
DATATYPE_STRING, true, null);
// root -> UnknownChunks
addElement("UnknownChunks", PNGMetadata.nativeMetadataFormatName,
1, Integer.MAX_VALUE);
// root -> UnknownChunks -> UnknownChunk
addElement("UnknownChunk", "UnknownChunks",
CHILD_POLICY_EMPTY);
addAttribute("UnknownChunk", "type",
DATATYPE_STRING, true, null);
addObjectValue("UnknownChunk", byte.class, 0, Integer.MAX_VALUE);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
public static synchronized IIOMetadataFormat getInstance() {
if (instance == null) {
instance = new PNGMetadataFormat();
}
return instance;
}
}

View File

@@ -0,0 +1,219 @@
/*
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.png;
import java.util.ListResourceBundle;
public class PNGMetadataFormatResources extends ListResourceBundle {
public PNGMetadataFormatResources() {}
protected Object[][] getContents() {
return new Object[][] {
// Node name, followed by description
{ "IHDR", "The IHDR chunk, containing the header" },
{ "PLTE", "The PLTE chunk, containing the palette" },
{ "PLTEEntry", "A palette entry" },
{ "bKGD", "The bKGD chunk, containing the background color" },
{ "bKGD_RGB", "An RGB background color, for RGB and RGBAlpha images" },
{ "bKGD_Grayscale",
"A grayscale background color, for Gray and GrayAlpha images" },
{ "bKGD_Palette", "A background palette index" },
{ "cHRM", "The cHRM chunk, containing color calibration" },
{ "gAMA", "The gAMA chunk, containing the image gamma" },
{ "hIST", "The hIST chunk, containing histogram information " },
{ "hISTEntry", "A histogram entry" },
{ "iCCP", "The iCCP chunk, containing an ICC color profile" },
{ "iTXt", "The iTXt chunk, containing internationalized text" },
{ "iTXtEntry", "A localized text entry" },
{ "pHYS",
"The pHYS chunk, containing the pixel size and aspect ratio" },
{ "sBIT", "The sBIT chunk, containing significant bit information" },
{ "sBIT_Grayscale", "Significant bit information for gray samples" },
{ "sBIT_GrayAlpha",
"Significant bit information for gray and alpha samples" },
{ "sBIT_RGB", "Significant bit information for RGB samples" },
{ "sBIT_RGBAlpha", "Significant bit information for RGBA samples" },
{ "sBIT_Palette",
"Significant bit information for RGB palette entries" },
{ "sPLT", "The sPLT chunk, containing a suggested palette" },
{ "sPLTEntry", "A suggested palette entry" },
{ "sRGB", "The sRGB chunk, containing rendering intent information" },
{ "tEXt", "The tEXt chunk, containing text" },
{ "tEXtEntry", "A text entry" },
{ "tIME", "The tIME chunk, containing the image modification time" },
{ "tRNS", "The tRNS chunk, containing transparency information" },
{ "tRNS_Grayscale",
"A grayscale value that should be considered transparent" },
{ "tRNS_RGB",
"An RGB value that should be considered transparent" },
{ "tRNS_Palette",
"A palette index that should be considered transparent" },
{ "zTXt", "The zTXt chunk, containing compressed text" },
{ "zTXtEntry", "A compressed text entry" },
{ "UnknownChunks", "A set of unknown chunks" },
{ "UnknownChunk", "Unknown chunk data stored as a byte array" },
// Node name + "/" + AttributeName, followed by description
{ "IHDR/width", "The width of the image in pixels" },
{ "IHDR/height", "The height of the image in pixels" },
{ "IHDR/bitDepth", "The bit depth of the image samples" },
{ "IHDR/colorType", "The color type of the image" },
{ "IHDR/compressionMethod",
"The compression used for image data, always \"deflate\"" },
{ "IHDR/filterMethod",
"The filtering method used for compression, always \"adaptive\"" },
{ "IHDR/interlaceMethod",
"The interlacing method, \"none\" or \"adam7\"" },
{ "PLTEEntry/index", "The index of a palette entry" },
{ "PLTEEntry/red", "The red value of a palette entry" },
{ "PLTEEntry/green", "The green value of a palette entry" },
{ "PLTEEntry/blue", "The blue value of a palette entry" },
{ "bKGD_Grayscale/gray", "A gray value to be used as a background" },
{ "bKGD_RGB/red", "A red value to be used as a background" },
{ "bKGD_RGB/green", "A green value to be used as a background" },
{ "bKGD_RGB/blue", "A blue value to be used as a background" },
{ "bKGD_Palette/index", "A palette index to be used as a background" },
{ "cHRM/whitePointX",
"The CIE x coordinate of the white point, multiplied by 1e5" },
{ "cHRM/whitePointY",
"The CIE y coordinate of the white point, multiplied by 1e5" },
{ "cHRM/redX",
"The CIE x coordinate of the red primary, multiplied by 1e5" },
{ "cHRM/redY",
"The CIE y coordinate of the red primary, multiplied by 1e5" },
{ "cHRM/greenX",
"The CIE x coordinate of the green primary, multiplied by 1e5" },
{ "cHRM/greenY",
"The CIE y coordinate of the green primary, multiplied by 1e5" },
{ "cHRM/blueX",
"The CIE x coordinate of the blue primary, multiplied by 1e5" },
{ "cHRM/blueY",
"The CIE y coordinate of the blue primary, multiplied by 1e5" },
{ "gAMA/value",
"The image gamma, multiplied by 1e5" },
{ "hISTEntry/index", "The palette index of this histogram entry" },
{ "hISTEntry/value", "The frequency of this histogram entry" },
{ "iCCP/profileName", "The name of this ICC profile" },
{ "iCCP/compressionMethod",
"The compression method used to store this ICC profile" },
{ "iTXtEntry/keyword", "The keyword" },
{ "iTXtEntry/compressionMethod",
"The compression method used to store this iTXt entry" },
{ "iTXtEntry/languageTag",
"The ISO tag describing the language this iTXt entry" },
{ "iTXtEntry/translatedKeyword",
"The translated keyword for iTXt entry" },
{ "iTXtEntry/text",
"The localized text" },
{ "pHYS/pixelsPerUnitXAxis",
"The number of horizontal pixels per unit, multiplied by 1e5" },
{ "pHYS/pixelsPerUnitYAxis",
"The number of vertical pixels per unit, multiplied by 1e5" },
{ "pHYS/unitSpecifier",
"The unit specifier for this chunk (i.e., meters)" },
{ "sBIT_Grayscale/gray",
"The number of significant bits of the gray samples" },
{ "sBIT_GrayAlpha/gray",
"The number of significant bits of the gray samples" },
{ "sBIT_GrayAlpha/alpha",
"The number of significant bits of the alpha samples" },
{ "sBIT_RGB/red",
"The number of significant bits of the red samples" },
{ "sBIT_RGB/green",
"The number of significant bits of the green samples" },
{ "sBIT_RGB/blue",
"The number of significant bits of the blue samples" },
{ "sBIT_RGBAlpha/red",
"The number of significant bits of the red samples" },
{ "sBIT_RGBAlpha/green",
"The number of significant bits of the green samples" },
{ "sBIT_RGBAlpha/blue",
"The number of significant bits of the blue samples" },
{ "sBIT_RGBAlpha/alpha",
"The number of significant bits of the alpha samples" },
{ "sBIT_Palette/red",
"The number of significant bits of the red palette entries" },
{ "sBIT_Palette/green",
"The number of significant bits of the green palette entries" },
{ "sBIT_Palette/blue",
"The number of significant bits of the blue palette entries" },
{ "sPLTEntry/index", "The index of a suggested palette entry" },
{ "sPLTEntry/red", "The red value of a suggested palette entry" },
{ "sPLTEntry/green", "The green value of a suggested palette entry" },
{ "sPLTEntry/blue", "The blue value of a suggested palette entry" },
{ "sPLTEntry/alpha", "The blue value of a suggested palette entry" },
{ "sRGB/renderingIntent", "The rendering intent" },
{ "tEXtEntry/keyword", "The keyword" },
{ "tEXtEntry/value", "The text" },
{ "tIME/year", "The year when the image was last modified" },
{ "tIME/month",
"The month when the image was last modified, 1 = January" },
{ "tIME/day",
"The day of the month when the image was last modified" },
{ "tIME/hour",
"The hour when the image was last modified" },
{ "tIME/minute",
"The minute when the image was last modified" },
{ "tIME/second",
"The second when the image was last modified, 60 = leap second" },
{ "tRNS_Grayscale/gray",
"The gray value to be considered transparent" },
{ "tRNS_RGB/red",
"The red value to be considered transparent" },
{ "tRNS_RGB/green",
"The green value to be considered transparent" },
{ "tRNS_RGB/blue",
"The blure value to be considered transparent" },
{ "tRNS_Palette/index",
"A palette index to be considered transparent" },
{ "tRNS_Palette/alpha",
"The transparency associated with the palette entry" },
{ "zTXtEntry/keyword", "The keyword" },
{ "zTXtEntry/compressionMethod", "The compression method" },
{ "zTXtEntry/text", "The compressed text" },
{ "UnknownChunk/type", "The 4-character type of the unknown chunk" }
};
}
}

View File

@@ -0,0 +1,192 @@
/*
* Copyright (c) 2000, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.png;
public class RowFilter {
private static final int abs(int x) {
return (x < 0) ? -x : x;
}
// Returns the sum of absolute differences
protected static int subFilter(byte[] currRow,
byte[] subFilteredRow,
int bytesPerPixel,
int bytesPerRow) {
int badness = 0;
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xff;
int left = currRow[i - bytesPerPixel] & 0xff;
int difference = curr - left;
subFilteredRow[i] = (byte)difference;
badness += abs(difference);
}
return badness;
}
// Returns the sum of absolute differences
protected static int upFilter(byte[] currRow,
byte[] prevRow,
byte[] upFilteredRow,
int bytesPerPixel,
int bytesPerRow) {
int badness = 0;
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xff;
int up = prevRow[i] & 0xff;
int difference = curr - up;
upFilteredRow[i] = (byte)difference;
badness += abs(difference);
}
return badness;
}
protected final int paethPredictor(int a, int b, int c) {
int p = a + b - c;
int pa = abs(p - a);
int pb = abs(p - b);
int pc = abs(p - c);
if ((pa <= pb) && (pa <= pc)) {
return a;
} else if (pb <= pc) {
return b;
} else {
return c;
}
}
public int filterRow(int colorType,
byte[] currRow,
byte[] prevRow,
byte[][] scratchRows,
int bytesPerRow,
int bytesPerPixel) {
// Use type 0 for palette images
if (colorType != PNGImageReader.PNG_COLOR_PALETTE) {
System.arraycopy(currRow, bytesPerPixel,
scratchRows[0], bytesPerPixel,
bytesPerRow);
return 0;
}
int[] filterBadness = new int[5];
for (int i = 0; i < 5; i++) {
filterBadness[i] = Integer.MAX_VALUE;
}
{
int badness = 0;
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xff;
badness += curr;
}
filterBadness[0] = badness;
}
{
byte[] subFilteredRow = scratchRows[1];
int badness = subFilter(currRow,
subFilteredRow,
bytesPerPixel,
bytesPerRow);
filterBadness[1] = badness;
}
{
byte[] upFilteredRow = scratchRows[2];
int badness = upFilter(currRow,
prevRow,
upFilteredRow,
bytesPerPixel,
bytesPerRow);
filterBadness[2] = badness;
}
{
byte[] averageFilteredRow = scratchRows[3];
int badness = 0;
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xff;
int left = currRow[i - bytesPerPixel] & 0xff;
int up = prevRow[i] & 0xff;
int difference = curr - (left + up)/2;;
averageFilteredRow[i] = (byte)difference;
badness += abs(difference);
}
filterBadness[3] = badness;
}
{
byte[] paethFilteredRow = scratchRows[4];
int badness = 0;
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
int curr = currRow[i] & 0xff;
int left = currRow[i - bytesPerPixel] & 0xff;
int up = prevRow[i] & 0xff;
int upleft = prevRow[i - bytesPerPixel] & 0xff;
int predictor = paethPredictor(left, up, upleft);
int difference = curr - predictor;
paethFilteredRow[i] = (byte)difference;
badness += abs(difference);
}
filterBadness[4] = badness;
}
int minBadness = filterBadness[0];
int filterType = 0;
for (int i = 1; i < 5; i++) {
if (filterBadness[i] < minBadness) {
minBadness = filterBadness[i];
filterType = i;
}
}
if (filterType == 0) {
System.arraycopy(currRow, bytesPerPixel,
scratchRows[0], bytesPerPixel,
bytesPerRow);
}
return filterType;
}
}

View File

@@ -0,0 +1,322 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.imageio.IIOException;
import javax.imageio.ImageReader;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import java.io.*;
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,
* and shift the decoded image origin if the proper decoding parameter
* are set in the provided <code>WBMPImageReadParam</code>.
*/
public class WBMPImageReader extends ImageReader {
/** The input stream where reads from */
private ImageInputStream iis = null;
/** Indicates whether the header is read. */
private boolean gotHeader = false;
/** The original image width. */
private int width;
/** The original image height. */
private int height;
private int wbmpType;
private WBMPMetadata metadata;
/** Constructs <code>WBMPImageReader</code> from the provided
* <code>ImageReaderSpi</code>.
*/
public WBMPImageReader(ImageReaderSpi originator) {
super(originator);
}
/** Overrides the method defined in the superclass. */
public void setInput(Object input,
boolean seekForwardOnly,
boolean ignoreMetadata) {
super.setInput(input, seekForwardOnly, ignoreMetadata);
iis = (ImageInputStream) input; // Always works
gotHeader = false;
}
/** Overrides the method defined in the superclass. */
public int getNumImages(boolean allowSearch) throws IOException {
if (iis == null) {
throw new IllegalStateException(I18N.getString("GetNumImages0"));
}
if (seekForwardOnly && allowSearch) {
throw new IllegalStateException(I18N.getString("GetNumImages1"));
}
return 1;
}
public int getWidth(int imageIndex) throws IOException {
checkIndex(imageIndex);
readHeader();
return width;
}
public int getHeight(int imageIndex) throws IOException {
checkIndex(imageIndex);
readHeader();
return height;
}
public boolean isRandomAccessEasy(int imageIndex) throws IOException {
checkIndex(imageIndex);
return true;
}
private void checkIndex(int imageIndex) {
if (imageIndex != 0) {
throw new IndexOutOfBoundsException(I18N.getString("WBMPImageReader0"));
}
}
public void readHeader() throws IOException {
if (gotHeader)
return;
if (iis == null) {
throw new IllegalStateException("Input source not set!");
}
metadata = new WBMPMetadata();
wbmpType = iis.readByte(); // TypeField
byte fixHeaderField = iis.readByte();
// check for valid wbmp image
if (fixHeaderField != 0
|| !isValidWbmpType(wbmpType))
{
throw new IIOException(I18N.getString("WBMPImageReader2"));
}
metadata.wbmpType = wbmpType;
// Read image width
width = ReaderUtil.readMultiByteInteger(iis);
metadata.width = width;
// Read image height
height = ReaderUtil.readMultiByteInteger(iis);
metadata.height = height;
gotHeader = true;
}
public Iterator getImageTypes(int imageIndex)
throws IOException {
checkIndex(imageIndex);
readHeader();
BufferedImage bi =
new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
ArrayList list = new ArrayList(1);
list.add(new ImageTypeSpecifier(bi));
return list.iterator();
}
public ImageReadParam getDefaultReadParam() {
return new ImageReadParam();
}
public IIOMetadata getImageMetadata(int imageIndex)
throws IOException {
checkIndex(imageIndex);
if (metadata == null) {
readHeader();
}
return metadata;
}
public IIOMetadata getStreamMetadata() throws IOException {
return null;
}
public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {
if (iis == null) {
throw new IllegalStateException(I18N.getString("WBMPImageReader1"));
}
checkIndex(imageIndex);
clearAbortRequest();
processImageStarted(imageIndex);
if (param == null)
param = getDefaultReadParam();
//read header
readHeader();
Rectangle sourceRegion = new Rectangle(0, 0, 0, 0);
Rectangle destinationRegion = new Rectangle(0, 0, 0, 0);
computeRegions(param, this.width, this.height,
param.getDestination(),
sourceRegion,
destinationRegion);
int scaleX = param.getSourceXSubsampling();
int scaleY = param.getSourceYSubsampling();
int xOffset = param.getSubsamplingXOffset();
int yOffset = param.getSubsamplingYOffset();
// If the destination is provided, then use it. Otherwise, create new one
BufferedImage bi = param.getDestination();
if (bi == null)
bi = new BufferedImage(destinationRegion.x + destinationRegion.width,
destinationRegion.y + destinationRegion.height,
BufferedImage.TYPE_BYTE_BINARY);
boolean noTransform =
destinationRegion.equals(new Rectangle(0, 0, width, height)) &&
destinationRegion.equals(new Rectangle(0, 0, bi.getWidth(), bi.getHeight()));
// Get the image data.
WritableRaster tile = bi.getWritableTile(0, 0);
// Get the SampleModel.
MultiPixelPackedSampleModel sm =
(MultiPixelPackedSampleModel)bi.getSampleModel();
if (noTransform) {
if (abortRequested()) {
processReadAborted();
return bi;
}
// If noTransform is necessary, read the data.
iis.read(((DataBufferByte)tile.getDataBuffer()).getData(),
0, height*sm.getScanlineStride());
processImageUpdate(bi,
0, 0,
width, height, 1, 1,
new int[]{0});
processImageProgress(100.0F);
} else {
int len = (this.width + 7) / 8;
byte[] buf = new byte[len];
byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData();
int lineStride = sm.getScanlineStride();
iis.skipBytes(len * sourceRegion.y);
int skipLength = len * (scaleY - 1);
// cache the values to avoid duplicated computation
int[] srcOff = new int[destinationRegion.width];
int[] destOff = new int[destinationRegion.width];
int[] srcPos = new int[destinationRegion.width];
int[] destPos = new int[destinationRegion.width];
for (int i = destinationRegion.x, x = sourceRegion.x, j = 0;
i < destinationRegion.x + destinationRegion.width;
i++, j++, x += scaleX) {
srcPos[j] = x >> 3;
srcOff[j] = 7 - (x & 7);
destPos[j] = i >> 3;
destOff[j] = 7 - (i & 7);
}
for (int j = 0, y = sourceRegion.y,
k = destinationRegion.y * lineStride;
j < destinationRegion.height; j++, y+=scaleY) {
if (abortRequested())
break;
iis.read(buf, 0, len);
for (int i = 0; i < destinationRegion.width; i++) {
//get the bit and assign to the data buffer of the raster
int v = (buf[srcPos[i]] >> srcOff[i]) & 1;
data[k + destPos[i]] |= v << destOff[i];
}
k += lineStride;
iis.skipBytes(skipLength);
processImageUpdate(bi,
0, j,
destinationRegion.width, 1, 1, 1,
new int[]{0});
processImageProgress(100.0F*j/destinationRegion.height);
}
}
if (abortRequested())
processReadAborted();
else
processImageComplete();
return bi;
}
public boolean canReadRaster() {
return true;
}
public Raster readRaster(int imageIndex,
ImageReadParam param) throws IOException {
BufferedImage bi = read(imageIndex, param);
return bi.getData();
}
public void reset() {
super.reset();
iis = null;
gotHeader = false;
}
/*
* This method verifies that given byte is valid wbmp type marker.
* At the moment only 0x0 marker is described by wbmp spec.
*/
boolean isValidWbmpType(int type) {
return type == 0;
}
}

View File

@@ -0,0 +1,130 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.util.Locale;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.spi.IIORegistry;
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"};
private static String[] entensions = {"wbmp"};
private static String[] mimeType = {"image/vnd.wap.wbmp"};
private boolean registered = false;
public WBMPImageReaderSpi() {
super("Oracle Corporation",
"1.0",
formatNames,
entensions,
mimeType,
"com.sun.imageio.plugins.wbmp.WBMPImageReader",
new Class[] { ImageInputStream.class },
writerSpiNames,
true,
null, null, null, null,
true,
WBMPMetadata.nativeMetadataFormatName,
"com.sun.imageio.plugins.wbmp.WBMPMetadataFormat",
null, null);
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
registered = true;
}
public String getDescription(Locale locale) {
return "Standard WBMP Image Reader";
}
public boolean canDecodeInput(Object source) throws IOException {
if (!(source instanceof ImageInputStream)) {
return false;
}
ImageInputStream stream = (ImageInputStream)source;
stream.mark();
try {
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
return false;
}
int width = ReaderUtil.readMultiByteInteger(stream);
int height = ReaderUtil.readMultiByteInteger(stream);
// check image dimension
if (width <= 0 || height <= 0) {
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.
return (width < MAX_WBMP_WIDTH) && (height < MAX_WBMP_HEIGHT);
}
dataLength -= stream.getStreamPosition();
long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1);
return (dataLength == scanSize * height);
} finally {
stream.reset();
}
}
public ImageReader createReaderInstance(Object extension)
throws IIOException {
return new WBMPImageReader(this);
}
}

View File

@@ -0,0 +1,315 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.io.IOException;
import javax.imageio.IIOImage;
import javax.imageio.IIOException;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import com.sun.imageio.plugins.common.I18N;
/**
* The Java Image IO plugin writer for encoding a binary RenderedImage into
* a WBMP format.
*
* The encoding process may clip, subsample using the parameters
* specified in the <code>ImageWriteParam</code>.
*
* @see com.sun.media.imageio.plugins.WBMPImageWriteParam
*/
public class WBMPImageWriter extends ImageWriter {
/** The output stream to write into */
private ImageOutputStream stream = null;
// Get the number of bits required to represent an int.
private static int getNumBits(int intValue) {
int numBits = 32;
int mask = 0x80000000;
while(mask != 0 && (intValue & mask) == 0) {
numBits--;
mask >>>= 1;
}
return numBits;
}
// Convert an int value to WBMP multi-byte format.
private static byte[] intToMultiByte(int intValue) {
int numBitsLeft = getNumBits(intValue);
byte[] multiBytes = new byte[(numBitsLeft + 6)/7];
int maxIndex = multiBytes.length - 1;
for(int b = 0; b <= maxIndex; b++) {
multiBytes[b] = (byte)((intValue >>> ((maxIndex - b)*7))&0x7f);
if(b != maxIndex) {
multiBytes[b] |= (byte)0x80;
}
}
return multiBytes;
}
/** Constructs <code>WBMPImageWriter</code> based on the provided
* <code>ImageWriterSpi</code>.
*/
public WBMPImageWriter(ImageWriterSpi originator) {
super(originator);
}
public void setOutput(Object output) {
super.setOutput(output); // validates output
if (output != null) {
if (!(output instanceof ImageOutputStream))
throw new IllegalArgumentException(I18N.getString("WBMPImageWriter"));
this.stream = (ImageOutputStream)output;
} else
this.stream = null;
}
public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
return null;
}
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
ImageWriteParam param) {
WBMPMetadata meta = new WBMPMetadata();
meta.wbmpType = 0; // default wbmp level
return meta;
}
public IIOMetadata convertStreamMetadata(IIOMetadata inData,
ImageWriteParam param) {
return null;
}
public IIOMetadata convertImageMetadata(IIOMetadata metadata,
ImageTypeSpecifier type,
ImageWriteParam param) {
return null;
}
public boolean canWriteRasters() {
return true;
}
public void write(IIOMetadata streamMetadata,
IIOImage image,
ImageWriteParam param) throws IOException {
if (stream == null) {
throw new IllegalStateException(I18N.getString("WBMPImageWriter3"));
}
if (image == null) {
throw new IllegalArgumentException(I18N.getString("WBMPImageWriter4"));
}
clearAbortRequest();
processImageStarted(0);
if (param == null)
param = getDefaultWriteParam();
RenderedImage input = null;
Raster inputRaster = null;
boolean writeRaster = image.hasRaster();
Rectangle sourceRegion = param.getSourceRegion();
SampleModel sampleModel = null;
if (writeRaster) {
inputRaster = image.getRaster();
sampleModel = inputRaster.getSampleModel();
} else {
input = image.getRenderedImage();
sampleModel = input.getSampleModel();
inputRaster = input.getData();
}
checkSampleModel(sampleModel);
if (sourceRegion == null)
sourceRegion = inputRaster.getBounds();
else
sourceRegion = sourceRegion.intersection(inputRaster.getBounds());
if (sourceRegion.isEmpty())
throw new RuntimeException(I18N.getString("WBMPImageWriter1"));
int scaleX = param.getSourceXSubsampling();
int scaleY = param.getSourceYSubsampling();
int xOffset = param.getSubsamplingXOffset();
int yOffset = param.getSubsamplingYOffset();
sourceRegion.translate(xOffset, yOffset);
sourceRegion.width -= xOffset;
sourceRegion.height -= yOffset;
int minX = sourceRegion.x / scaleX;
int minY = sourceRegion.y / scaleY;
int w = (sourceRegion.width + scaleX - 1) / scaleX;
int h = (sourceRegion.height + scaleY - 1) / scaleY;
Rectangle destinationRegion = new Rectangle(minX, minY, w, h);
sampleModel = sampleModel.createCompatibleSampleModel(w, h);
SampleModel destSM= sampleModel;
// If the data are not formatted nominally then reformat.
if(sampleModel.getDataType() != DataBuffer.TYPE_BYTE ||
!(sampleModel instanceof MultiPixelPackedSampleModel) ||
((MultiPixelPackedSampleModel)sampleModel).getDataBitOffset() != 0) {
destSM =
new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE,
w, h, 1,
w + 7 >> 3, 0);
}
if (!destinationRegion.equals(sourceRegion)) {
if (scaleX == 1 && scaleY == 1)
inputRaster = inputRaster.createChild(inputRaster.getMinX(),
inputRaster.getMinY(),
w, h, minX, minY, null);
else {
WritableRaster ras = Raster.createWritableRaster(destSM,
new Point(minX, minY));
byte[] data = ((DataBufferByte)ras.getDataBuffer()).getData();
for(int j = minY, y = sourceRegion.y, k = 0;
j < minY + h; j++, y += scaleY) {
for (int i = 0, x = sourceRegion.x;
i <w; i++, x +=scaleX) {
int v = inputRaster.getSample(x, y, 0);
data[k + (i >> 3)] |= v << (7 - (i & 7));
}
k += w + 7 >> 3;
}
inputRaster = ras;
}
}
// If the data are not formatted nominally then reformat.
if(!destSM.equals(inputRaster.getSampleModel())) {
WritableRaster raster =
Raster.createWritableRaster(destSM,
new Point(inputRaster.getMinX(),
inputRaster.getMinY()));
raster.setRect(inputRaster);
inputRaster = raster;
}
// Check whether the image is white-is-zero.
boolean isWhiteZero = false;
if(!writeRaster && input.getColorModel() instanceof IndexColorModel) {
IndexColorModel icm = (IndexColorModel)input.getColorModel();
isWhiteZero = icm.getRed(0) > icm.getRed(1);
}
// Get the line stride, bytes per row, and data array.
int lineStride =
((MultiPixelPackedSampleModel)destSM).getScanlineStride();
int bytesPerRow = (w + 7)/8;
byte[] bdata = ((DataBufferByte)inputRaster.getDataBuffer()).getData();
// Write WBMP header.
stream.write(0); // TypeField
stream.write(0); // FixHeaderField
stream.write(intToMultiByte(w)); // width
stream.write(intToMultiByte(h)); // height
// Write the data.
if(!isWhiteZero && lineStride == bytesPerRow) {
// Write the entire image.
stream.write(bdata, 0, h * bytesPerRow);
processImageProgress(100.0F);
} else {
// Write the image row-by-row.
int offset = 0;
if(!isWhiteZero) {
// Black-is-zero
for(int row = 0; row < h; row++) {
if (abortRequested())
break;
stream.write(bdata, offset, bytesPerRow);
offset += lineStride;
processImageProgress(100.0F * row / h);
}
} else {
// White-is-zero: need to invert data.
byte[] inverted = new byte[bytesPerRow];
for(int row = 0; row < h; row++) {
if (abortRequested())
break;
for(int col = 0; col < bytesPerRow; col++) {
inverted[col] = (byte)(~(bdata[col+offset]));
}
stream.write(inverted, 0, bytesPerRow);
offset += lineStride;
processImageProgress(100.0F * row / h);
}
}
}
if (abortRequested())
processWriteAborted();
else {
processImageComplete();
stream.flushBefore(stream.getStreamPosition());
}
}
public void reset() {
super.reset();
stream = null;
}
private void checkSampleModel(SampleModel sm) {
int type = sm.getDataType();
if (type < DataBuffer.TYPE_BYTE || type > DataBuffer.TYPE_INT
|| sm.getNumBands() != 1 || sm.getSampleSize(0) != 1)
throw new IllegalArgumentException(I18N.getString("WBMPImageWriter2"));
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.spi.ServiceRegistry;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.ImageWriter;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.IIOException;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.SampleModel;
import java.util.Locale;
public class WBMPImageWriterSpi extends ImageWriterSpi {
private static String [] readerSpiNames =
{"com.sun.imageio.plugins.wbmp.WBMPImageReaderSpi"};
private static String[] formatNames = {"wbmp", "WBMP"};
private static String[] entensions = {"wbmp"};
private static String[] mimeType = {"image/vnd.wap.wbmp"};
private boolean registered = false;
public WBMPImageWriterSpi() {
super("Oracle Corporation",
"1.0",
formatNames,
entensions,
mimeType,
"com.sun.imageio.plugins.wbmp.WBMPImageWriter",
new Class[] { ImageOutputStream.class },
readerSpiNames,
true,
null, null, null, null,
true,
null, null, null, null);
}
public String getDescription(Locale locale) {
return "Standard WBMP Image Writer";
}
public void onRegistration(ServiceRegistry registry,
Class<?> category) {
if (registered) {
return;
}
registered = true;
}
public boolean canEncodeImage(ImageTypeSpecifier type) {
SampleModel sm = type.getSampleModel();
if (!(sm instanceof MultiPixelPackedSampleModel))
return false;
if (sm.getSampleSize(0) != 1)
return false;
return true;
}
public ImageWriter createWriterInstance(Object extension)
throws IIOException {
return new WBMPImageWriter(this);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import org.w3c.dom.Node;
import com.sun.imageio.plugins.common.I18N;
import com.sun.imageio.plugins.common.ImageUtil;
public class WBMPMetadata extends IIOMetadata {
static final String nativeMetadataFormatName =
"javax_imageio_wbmp_1.0";
public int wbmpType;
public int width;
public int height;
public WBMPMetadata() {
super(true,
nativeMetadataFormatName,
"com.sun.imageio.plugins.wbmp.WBMPMetadataFormat",
null, null);
}
public boolean isReadOnly() {
return true;
}
public Node getAsTree(String formatName) {
if (formatName.equals(nativeMetadataFormatName)) {
return getNativeTree();
} else if (formatName.equals
(IIOMetadataFormatImpl.standardMetadataFormatName)) {
return getStandardTree();
} else {
throw new IllegalArgumentException(I18N.getString("WBMPMetadata0"));
}
}
private Node getNativeTree() {
IIOMetadataNode root =
new IIOMetadataNode(nativeMetadataFormatName);
addChildNode(root, "WBMPType", new Integer(wbmpType));
addChildNode(root, "Width", new Integer(width));
addChildNode(root, "Height", new Integer(height));
return root;
}
public void setFromTree(String formatName, Node root) {
throw new IllegalStateException(I18N.getString("WBMPMetadata1"));
}
public void mergeTree(String formatName, Node root) {
throw new IllegalStateException(I18N.getString("WBMPMetadata1"));
}
public void reset() {
throw new IllegalStateException(I18N.getString("WBMPMetadata1"));
}
private IIOMetadataNode addChildNode(IIOMetadataNode root,
String name,
Object object) {
IIOMetadataNode child = new IIOMetadataNode(name);
if (object != null) {
child.setUserObject(object);
child.setNodeValue(ImageUtil.convertObjectToString(object));
}
root.appendChild(child);
return child;
}
protected IIOMetadataNode getStandardChromaNode() {
IIOMetadataNode node = new IIOMetadataNode("Chroma");
IIOMetadataNode subNode = new IIOMetadataNode("BlackIsZero");
subNode.setAttribute("value", "TRUE");
node.appendChild(subNode);
return node;
}
protected IIOMetadataNode getStandardDimensionNode() {
IIOMetadataNode dimension_node = new IIOMetadataNode("Dimension");
IIOMetadataNode node = null; // scratch node
// PixelAspectRatio not in image
node = new IIOMetadataNode("ImageOrientation");
node.setAttribute("value", "Normal");
dimension_node.appendChild(node);
return dimension_node;
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.plugins.wbmp;
import java.util.Arrays;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataFormatImpl;
public class WBMPMetadataFormat extends IIOMetadataFormatImpl {
private static IIOMetadataFormat instance = null;
private WBMPMetadataFormat() {
super(WBMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_SOME);
// root -> ImageDescriptor
addElement("ImageDescriptor",
WBMPMetadata.nativeMetadataFormatName,
CHILD_POLICY_EMPTY);
addAttribute("ImageDescriptor", "WBMPType",
DATATYPE_INTEGER, true, "0");
addAttribute("ImageDescriptor", "Width",
DATATYPE_INTEGER, true, null,
"0", "65535", true, true);
addAttribute("ImageDescriptor", "Height",
DATATYPE_INTEGER, true, null,
"1", "65535", true, true);
}
public boolean canNodeAppear(String elementName,
ImageTypeSpecifier imageType) {
return true;
}
public static synchronized IIOMetadataFormat getInstance() {
if (instance == null) {
instance = new WBMPMetadataFormat();
}
return instance;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.util.Locale;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.FileImageInputStream;
public class FileImageInputStreamSpi extends ImageInputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class inputClass = File.class;
public FileImageInputStreamSpi() {
super(vendorName, version, inputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates a FileImageInputStream from a File";
}
public ImageInputStream createInputStreamInstance(Object input,
boolean useCache,
File cacheDir) {
if (input instanceof File) {
try {
return new FileImageInputStream((File)input);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.util.Locale;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.FileImageOutputStream;
public class FileImageOutputStreamSpi extends ImageOutputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class outputClass = File.class;
public FileImageOutputStreamSpi() {
super(vendorName, version, outputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates a FileImageOutputStream from a File";
}
public ImageOutputStream createOutputStreamInstance(Object output,
boolean useCache,
File cacheDir) {
if (output instanceof File) {
try {
return new FileImageOutputStream((File)output);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.util.Locale;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.FileCacheImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
public class InputStreamImageInputStreamSpi extends ImageInputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class inputClass = InputStream.class;
public InputStreamImageInputStreamSpi() {
super(vendorName, version, inputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates a FileCacheImageInputStream or MemoryCacheImageInputStream from an InputStream";
}
public boolean canUseCacheFile() {
return true;
}
public boolean needsCacheFile() {
return false;
}
public ImageInputStream createInputStreamInstance(Object input,
boolean useCache,
File cacheDir)
throws IOException {
if (input instanceof InputStream) {
InputStream is = (InputStream)input;
if (useCache) {
return new FileCacheImageInputStream(is, cacheDir);
} else {
return new MemoryCacheImageInputStream(is);
}
} else {
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Locale;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.FileCacheImageOutputStream;
import javax.imageio.stream.MemoryCacheImageOutputStream;
public class OutputStreamImageOutputStreamSpi extends ImageOutputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class outputClass = OutputStream.class;
public OutputStreamImageOutputStreamSpi() {
super(vendorName, version, outputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates an OutputStreamImageOutputStream from an OutputStream";
}
public boolean canUseCacheFile() {
return true;
}
public boolean needsCacheFile() {
return false;
}
public ImageOutputStream createOutputStreamInstance(Object output,
boolean useCache,
File cacheDir)
throws IOException {
if (output instanceof OutputStream) {
OutputStream os = (OutputStream)output;
if (useCache) {
return new FileCacheImageOutputStream(os, cacheDir);
} else {
return new MemoryCacheImageOutputStream(os);
}
} else {
throw new IllegalArgumentException();
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Locale;
import javax.imageio.spi.ImageInputStreamSpi;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.FileImageInputStream;
public class RAFImageInputStreamSpi extends ImageInputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class inputClass = RandomAccessFile.class;
public RAFImageInputStreamSpi() {
super(vendorName, version, inputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates a FileImageInputStream from a RandomAccessFile";
}
public ImageInputStream createInputStreamInstance(Object input,
boolean useCache,
File cacheDir) {
if (input instanceof RandomAccessFile) {
try {
return new FileImageInputStream((RandomAccessFile)input);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException
("input not a RandomAccessFile!");
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.spi;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Locale;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.imageio.stream.FileImageOutputStream;
public class RAFImageOutputStreamSpi extends ImageOutputStreamSpi {
private static final String vendorName = "Oracle Corporation";
private static final String version = "1.0";
private static final Class outputClass = RandomAccessFile.class;
public RAFImageOutputStreamSpi() {
super(vendorName, version, outputClass);
}
public String getDescription(Locale locale) {
return "Service provider that instantiates a FileImageOutputStream from a RandomAccessFile";
}
public ImageOutputStream createOutputStreamInstance(Object output,
boolean useCache,
File cacheDir) {
if (output instanceof RandomAccessFile) {
try {
return new FileImageOutputStream((RandomAccessFile)output);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
throw new IllegalArgumentException
("input not a RandomAccessFile!");
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.stream;
import java.io.Closeable;
import java.io.IOException;
import sun.java2d.DisposerRecord;
/**
* Convenience class that closes a given resource (e.g. RandomAccessFile),
* typically associated with an Image{Input,Output}Stream, prior to the
* stream being garbage collected.
*/
public class CloseableDisposerRecord implements DisposerRecord {
private Closeable closeable;
public CloseableDisposerRecord(Closeable closeable) {
this.closeable = closeable;
}
public synchronized void dispose() {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
} finally {
closeable = null;
}
}
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.stream;
import java.io.IOException;
import java.util.Set;
import java.util.WeakHashMap;
import javax.imageio.stream.ImageInputStream;
/**
* This class provide means to properly close hanging
* image input/output streams on VM shutdown.
* This might be useful for proper cleanup such as removal
* of temporary files.
*
* Addition of stream do not prevent it from being garbage collected
* if no other references to it exists. Stream can be closed
* explicitly without removal from StreamCloser queue.
* Explicit removal from the queue only helps to save some memory.
*/
public class StreamCloser {
private static WeakHashMap<CloseAction, Object> toCloseQueue;
private static Thread streamCloser;
public static void addToQueue(CloseAction ca) {
synchronized (StreamCloser.class) {
if (toCloseQueue == null) {
toCloseQueue =
new WeakHashMap<CloseAction, Object>();
}
toCloseQueue.put(ca, null);
if (streamCloser == null) {
final Runnable streamCloserRunnable = new Runnable() {
public void run() {
if (toCloseQueue != null) {
synchronized (StreamCloser.class) {
Set<CloseAction> set =
toCloseQueue.keySet();
// Make a copy of the set in order to avoid
// concurrent modification (the is.close()
// will in turn call removeFromQueue())
CloseAction[] actions =
new CloseAction[set.size()];
actions = set.toArray(actions);
for (CloseAction ca : actions) {
if (ca != null) {
try {
ca.performAction();
} catch (IOException e) {
}
}
}
}
}
}
};
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
/* The thread must be a member of a thread group
* which will not get GCed before VM exit.
* Make its parent the top-level thread group.
*/
ThreadGroup tg =
Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
streamCloser = new Thread(tg, streamCloserRunnable);
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
streamCloser.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(streamCloser);
return null;
}
});
}
}
}
public static void removeFromQueue(CloseAction ca) {
synchronized (StreamCloser.class) {
if (toCloseQueue != null) {
toCloseQueue.remove(ca);
}
}
}
public static CloseAction createCloseAction(ImageInputStream iis) {
return new CloseAction(iis);
}
public static final class CloseAction {
private ImageInputStream iis;
private CloseAction(ImageInputStream iis) {
this.iis = iis;
}
public void performAction() throws IOException {
if (iis != null) {
iis.close();
}
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.imageio.stream;
import java.io.IOException;
import javax.imageio.stream.ImageInputStream;
/**
* Small class to assist in properly closing an ImageInputStream instance
* prior to garbage collection. The ImageInputStreamImpl class defines a
* finalize() method, but in a number of its public subclasses
* (e.g. FileImageInputStream) we override the finalize() method to be
* empty for performance reasons, and instead rely on the Disposer mechanism
* for closing/disposing resources. This is fine when one of these classes
* is instantiated directly (e.g. new FileImageInputStream()) but in the
* unlikely case where a user defines their own subclass of one of those
* streams, we need some way to get back to the behavior of
* ImageInputStreamImpl, which will call close() as part of finalization.
*
* Typically an Image{Input,Output}Stream will construct an instance of
* StreamFinalizer in its constructor if it detects that it has been
* subclassed by the user. The ImageInputStream instance will hold a
* reference to the StreamFinalizer, and the StreamFinalizer will hold a
* reference back to the ImageInputStream from which it was created. When
* both are no longer reachable, the StreamFinalizer.finalize() method will
* be called, which will take care of closing down the ImageInputStream.
*
* Clearly this is a bit of a hack, but it will likely only be used in the
* rarest of circumstances: when a user has subclassed one of the public
* stream classes. (It should be no worse than the old days when the public
* stream classes had non-empty finalize() methods.)
*/
public class StreamFinalizer {
private ImageInputStream stream;
public StreamFinalizer(ImageInputStream stream) {
this.stream = stream;
}
protected void finalize() throws Throwable {
try {
stream.close();
} catch (IOException e) {
} finally {
stream = null;
super.finalize();
}
}
}