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
039package javax.imageio.plugins.jpeg;
040
041import gnu.java.lang.CPStringBuilder;
042
043/**
044 * The JPEGHuffmanTable class represents a Huffman table read from a
045 * JPEG image file.  The standard JPEG AC and DC chrominance and
046 * luminance values are provided as static fields.
047 */
048public class JPEGHuffmanTable
049{
050  /**
051   * Huffman code lengths.
052   */
053  private short[] lengths;
054
055  /**
056   * Huffman values.
057   */
058  private short[] values;
059
060  // The private constructors are used for these final fields to avoid
061  // unnecessary copying.
062  /**
063   * The standard JPEG AC chrominance Huffman table.
064   */
065  public static final JPEGHuffmanTable StdACChrominance =
066      new JPEGHuffmanTable(new short[] { 0, 2, 1, 2, 4, 4, 3, 4, 7, 5,
067                                         4, 4, 0, 1, 2, 0x77 },
068                           new short[]  { 0x00, 0x01, 0x02, 0x03, 0x11,
069                                          0x04, 0x05, 0x21, 0x31, 0x06,
070                                          0x12, 0x41, 0x51, 0x07, 0x61,
071                                          0x71, 0x13, 0x22, 0x32, 0x81,
072                                          0x08, 0x14, 0x42, 0x91, 0xa1,
073                                          0xb1, 0xc1, 0x09, 0x23, 0x33,
074                                          0x52, 0xf0, 0x15, 0x62, 0x72,
075                                          0xd1, 0x0a, 0x16, 0x24, 0x34,
076                                          0xe1, 0x25, 0xf1, 0x17, 0x18,
077                                          0x19, 0x1a, 0x26, 0x27, 0x28,
078                                          0x29, 0x2a, 0x35, 0x36, 0x37,
079                                          0x38, 0x39, 0x3a, 0x43, 0x44,
080                                          0x45, 0x46, 0x47, 0x48, 0x49,
081                                          0x4a, 0x53, 0x54, 0x55, 0x56,
082                                          0x57, 0x58, 0x59, 0x5a, 0x63,
083                                          0x64, 0x65, 0x66, 0x67, 0x68,
084                                          0x69, 0x6a, 0x73, 0x74, 0x75,
085                                          0x76, 0x77, 0x78, 0x79, 0x7a,
086                                          0x82, 0x83, 0x84, 0x85, 0x86,
087                                          0x87, 0x88, 0x89, 0x8a, 0x92,
088                                          0x93, 0x94, 0x95, 0x96, 0x97,
089                                          0x98, 0x99, 0x9a, 0xa2, 0xa3,
090                                          0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
091                                          0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
092                                          0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
093                                          0xba, 0xc2, 0xc3, 0xc4, 0xc5,
094                                          0xc6, 0xc7, 0xc8, 0xc9, 0xca,
095                                          0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
096                                          0xd7, 0xd8, 0xd9, 0xda, 0xe2,
097                                          0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
098                                          0xe8, 0xe9, 0xea, 0xf2, 0xf3,
099                                          0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
100                                          0xf9, 0xfa }, false);
101
102  /**
103   * The standard JPEG AC luminance Huffman table.
104   */
105  public static final JPEGHuffmanTable StdACLuminance =
106      new JPEGHuffmanTable(new short[] { 0, 2, 1, 3, 3, 2, 4, 3, 5, 5,
107                                         4, 4, 0, 0, 1, 0x7d },
108                           new short[] { 0x01, 0x02, 0x03, 0x00, 0x04,
109                                         0x11, 0x05, 0x12, 0x21, 0x31,
110                                         0x41, 0x06, 0x13, 0x51, 0x61,
111                                         0x07, 0x22, 0x71, 0x14, 0x32,
112                                         0x81, 0x91, 0xa1, 0x08, 0x23,
113                                         0x42, 0xb1, 0xc1, 0x15, 0x52,
114                                         0xd1, 0xf0, 0x24, 0x33, 0x62,
115                                         0x72, 0x82, 0x09, 0x0a, 0x16,
116                                         0x17, 0x18, 0x19, 0x1a, 0x25,
117                                         0x26, 0x27, 0x28, 0x29, 0x2a,
118                                         0x34, 0x35, 0x36, 0x37, 0x38,
119                                         0x39, 0x3a, 0x43, 0x44, 0x45,
120                                         0x46, 0x47, 0x48, 0x49, 0x4a,
121                                         0x53, 0x54, 0x55, 0x56, 0x57,
122                                         0x58, 0x59, 0x5a, 0x63, 0x64,
123                                         0x65, 0x66, 0x67, 0x68, 0x69,
124                                         0x6a, 0x73, 0x74, 0x75, 0x76,
125                                         0x77, 0x78, 0x79, 0x7a, 0x83,
126                                         0x84, 0x85, 0x86, 0x87, 0x88,
127                                         0x89, 0x8a, 0x92, 0x93, 0x94,
128                                         0x95, 0x96, 0x97, 0x98, 0x99,
129                                         0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
130                                         0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
131                                         0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
132                                         0xb7, 0xb8, 0xb9, 0xba, 0xc2,
133                                         0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
134                                         0xc8, 0xc9, 0xca, 0xd2, 0xd3,
135                                         0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
136                                         0xd9, 0xda, 0xe1, 0xe2, 0xe3,
137                                         0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
138                                         0xe9, 0xea, 0xf1, 0xf2, 0xf3,
139                                         0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
140                                         0xf9, 0xfa }, false);
141
142  /**
143   * The standard JPEG DC chrominance Huffman table.
144   */
145  public static final JPEGHuffmanTable StdDCChrominance =
146      new JPEGHuffmanTable(new short[] { 0, 3, 1, 1, 1, 1, 1, 1, 1, 1,
147                                         1, 0, 0, 0, 0, 0 },
148                           new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
149                                         10, 11 }, false);
150
151  /**
152   * The standard JPEG DC luminance Huffman table.
153   */
154  public static final JPEGHuffmanTable StdDCLuminance =
155      new JPEGHuffmanTable(new short[] { 0, 1, 5, 1, 1, 1, 1, 1, 1, 0,
156                                         0, 0, 0, 0, 0, 0 },
157                           new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
158                                         10, 11 }, false);
159
160  /**
161   * Construct and initialize a Huffman table. Copies are created of
162   * the array arguments. lengths[index] stores the number of Huffman
163   * values with Huffman codes of length index + 1. The values array
164   * stores the Huffman values in order of increasing code length.
165   *
166   * @param lengths an array of Huffman code lengths
167   * @param values a sorted array of Huffman values
168   * @throws IllegalArgumentException if either parameter is null, if
169   * lengths.length > 16 or values.length > 256, if any value in
170   * length or values is negative, or if the parameters do not
171   * describe a valid Huffman table
172   */
173  public JPEGHuffmanTable(short[] lengths, short[] values)
174  {
175    // Create copies of the lengths and values arguments.
176    this(checkLengths(lengths), checkValues(values, lengths), true);
177  }
178
179  /**
180   * Private constructor that avoids unnecessary copying and argument
181   * checking.
182   *
183   * @param lengths an array of Huffman code lengths
184   * @param values a sorted array of Huffman values
185   * @param copy true if copies should be created of the given arrays
186   */
187  private JPEGHuffmanTable(short[] lengths, short[] values, boolean copy)
188  {
189    this.lengths = copy ? (short[]) lengths.clone() : lengths;
190    this.values = copy ? (short[]) values.clone() : values;
191  }
192
193  private static short[] checkLengths(short[] lengths)
194  {
195    if (lengths == null || lengths.length > 16)
196      throw new IllegalArgumentException("invalid length array");
197
198    for (int i = 0; i < lengths.length; i++)
199      {
200        if (lengths[i] < 0)
201          throw new IllegalArgumentException("negative length");
202      }
203
204    int sum = 0;
205    for (int i = 0; i < lengths.length; i++)
206      {
207        if (lengths[i] > ((1 << (i + 1)) - 1))
208          throw new IllegalArgumentException("invalid number of codes"
209                                             + " for code length " + (i + 1));
210        sum += lengths[i];
211      }
212
213    return lengths;
214  }
215
216  private static short[] checkValues(short[] values, short[] lengths)
217  {
218    if (values == null || values.length > 256)
219      throw new IllegalArgumentException("invalid values array");
220
221    for (int i = 0; i < values.length; i++)
222      {
223        if (values[i] < 0)
224          throw new IllegalArgumentException("negative value");
225      }
226    // lengths is known-valid by this point.
227    int sum = 0;
228    for (int i = 0; i < lengths.length; i++)
229      sum += lengths[i];
230
231    if (values.length != sum)
232      throw new IllegalArgumentException("invalid number of values"
233                                         + " for number of codes");
234
235    return values;
236  }
237
238  /**
239   * Retrieve a copy of the array of Huffman code lengths.  If the
240   * returned array is called lengthcount, there are
241   * lengthcount[index] codes of length index + 1.
242   *
243   * @return a copy of the array of Huffman code lengths
244   */
245  public short[] getLengths()
246  {
247    return (short[]) lengths.clone();
248  }
249
250  /**
251   * Retrieve a copy of the array of Huffman values, sorted in order
252   * of increasing code length.
253   *
254   * @return a copy of the array of Huffman values
255   */
256  public short[] getValues()
257  {
258    return (short[]) values.clone();
259  }
260
261  /**
262   * Create a string representation of this JPEG Huffman table.
263   *
264   * @return a string representation of this JPEG Huffman table.
265   */
266  public String toString()
267  {
268    CPStringBuilder buffer = new CPStringBuilder();
269
270    buffer.append("JPEGHuffmanTable:\nlengths:");
271
272    for (int i = 0; i < lengths.length; i++)
273      buffer.append(" " + lengths[i]);
274
275    buffer.append("\nvalues:");
276
277    for (int i = 0; i < values.length; i++)
278      buffer.append(" " + values[i]);
279
280    return buffer.toString();
281  }
282}