1 /*
2 * Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.imageio.plugins.jpeg;
27
28 import java.util.Arrays;
29
30 /**
31 * A class encapsulating a single JPEG Huffman table.
32 * Fields are provided for the "standard" tables taken
33 * from Annex K of the JPEG specification.
34 * These are the tables used as defaults.
35 * <p>
36 * For more information about the operation of the standard JPEG plug-in,
37 * see the <A HREF="../../metadata/doc-files/jpeg_metadata.html">JPEG
38 * metadata format specification and usage notes</A>
39 */
40
41 public class JPEGHuffmanTable {
42
43 /* The data for the publically defined tables, as specified in ITU T.81
44 * JPEG specification section K3.3 and used in the IJG library.
45 */
46 private static final short[] StdDCLuminanceLengths = {
47 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
48 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 };
50
51 private static final short[] StdDCLuminanceValues = {
52 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
53 0x08, 0x09, 0x0a, 0x0b,
54 };
55
56 private static final short[] StdDCChrominanceLengths = {
57 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
58 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
59 };
60
61 private static final short[] StdDCChrominanceValues = {
62 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
63 0x08, 0x09, 0x0a, 0x0b,
64 };
65
66 private static final short[] StdACLuminanceLengths = {
67 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
68 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
69 };
70
71 private static final short[] StdACLuminanceValues = {
72 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
73 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
74 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
75 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
76 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
77 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
78 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
79 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
80 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
81 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
82 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
83 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
84 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
85 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
86 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
87 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
88 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
89 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
90 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
91 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
92 0xf9, 0xfa,
93 };
94
95 private static final short[] StdACChrominanceLengths = {
96 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
97 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
98 };
99
100 private static final short[] StdACChrominanceValues = {
101 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
102 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
103 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
104 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
105 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
106 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
107 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
108 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
109 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
110 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
111 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
112 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
113 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
114 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
115 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
116 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
117 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
118 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
119 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
120 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
121 0xf9, 0xfa,
122 };
123
124 /**
125 * The standard DC luminance Huffman table.
126 */
127 public static final JPEGHuffmanTable
128 StdDCLuminance = new JPEGHuffmanTable(StdDCLuminanceLengths,
129 StdDCLuminanceValues, false);
130
131 /**
132 * The standard DC chrominance Huffman table.
133 */
134 public static final JPEGHuffmanTable
135 StdDCChrominance = new JPEGHuffmanTable(StdDCChrominanceLengths,
136 StdDCChrominanceValues, false);
137
138 /**
139 * The standard AC luminance Huffman table.
140 */
141 public static final JPEGHuffmanTable
142 StdACLuminance = new JPEGHuffmanTable(StdACLuminanceLengths,
143 StdACLuminanceValues, false);
144
145 /**
146 * The standard AC chrominance Huffman table.
147 */
148 public static final JPEGHuffmanTable
149 StdACChrominance = new JPEGHuffmanTable(StdACChrominanceLengths,
150 StdACChrominanceValues, false);
151
152 private short[] lengths;
153 private short[] values;
154
155 /**
156 * Creates a Huffman table and initializes it. The input arrays are copied.
157 * The arrays must describe a possible Huffman table.
158 * For example, 3 codes cannot be expressed with a single bit.
159 *
160 * @param lengths an array of {@code short}s where <code>lengths[k]</code>
161 * is equal to the number of values with corresponding codes of
162 * length <code>k + 1</code> bits.
163 * @param values an array of shorts containing the values in
164 * order of increasing code length.
165 * @throws IllegalArgumentException if <code>lengths</code> or
166 * <code>values</code> are null, the length of <code>lengths</code> is
167 * greater than 16, the length of <code>values</code> is greater than 256,
168 * if any value in <code>lengths</code> or <code>values</code> is less
169 * than zero, or if the arrays do not describe a valid Huffman table.
170 */
171 public JPEGHuffmanTable(short[] lengths, short[] values) {
172 if (lengths == null || values == null ||
173 lengths.length == 0 || values.length == 0 ||
174 lengths.length > 16 || values.length > 256) {
175 throw new IllegalArgumentException("Illegal lengths or values");
176 }
177 for (int i = 0; i<lengths.length; i++) {
178 if (lengths[i] < 0) {
179 throw new IllegalArgumentException("lengths["+i+"] < 0");
180 }
181 }
182 for (int i = 0; i<values.length; i++) {
183 if (values[i] < 0) {
184 throw new IllegalArgumentException("values["+i+"] < 0");
185 }
186 }
187 this.lengths = Arrays.copyOf(lengths, lengths.length);
188 this.values = Arrays.copyOf(values, values.length);
189 validate();
190 }
191
192 private void validate() {
193 int sumOfLengths = 0;
194 for (int i=0; i<lengths.length; i++) {
195 sumOfLengths += lengths[i];
196 }
197 if (sumOfLengths != values.length) {
198 throw new IllegalArgumentException("lengths do not correspond " +
199 "to length of value table");
200 }
201 }
202
203 /* Internal version which avoids the overhead of copying and checking */
204 private JPEGHuffmanTable(short[] lengths, short[] values, boolean copy) {
205 if (copy) {
206 this.lengths = Arrays.copyOf(lengths, lengths.length);
207 this.values = Arrays.copyOf(values, values.length);
208 } else {
209 this.lengths = lengths;
210 this.values = values;
211 }
212 }
213
214 /**
215 * Returns an array of <code>short</code>s containing the number of values
216 * for each length in the Huffman table. The returned array is a copy.
217 *
218 * @return a <code>short</code> array where <code>array[k-1]</code>
219 * is equal to the number of values in the table of length <code>k</code>.
220 * @see #getValues
221 */
222 public short[] getLengths() {
223 return Arrays.copyOf(lengths, lengths.length);
224 }
225
226 /**
227 * Returns an array of <code>short</code>s containing the values arranged
228 * by increasing length of their corresponding codes.
229 * The interpretation of the array is dependent on the values returned
230 * from <code>getLengths</code>. The returned array is a copy.
231 *
232 * @return a <code>short</code> array of values.
233 * @see #getLengths
234 */
235 public short[] getValues() {
236 return Arrays.copyOf(values, values.length);
237 }
238
239 /**
240 * Returns a {@code String} representing this Huffman table.
241 * @return a {@code String} representing this Huffman table.
242 */
243 public String toString() {
244 String ls = System.getProperty("line.separator", "\n");
245 StringBuilder sb = new StringBuilder("JPEGHuffmanTable");
246 sb.append(ls).append("lengths:");
247 for (int i=0; i<lengths.length; i++) {
248 sb.append(" ").append(lengths[i]);
249 }
250 sb.append(ls).append("values:");
251 for (int i=0; i<values.length; i++) {
252 sb.append(" ").append(values[i]);
253 }
254 return sb.toString();
255 }
256 }