X-Git-Url: http://www2.svjatoslav.eu/gitweb/?p=imagesqueeze.git;a=blobdiff_plain;f=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fimagesqueeze%2Fcodec%2FImageEncoder.java;fp=src%2Fmain%2Fjava%2Feu%2Fsvjatoslav%2Fimagesqueeze%2Fcodec%2FImageEncoder.java;h=613064c14e2b717455e5843ee2502a82b0bd1b43;hp=46c2135b19f573dfad711835abf255f4ceb05bb1;hb=4bcffe8896c08c9f60b2707da71bb39a64618d93;hpb=c7d0b8e1723045c0df086d9214a35f54db47684c diff --git a/src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageEncoder.java b/src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageEncoder.java index 46c2135..613064c 100755 --- a/src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageEncoder.java +++ b/src/main/java/eu/svjatoslav/imagesqueeze/codec/ImageEncoder.java @@ -1,3 +1,12 @@ +/* + * Imagesqueeze - Image codec optimized for photos. + * Copyright (C) 2012, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + package eu.svjatoslav.imagesqueeze.codec; /** @@ -8,6 +17,7 @@ import java.awt.image.DataBufferByte; import java.awt.image.WritableRaster; import java.io.IOException; +import eu.svjatoslav.commons.data.BitOutputStream; public class ImageEncoder { @@ -17,78 +27,81 @@ public class ImageEncoder { Channel yChannel; Channel uChannel; Channel vChannel; - + Approximator approximator; int bitsForY; int bitsForU; int bitsForV; - - //ColorStats colorStats = new ColorStats(); + + // ColorStats colorStats = new ColorStats(); OperatingContext context = new OperatingContext(); OperatingContext context2 = new OperatingContext(); BitOutputStream bitOutputStream; - public ImageEncoder(Image image){ + public ImageEncoder(final Image image) { approximator = new Approximator(); - //bitOutputStream = outputStream; + // bitOutputStream = outputStream; this.image = image; } - - public void encode(BitOutputStream bitOutputStream) throws IOException { + public void encode(final BitOutputStream bitOutputStream) + throws IOException { this.bitOutputStream = bitOutputStream; - + approximator.initialize(); - + approximator.save(bitOutputStream); - + width = image.metaData.width; height = image.metaData.height; - WritableRaster raster = image.bufferedImage.getRaster(); - DataBufferByte dbi = (DataBufferByte)raster.getDataBuffer(); - byte [] pixels = dbi.getData(); + final WritableRaster raster = image.bufferedImage.getRaster(); + final DataBufferByte dbi = (DataBufferByte) raster.getDataBuffer(); + final byte[] pixels = dbi.getData(); - if (yChannel == null){ - yChannel = new Channel(width, height); + if (yChannel == null) { + yChannel = new Channel(width, height); } else { yChannel.reset(); } - - if (uChannel == null){ - uChannel = new Channel(width, height); + + if (uChannel == null) { + uChannel = new Channel(width, height); } else { uChannel.reset(); } - - if (vChannel == null){ - vChannel = new Channel(width, height); + + if (vChannel == null) { + vChannel = new Channel(width, height); } else { vChannel.reset(); } - + // create YUV map out of RGB raster data - Color color = new Color(); - - for (int y=0; y < height; y++){ - for (int x=0; x < width; x++){ + final Color color = new Color(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { - int index = (y * width) + x; - int colorBufferIndex = index * 3; + final int index = (y * width) + x; + final int colorBufferIndex = index * 3; - int blue = pixels[colorBufferIndex]; - if (blue < 0) blue = blue + 256; + int blue = pixels[colorBufferIndex]; + if (blue < 0) + blue = blue + 256; - int green = pixels[colorBufferIndex+1]; - if (green < 0) green = green + 256; + int green = pixels[colorBufferIndex + 1]; + if (green < 0) + green = green + 256; - int red = pixels[colorBufferIndex+2]; - if (red < 0) red = red + 256; + int red = pixels[colorBufferIndex + 2]; + if (red < 0) + red = red + 256; color.r = red; color.g = green; @@ -96,19 +109,19 @@ public class ImageEncoder { color.RGB2YUV(); - yChannel.map[index] = (byte)color.y; - uChannel.map[index] = (byte)color.u; - vChannel.map[index] = (byte)color.v; + yChannel.map[index] = (byte) color.y; + uChannel.map[index] = (byte) color.u; + vChannel.map[index] = (byte) color.v; } } yChannel.decodedMap[0] = yChannel.map[0]; uChannel.decodedMap[0] = uChannel.map[0]; vChannel.decodedMap[0] = vChannel.map[0]; - - bitOutputStream.storeBits(byteToInt(yChannel.map[0]), 8); - bitOutputStream.storeBits(byteToInt(uChannel.map[0]), 8); - bitOutputStream.storeBits(byteToInt(vChannel.map[0]), 8); + + bitOutputStream.storeBits(byteToInt(yChannel.map[0]), 8); + bitOutputStream.storeBits(byteToInt(uChannel.map[0]), 8); + bitOutputStream.storeBits(byteToInt(vChannel.map[0]), 8); // detect initial step int largestDimension; @@ -118,364 +131,413 @@ public class ImageEncoder { } else { largestDimension = height; } - - while (initialStep < largestDimension){ + + while (initialStep < largestDimension) { initialStep = initialStep * 2; } - + rangeGrid(initialStep); rangeRoundGrid(2); saveGrid(initialStep); } - public void printStatistics(){ + private void encodeChannel(final Table table, final Channel channel, + final int averageDecodedValue, final int index, final int value, + final int range, final int parentIndex) throws IOException { + + final byte[] decodedRangeMap = channel.decodedRangeMap; + final byte[] decodedMap = channel.decodedMap; + + final int inheritedRange = byteToInt(decodedRangeMap[parentIndex]); + + final int inheritedBitCount = table + .proposeBitcountForRange(inheritedRange); + + if (inheritedBitCount > 0) { + int computedRange; + computedRange = table.proposeRangeForRange(range, inheritedRange); + decodedRangeMap[index] = (byte) computedRange; + + channel.bitCount++; + if (computedRange != inheritedRange) { + // brightness range shrinked + bitOutputStream.storeBits(1, 1); + } else { + // brightness range stayed the same + bitOutputStream.storeBits(0, 1); + } + + // encode brightness into available amount of bits + final int computedBitCount = table + .proposeBitcountForRange(computedRange); + + if (computedBitCount > 0) { + + final int differenceToEncode = -(value - averageDecodedValue); + final int bitEncodedDifference = encodeValueIntoGivenBits( + differenceToEncode, computedRange, computedBitCount); + + channel.bitCount = channel.bitCount + computedBitCount; + bitOutputStream.storeBits(bitEncodedDifference, + computedBitCount); + + final int decodedDifference = decodeValueFromGivenBits( + bitEncodedDifference, computedRange, computedBitCount); + int decodedValue = averageDecodedValue - decodedDifference; + if (decodedValue > 255) + decodedValue = 255; + if (decodedValue < 0) + decodedValue = 0; + + decodedMap[index] = (byte) decodedValue; + } else { + decodedMap[index] = (byte) averageDecodedValue; + } + + } else { + decodedRangeMap[index] = (byte) inheritedRange; + decodedMap[index] = (byte) averageDecodedValue; + } + } + + public void printStatistics() { System.out.println("Y channel:"); yChannel.printStatistics(); System.out.println("U channel:"); uChannel.printStatistics(); - + System.out.println("V channel:"); - vChannel.printStatistics(); + vChannel.printStatistics(); } - - public void rangeGrid(int step){ - //gridSquare(step / 2, step / 2, step, pixels); + public void rangeGrid(final int step) { + + // gridSquare(step / 2, step / 2, step, pixels); rangeGridDiagonal(step / 2, step / 2, step); rangeGridSquare(step / 2, 0, step); rangeGridSquare(0, step / 2, step); - if (step > 2) rangeGrid(step / 2); + if (step > 2) + rangeGrid(step / 2); } + public void rangeGridDiagonal(final int offsetX, final int offsetY, + final int step) { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - public void rangeRoundGrid(int step){ - - rangeRoundGridDiagonal(step / 2, step / 2, step); - rangeRoundGridSquare(step / 2, 0, step); - rangeRoundGridSquare(0, step / 2, step); - - if (step < 1024) rangeRoundGrid(step * 2); - } + final int index = (y * width) + x; + final int halfStep = step / 2; - public void saveGrid(int step) throws IOException { + context.initialize(image, yChannel.map, uChannel.map, + vChannel.map); - saveGridDiagonal(step / 2, step / 2, step); - saveGridSquare(step / 2, 0, step); - saveGridSquare(0, step / 2, step); + context.measureNeighborEncode(x - halfStep, y - halfStep); + context.measureNeighborEncode(x + halfStep, y - halfStep); + context.measureNeighborEncode(x - halfStep, y + halfStep); + context.measureNeighborEncode(x + halfStep, y + halfStep); - if (step > 2) saveGrid(step / 2); + yChannel.rangeMap[index] = (byte) context.getYRange(index); + uChannel.rangeMap[index] = (byte) context.getURange(index); + vChannel.rangeMap[index] = (byte) context.getVRange(index); + } + } } + public void rangeGridSquare(final int offsetX, final int offsetY, + final int step) { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - public void rangeGridSquare(int offsetX, int offsetY, int step){ - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ + final int index = (y * width) + x; + final int halfStep = step / 2; - int index = (y * width) + x; - int halfStep = step / 2; + context.initialize(image, yChannel.map, uChannel.map, + vChannel.map); - context.initialize(image, yChannel.map, uChannel.map, vChannel.map); - context.measureNeighborEncode(x - halfStep, y); context.measureNeighborEncode(x + halfStep, y); context.measureNeighborEncode(x, y - halfStep); context.measureNeighborEncode(x, y + halfStep); - yChannel.rangeMap[index] = (byte)context.getYRange(index); - uChannel.rangeMap[index] = (byte)context.getURange(index); - vChannel.rangeMap[index] = (byte)context.getVRange(index); - } - } + yChannel.rangeMap[index] = (byte) context.getYRange(index); + uChannel.rangeMap[index] = (byte) context.getURange(index); + vChannel.rangeMap[index] = (byte) context.getVRange(index); + } + } } - public void rangeGridDiagonal(int offsetX, int offsetY, int step){ - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ + public void rangeRoundGrid(final int step) { - int index = (y * width) + x; - int halfStep = step / 2; - - context.initialize(image, yChannel.map, uChannel.map, vChannel.map); - - context.measureNeighborEncode(x - halfStep, y - halfStep); - context.measureNeighborEncode(x + halfStep, y - halfStep); - context.measureNeighborEncode(x - halfStep, y + halfStep); - context.measureNeighborEncode(x + halfStep, y + halfStep); + rangeRoundGridDiagonal(step / 2, step / 2, step); + rangeRoundGridSquare(step / 2, 0, step); + rangeRoundGridSquare(0, step / 2, step); - yChannel.rangeMap[index] = (byte)context.getYRange(index); - uChannel.rangeMap[index] = (byte)context.getURange(index); - vChannel.rangeMap[index] = (byte)context.getVRange(index); - } - } + if (step < 1024) + rangeRoundGrid(step * 2); } - public void rangeRoundGridDiagonal(int offsetX, int offsetY, int step){ - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ + public void rangeRoundGridDiagonal(final int offsetX, final int offsetY, + final int step) { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - int index = (y * width) + x; + final int index = (y * width) + x; - int yRange = byteToInt(yChannel.rangeMap[index]); - int uRange = byteToInt(uChannel.rangeMap[index]); - int vRange = byteToInt(vChannel.rangeMap[index]); + final int yRange = byteToInt(yChannel.rangeMap[index]); + final int uRange = byteToInt(uChannel.rangeMap[index]); + final int vRange = byteToInt(vChannel.rangeMap[index]); - int halfStep = step / 2; + final int halfStep = step / 2; - int parentIndex = ((y - halfStep) * width) + (x - halfStep); + final int parentIndex = ((y - halfStep) * width) + + (x - halfStep); - int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]); + int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]); - if (parentYRange < yRange){ + if (parentYRange < yRange) { parentYRange = yRange; - yChannel.rangeMap[parentIndex] = (byte)parentYRange; + yChannel.rangeMap[parentIndex] = (byte) parentYRange; } int parentURange = byteToInt(uChannel.rangeMap[parentIndex]); - if (parentURange < uRange){ + if (parentURange < uRange) { parentURange = uRange; - uChannel.rangeMap[parentIndex] = (byte)parentURange; + uChannel.rangeMap[parentIndex] = (byte) parentURange; } int parentVRange = byteToInt(vChannel.rangeMap[parentIndex]); - if (parentVRange < vRange){ + if (parentVRange < vRange) { parentVRange = vRange; - vChannel.rangeMap[parentIndex] = (byte)parentVRange; + vChannel.rangeMap[parentIndex] = (byte) parentVRange; } - } - } + } + } } - public void rangeRoundGridSquare(int offsetX, int offsetY, int step){ - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ + public void rangeRoundGridSquare(final int offsetX, final int offsetY, + final int step) { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - int index = (y * width) + x; - - int yRange = byteToInt(yChannel.rangeMap[index]); - int uRange = byteToInt(uChannel.rangeMap[index]); - int vRange = byteToInt(vChannel.rangeMap[index]); + final int index = (y * width) + x; - int halfStep = step / 2; + final int yRange = byteToInt(yChannel.rangeMap[index]); + final int uRange = byteToInt(uChannel.rangeMap[index]); + final int vRange = byteToInt(vChannel.rangeMap[index]); + + final int halfStep = step / 2; int parentIndex; - if (offsetX > 0){ - parentIndex = (y * width) + (x - halfStep); + if (offsetX > 0) { + parentIndex = (y * width) + (x - halfStep); } else { - parentIndex = ((y - halfStep) * width) + x; + parentIndex = ((y - halfStep) * width) + x; } - int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]); + int parentYRange = byteToInt(yChannel.rangeMap[parentIndex]); - if (parentYRange < yRange){ + if (parentYRange < yRange) { parentYRange = yRange; - yChannel.rangeMap[parentIndex] = (byte)parentYRange; + yChannel.rangeMap[parentIndex] = (byte) parentYRange; } int parentURange = byteToInt(uChannel.rangeMap[parentIndex]); - if (parentURange < uRange){ + if (parentURange < uRange) { parentURange = uRange; - uChannel.rangeMap[parentIndex] = (byte)parentURange; + uChannel.rangeMap[parentIndex] = (byte) parentURange; } int parentVRange = byteToInt(vChannel.rangeMap[parentIndex]); - if (parentVRange < vRange){ + if (parentVRange < vRange) { parentVRange = vRange; - vChannel.rangeMap[parentIndex] = (byte)parentVRange; + vChannel.rangeMap[parentIndex] = (byte) parentVRange; } - } - } + } + } } - public void saveGridSquare(int offsetX, int offsetY, int step) throws IOException{ - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ - - int halfStep = step / 2; + public void saveGrid(final int step) throws IOException { - context2.initialize(image, yChannel.decodedMap, uChannel.decodedMap, vChannel.decodedMap); - context2.measureNeighborEncode(x - halfStep, y); - context2.measureNeighborEncode(x + halfStep, y); - context2.measureNeighborEncode(x, y - halfStep); - context2.measureNeighborEncode(x, y + halfStep); - - - savePixel(step, offsetX, offsetY, x, y, - context2.colorStats.getAverageY(), - context2.colorStats.getAverageU(), - context2.colorStats.getAverageV()); + saveGridDiagonal(step / 2, step / 2, step); + saveGridSquare(step / 2, 0, step); + saveGridSquare(0, step / 2, step); - } - } + if (step > 2) + saveGrid(step / 2); } - public void saveGridDiagonal(int offsetX, int offsetY, int step) throws IOException { - for (int y = offsetY; y < height; y = y + step){ - for (int x = offsetX; x < width; x = x + step){ - - int halfStep = step / 2; + public void saveGridDiagonal(final int offsetX, final int offsetY, + final int step) throws IOException { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - context2.initialize(image, yChannel.decodedMap, uChannel.decodedMap, vChannel.decodedMap); + final int halfStep = step / 2; + + context2.initialize(image, yChannel.decodedMap, + uChannel.decodedMap, vChannel.decodedMap); context2.measureNeighborEncode(x - halfStep, y - halfStep); context2.measureNeighborEncode(x + halfStep, y - halfStep); context2.measureNeighborEncode(x - halfStep, y + halfStep); context2.measureNeighborEncode(x + halfStep, y + halfStep); - - + savePixel(step, offsetX, offsetY, x, y, context2.colorStats.getAverageY(), context2.colorStats.getAverageU(), - context2.colorStats.getAverageV()); - - } - } + context2.colorStats.getAverageV()); + + } + } } - public void savePixel(int step, int offsetX, int offsetY, int x, int y, int averageDecodedY, int averageDecodedU, int averageDecodedV) throws IOException { + public void saveGridSquare(final int offsetX, final int offsetY, + final int step) throws IOException { + for (int y = offsetY; y < height; y = y + step) { + for (int x = offsetX; x < width; x = x + step) { - int index = (y * width) + x; + final int halfStep = step / 2; - int py = byteToInt(yChannel.map[index]); - int pu = byteToInt(uChannel.map[index]); - int pv = byteToInt(vChannel.map[index]); - - int yRange = byteToInt(yChannel.rangeMap[index]); - int uRange = byteToInt(uChannel.rangeMap[index]); - int vRange = byteToInt(vChannel.rangeMap[index]); + context2.initialize(image, yChannel.decodedMap, + uChannel.decodedMap, vChannel.decodedMap); + context2.measureNeighborEncode(x - halfStep, y); + context2.measureNeighborEncode(x + halfStep, y); + context2.measureNeighborEncode(x, y - halfStep); + context2.measureNeighborEncode(x, y + halfStep); - int halfStep = step / 2; + savePixel(step, offsetX, offsetY, x, y, + context2.colorStats.getAverageY(), + context2.colorStats.getAverageU(), + context2.colorStats.getAverageV()); + + } + } + } + + public void savePixel(final int step, final int offsetX, final int offsetY, + final int x, final int y, final int averageDecodedY, + final int averageDecodedU, final int averageDecodedV) + throws IOException { + + final int index = (y * width) + x; + + final int py = byteToInt(yChannel.map[index]); + final int pu = byteToInt(uChannel.map[index]); + final int pv = byteToInt(vChannel.map[index]); + + final int yRange = byteToInt(yChannel.rangeMap[index]); + final int uRange = byteToInt(uChannel.rangeMap[index]); + final int vRange = byteToInt(vChannel.rangeMap[index]); + + final int halfStep = step / 2; int parentIndex; - if (offsetX > 0){ - if (offsetY > 0){ + if (offsetX > 0) { + if (offsetY > 0) { // diagonal approach - parentIndex = ((y - halfStep) * width) + (x - halfStep); + parentIndex = ((y - halfStep) * width) + (x - halfStep); } else { // take left pixel - parentIndex = (y * width) + (x - halfStep); - } + parentIndex = (y * width) + (x - halfStep); + } } else { // take upper pixel - parentIndex = ((y - halfStep) * width) + x; + parentIndex = ((y - halfStep) * width) + x; } - encodeChannel( - approximator.yTable, - yChannel, - averageDecodedY, - index, - py, - yRange, - parentIndex); - - encodeChannel( - approximator.uTable, - uChannel, - averageDecodedU, - index, - pu, - uRange, - parentIndex); - - encodeChannel( - approximator.vTable, - vChannel, - averageDecodedV, - index, - pv, - vRange, - parentIndex); + encodeChannel(approximator.yTable, yChannel, averageDecodedY, index, + py, yRange, parentIndex); + + encodeChannel(approximator.uTable, uChannel, averageDecodedU, index, + pu, uRange, parentIndex); + + encodeChannel(approximator.vTable, vChannel, averageDecodedV, index, + pv, vRange, parentIndex); } + public static int byteToInt(final byte input) { + int result = input; + if (result < 0) + result = result + 256; + return result; + } - private void encodeChannel(Table table, Channel channel, int averageDecodedValue, int index, - int value, int range, int parentIndex) - throws IOException { - - byte[] decodedRangeMap = channel.decodedRangeMap; - byte[] decodedMap = channel.decodedMap; - - int inheritedRange = byteToInt(decodedRangeMap[parentIndex]); + public static int decodeValueFromGivenBits(final int encodedBits, + final int range, final int bitCount) { + final int negativeBit = encodedBits & 1; - int inheritedBitCount = table.proposeBitcountForRange(inheritedRange); + final int remainingBitCount = bitCount - 1; - if (inheritedBitCount > 0){ - int computedRange; - computedRange = table.proposeRangeForRange(range, inheritedRange); - decodedRangeMap[index] = (byte)computedRange; + if (remainingBitCount == 0) { + // no more bits remaining to encode actual value - channel.bitCount++; - if (computedRange != inheritedRange){ - // brightness range shrinked - bitOutputStream.storeBits(1, 1); + if (negativeBit == 0) { + return range; } else { - // brightness range stayed the same - bitOutputStream.storeBits(0, 1); + return -range; } + } else { + // still one or more bits left, encode value as precisely as + // possible - // encode brightness into available amount of bits - int computedBitCount = table.proposeBitcountForRange(computedRange); - - if (computedBitCount > 0){ + final int encodedValue = (encodedBits >>> 1) + 1; - int differenceToEncode = -(value - averageDecodedValue); - int bitEncodedDifference = encodeValueIntoGivenBits(differenceToEncode, computedRange, computedBitCount); + final int realvalueForThisBitcount = 1 << remainingBitCount; - channel.bitCount = channel.bitCount + computedBitCount; - bitOutputStream.storeBits(bitEncodedDifference, computedBitCount); + // int valueMultiplier = range / realvalueForThisBitcount; + int decodedValue = (range * encodedValue) + / realvalueForThisBitcount; - int decodedDifference = decodeValueFromGivenBits(bitEncodedDifference, computedRange, computedBitCount); - int decodedValue = averageDecodedValue - decodedDifference; - if (decodedValue > 255) decodedValue = 255; - if (decodedValue < 0) decodedValue = 0; + if (decodedValue > range) + decodedValue = range; - decodedMap[index] = (byte)decodedValue; - } else { - decodedMap[index] = (byte)averageDecodedValue; - } + if (negativeBit == 0) { + return decodedValue; + } else { + return -decodedValue; + } - } else { - decodedRangeMap[index] = (byte)inheritedRange; - decodedMap[index] = (byte)averageDecodedValue; } } - public static int encodeValueIntoGivenBits(int value, int range, int bitCount){ + public static int encodeValueIntoGivenBits(int value, final int range, + final int bitCount) { int negativeBit = 0; - if (value <0){ + if (value < 0) { negativeBit = 1; value = -value; } - int remainingBitCount = bitCount - 1; + final int remainingBitCount = bitCount - 1; - if (remainingBitCount == 0){ + if (remainingBitCount == 0) { // no more bits remaining to encode actual value return negativeBit; } else { - // still one or more bits left, encode value as precisely as possible - - if (value > range) value = range; + // still one or more bits left, encode value as precisely as + // possible + if (value > range) + value = range; - int realvalueForThisBitcount = 1 << remainingBitCount; + final int realvalueForThisBitcount = 1 << remainingBitCount; // int valueMultiplier = range / realvalueForThisBitcount; - int encodedValue = value * realvalueForThisBitcount / range; + int encodedValue = (value * realvalueForThisBitcount) / range; - if (encodedValue >= realvalueForThisBitcount) encodedValue = realvalueForThisBitcount - 1; + if (encodedValue >= realvalueForThisBitcount) + encodedValue = realvalueForThisBitcount - 1; encodedValue = (encodedValue << 1) + negativeBit; @@ -483,47 +545,4 @@ public class ImageEncoder { } } - - public static int decodeValueFromGivenBits(int encodedBits, int range, int bitCount){ - int negativeBit = encodedBits & 1; - - int remainingBitCount = bitCount - 1; - - if (remainingBitCount == 0){ - // no more bits remaining to encode actual value - - if (negativeBit == 0){ - return range; - } else { - return -range; - } - - } else { - // still one or more bits left, encode value as precisely as possible - - int encodedValue = (encodedBits >>> 1) + 1; - - int realvalueForThisBitcount = 1 << remainingBitCount; - - // int valueMultiplier = range / realvalueForThisBitcount; - int decodedValue = range * encodedValue / realvalueForThisBitcount; - - - if (decodedValue > range) decodedValue = range; - - if (negativeBit == 0){ - return decodedValue; - } else { - return -decodedValue; - } - - } - } - - public static int byteToInt(byte input){ - int result = input; - if (result < 0) result = result + 256; - return result; - } - }