| 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 |
} |
|---|