001    /* JPEGHuffmanTable.java --
002     Copyright (C)  2006  Free Software Foundation, Inc.
003    
004     This file is part of GNU Classpath.
005    
006     GNU Classpath is free software; you can redistribute it and/or modify
007     it under the terms of the GNU General Public License as published by
008     the Free Software Foundation; either version 2, or (at your option)
009     any later version.
010    
011     GNU Classpath is distributed in the hope that it will be useful, but
012     WITHOUT ANY WARRANTY; without even the implied warranty of
013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     General Public License for more details.
015    
016     You should have received a copy of the GNU General Public License
017     along with GNU Classpath; see the file COPYING.  If not, write to the
018     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019     02110-1301 USA.
020    
021     Linking this library statically or dynamically with other modules is
022     making a combined work based on this library.  Thus, the terms and
023     conditions of the GNU General Public License cover the whole
024     combination.
025    
026     As a special exception, the copyright holders of this library give you
027     permission to link this library with independent modules to produce an
028     executable, regardless of the license terms of these independent
029     modules, and to copy and distribute the resulting executable under
030     terms of your choice, provided that you also meet, for each linked
031     independent module, the terms and conditions of the license of that
032     module.  An independent module is a module which is not derived from
033     or based on this library.  If you modify this library, you may extend
034     this exception to your version of the library, but you are not
035     obligated to do so.  If you do not wish to do so, delete this
036     exception statement from your version. */
037    
038    
039    package javax.imageio.plugins.jpeg;
040    
041    /**
042     * The JPEGHuffmanTable class represents a Huffman table read from a
043     * JPEG image file.  The standard JPEG AC and DC chrominance and
044     * luminance values are provided as static fields.
045     */
046    public class JPEGHuffmanTable
047    {
048      /**
049       * Huffman code lengths.
050       */
051      private short[] lengths;
052    
053      /**
054       * Huffman values.
055       */
056      private short[] values;
057    
058      // The private constructors are used for these final fields to avoid
059      // unnecessary copying.
060      /**
061       * The standard JPEG AC chrominance Huffman table.
062       */
063      public static final JPEGHuffmanTable StdACChrominance =
064          new JPEGHuffmanTable(new short[] { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5,
065                                             4, 4, 0, 1, 2, 0x77 },
066                               new short[]  { 0x00, 0x01, 0x02, 0x03, 0x11,
067                                              0x04, 0x05, 0x21, 0x31, 0x06,
068                                              0x12, 0x41, 0x51, 0x07, 0x61,
069                                              0x71, 0x13, 0x22, 0x32, 0x81,
070                                              0x08, 0x14, 0x42, 0x91, 0xa1,
071                                              0xb1, 0xc1, 0x09, 0x23, 0x33,
072                                              0x52, 0xf0, 0x15, 0x62, 0x72,
073                                              0xd1, 0x0a, 0x16, 0x24, 0x34,
074                                              0xe1, 0x25, 0xf1, 0x17, 0x18,
075                                              0x19, 0x1a, 0x26, 0x27, 0x28,
076                                              0x29, 0x2a, 0x35, 0x36, 0x37,
077                                              0x38, 0x39, 0x3a, 0x43, 0x44,
078                                              0x45, 0x46, 0x47, 0x48, 0x49,
079                                              0x4a, 0x53, 0x54, 0x55, 0x56,
080                                              0x57, 0x58, 0x59, 0x5a, 0x63,
081                                              0x64, 0x65, 0x66, 0x67, 0x68,
082                                              0x69, 0x6a, 0x73, 0x74, 0x75,
083                                              0x76, 0x77, 0x78, 0x79, 0x7a,
084                                              0x82, 0x83, 0x84, 0x85, 0x86,
085                                              0x87, 0x88, 0x89, 0x8a, 0x92,
086                                              0x93, 0x94, 0x95, 0x96, 0x97,
087                                              0x98, 0x99, 0x9a, 0xa2, 0xa3,
088                                              0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
089                                              0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
090                                              0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
091                                              0xba, 0xc2, 0xc3, 0xc4, 0xc5,
092                                              0xc6, 0xc7, 0xc8, 0xc9, 0xca,
093                                              0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
094                                              0xd7, 0xd8, 0xd9, 0xda, 0xe2,
095                                              0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
096                                              0xe8, 0xe9, 0xea, 0xf2, 0xf3,
097                                              0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
098                                              0xf9, 0xfa }, false);
099    
100      /**
101       * The standard JPEG AC luminance Huffman table.
102       */
103      public static final JPEGHuffmanTable StdACLuminance =
104          new JPEGHuffmanTable(new short[] { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5,
105                                             4, 4, 0, 0, 1, 0x7d },
106                               new short[] { 0x01, 0x02, 0x03, 0x00, 0x04,
107                                             0x11, 0x05, 0x12, 0x21, 0x31,
108                                             0x41, 0x06, 0x13, 0x51, 0x61,
109                                             0x07, 0x22, 0x71, 0x14, 0x32,
110                                             0x81, 0x91, 0xa1, 0x08, 0x23,
111                                             0x42, 0xb1, 0xc1, 0x15, 0x52,
112                                             0xd1, 0xf0, 0x24, 0x33, 0x62,
113                                             0x72, 0x82, 0x09, 0x0a, 0x16,
114                                             0x17, 0x18, 0x19, 0x1a, 0x25,
115                                             0x26, 0x27, 0x28, 0x29, 0x2a,
116                                             0x34, 0x35, 0x36, 0x37, 0x38,
117                                             0x39, 0x3a, 0x43, 0x44, 0x45,
118                                             0x46, 0x47, 0x48, 0x49, 0x4a,
119                                             0x53, 0x54, 0x55, 0x56, 0x57,
120                                             0x58, 0x59, 0x5a, 0x63, 0x64,
121                                             0x65, 0x66, 0x67, 0x68, 0x69,
122                                             0x6a, 0x73, 0x74, 0x75, 0x76,
123                                             0x77, 0x78, 0x79, 0x7a, 0x83,
124                                             0x84, 0x85, 0x86, 0x87, 0x88,
125                                             0x89, 0x8a, 0x92, 0x93, 0x94,
126                                             0x95, 0x96, 0x97, 0x98, 0x99,
127                                             0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
128                                             0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
129                                             0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
130                                             0xb7, 0xb8, 0xb9, 0xba, 0xc2,
131                                             0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
132                                             0xc8, 0xc9, 0xca, 0xd2, 0xd3,
133                                             0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
134                                             0xd9, 0xda, 0xe1, 0xe2, 0xe3,
135                                             0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
136                                             0xe9, 0xea, 0xf1, 0xf2, 0xf3,
137                                             0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
138                                             0xf9, 0xfa }, false);
139    
140      /**
141       * The standard JPEG DC chrominance Huffman table.
142       */
143      public static final JPEGHuffmanTable StdDCChrominance =
144          new JPEGHuffmanTable(new short[] { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1,
145                                             1, 0, 0, 0, 0, 0 },
146                               new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
147                                             10, 11 }, false);
148    
149      /**
150       * The standard JPEG DC luminance Huffman table.
151       */
152      public static final JPEGHuffmanTable StdDCLuminance =
153          new JPEGHuffmanTable(new short[] { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0,
154                                             0, 0, 0, 0, 0, 0 },
155                               new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
156                                             10, 11 }, false);
157    
158      /**
159       * Construct and initialize a Huffman table. Copies are created of
160       * the array arguments. lengths[index] stores the number of Huffman
161       * values with Huffman codes of length index + 1. The values array
162       * stores the Huffman values in order of increasing code length.
163       * 
164       * @param lengths an array of Huffman code lengths
165       * @param values a sorted array of Huffman values
166       * @throws IllegalArgumentException if either parameter is null, if
167       * lengths.length > 16 or values.length > 256, if any value in
168       * length or values is negative, or if the parameters do not
169       * describe a valid Huffman table
170       */
171      public JPEGHuffmanTable(short[] lengths, short[] values)
172      {
173        // Create copies of the lengths and values arguments.
174        this(checkLengths(lengths), checkValues(values, lengths), true);
175      }
176    
177      /**
178       * Private constructor that avoids unnecessary copying and argument
179       * checking.
180       *
181       * @param lengths an array of Huffman code lengths
182       * @param values a sorted array of Huffman values
183       * @param copy true if copies should be created of the given arrays
184       */
185      private JPEGHuffmanTable(short[] lengths, short[] values, boolean copy)
186      {
187        this.lengths = copy ? (short[]) lengths.clone() : lengths;
188        this.values = copy ? (short[]) values.clone() : values;
189      }
190    
191      private static short[] checkLengths(short[] lengths)
192      {
193        if (lengths == null || lengths.length > 16)
194          throw new IllegalArgumentException("invalid length array");
195    
196        for (int i = 0; i < lengths.length; i++)
197          {
198            if (lengths[i] < 0)
199              throw new IllegalArgumentException("negative length");
200          }
201    
202        int sum = 0;
203        for (int i = 0; i < lengths.length; i++)
204          {
205            if (lengths[i] > ((1 << (i + 1)) - 1))
206              throw new IllegalArgumentException("invalid number of codes"
207                                                 + " for code length " + (i + 1));
208            sum += lengths[i];
209          }
210    
211        return lengths;
212      }
213    
214      private static short[] checkValues(short[] values, short[] lengths)
215      {
216        if (values == null || values.length > 256)
217          throw new IllegalArgumentException("invalid values array");
218    
219        for (int i = 0; i < values.length; i++)
220          {
221            if (values[i] < 0)
222              throw new IllegalArgumentException("negative value");
223          }
224        // lengths is known-valid by this point.
225        int sum = 0;
226        for (int i = 0; i < lengths.length; i++)
227          sum += lengths[i];
228    
229        if (values.length != sum)
230          throw new IllegalArgumentException("invalid number of values"
231                                             + " for number of codes");
232    
233        return values;
234      }
235    
236      /**
237       * Retrieve a copy of the array of Huffman code lengths.  If the
238       * returned array is called lengthcount, there are
239       * lengthcount[index] codes of length index + 1.
240       *
241       * @return a copy of the array of Huffman code lengths
242       */
243      public short[] getLengths()
244      {
245        return (short[]) lengths.clone();
246      }
247    
248      /**
249       * Retrieve a copy of the array of Huffman values, sorted in order
250       * of increasing code length.
251       *
252       * @return a copy of the array of Huffman values
253       */
254      public short[] getValues()
255      {
256        return (short[]) values.clone();
257      }
258    
259      /**
260       * Create a string representation of this JPEG Huffman table.
261       *
262       * @return a string representation of this JPEG Huffman table.
263       */
264      public String toString()
265      {
266        StringBuffer buffer = new StringBuffer();
267        
268        buffer.append("JPEGHuffmanTable:\nlengths:");
269        
270        for (int i = 0; i < lengths.length; i++)
271          buffer.append(" " + lengths[i]);
272        
273        buffer.append("\nvalues:");
274        
275        for (int i = 0; i < values.length; i++)
276          buffer.append(" " + values[i]);
277        
278        return buffer.toString();
279      }
280    }