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