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