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,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);
}
}
}