KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > imageio > plugins > jpeg > DQTMarkerSegment


1 /*
2  * @(#)DQTMarkerSegment.java 1.5 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
8 package com.sun.imageio.plugins.jpeg;
9
10 import javax.imageio.IIOException JavaDoc;
11 import javax.imageio.metadata.IIOInvalidTreeException JavaDoc;
12 import javax.imageio.metadata.IIOMetadataNode JavaDoc;
13 import javax.imageio.stream.ImageOutputStream JavaDoc;
14 import javax.imageio.plugins.jpeg.JPEGQTable JavaDoc;
15
16 import java.io.IOException JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.Iterator JavaDoc;
20
21 import org.w3c.dom.Node JavaDoc;
22 import org.w3c.dom.NodeList JavaDoc;
23 import org.w3c.dom.NamedNodeMap JavaDoc;
24
25 /**
26  * A DQT (Define Quantization Table) marker segment.
27  */

28 class DQTMarkerSegment extends MarkerSegment {
29     List JavaDoc tables = new ArrayList JavaDoc(); // Could be 1 to 4
30

31     DQTMarkerSegment(float quality, boolean needTwo) {
32         super(JPEG.DQT);
33         tables.add(new Qtable(true, quality));
34         if (needTwo) {
35             tables.add(new Qtable(false, quality));
36         }
37     }
38
39     DQTMarkerSegment(JPEGBuffer buffer) throws IOException JavaDoc {
40         super(buffer);
41         int count = length;
42         while (count > 0) {
43             Qtable newGuy = new Qtable(buffer);
44             tables.add(newGuy);
45             count -= newGuy.data.length+1;
46         }
47         buffer.bufAvail -= length;
48     }
49
50     DQTMarkerSegment(JPEGQTable JavaDoc[] qtables) {
51         super(JPEG.DQT);
52         for (int i = 0; i < qtables.length; i++) {
53             tables.add(new Qtable(qtables[i], i));
54         }
55     }
56
57     DQTMarkerSegment(Node JavaDoc node) throws IIOInvalidTreeException JavaDoc {
58         super(JPEG.DQT);
59         NodeList JavaDoc children = node.getChildNodes();
60         int size = children.getLength();
61         if ((size < 1) || (size > 4)) {
62             throw new IIOInvalidTreeException JavaDoc("Invalid DQT node", node);
63         }
64         for (int i = 0; i < size; i++) {
65             tables.add(new Qtable(children.item(i)));
66         }
67     }
68
69     protected Object JavaDoc clone() {
70         DQTMarkerSegment newGuy = (DQTMarkerSegment) super.clone();
71         newGuy.tables = new ArrayList JavaDoc(tables.size());
72         Iterator JavaDoc iter = tables.iterator();
73         while (iter.hasNext()) {
74             Qtable table = (Qtable) iter.next();
75             newGuy.tables.add(table.clone());
76         }
77         return newGuy;
78     }
79
80     IIOMetadataNode JavaDoc getNativeNode() {
81         IIOMetadataNode JavaDoc node = new IIOMetadataNode JavaDoc("dqt");
82         for (int i= 0; i<tables.size(); i++) {
83             Qtable table = (Qtable) tables.get(i);
84             node.appendChild(table.getNativeNode());
85         }
86         return node;
87     }
88
89     /**
90      * Writes the data for this segment to the stream in
91      * valid JPEG format.
92      */

93     void write(ImageOutputStream JavaDoc ios) throws IOException JavaDoc {
94         // We don't write DQT segments; the IJG library does.
95
}
96
97     void print() {
98         printTag("DQT");
99         System.out.println("Num tables: "
100                            + Integer.toString(tables.size()));
101         for (int i= 0; i<tables.size(); i++) {
102             Qtable table = (Qtable) tables.get(i);
103             table.print();
104         }
105         System.out.println();
106     }
107
108     /**
109      * Assuming the given table was generated by scaling the "standard"
110      * visually lossless luminance table, extract the scale factor that
111      * was used.
112      */

113     Qtable getChromaForLuma(Qtable luma) {
114         Qtable newGuy = null;
115         // Determine if the table is all the same values
116
// if so, use the same table
117
boolean allSame = true;
118         for (int i = 1; i < luma.QTABLE_SIZE; i++) {
119             if (luma.data[i] != luma.data[i-1]) {
120                 allSame = false;
121                 break;
122             }
123         }
124         if (allSame) {
125             newGuy = (Qtable) luma.clone();
126             newGuy.tableID = 1;
127         } else {
128             // Otherwise, find the largest coefficient less than 255. This is
129
// the largest value that we know did not clamp on scaling.
130
int largestPos = 0;
131             for (int i = 1; i < luma.QTABLE_SIZE; i++) {
132                 if (luma.data[i] > luma.data[largestPos]) {
133                     largestPos = i;
134                 }
135             }
136             // Compute the scale factor by dividing it by the value in the
137
// same position from the "standard" table.
138
// If the given table was not generated by scaling the standard,
139
// the resulting table will still be reasonable, as it will reflect
140
// a comparable scaling of chrominance frequency response of the
141
// eye.
142
float scaleFactor = ((float)(luma.data[largestPos]))
143                 / ((float)(JPEGQTable.K1Div2Luminance.getTable()[largestPos]));
144             // generate a new table
145
JPEGQTable JavaDoc jpegTable =
146                 JPEGQTable.K2Div2Chrominance.getScaledInstance(scaleFactor,
147                                                                true);
148             newGuy = new Qtable(jpegTable, 1);
149         }
150         return newGuy;
151     }
152
153     Qtable getQtableFromNode(Node JavaDoc node) throws IIOInvalidTreeException JavaDoc {
154         return new Qtable(node);
155     }
156
157     /**
158      * A quantization table within a DQT marker segment.
159      */

160     class Qtable implements Cloneable JavaDoc {
161         int elementPrecision;
162         int tableID;
163         final int QTABLE_SIZE = 64;
164         int [] data; // 64 elements, in natural order
165

166         /**
167          * The zigzag-order position of the i'th element
168          * of a DCT block read in natural order.
169          */

170         private final int [] zigzag = {
171             0, 1, 5, 6, 14, 15, 27, 28,
172             2, 4, 7, 13, 16, 26, 29, 42,
173             3, 8, 12, 17, 25, 30, 41, 43,
174             9, 11, 18, 24, 31, 40, 44, 53,
175             10, 19, 23, 32, 39, 45, 52, 54,
176             20, 22, 33, 38, 46, 51, 55, 60,
177             21, 34, 37, 47, 50, 56, 59, 61,
178             35, 36, 48, 49, 57, 58, 62, 63
179         };
180
181         Qtable(boolean wantLuma, float quality) {
182             elementPrecision = 0;
183             JPEGQTable JavaDoc base = null;
184             if (wantLuma) {
185                 tableID = 0;
186                 base = JPEGQTable.K1Div2Luminance;
187             } else {
188                 tableID = 1;
189                 base = JPEGQTable.K2Div2Chrominance;
190             }
191             if (quality != JPEG.DEFAULT_QUALITY) {
192                 quality = JPEG.convertToLinearQuality(quality);
193                 if (wantLuma) {
194                     base = JPEGQTable.K1Luminance.getScaledInstance
195                         (quality, true);
196                 } else {
197                     base = JPEGQTable.K2Div2Chrominance.getScaledInstance
198                         (quality, true);
199                 }
200             }
201             data = base.getTable();
202         }
203
204         Qtable(JPEGBuffer buffer) throws IIOException JavaDoc {
205             elementPrecision = buffer.buf[buffer.bufPtr] >>> 4;
206             tableID = buffer.buf[buffer.bufPtr++] & 0xf;
207             if (elementPrecision != 0) {
208                 // IJG is compiled for 8-bits, so this shouldn't happen
209
throw new IIOException JavaDoc ("Unsupported element precision");
210             }
211             data = new int [QTABLE_SIZE];
212             // Read from zig-zag order to natural order
213
for (int i = 0; i < QTABLE_SIZE; i++) {
214                 data[i] = buffer.buf[buffer.bufPtr+zigzag[i]] & 0xff;
215             }
216             buffer.bufPtr += QTABLE_SIZE;
217         }
218
219         Qtable(JPEGQTable JavaDoc table, int id) {
220             elementPrecision = 0;
221             tableID = id;
222             data = table.getTable();
223         }
224
225         Qtable(Node JavaDoc node) throws IIOInvalidTreeException JavaDoc {
226             if (node.getNodeName().equals("dqtable")) {
227                 NamedNodeMap JavaDoc attrs = node.getAttributes();
228                 int count = attrs.getLength();
229                 if ((count < 1) || (count > 2)) {
230                     throw new IIOInvalidTreeException JavaDoc
231                         ("dqtable node must have 1 or 2 attributes", node);
232                 }
233                 elementPrecision = 0;
234                 tableID = getAttributeValue(node, attrs, "qtableId", 0, 3, true);
235                 if (node instanceof IIOMetadataNode JavaDoc) {
236                     IIOMetadataNode JavaDoc ourNode = (IIOMetadataNode JavaDoc) node;
237                     JPEGQTable JavaDoc table = (JPEGQTable JavaDoc) ourNode.getUserObject();
238                     if (table == null) {
239                         throw new IIOInvalidTreeException JavaDoc
240                             ("dqtable node must have user object", node);
241                     }
242                     data = table.getTable();
243                 } else {
244                     throw new IIOInvalidTreeException JavaDoc
245                         ("dqtable node must have user object", node);
246                 }
247             } else {
248                 throw new IIOInvalidTreeException JavaDoc
249                     ("Invalid node, expected dqtable", node);
250             }
251         }
252
253         protected Object JavaDoc clone() {
254             Qtable newGuy = null;
255             try {
256                 newGuy = (Qtable) super.clone();
257             } catch (CloneNotSupportedException JavaDoc e) {} // won't happen
258
if (data != null) {
259                 newGuy.data = (int []) data.clone();
260             }
261             return newGuy;
262         }
263
264         IIOMetadataNode JavaDoc getNativeNode() {
265             IIOMetadataNode JavaDoc node = new IIOMetadataNode JavaDoc("dqtable");
266             node.setAttribute("elementPrecision",
267                               Integer.toString(elementPrecision));
268             node.setAttribute("qtableId",
269                               Integer.toString(tableID));
270             node.setUserObject(new JPEGQTable JavaDoc(data));
271             return node;
272         }
273
274         void print() {
275             System.out.println("Table id: " + Integer.toString(tableID));
276             System.out.println("Element precision: "
277                                + Integer.toString(elementPrecision));
278         
279             (new JPEGQTable JavaDoc(data)).toString();
280             /*
281               for (int i = 0; i < 64; i++) {
282               if (i % 8 == 0) {
283               System.out.println();
284               }
285               System.out.print(" " + Integer.toString(data[i]));
286               }
287               System.out.println();
288             */

289         }
290     }
291 }
292
293
Popular Tags