2 * Imagesqueeze - Image codec optimized for photos.
3 * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU General Public License
7 * as published by the Free Software Foundation.
10 package eu.svjatoslav.imagesqueeze.codec;
12 import java.io.IOException;
14 import eu.svjatoslav.commons.data.BitInputStream;
15 import eu.svjatoslav.commons.data.BitOutputStream;
21 public class Table implements Comparable<Table> {
23 int[] range = new int[100];
24 int[] switchTreshold = new int[100];
25 int[] bitcount = new int[100];
27 int[] bitCountForRange = new int[256];
28 int[] proposedRangeForActualRange = new int[256];
29 int[] proposedRangeForActualRangeLow = new int[256];
30 int[] proposedRangeForActualRangeHigh = new int[256];
31 byte[] proposedDecreasedRange = new byte[256];
36 * @param switchTreshold
37 * - switch to this range when actual range in equal or below
40 public void addEntry(int range, int switchTreshold, int bitcount) {
46 if (switchTreshold < 0)
48 if (switchTreshold > 255)
56 this.range[usedEntries] = range;
57 this.switchTreshold[usedEntries] = switchTreshold;
58 this.bitcount[usedEntries] = bitcount;
63 * Compares two tables. Ignores table initialization.
66 public int compareTo(final Table o) {
67 if (usedEntries < o.usedEntries)
69 if (usedEntries > o.usedEntries)
72 for (int i = 0; i < usedEntries; i++) {
73 if (range[i] < o.range[i])
75 if (range[i] > o.range[i])
78 if (switchTreshold[i] < o.switchTreshold[i])
80 if (switchTreshold[i] > o.switchTreshold[i])
83 if (bitcount[i] < o.bitcount[i])
85 if (bitcount[i] > o.bitcount[i])
92 public void computeLookupTables() {
93 int currentCheckPointer = 0;
95 for (int i = 0; i < 256; i++) {
97 if (range[currentCheckPointer] == i)
98 currentCheckPointer++;
100 if (currentCheckPointer > 0)
101 bitCountForRange[i] = bitcount[currentCheckPointer - 1];
103 bitCountForRange[i] = 0;
107 for (int i = 0; i < 256; i++) {
111 for (seek = 0; seek < usedEntries; seek++)
112 if (switchTreshold[seek] >= i)
116 proposedRangeForActualRange[i] = range[seek];
118 proposedRangeForActualRangeLow[i] = 0;
120 proposedRangeForActualRangeLow[i] = switchTreshold[seek - 1] + 1;
121 proposedRangeForActualRangeHigh[i] = switchTreshold[seek];
124 currentCheckPointer = usedEntries - 2;
125 for (int i = 255; i >= 0; i--) {
126 if (range[currentCheckPointer] == i)
127 currentCheckPointer--;
129 if (currentCheckPointer < 0)
130 proposedDecreasedRange[i] = 0;
132 proposedDecreasedRange[i] = (byte) (range[currentCheckPointer]);
137 public void load(final BitInputStream inputStream) throws IOException {
140 final int availableEntries = ImageDecoder
141 .readIntegerCompressed8(inputStream);
143 for (int i = 0; i < availableEntries; i++)
144 addEntry(inputStream.readBits(8), inputStream.readBits(8),
145 inputStream.readBits(4));
148 public int proposeBitcountForRange(int range) {
153 final int proposal = bitCountForRange[range];
157 public int proposeDecreasedRange(int range) {
163 return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
166 public int proposeRangeForRange(final int actualRange, int inheritedRange) {
168 if (inheritedRange > 255)
169 inheritedRange = 255;
170 if (inheritedRange < 0)
173 if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange)
174 return inheritedRange;
176 return proposeDecreasedRange(inheritedRange);
179 public void reset() {
180 range = new int[100];
181 switchTreshold = new int[100];
182 bitcount = new int[100];
184 bitCountForRange = new int[256];
185 proposedRangeForActualRange = new int[256];
186 proposedRangeForActualRangeLow = new int[256];
187 proposedRangeForActualRangeHigh = new int[256];
188 proposedDecreasedRange = new byte[256];
193 public void save(final BitOutputStream outputStream) throws IOException {
194 ImageEncoder.storeIntegerCompressed8(outputStream, usedEntries);
196 for (int i = 0; i < usedEntries; i++) {
197 outputStream.storeBits(range[i], 8);
198 outputStream.storeBits(switchTreshold[i], 8);
199 outputStream.storeBits(bitcount[i], 4);