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++;
101 if (currentCheckPointer > 0) {
102 bitCountForRange[i] = bitcount[currentCheckPointer - 1];
104 bitCountForRange[i] = 0;
109 for (int i = 0; i < 256; i++) {
113 for (seek = 0; seek < usedEntries; seek++) {
115 if (switchTreshold[seek] >= i)
121 proposedRangeForActualRange[i] = range[seek];
123 proposedRangeForActualRangeLow[i] = 0;
125 proposedRangeForActualRangeLow[i] = switchTreshold[seek - 1] + 1;
127 proposedRangeForActualRangeHigh[i] = switchTreshold[seek];
130 currentCheckPointer = usedEntries - 2;
131 for (int i = 255; i >= 0; i--) {
132 if (range[currentCheckPointer] == i)
133 currentCheckPointer--;
135 if (currentCheckPointer < 0) {
136 proposedDecreasedRange[i] = 0;
138 proposedDecreasedRange[i] = (byte) (range[currentCheckPointer]);
144 public void load(final BitInputStream inputStream) throws IOException {
147 final int availableEntries = inputStream.readIntegerCompressed8();
149 for (int i = 0; i < availableEntries; i++) {
150 addEntry(inputStream.readBits(8), inputStream.readBits(8),
151 inputStream.readBits(4));
155 public int proposeBitcountForRange(int range) {
160 final int proposal = bitCountForRange[range];
164 public int proposeDecreasedRange(int range) {
170 return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
173 public int proposeRangeForRange(final int actualRange, int inheritedRange) {
175 if (inheritedRange > 255)
176 inheritedRange = 255;
177 if (inheritedRange < 0)
180 if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange) {
181 return inheritedRange;
184 return proposeDecreasedRange(inheritedRange);
187 public void reset() {
188 range = new int[100];
189 switchTreshold = new int[100];
190 bitcount = new int[100];
192 bitCountForRange = new int[256];
193 proposedRangeForActualRange = new int[256];
194 proposedRangeForActualRangeLow = new int[256];
195 proposedRangeForActualRangeHigh = new int[256];
196 proposedDecreasedRange = new byte[256];
201 public void save(final BitOutputStream outputStream) throws IOException {
202 outputStream.storeIntegerCompressed8(usedEntries);
204 for (int i = 0; i < usedEntries; i++) {
205 outputStream.storeBits(range[i], 8);
206 outputStream.storeBits(switchTreshold[i], 8);
207 outputStream.storeBits(bitcount[i], 4);