root/dwt/internal/image/PngHuffmanTable.d

Revision 246:fd9c62a2998e, 4.3 kB (checked in by Frank Benoit <benoit@tionex.de>, 6 months ago)

Updater SWT 3.4M7 to 3.4

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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.PngHuffmanTable;
14
15 import dwt.internal.image.PngDecodingDataStream;
16
17 public class PngHuffmanTable {
18     CodeLengthInfo[] codeLengthInfo;
19     int[] codeValues;
20
21     static const int MAX_CODE_LENGTH = 15;
22     static const int BAD_CODE = 0xFFFFFFF;
23     static const int incs[] = [1391376, 463792, 198768, 86961, 33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1];
24
25 this (int[] lengths) {
26     initialize(lengths);
27     generateTable(lengths);
28 }
29
30 private void initialize(int[] lengths) {
31     codeValues = new int[lengths.length];
32     for (int i = 0; i < codeValues.length; i++) {
33         codeValues[i] = i;
34     }
35
36     // minCodesByLength[n] : The smallest Huffman code of length n + 1.
37     // maxCodesByLength[n] : The largest Huffman code of length n + 1.
38     // indexesByLength[n] : Index into the values array. First value with a code of length n + 1.
39     codeLengthInfo = new CodeLengthInfo[MAX_CODE_LENGTH];
40     for (int i = 0; i < MAX_CODE_LENGTH; i++) {
41         codeLengthInfo[i] = new CodeLengthInfo();
42         codeLengthInfo[i].length = i;
43         codeLengthInfo[i].baseIndex = 0;
44         codeLengthInfo[i].min = BAD_CODE;
45         codeLengthInfo[i].max = -1;
46     }
47 }
48
49 private void generateTable(int[] lengths) {
50     // Sort the values using shellsort. Primary key is code size. Secondary key is value.
51     int codeValuesTemp;
52     for (int k = 0; k < 16; k++) {
53         for (int h = incs[k], i = h; i < lengths.length; i++) {
54             int v = lengths[i];
55             codeValuesTemp = codeValues[i];
56             int j = i;
57             while (j >= h && (lengths[j - h] > v || (lengths[j - h] is v && codeValues[j - h] > codeValuesTemp))) {
58                 lengths[j] = lengths[j - h];
59                 codeValues[j] = codeValues[j - h];
60                 j -= h;
61             }
62             lengths[j] = v;
63             codeValues[j] = codeValuesTemp;
64         }
65     }
66
67     // These values in these arrays correspond to the elements of the
68     // "values" array. The Huffman code for codeValues[N] is codes[N]
69     // and the length of the code is lengths[N].
70     int[] codes = new int[lengths.length];
71     int lastLength = 0;
72     int code = 0;
73     for (int i = 0; i < lengths.length; i++) {
74         while (lastLength !is lengths[i]) {
75             lastLength++;
76             code <<= 1;
77         }
78         if (lastLength !is 0) {
79             codes[i] = code;
80             code++;
81         }
82     }
83
84     int last = 0;
85     for (int i = 0; i < lengths.length; i++) {
86         if (last !is lengths[i]) {
87             last = lengths[i];
88             codeLengthInfo[last - 1].baseIndex = i;
89             codeLengthInfo[last - 1].min = codes[i];
90         }
91         if (last !is 0) codeLengthInfo[last - 1].max = codes[i];
92     }
93 }
94
95 int getNextValue(PngDecodingDataStream stream) {
96     int code = stream.getNextIdatBit();
97     int codelength = 0;
98
99     // Here we are taking advantage of the fact that 1 bits are used as
100     // a prefix to the longer codeValues.
101     while (codelength < MAX_CODE_LENGTH && code > codeLengthInfo[codelength].max) {
102         code = ((code << 1) | stream.getNextIdatBit());
103         codelength++;
104     }
105     if (codelength >= MAX_CODE_LENGTH) stream.error();
106
107     // Now we have a Huffman code of length (codelength + 1) that
108     // is somewhere in the range
109     // minCodesByLength[codelength]..maxCodesByLength[codelength].
110     // This code is the (offset + 1)'th code of (codelength + 1);
111     int offset = code - codeLengthInfo[codelength].min;
112
113     // indexesByLength[codelength] is the first code of length (codelength + 1)
114     // so now we can look up the value for the Huffman code in the table.
115     int index = codeLengthInfo[codelength].baseIndex + offset;
116     return codeValues[index];
117 }
118
119 static class CodeLengthInfo {
120     int length;
121     int max;
122     int min;
123     int baseIndex;
124 }
125
126 }
Note: See TracBrowser for help on using the browser.