| /* |
| * 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)); |
| } |
| */ |
| } |
| } |
| |
| } |