+/*
+ * Imagesqueeze - Image codec. Copyright ©2012-2019, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
+ */
+
package eu.svjatoslav.imagesqueeze.codec;
+import eu.svjatoslav.commons.data.BitInputStream;
+import eu.svjatoslav.commons.data.BitOutputStream;
+
import java.io.IOException;
/**
* Quick lookup table.
*/
-public class Table implements Comparable<Table>{
-
- int [] range = new int[100];
- int [] switchTreshold = new int[100];
- int [] bitcount = new int[100];
-
-
- int [] bitCountForRange = new int[256];
- int [] proposedRangeForActualRange = new int[256];
- int [] proposedRangeForActualRangeLow = new int[256];
- int [] proposedRangeForActualRangeHigh = new int[256];
- byte [] proposedDecreasedRange = new byte[256];
-
-
- int usedEntries = 0;
-
-
- public void computeLookupTables(){
- int currentCheckPointer = 0;
-
- for (int i=0; i<256; i++){
-
- if (range[currentCheckPointer] == i){
- currentCheckPointer++;
- }
-
- if (currentCheckPointer > 0){
- bitCountForRange[i] = bitcount[currentCheckPointer-1];
- } else {
- bitCountForRange[i] = 0;
- }
-
- }
-
- for (int i=0; i<256; i++){
-
- int seek;
- seekLoop:{
- for (seek = 0; seek < usedEntries; seek ++){
-
- if (switchTreshold[seek] >= i) break seekLoop;
-
- }
- }
-
- proposedRangeForActualRange[i] = range[seek];
- if (seek == 0){
- proposedRangeForActualRangeLow[i] = 0;
- } else {
- proposedRangeForActualRangeLow[i] = switchTreshold[seek-1]+1;
- }
- proposedRangeForActualRangeHigh[i] = switchTreshold[seek];
- }
-
-
- currentCheckPointer = usedEntries - 2;
- for (int i=255; i >= 0; i--){
- if (range[currentCheckPointer] == i) currentCheckPointer--;
-
- if (currentCheckPointer < 0){
- proposedDecreasedRange[i] = 0;
- } else {
- proposedDecreasedRange[i] = (byte)(range[currentCheckPointer]);
- }
- }
-
- }
-
- /**
- * @param switchTreshold - switch to this range when actual range in equal or below this treshold
- */
- public void addEntry(int range, int switchTreshold, int bitcount){
- if (range < 0) range = 0;
- if (range > 255) range = 255;
-
- if (switchTreshold < 0) switchTreshold = 0;
- if (switchTreshold > 255) switchTreshold = 255;
-
- if (bitcount < 0) bitcount = 0;
- if (bitcount > 8) bitcount = 8;
-
-
- this.range[usedEntries] = range;
- this.switchTreshold[usedEntries] = switchTreshold;
- this.bitcount[usedEntries] = bitcount;
- usedEntries++;
- }
-
-
-
-
- public int proposeRangeForRange(int actualRange, int inheritedRange){
-
- if (inheritedRange > 255) inheritedRange = 255;
- if (inheritedRange < 0) inheritedRange = 0;
-
- if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange){
- return inheritedRange;
- }
-
- return proposeDecreasedRange(inheritedRange);
- }
-
-
- public int proposeDecreasedRange(int range){
- if (range > 255) range = 255;
- if (range < 0) range = 0;
-
- return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
- }
-
-
- public int proposeBitcountForRange(int range){
- if (range > 255) range = 255;
- if (range < 0) range = 0;
- int proposal = bitCountForRange[range];
- return proposal;
- }
-
- /**
- * Compares two tables.
- * Ignores table initialization.
- */
- public int compareTo(Table o) {
- if (usedEntries < o.usedEntries) return -1;
- if (usedEntries > o.usedEntries) return 1;
-
- for (int i=0; i<usedEntries; i++){
- if (range[i] < o.range[i]) return -1;
- if (range[i] > o.range[i]) return 1;
-
- if (switchTreshold[i] < o.switchTreshold[i]) return -1;
- if (switchTreshold[i] > o.switchTreshold[i]) return 1;
-
- if (bitcount[i] < o.bitcount[i]) return -1;
- if (bitcount[i] > o.bitcount[i]) return 1;
- }
-
- return 0;
- }
-
- public void save(BitOutputStream outputStream) throws IOException {
- outputStream.storeIntegerCompressed8(usedEntries);
-
- for (int i=0; i < usedEntries; i++){
- outputStream.storeBits(this.range[i], 8);
- outputStream.storeBits(this.switchTreshold[i], 8);
- outputStream.storeBits(this.bitcount[i], 4);
- }
- }
-
- public void reset(){
- range = new int[100];
- switchTreshold = new int[100];
- bitcount = new int[100];
-
-
- bitCountForRange = new int[256];
- proposedRangeForActualRange = new int[256];
- proposedRangeForActualRangeLow = new int[256];
- proposedRangeForActualRangeHigh = new int[256];
- proposedDecreasedRange = new byte[256];
-
- usedEntries = 0;
- }
-
- public void load(BitInputStream inputStream) throws IOException {
- reset();
-
- int availableEntries = inputStream.readIntegerCompressed8();
-
- for (int i=0; i < availableEntries; i++){
- addEntry(inputStream.readBits(8), inputStream.readBits(8), inputStream.readBits(4));
- }
- }
-
-
+public class Table {
+
+ private int[] range = new int[100];
+ private int[] switchThreshold = new int[100];
+ private int[] bitCount = new int[100];
+
+ private int[] bitCountForRange = new int[256];
+ private int[] proposedRangeForActualRange = new int[256];
+ private int[] proposedRangeForActualRangeLow = new int[256];
+ private int[] proposedRangeForActualRangeHigh = new int[256];
+ private byte[] proposedDecreasedRange = new byte[256];
+
+ private int usedEntries = 0;
+
+ /**
+ * @param switchThreshold - switch to this range when actual range in equal or below
+ * this threshold
+ */
+ public void addEntry(int range, int switchThreshold, int bitcount) {
+ if (range < 0)
+ range = 0;
+ if (range > 255)
+ range = 255;
+
+ if (switchThreshold < 0)
+ switchThreshold = 0;
+ if (switchThreshold > 255)
+ switchThreshold = 255;
+
+ if (bitcount < 0)
+ bitcount = 0;
+ if (bitcount > 8)
+ bitcount = 8;
+
+ this.range[usedEntries] = range;
+ this.switchThreshold[usedEntries] = switchThreshold;
+ this.bitCount[usedEntries] = bitcount;
+ usedEntries++;
+ }
+
+ public void computeLookupTables() {
+ int currentCheckPointer = 0;
+
+ for (int i = 0; i < 256; i++) {
+
+ if (range[currentCheckPointer] == i)
+ currentCheckPointer++;
+
+ if (currentCheckPointer > 0)
+ bitCountForRange[i] = bitCount[currentCheckPointer - 1];
+ else
+ bitCountForRange[i] = 0;
+
+ }
+
+ for (int i = 0; i < 256; i++) {
+
+ int seek;
+ seekLoop:
+ {
+ for (seek = 0; seek < usedEntries; seek++)
+ if (switchThreshold[seek] >= i)
+ break seekLoop;
+ }
+
+ proposedRangeForActualRange[i] = range[seek];
+ if (seek == 0)
+ proposedRangeForActualRangeLow[i] = 0;
+ else
+ proposedRangeForActualRangeLow[i] = switchThreshold[seek - 1] + 1;
+ proposedRangeForActualRangeHigh[i] = switchThreshold[seek];
+ }
+
+ currentCheckPointer = usedEntries - 2;
+ for (int i = 255; i >= 0; i--) {
+ if (range[currentCheckPointer] == i)
+ currentCheckPointer--;
+
+ if (currentCheckPointer < 0)
+ proposedDecreasedRange[i] = 0;
+ else
+ proposedDecreasedRange[i] = (byte) (range[currentCheckPointer]);
+ }
+
+ }
+
+ public void load(final BitInputStream inputStream) throws IOException {
+ reset();
+
+ final int availableEntries = ImageDecoder
+ .readIntegerCompressed8(inputStream);
+
+ for (int i = 0; i < availableEntries; i++)
+ addEntry(inputStream.readBits(8), inputStream.readBits(8),
+ inputStream.readBits(4));
+ }
+
+ public int proposeBitcountForRange(int range) {
+ if (range > 255)
+ range = 255;
+ if (range < 0)
+ range = 0;
+ return bitCountForRange[range];
+ }
+
+ public int proposeDecreasedRange(int range) {
+ if (range > 255)
+ range = 255;
+ if (range < 0)
+ range = 0;
+
+ return ImageEncoder.byteToInt(proposedDecreasedRange[range]);
+ }
+
+ public int proposeRangeForRange(final int actualRange, int inheritedRange) {
+
+ if (inheritedRange > 255)
+ inheritedRange = 255;
+ if (inheritedRange < 0)
+ inheritedRange = 0;
+
+ if (proposedRangeForActualRangeLow[inheritedRange] <= actualRange)
+ return inheritedRange;
+
+ return proposeDecreasedRange(inheritedRange);
+ }
+
+ public void reset() {
+ range = new int[100];
+ switchThreshold = new int[100];
+ bitCount = new int[100];
+
+ bitCountForRange = new int[256];
+ proposedRangeForActualRange = new int[256];
+ proposedRangeForActualRangeLow = new int[256];
+ proposedRangeForActualRangeHigh = new int[256];
+ proposedDecreasedRange = new byte[256];
+
+ usedEntries = 0;
+ }
+
+ public void save(final BitOutputStream outputStream) throws IOException {
+ ImageEncoder.storeIntegerCompressed8(outputStream, usedEntries);
+
+ for (int i = 0; i < usedEntries; i++) {
+ outputStream.storeBits(range[i], 8);
+ outputStream.storeBits(switchThreshold[i], 8);
+ outputStream.storeBits(bitCount[i], 4);
+ }
+ }
}