224 lines · 7.7 KB · Java
RawDownload
/* * 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;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        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();    }}