1/*
2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.imageio.plugins.jpeg;
27
28import javax.imageio.IIOException;
29import javax.imageio.metadata.IIOInvalidTreeException;
30import javax.imageio.metadata.IIOMetadataNode;
31import javax.imageio.stream.ImageOutputStream;
32
33import java.io.IOException;
34
35import org.w3c.dom.Node;
36import org.w3c.dom.NamedNodeMap;
37
38/**
39 * An Adobe APP14 (Application-Specific) marker segment.
40 */
41class AdobeMarkerSegment extends MarkerSegment {
42    int version;
43    int flags0;
44    int flags1;
45    int transform;
46    private static final int ID_SIZE = 5;
47
48    AdobeMarkerSegment(int transform) {
49        super(JPEG.APP14);
50        version = 101;
51        flags0 = 0;
52        flags1 = 0;
53        this.transform = transform;
54    }
55
56    AdobeMarkerSegment(JPEGBuffer buffer) throws IOException {
57        super(buffer);
58        buffer.bufPtr += ID_SIZE; // Skip the id
59        version = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
60        version |= buffer.buf[buffer.bufPtr++] & 0xff;
61        flags0 = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
62        flags0 |= buffer.buf[buffer.bufPtr++] & 0xff;
63        flags1 = (buffer.buf[buffer.bufPtr++] & 0xff) << 8;
64        flags1 |= buffer.buf[buffer.bufPtr++] & 0xff;
65        transform = buffer.buf[buffer.bufPtr++] & 0xff;
66        buffer.bufAvail -= length;
67    }
68
69    AdobeMarkerSegment(Node node) throws IIOInvalidTreeException {
70        this(0); // default transform will be changed
71        updateFromNativeNode(node, true);
72    }
73
74    IIOMetadataNode getNativeNode() {
75        IIOMetadataNode node = new IIOMetadataNode("app14Adobe");
76        node.setAttribute("version", Integer.toString(version));
77        node.setAttribute("flags0", Integer.toString(flags0));
78        node.setAttribute("flags1", Integer.toString(flags1));
79        node.setAttribute("transform", Integer.toString(transform));
80
81        return node;
82    }
83
84    void updateFromNativeNode(Node node, boolean fromScratch)
85        throws IIOInvalidTreeException {
86        // Only the transform is required
87        NamedNodeMap attrs = node.getAttributes();
88        transform = getAttributeValue(node, attrs, "transform", 0, 2, true);
89        int count = attrs.getLength();
90        if (count > 4) {
91            throw new IIOInvalidTreeException
92                ("Adobe APP14 node cannot have > 4 attributes", node);
93        }
94        if (count > 1) {
95            int value = getAttributeValue(node, attrs, "version",
96                                          100, 255, false);
97            version = (value != -1) ? value : version;
98            value = getAttributeValue(node, attrs, "flags0", 0, 65535, false);
99            flags0 = (value != -1) ? value : flags0;
100            value = getAttributeValue(node, attrs, "flags1", 0, 65535, false);
101            flags1 = (value != -1) ? value : flags1;
102        }
103    }
104
105    /**
106     * Writes the data for this segment to the stream in
107     * valid JPEG format.
108     */
109    void write(ImageOutputStream ios) throws IOException {
110        length = 14;
111        writeTag(ios);
112        byte [] id = {0x41, 0x64, 0x6F, 0x62, 0x65};
113        ios.write(id);
114        write2bytes(ios, version);
115        write2bytes(ios, flags0);
116        write2bytes(ios, flags1);
117        ios.write(transform);
118    }
119
120    static void writeAdobeSegment(ImageOutputStream ios, int transform)
121        throws IOException {
122        (new AdobeMarkerSegment(transform)).write(ios);
123    }
124
125    void print () {
126        printTag("Adobe APP14");
127        System.out.print("Version: ");
128        System.out.println(version);
129        System.out.print("Flags0: 0x");
130        System.out.println(Integer.toHexString(flags0));
131        System.out.print("Flags1: 0x");
132        System.out.println(Integer.toHexString(flags1));
133        System.out.print("Transform: ");
134        System.out.println(transform);
135    }
136}
137