View Javadoc
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  
26  package com.sun.imageio.plugins.jpeg;
27  
28  //import javax.imageio.IIOException;
29  import javax.imageio.metadata.IIOInvalidTreeException;
30  import javax.imageio.metadata.IIOMetadataNode;
31  import javax.imageio.stream.ImageOutputStream;
32  
33  import java.io.IOException;
34  
35  import org.w3c.dom.Node;
36  import org.w3c.dom.NodeList;
37  import org.w3c.dom.NamedNodeMap;
38  
39  /**
40   * An SOS (Start Of Scan) marker segment.
41   */
42  class SOSMarkerSegment extends MarkerSegment {
43      int startSpectralSelection;
44      int endSpectralSelection;
45      int approxHigh;
46      int approxLow;
47      ScanComponentSpec [] componentSpecs; // Array size is numScanComponents
48  
49      SOSMarkerSegment(boolean willSubsample,
50                       byte[] componentIDs,
51                       int numComponents) {
52          super(JPEG.SOS);
53          startSpectralSelection = 0;
54          endSpectralSelection = 63;
55          approxHigh = 0;
56          approxLow = 0;
57          componentSpecs = new ScanComponentSpec[numComponents];
58          for (int i = 0; i < numComponents; i++) {
59              int tableSel = 0;
60              if (willSubsample) {
61                  if ((i == 1) || (i == 2)) {
62                      tableSel = 1;
63                  }
64              }
65              componentSpecs[i] = new ScanComponentSpec(componentIDs[i],
66                                                        tableSel);
67          }
68      }
69  
70      SOSMarkerSegment(JPEGBuffer buffer) throws IOException {
71          super(buffer);
72          int numComponents = buffer.buf[buffer.bufPtr++];
73          componentSpecs = new ScanComponentSpec[numComponents];
74          for (int i = 0; i < numComponents; i++) {
75              componentSpecs[i] = new ScanComponentSpec(buffer);
76          }
77          startSpectralSelection = buffer.buf[buffer.bufPtr++];
78          endSpectralSelection = buffer.buf[buffer.bufPtr++];
79          approxHigh = buffer.buf[buffer.bufPtr] >> 4;
80          approxLow = buffer.buf[buffer.bufPtr++] &0xf;
81          buffer.bufAvail -= length;
82      }
83  
84      SOSMarkerSegment(Node node) throws IIOInvalidTreeException {
85          super(JPEG.SOS);
86          startSpectralSelection = 0;
87          endSpectralSelection = 63;
88          approxHigh = 0;
89          approxLow = 0;
90          updateFromNativeNode(node, true);
91      }
92  
93      protected Object clone () {
94          SOSMarkerSegment newGuy = (SOSMarkerSegment) super.clone();
95          if (componentSpecs != null) {
96              newGuy.componentSpecs =
97                  (ScanComponentSpec []) componentSpecs.clone();
98              for (int i = 0; i < componentSpecs.length; i++) {
99                  newGuy.componentSpecs[i] =
100                     (ScanComponentSpec) componentSpecs[i].clone();
101             }
102         }
103         return newGuy;
104     }
105 
106     IIOMetadataNode getNativeNode() {
107         IIOMetadataNode node = new IIOMetadataNode("sos");
108         node.setAttribute("numScanComponents",
109                           Integer.toString(componentSpecs.length));
110         node.setAttribute("startSpectralSelection",
111                           Integer.toString(startSpectralSelection));
112         node.setAttribute("endSpectralSelection",
113                           Integer.toString(endSpectralSelection));
114         node.setAttribute("approxHigh",
115                           Integer.toString(approxHigh));
116         node.setAttribute("approxLow",
117                           Integer.toString(approxLow));
118         for (int i = 0; i < componentSpecs.length; i++) {
119             node.appendChild(componentSpecs[i].getNativeNode());
120         }
121 
122         return node;
123     }
124 
125     void updateFromNativeNode(Node node, boolean fromScratch)
126         throws IIOInvalidTreeException {
127         NamedNodeMap attrs = node.getAttributes();
128         int numComponents = getAttributeValue(node, attrs, "numScanComponents",
129                                               1, 4, true);
130         int value = getAttributeValue(node, attrs, "startSpectralSelection",
131                                       0, 63, false);
132         startSpectralSelection = (value != -1) ? value : startSpectralSelection;
133         value = getAttributeValue(node, attrs, "endSpectralSelection",
134                                   0, 63, false);
135         endSpectralSelection = (value != -1) ? value : endSpectralSelection;
136         value = getAttributeValue(node, attrs, "approxHigh", 0, 15, false);
137         approxHigh = (value != -1) ? value : approxHigh;
138         value = getAttributeValue(node, attrs, "approxLow", 0, 15, false);
139         approxLow = (value != -1) ? value : approxLow;
140 
141         // Now the children
142         NodeList children = node.getChildNodes();
143         if (children.getLength() != numComponents) {
144             throw new IIOInvalidTreeException
145                 ("numScanComponents must match the number of children", node);
146         }
147         componentSpecs = new ScanComponentSpec[numComponents];
148         for (int i = 0; i < numComponents; i++) {
149             componentSpecs[i] = new ScanComponentSpec(children.item(i));
150         }
151     }
152 
153     /**
154      * Writes the data for this segment to the stream in
155      * valid JPEG format.
156      */
157     void write(ImageOutputStream ios) throws IOException {
158         // We don't write SOS segments; the IJG library does.
159     }
160 
161     void print () {
162         printTag("SOS");
163         System.out.print("Start spectral selection: ");
164         System.out.println(startSpectralSelection);
165         System.out.print("End spectral selection: ");
166         System.out.println(endSpectralSelection);
167         System.out.print("Approx high: ");
168         System.out.println(approxHigh);
169         System.out.print("Approx low: ");
170         System.out.println(approxLow);
171         System.out.print("Num scan components: ");
172         System.out.println(componentSpecs.length);
173         for (int i = 0; i< componentSpecs.length; i++) {
174             componentSpecs[i].print();
175         }
176     }
177 
178     ScanComponentSpec getScanComponentSpec(byte componentSel, int tableSel) {
179         return new ScanComponentSpec(componentSel, tableSel);
180     }
181 
182     /**
183      * A scan component spec within an SOS marker segment.
184      */
185     class ScanComponentSpec implements Cloneable {
186         int componentSelector;
187         int dcHuffTable;
188         int acHuffTable;
189 
190         ScanComponentSpec(byte componentSel, int tableSel) {
191             componentSelector = componentSel;
192             dcHuffTable = tableSel;
193             acHuffTable = tableSel;
194         }
195 
196         ScanComponentSpec(JPEGBuffer buffer) {
197             // Parent already loaded the buffer
198             componentSelector = buffer.buf[buffer.bufPtr++];
199             dcHuffTable = buffer.buf[buffer.bufPtr] >> 4;
200             acHuffTable = buffer.buf[buffer.bufPtr++] & 0xf;
201         }
202 
203         ScanComponentSpec(Node node) throws IIOInvalidTreeException {
204             NamedNodeMap attrs = node.getAttributes();
205             componentSelector = getAttributeValue(node, attrs, "componentSelector",
206                                                   0, 255, true);
207             dcHuffTable = getAttributeValue(node, attrs, "dcHuffTable",
208                                             0, 3, true);
209             acHuffTable = getAttributeValue(node, attrs, "acHuffTable",
210                                             0, 3, true);
211         }
212 
213         protected Object clone() {
214             try {
215                 return super.clone();
216             } catch (CloneNotSupportedException e) {} // won't happen
217             return null;
218         }
219 
220         IIOMetadataNode getNativeNode() {
221             IIOMetadataNode node = new IIOMetadataNode("scanComponentSpec");
222             node.setAttribute("componentSelector",
223                               Integer.toString(componentSelector));
224             node.setAttribute("dcHuffTable",
225                               Integer.toString(dcHuffTable));
226             node.setAttribute("acHuffTable",
227                               Integer.toString(acHuffTable));
228             return node;
229         }
230 
231         void print () {
232             System.out.print("Component Selector: ");
233             System.out.println(componentSelector);
234             System.out.print("DC huffman table: ");
235             System.out.println(dcHuffTable);
236             System.out.print("AC huffman table: ");
237             System.out.println(acHuffTable);
238         }
239     }
240 
241 }