View Javadoc
1   /*
2    * Copyright (c) 2007, 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 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 }