root/dwt/internal/image/PngHuffmanTables.d

Revision 2:57151e2793a2, 5.9 kB (checked in by Frank Benoit <benoit@tionex.de>, 1 year ago)

More common modules from dwt-linux

Line 
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  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module dwt.internal.image.PngHuffmanTables;
14
15 import dwt.internal.image.PngHuffmanTable;
16 import dwt.internal.image.PngDecodingDataStream;
17 import dwt.internal.image.PngLzBlockReader;
18
19 public class PngHuffmanTables {
20     PngHuffmanTable literalTable;
21     PngHuffmanTable distanceTable;
22
23     static PngHuffmanTable FixedLiteralTable;
24     static PngHuffmanTable FixedDistanceTable;
25
26     static final int LiteralTableSize = 288;
27     static final int[] FixedLiteralLengths = [
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         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
31         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
32         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
33         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
34         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
35         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
36         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
37         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
38         9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, 7, 7, 7,
39         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
40     ];
41
42     static final int DistanceTableSize = 32;
43     static final int[] FixedDistanceLengths = [
44         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
45         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
46     ];
47
48     static final int LengthCodeTableSize = 19;
49     static final int[] LengthCodeOrder = [
50         16, 17, 18, 0, 8, 7, 9, 6, 10, 5,
51         11, 4, 12, 3, 13, 2, 14, 1, 15
52     ];
53
54 static PngHuffmanTables getDynamicTables(PngDecodingDataStream stream)  {
55     return new PngHuffmanTables(stream);
56 }
57 static PngHuffmanTables getFixedTables() {
58     return new PngHuffmanTables();
59 }
60
61 private PngHuffmanTable getFixedLiteralTable() {
62     if (FixedLiteralTable is null) {
63         FixedLiteralTable = new PngHuffmanTable(FixedLiteralLengths);
64     }
65     return FixedLiteralTable;
66 }
67
68 private PngHuffmanTable getFixedDistanceTable() {
69     if (FixedDistanceTable is null) {
70         FixedDistanceTable = new PngHuffmanTable(FixedDistanceLengths);
71     }
72     return FixedDistanceTable;
73 }
74
75 private this () {
76     literalTable = getFixedLiteralTable();
77     distanceTable = getFixedDistanceTable();
78 }
79
80 private this (PngDecodingDataStream stream)  {
81     int literals = PngLzBlockReader.FIRST_LENGTH_CODE
82         + stream.getNextIdatBits(5);
83     int distances = PngLzBlockReader.FIRST_DISTANCE_CODE
84         + stream.getNextIdatBits(5);
85     int codeLengthCodes = PngLzBlockReader.FIRST_CODE_LENGTH_CODE
86         + stream.getNextIdatBits(4);
87
88     if (codeLengthCodes > PngLzBlockReader.LAST_CODE_LENGTH_CODE) {
89         stream.error();
90     }
91
92     /* Tricky, tricky, tricky. The length codes are stored in
93      * a very odd order. (For the order, see the definition of
94      * the static field lengthCodeOrder.) Also, the data may
95      * not contain values for all the codes. It may just contain
96      * values for the first X number of codes. The table should
97      * be of size <LengthCodeTableSize> regardless of the number
98      * of values actually given in the table.
99      */
100     int[] lengthCodes = new int[LengthCodeTableSize];
101     for (int i = 0; i < codeLengthCodes; i++) {
102         lengthCodes[LengthCodeOrder[i]] = stream.getNextIdatBits(3);
103     }
104     PngHuffmanTable codeLengthsTable = new PngHuffmanTable(lengthCodes);
105
106     int[] literalLengths = readLengths(
107         stream, literals, codeLengthsTable, LiteralTableSize);
108     int[] distanceLengths = readLengths(
109         stream, distances, codeLengthsTable, DistanceTableSize);
110
111     literalTable = new PngHuffmanTable(literalLengths);
112     distanceTable = new PngHuffmanTable(distanceLengths);
113 }
114
115 private int [] readLengths (PngDecodingDataStream stream,
116     int numLengths,
117     PngHuffmanTable lengthsTable,
118     int tableSize)
119 {
120     int[] lengths = new int[tableSize];
121
122     for (int index = 0; index < numLengths;) {
123         int value = lengthsTable.getNextValue(stream);
124         if (value < 16) {
125             // Literal value
126             lengths[index] = value;
127             index++;
128         } else if (value is 16) {
129             // Repeat the previous code 3-6 times.
130             int count = stream.getNextIdatBits(2) + 3;
131             for (int i = 0; i < count; i++) {
132                 lengths[index] = lengths [index - 1];
133                 index++;
134             }
135         } else if (value is 17) {
136             // Repeat 0 3-10 times.
137             int count = stream.getNextIdatBits(3) + 3;
138             for (int i = 0; i < count; i++) {
139                 lengths[index] = 0;
140                 index++;
141             }
142         } else if (value is 18) {
143             // Repeat 0 11-138 times.
144             int count = stream.getNextIdatBits(7) + 11;
145             for (int i = 0; i < count; i++) {
146                 lengths[index] = 0;
147                 index++;
148             }
149         } else {
150             stream.error();
151         }
152     }
153     return lengths;
154 }
155
156 int getNextLiteralValue(PngDecodingDataStream stream)  {
157     return literalTable.getNextValue(stream);
158 }
159
160 int getNextDistanceValue(PngDecodingDataStream stream)  {
161     return distanceTable.getNextValue(stream);
162 }
163
164 }
Note: See TracBrowser for help on using the browser.