Skip to main content
summaryrefslogtreecommitdiffstats
blob: 09bd04ef3da6b47acf9cd7e04cdd0040da79ed58 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.internal.image;

import java.io.*;

public class PngHuffmanTables {
	PngHuffmanTable literalTable;
	PngHuffmanTable distanceTable;
	
	static PngHuffmanTable FixedLiteralTable;
	static PngHuffmanTable FixedDistanceTable;
	
	static final int LiteralTableSize = 288;
	static final int[] FixedLiteralLengths = {
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
        9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
	};

	static final int DistanceTableSize = 32;
	static final int[] FixedDistanceLengths = {
		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
		5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
	};
	
	static final int LengthCodeTableSize = 19;
	static final int[] LengthCodeOrder = {
		16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
		11, 4, 12, 3, 13, 2, 14, 1, 15
	};
	
static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream) throws IOException {
	return new PngHuffmanTables(stream);
}
static PngHuffmanTables getFixedTables() {
	return new PngHuffmanTables();
}

private PngHuffmanTable getFixedLiteralTable() {
	if (FixedLiteralTable == null) {
		FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
	}
	return FixedLiteralTable;
}

private PngHuffmanTable getFixedDistanceTable() {
	if (FixedDistanceTable == null) {
		FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
	}
	return FixedDistanceTable;
}

private PngHuffmanTables () {
	literalTable = getFixedLiteralTable();
	distanceTable = getFixedDistanceTable();
}

private PngHuffmanTables (PngDecodingDataStream stream) throws IOException {
	int literals = PngLzBlockReader.FIRST_LENGTH_CODE 
		+ stream.getNextIdatBits(5);
	int distances = PngLzBlockReader.FIRST_DISTANCE_CODE 
		+ stream.getNextIdatBits(5);
	int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE 
		+ stream.getNextIdatBits(4);

	if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
		stream.error();
	}
	
	/* Tricky, tricky, tricky. The length codes are stored in
	 * a very odd order. (For the order, see the definition of
	 * the static field lengthCodeOrder.) Also, the data may 
	 * not contain values for all the codes. It may just contain 
	 * values for the first X number of codes. The table should
	 * be of size <LengthCodeTableSize> regardless of the number
	 * of values actually given in the table.
	 */	
	int[] lengthCodes = new int[LengthCodeTableSize];
	for (int i = 0; i < codeLengthCodes; i++) {
		lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
	}
	PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
	
	int[] literalLengths = readLengths(
		stream, literals, codeLengthsTable, LiteralTableSize);
	int[] distanceLengths = readLengths(
		stream, distances, codeLengthsTable, DistanceTableSize);
	
	literalTable = new PngHuffmanTable(literalLengths);
	distanceTable = new PngHuffmanTable(distanceLengths);
}

private int [] readLengths (PngDecodingDataStream stream, 
	int numLengths, 
	PngHuffmanTable lengthsTable,
	int tableSize) throws IOException
{
	int[] lengths = new int[tableSize];
	
	for (int index = 0; index < numLengths;) {
		int value = lengthsTable.getNextValue(stream);
		if (value < 16) {
			// Literal value
			lengths[index] = value;
			index++;
		} else if (value == 16) {
			// Repeat the previous code 3-6 times.
			int count = stream.getNextIdatBits(2) + 3;
			for (int i = 0; i < count; i++) {
				lengths[index] = lengths [index - 1];
				index++;
			}
		} else if (value == 17) {
			// Repeat 0 3-10 times.
			int count = stream.getNextIdatBits(3) + 3;
			for (int i = 0; i < count; i++) {
				lengths[index] = 0;
				index++;
			}
		} else if (value == 18) {
			// Repeat 0 11-138 times.
			int count = stream.getNextIdatBits(7) + 11;
			for (int i = 0; i < count; i++) {
				lengths[index] = 0;
				index++;
			}
		} else {
			stream.error();
		}
	}
	return lengths;
}

int getNextLiteralValue(PngDecodingDataStream stream) throws IOException {
	return literalTable.getNextValue(stream);
}

int getNextDistanceValue(PngDecodingDataStream stream) throws IOException {
	return distanceTable.getNextValue(stream);
}

}

Back to the top