Moved to java 1.8. Code cleanup and formatting.
[imagesqueeze.git] / src / main / java / eu / svjatoslav / imagesqueeze / codec / ImageDecoder.java
index 53f2d91..24c1e27 100755 (executable)
@@ -13,239 +13,231 @@ package eu.svjatoslav.imagesqueeze.codec;
  * Compressed image pixels decoder.
  */
 
+import eu.svjatoslav.commons.data.BitInputStream;
+
 import java.awt.image.DataBufferByte;
 import java.awt.image.WritableRaster;
 import java.io.IOException;
 
-import eu.svjatoslav.commons.data.BitInputStream;
-
-public class ImageDecoder {
-
-       public static int readIntegerCompressed8(final BitInputStream inputStream)
-                       throws IOException {
-
-               if (inputStream.readBits(1) == 0)
-                       return inputStream.readBits(8);
-               else
-                       return inputStream.readBits(32);
-       }
-
-       int width, height;
-
-       Image image;
-       byte[] decodedYRangeMap;
-
-       byte[] decodedYMap;
-       byte[] decodedURangeMap;
-
-       byte[] decodedUMap;
-       byte[] decodedVRangeMap;
-
-       byte[] decodedVMap;
-
-       Color tmpColor = new Color();
-       Approximator approximator;
-
-       BitInputStream bitInputStream;
-       ColorStats colorStats = new ColorStats();
-
-       OperatingContext context = new OperatingContext();
-
-       public ImageDecoder(final Image image, final BitInputStream bitInputStream) {
-               approximator = new Approximator();
-
-               this.image = image;
-               this.bitInputStream = bitInputStream;
-
-               width = image.metaData.width;
-               height = image.metaData.height;
-
-               decodedYRangeMap = new byte[width * height];
-               decodedYRangeMap[0] = (byte) (255);
-               decodedYMap = new byte[width * height];
-
-               decodedURangeMap = new byte[width * height];
-               decodedURangeMap[0] = (byte) (255);
-               decodedUMap = new byte[width * height];
-
-               decodedVRangeMap = new byte[width * height];
-               decodedVRangeMap[0] = (byte) (255);
-               decodedVMap = new byte[width * height];
-
-       }
-
-       public void decode() throws IOException {
-               approximator.load(bitInputStream);
-               approximator.computeLookupTables();
-
-               final WritableRaster raster = image.bufferedImage.getRaster();
-               final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
-               final byte[] pixels = dbi.getData();
+class ImageDecoder {
 
-               // load top-, left-most pixel.
-               decodedYMap[0] = (byte) bitInputStream.readBits(8);
-               decodedUMap[0] = (byte) bitInputStream.readBits(8);
-               decodedVMap[0] = (byte) bitInputStream.readBits(8);
+    private final int width;
+    private final int height;
+    private final Image image;
+    private final byte[] decodedYRangeMap;
+    private final byte[] decodedYMap;
+    private final byte[] decodedURangeMap;
+    private final byte[] decodedUMap;
+    private final byte[] decodedVRangeMap;
+    private final byte[] decodedVMap;
+    private final Approximator approximator;
+    private final BitInputStream bitInputStream;
+    private final OperatingContext context = new OperatingContext();
 
-               final Color color = new Color();
-               color.y = ImageEncoder.byteToInt(decodedYMap[0]);
-               color.u = ImageEncoder.byteToInt(decodedUMap[0]);
-               color.v = ImageEncoder.byteToInt(decodedVMap[0]);
+    public ImageDecoder(final Image image, final BitInputStream bitInputStream) {
+        approximator = new Approximator();
 
-               color.YUV2RGB();
+        this.image = image;
+        this.bitInputStream = bitInputStream;
 
-               pixels[0] = (byte) color.r;
-               pixels[0 + 1] = (byte) color.g;
-               pixels[0 + 2] = (byte) color.b;
+        width = image.metaData.width;
+        height = image.metaData.height;
 
-               // detect initial step
-               int largestDimension;
-               int initialStep = 2;
-               if (width > height)
-                       largestDimension = width;
-               else
-                       largestDimension = height;
+        decodedYRangeMap = new byte[width * height];
+        decodedYRangeMap[0] = (byte) (255);
+        decodedYMap = new byte[width * height];
 
-               while (initialStep < largestDimension)
-                       initialStep = initialStep * 2;
+        decodedURangeMap = new byte[width * height];
+        decodedURangeMap[0] = (byte) (255);
+        decodedUMap = new byte[width * height];
 
-               grid(initialStep, pixels);
-       }
+        decodedVRangeMap = new byte[width * height];
+        decodedVRangeMap[0] = (byte) (255);
+        decodedVMap = new byte[width * height];
 
-       public void grid(final int step, final byte[] pixels) throws IOException {
+    }
 
-               gridDiagonal(step / 2, step / 2, step, pixels);
-               gridSquare(step / 2, 0, step, pixels);
-               gridSquare(0, step / 2, step, pixels);
+    public static int readIntegerCompressed8(final BitInputStream inputStream)
+            throws IOException {
 
-               if (step > 2)
-                       grid(step / 2, pixels);
-       }
+        if (inputStream.readBits(1) == 0)
+            return inputStream.readBits(8);
+        else
+            return inputStream.readBits(32);
+    }
 
-       public void gridDiagonal(final int offsetX, final int offsetY,
-                       final int step, final byte[] pixels) throws IOException {
+    public void decode() throws IOException {
+        approximator.load(bitInputStream);
+        approximator.computeLookupTables();
 
-               for (int y = offsetY; y < height; y = y + step)
-                       for (int x = offsetX; x < width; x = x + step) {
+        final WritableRaster raster = image.bufferedImage.getRaster();
+        final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer();
+        final byte[] pixels = dbi.getData();
 
-                               final int halfStep = step / 2;
+        // load top-, left-most pixel.
+        decodedYMap[0] = (byte) bitInputStream.readBits(8);
+        decodedUMap[0] = (byte) bitInputStream.readBits(8);
+        decodedVMap[0] = (byte) bitInputStream.readBits(8);
 
-                               context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
-                               context.measureNeighborEncode(x - halfStep, y - halfStep);
-                               context.measureNeighborEncode(x + halfStep, y - halfStep);
-                               context.measureNeighborEncode(x - halfStep, y + halfStep);
-                               context.measureNeighborEncode(x + halfStep, y + halfStep);
+        final Color color = new Color();
+        color.y = ImageEncoder.byteToInt(decodedYMap[0]);
+        color.u = ImageEncoder.byteToInt(decodedUMap[0]);
+        color.v = ImageEncoder.byteToInt(decodedVMap[0]);
 
-                               loadPixel(step, offsetX, offsetY, x, y, pixels,
-                                               context.colorStats.getAverageY(),
-                                               context.colorStats.getAverageU(),
-                                               context.colorStats.getAverageV());
+        color.YUV2RGB();
 
-                       }
-       }
+        pixels[0] = (byte) color.r;
+        pixels[0 + 1] = (byte) color.g;
+        pixels[0 + 2] = (byte) color.b;
 
-       public void gridSquare(final int offsetX, final int offsetY,
-                       final int step, final byte[] pixels) throws IOException {
+        // detect initial step
+        int largestDimension;
+        int initialStep = 2;
+        if (width > height)
+            largestDimension = width;
+        else
+            largestDimension = height;
+
+        while (initialStep < largestDimension)
+            initialStep = initialStep * 2;
 
-               for (int y = offsetY; y < height; y = y + step)
-                       for (int x = offsetX; x < width; x = x + step) {
+        grid(initialStep, pixels);
+    }
+
+    private void grid(final int step, final byte[] pixels) throws IOException {
+
+        gridDiagonal(step / 2, step / 2, step, pixels);
+        gridSquare(step / 2, 0, step, pixels);
+        gridSquare(0, step / 2, step, pixels);
 
-                               final int halfStep = step / 2;
-
-                               context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
-                               context.measureNeighborEncode(x - halfStep, y);
-                               context.measureNeighborEncode(x + halfStep, y);
-                               context.measureNeighborEncode(x, y - halfStep);
-                               context.measureNeighborEncode(x, y + halfStep);
-
-                               loadPixel(step, offsetX, offsetY, x, y, pixels,
-                                               context.colorStats.getAverageY(),
-                                               context.colorStats.getAverageU(),
-                                               context.colorStats.getAverageV());
-
-                       }
-       }
-
-       private int loadChannel(final byte[] decodedRangeMap,
-                       final byte[] decodedMap, final Table table,
-                       final int averageDecodedValue, final int index,
-                       final int parentIndex) throws IOException {
-               int decodedValue = averageDecodedValue;
-
-               final int inheritedRange = ImageEncoder
-                               .byteToInt(decodedRangeMap[parentIndex]);
-               int computedRange = inheritedRange;
-
-               final int bitCount = table.proposeBitcountForRange(inheritedRange);
-               int computedRangeBitCount = 0;
-               if (bitCount > 0) {
-
-                       final int rangeDecreases = bitInputStream.readBits(1);
-                       if (rangeDecreases != 0)
-                               computedRange = table.proposeDecreasedRange(inheritedRange);
-
-                       decodedRangeMap[index] = (byte) computedRange;
-                       computedRangeBitCount = table
-                                       .proposeBitcountForRange(computedRange);
-
-                       if (computedRangeBitCount > 0) {
-
-                               final int encodedDifference = bitInputStream
-                                               .readBits(computedRangeBitCount);
-
-                               final int decodedDifference = ImageEncoder
-                                               .decodeValueFromGivenBits(encodedDifference,
-                                                               computedRange, computedRangeBitCount);
-
-                               decodedValue = averageDecodedValue - decodedDifference;
-                               if (decodedValue > 255)
-                                       decodedValue = 255;
-                               if (decodedValue < 0)
-                                       decodedValue = 0;
-                       }
-               } else
-                       decodedRangeMap[index] = (byte) inheritedRange;
-               decodedMap[index] = (byte) decodedValue;
-               return decodedValue;
-       }
+        if (step > 2)
+            grid(step / 2, pixels);
+    }
+
+    private void gridDiagonal(final int offsetX, final int offsetY,
+                              final int step, final byte[] pixels) throws IOException {
+
+        for (int y = offsetY; y < height; y = y + step)
+            for (int x = offsetX; x < width; x = x + step) {
+
+                final int halfStep = step / 2;
+
+                context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
+                context.measureNeighborEncode(x - halfStep, y - halfStep);
+                context.measureNeighborEncode(x + halfStep, y - halfStep);
+                context.measureNeighborEncode(x - halfStep, y + halfStep);
+                context.measureNeighborEncode(x + halfStep, y + halfStep);
+
+                loadPixel(step, offsetX, offsetY, x, y, pixels,
+                        context.colorStats.getAverageY(),
+                        context.colorStats.getAverageU(),
+                        context.colorStats.getAverageV());
+
+            }
+    }
+
+    private void gridSquare(final int offsetX, final int offsetY,
+                            final int step, final byte[] pixels) throws IOException {
+
+        for (int y = offsetY; y < height; y = y + step)
+            for (int x = offsetX; x < width; x = x + step) {
+
+                final int halfStep = step / 2;
+
+                context.initialize(image, decodedYMap, decodedUMap, decodedVMap);
+                context.measureNeighborEncode(x - halfStep, y);
+                context.measureNeighborEncode(x + halfStep, y);
+                context.measureNeighborEncode(x, y - halfStep);
+                context.measureNeighborEncode(x, y + halfStep);
+
+                loadPixel(step, offsetX, offsetY, x, y, pixels,
+                        context.colorStats.getAverageY(),
+                        context.colorStats.getAverageU(),
+                        context.colorStats.getAverageV());
+
+            }
+    }
+
+    private int loadChannel(final byte[] decodedRangeMap,
+                            final byte[] decodedMap, final Table table,
+                            final int averageDecodedValue, final int index,
+                            final int parentIndex) throws IOException {
+        int decodedValue = averageDecodedValue;
+
+        final int inheritedRange = ImageEncoder
+                .byteToInt(decodedRangeMap[parentIndex]);
+        int computedRange = inheritedRange;
+
+        final int bitCount = table.proposeBitcountForRange(inheritedRange);
+        int computedRangeBitCount;
+        if (bitCount > 0) {
+
+            final int rangeDecreases = bitInputStream.readBits(1);
+            if (rangeDecreases != 0)
+                computedRange = table.proposeDecreasedRange(inheritedRange);
+
+            decodedRangeMap[index] = (byte) computedRange;
+            computedRangeBitCount = table
+                    .proposeBitcountForRange(computedRange);
+
+            if (computedRangeBitCount > 0) {
+
+                final int encodedDifference = bitInputStream
+                        .readBits(computedRangeBitCount);
+
+                final int decodedDifference = ImageEncoder
+                        .decodeValueFromGivenBits(encodedDifference,
+                                computedRange, computedRangeBitCount);
+
+                decodedValue = averageDecodedValue - decodedDifference;
+                if (decodedValue > 255)
+                    decodedValue = 255;
+                if (decodedValue < 0)
+                    decodedValue = 0;
+            }
+        } else
+            decodedRangeMap[index] = (byte) inheritedRange;
+        decodedMap[index] = (byte) decodedValue;
+        return decodedValue;
+    }
 
-       public void loadPixel(final int step, final int offsetX, final int offsetY,
-                       final int x, final int y, final byte[] pixels,
-                       final int averageDecodedY, final int averageDecodedU,
-                       final int averageDecodedV) throws IOException {
-
-               final int index = (y * width) + x;
-
-               final int halfStep = step / 2;
-
-               int parentIndex;
-               if (offsetX > 0) {
-                       if (offsetY > 0)
-                               // diagonal approach
-                               parentIndex = ((y - halfStep) * width) + (x - halfStep);
-                       else
-                               // take left pixel
-                               parentIndex = (y * width) + (x - halfStep);
-               } else
-                       // take upper pixel
-                       parentIndex = ((y - halfStep) * width) + x;
-
-               final int colorBufferIndex = index * 3;
-
-               final Color color = new Color();
-               color.y = loadChannel(decodedYRangeMap, decodedYMap,
-                               approximator.yTable, averageDecodedY, index, parentIndex);
-               color.u = loadChannel(decodedURangeMap, decodedUMap,
-                               approximator.uTable, averageDecodedU, index, parentIndex);
-               color.v = loadChannel(decodedVRangeMap, decodedVMap,
-                               approximator.vTable, averageDecodedV, index, parentIndex);
-
-               color.YUV2RGB();
-
-               pixels[colorBufferIndex] = (byte) color.r;
-               pixels[colorBufferIndex + 1] = (byte) color.g;
-               pixels[colorBufferIndex + 2] = (byte) color.b;
-
-       }
+    private void loadPixel(final int step, final int offsetX, final int offsetY,
+                           final int x, final int y, final byte[] pixels,
+                           final int averageDecodedY, final int averageDecodedU,
+                           final int averageDecodedV) throws IOException {
+
+        final int index = (y * width) + x;
+
+        final int halfStep = step / 2;
+
+        int parentIndex;
+        if (offsetX > 0) {
+            if (offsetY > 0)
+                // diagonal approach
+                parentIndex = ((y - halfStep) * width) + (x - halfStep);
+            else
+                // take left pixel
+                parentIndex = (y * width) + (x - halfStep);
+        } else
+            // take upper pixel
+            parentIndex = ((y - halfStep) * width) + x;
+
+        final int colorBufferIndex = index * 3;
+
+        final Color color = new Color();
+        color.y = loadChannel(decodedYRangeMap, decodedYMap,
+                approximator.yTable, averageDecodedY, index, parentIndex);
+        color.u = loadChannel(decodedURangeMap, decodedUMap,
+                approximator.uTable, averageDecodedU, index, parentIndex);
+        color.v = loadChannel(decodedVRangeMap, decodedVMap,
+                approximator.vTable, averageDecodedV, index, parentIndex);
+
+        color.YUV2RGB();
+
+        pixels[colorBufferIndex] = (byte) color.r;
+        pixels[colorBufferIndex + 1] = (byte) color.g;
+        pixels[colorBufferIndex + 2] = (byte) color.b;
+
+    }
 
 }