1 /* 2 * Copyright (c) 2001, 2014, 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 SOSMarkerSegment clone () { 94 SOSMarkerSegment newGuy = (SOSMarkerSegment) super.clone(); 95 if (componentSpecs != null) { 96 newGuy.componentSpecs = componentSpecs.clone(); 97 for (int i = 0; i < componentSpecs.length; i++) { 98 newGuy.componentSpecs[i] = 99 (ScanComponentSpec) componentSpecs[i].clone(); 100 } 101 } 102 return newGuy; 103 } 104 105 IIOMetadataNode getNativeNode() { 106 IIOMetadataNode node = new IIOMetadataNode("sos"); 107 node.setAttribute("numScanComponents", 108 Integer.toString(componentSpecs.length)); 109 node.setAttribute("startSpectralSelection", 110 Integer.toString(startSpectralSelection)); 111 node.setAttribute("endSpectralSelection", 112 Integer.toString(endSpectralSelection)); 113 node.setAttribute("approxHigh", 114 Integer.toString(approxHigh)); 115 node.setAttribute("approxLow", 116 Integer.toString(approxLow)); 117 for (int i = 0; i < componentSpecs.length; i++) { 118 node.appendChild(componentSpecs[i].getNativeNode()); 119 } 120 121 return node; 122 } 123 124 void updateFromNativeNode(Node node, boolean fromScratch) 125 throws IIOInvalidTreeException { 126 NamedNodeMap attrs = node.getAttributes(); 127 int numComponents = getAttributeValue(node, attrs, "numScanComponents", 128 1, 4, true); 129 int value = getAttributeValue(node, attrs, "startSpectralSelection", 130 0, 63, false); 131 startSpectralSelection = (value != -1) ? value : startSpectralSelection; 132 value = getAttributeValue(node, attrs, "endSpectralSelection", 133 0, 63, false); 134 endSpectralSelection = (value != -1) ? value : endSpectralSelection; 135 value = getAttributeValue(node, attrs, "approxHigh", 0, 15, false); 136 approxHigh = (value != -1) ? value : approxHigh; 137 value = getAttributeValue(node, attrs, "approxLow", 0, 15, false); 138 approxLow = (value != -1) ? value : approxLow; 139 140 // Now the children 141 NodeList children = node.getChildNodes(); 142 if (children.getLength() != numComponents) { 143 throw new IIOInvalidTreeException 144 ("numScanComponents must match the number of children", node); 145 } 146 componentSpecs = new ScanComponentSpec[numComponents]; 147 for (int i = 0; i < numComponents; i++) { 148 componentSpecs[i] = new ScanComponentSpec(children.item(i)); 149 } 150 } 151 152 /** 153 * Writes the data for this segment to the stream in 154 * valid JPEG format. 155 */ 156 void write(ImageOutputStream ios) throws IOException { 157 // We don't write SOS segments; the IJG library does. 158 } 159 160 void print () { 161 printTag("SOS"); 162 System.out.print("Start spectral selection: "); 163 System.out.println(startSpectralSelection); 164 System.out.print("End spectral selection: "); 165 System.out.println(endSpectralSelection); 166 System.out.print("Approx high: "); 167 System.out.println(approxHigh); 168 System.out.print("Approx low: "); 169 System.out.println(approxLow); 170 System.out.print("Num scan components: "); 171 System.out.println(componentSpecs.length); 172 for (int i = 0; i< componentSpecs.length; i++) { 173 componentSpecs[i].print(); 174 } 175 } 176 177 ScanComponentSpec getScanComponentSpec(byte componentSel, int tableSel) { 178 return new ScanComponentSpec(componentSel, tableSel); 179 } 180 181 /** 182 * A scan component spec within an SOS marker segment. 183 */ 184 class ScanComponentSpec implements Cloneable { 185 int componentSelector; 186 int dcHuffTable; 187 int acHuffTable; 188 189 ScanComponentSpec(byte componentSel, int tableSel) { 190 componentSelector = componentSel; 191 dcHuffTable = tableSel; 192 acHuffTable = tableSel; 193 } 194 195 ScanComponentSpec(JPEGBuffer buffer) { 196 // Parent already loaded the buffer 197 componentSelector = buffer.buf[buffer.bufPtr++]; 198 dcHuffTable = buffer.buf[buffer.bufPtr] >> 4; 199 acHuffTable = buffer.buf[buffer.bufPtr++] & 0xf; 200 } 201 202 ScanComponentSpec(Node node) throws IIOInvalidTreeException { 203 NamedNodeMap attrs = node.getAttributes(); 204 componentSelector = getAttributeValue(node, attrs, "componentSelector", 205 0, 255, true); 206 dcHuffTable = getAttributeValue(node, attrs, "dcHuffTable", 207 0, 3, true); 208 acHuffTable = getAttributeValue(node, attrs, "acHuffTable", 209 0, 3, true); 210 } 211 212 protected Object clone() { 213 try { 214 return super.clone(); 215 } catch (CloneNotSupportedException e) {} // won't happen 216 return null; 217 } 218 219 IIOMetadataNode getNativeNode() { 220 IIOMetadataNode node = new IIOMetadataNode("scanComponentSpec"); 221 node.setAttribute("componentSelector", 222 Integer.toString(componentSelector)); 223 node.setAttribute("dcHuffTable", 224 Integer.toString(dcHuffTable)); 225 node.setAttribute("acHuffTable", 226 Integer.toString(acHuffTable)); 227 return node; 228 } 229 230 void print () { 231 System.out.print("Component Selector: "); 232 System.out.println(componentSelector); 233 System.out.print("DC huffman table: "); 234 System.out.println(dcHuffTable); 235 System.out.print("AC huffman table: "); 236 System.out.println(acHuffTable); 237 } 238 } 239 240 }