KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > swt > internal > image > PngHuffmanTables


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.swt.internal.image;
12
13 import java.io.*;
14
15 public class PngHuffmanTables {
16     PngHuffmanTable literalTable;
17     PngHuffmanTable distanceTable;
18     
19     static PngHuffmanTable FixedLiteralTable;
20     static PngHuffmanTable FixedDistanceTable;
21     
22     static final int LiteralTableSize = 288;
23     static final int[] FixedLiteralLengths = {
24         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
25         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
26         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
27         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
28         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
29         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
30         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
31         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
32         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
33         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
34         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
35         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
36     };
37
38     static final int DistanceTableSize = 32;
39     static final int[] FixedDistanceLengths = {
40         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
41         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
42     };
43     
44     static final int LengthCodeTableSize = 19;
45     static final int[] LengthCodeOrder = {
46         16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
47         11, 4, 12, 3, 13, 2, 14, 1, 15
48     };
49     
50 static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream) throws IOException {
51     return new PngHuffmanTables(stream);
52 }
53 static PngHuffmanTables getFixedTables() {
54     return new PngHuffmanTables();
55 }
56
57 private PngHuffmanTable getFixedLiteralTable() {
58     if (FixedLiteralTable == null) {
59         FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
60     }
61     return FixedLiteralTable;
62 }
63
64 private PngHuffmanTable getFixedDistanceTable() {
65     if (FixedDistanceTable == null) {
66         FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
67     }
68     return FixedDistanceTable;
69 }
70
71 private PngHuffmanTables () {
72     literalTable = getFixedLiteralTable();
73     distanceTable = getFixedDistanceTable();
74 }
75
76 private PngHuffmanTables (PngDecodingDataStream stream) throws IOException {
77     int literals = PngLzBlockReader.FIRST_LENGTH_CODE
78         + stream.getNextIdatBits(5);
79     int distances = PngLzBlockReader.FIRST_DISTANCE_CODE
80         + stream.getNextIdatBits(5);
81     int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE
82         + stream.getNextIdatBits(4);
83
84     if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
85         stream.error();
86     }
87     
88     /* Tricky, tricky, tricky. The length codes are stored in
89      * a very odd order. (For the order, see the definition of
90      * the static field lengthCodeOrder.) Also, the data may
91      * not contain values for all the codes. It may just contain
92      * values for the first X number of codes. The table should
93      * be of size <LengthCodeTableSize> regardless of the number
94      * of values actually given in the table.
95      */

96     int[] lengthCodes = new int[LengthCodeTableSize];
97     for (int i = 0; i < codeLengthCodes; i++) {
98         lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
99     }
100     PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
101     
102     int[] literalLengths = readLengths(
103         stream, literals, codeLengthsTable, LiteralTableSize);
104     int[] distanceLengths = readLengths(
105         stream, distances, codeLengthsTable, DistanceTableSize);
106     
107     literalTable = new PngHuffmanTable(literalLengths);
108     distanceTable = new PngHuffmanTable(distanceLengths);
109 }
110
111 private int [] readLengths (PngDecodingDataStream stream,
112     int numLengths,
113     PngHuffmanTable lengthsTable,
114     int tableSize) throws IOException
115 {
116     int[] lengths = new int[tableSize];
117     
118     for (int index = 0; index < numLengths;) {
119         int value = lengthsTable.getNextValue(stream);
120         if (value < 16) {
121             // Literal value
122
lengths[index] = value;
123             index++;
124         } else if (value == 16) {
125             // Repeat the previous code 3-6 times.
126
int count = stream.getNextIdatBits(2) + 3;
127             for (int i = 0; i < count; i++) {
128                 lengths[index] = lengths [index - 1];
129                 index++;
130             }
131         } else if (value == 17) {
132             // Repeat 0 3-10 times.
133
int count = stream.getNextIdatBits(3) + 3;
134             for (int i = 0; i < count; i++) {
135                 lengths[index] = 0;
136                 index++;
137             }
138         } else if (value == 18) {
139             // Repeat 0 11-138 times.
140
int count = stream.getNextIdatBits(7) + 11;
141             for (int i = 0; i < count; i++) {
142                 lengths[index] = 0;
143                 index++;
144             }
145         } else {
146             stream.error();
147         }
148     }
149     return lengths;
150 }
151
152 int getNextLiteralValue(PngDecodingDataStream stream) throws IOException {
153     return literalTable.getNextValue(stream);
154 }
155
156 int getNextDistanceValue(PngDecodingDataStream stream) throws IOException {
157     return distanceTable.getNextValue(stream);
158 }
159
160 }
161
Popular Tags