diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java index ade640b3..23bd8444 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java @@ -32,6 +32,12 @@ package com.twelvemonkeys.imageio.plugins.webp.lossless; import com.twelvemonkeys.imageio.plugins.webp.LSBBitReader; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.ColorIndexingTransform; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.ColorTransform; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.PredictorTransform; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.SubtractGreenTransform; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.Transform; +import com.twelvemonkeys.imageio.plugins.webp.lossless.transform.TransformType; import javax.imageio.IIOException; import javax.imageio.stream.ImageInputStream; @@ -40,7 +46,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import static com.twelvemonkeys.imageio.util.RasterUtils.asByteRaster; import static java.lang.Math.*; /** @@ -97,58 +102,38 @@ public final class VP8LDecoder { // TODO: Each transform type can only be present once in the stream. switch (transformType) { - case TransformType.PREDICTOR_TRANSFORM: { + case TransformType.PREDICTOR_TRANSFORM: System.err.println("transformType: PREDICTOR_TRANSFORM"); -// int sizeBits = (int) readBits(3) + 2; - int sizeBits = (int) lsbBitReader.readBits(3) + 2; - int size = 1 << sizeBits; - - int blockWidth = size; - int blockHeight = size; - -// int blockSize = divRoundUp(width, size); - int blockSize = divRoundUp(xSize, size); - - for (int y = 0; y < ySize; y++) { - for (int x = 0; x < xSize; x++) { - int blockIndex = (y >> sizeBits) * blockSize + (x >> sizeBits); - } - } - - // Special rules: - // Top-left pixel of image is predicted BLACK - // Rest of top pixels is predicted L - // Rest of leftmost pixels are predicted T - // Rightmost pixels using TR, uses LEFTMOST pixel on SAME ROW (same distance as TR in memory!) - -// WritableRaster data = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, blockWidth, blockHeight, blockWidth, 1, new int[] {0}, null); -// readVP8Lossless(data, false); -// - break; - } + //Intentional Fallthrough case TransformType.COLOR_TRANSFORM: { // The two first transforms contains the exact same data, can be combined - System.err.println("transformType: COLOR_TRANSFORM"); + if (transformType == TransformType.COLOR_TRANSFORM) { + System.err.println("transformType: COLOR_TRANSFORM"); + } - int sizeBits = (int) lsbBitReader.readBits(3) + 2; -// int size = 1 << sizeBits; - - // TODO: Understand difference between spec divRoundUp and impl VP8LSubSampleSize + byte sizeBits = (byte) (lsbBitReader.readBits(3) + 2); int blockWidth = subSampleSize(xSize, sizeBits); int blockHeight = subSampleSize(ySize, sizeBits); - WritableRaster data = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, blockWidth, blockHeight, blockWidth, 1, new int[] {0}, null); - readVP8Lossless(data, false); + WritableRaster raster = + Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, blockWidth, blockHeight, 4 * blockWidth, 4, + new int[] {0, 1, 2, 3}, null); + readVP8Lossless(raster, false); - transforms.add(new Transform(transformType, ((DataBufferByte) data.getDataBuffer()).getData())); + //Keep data as raster for convenient (x,y) indexing + if (transformType == TransformType.PREDICTOR_TRANSFORM) { + transforms.add(0, new PredictorTransform(raster, sizeBits)); + } + else { + transforms.add(0, new ColorTransform(raster, sizeBits)); + } break; } case TransformType.SUBTRACT_GREEN: { System.err.println("transformType: SUBTRACT_GREEN"); // No data here - -// addGreenToBlueAndRed(); + transforms.add(0, new SubtractGreenTransform()); break; } case TransformType.COLOR_INDEXING_TRANSFORM: { @@ -167,41 +152,36 @@ public final class VP8LDecoder { System.err.println("safeColorTableSize: " + safeColorTableSize); - int[] colorTable = new int[safeColorTableSize]; + byte[] colorTable = new byte[safeColorTableSize * 4]; // The color table can be obtained by reading an image, // without the RIFF header, image size, and transforms, // assuming a height of one pixel and a width of // color_table_size. The color table is always // subtraction-coded to reduce image entropy. - // TODO: Read *without transforms*, using SUBTRACT_GREEN only! - readVP8Lossless(asByteRaster( - Raster.createPackedRaster( - new DataBufferInt(colorTable, colorTableSize), - colorTableSize, 1, colorTableSize, - new int[] {0}, null - ) - ), false); + readVP8Lossless( + Raster.createInterleavedRaster( + new DataBufferByte(colorTable, colorTableSize * 4), + colorTableSize, 1, colorTableSize * 4, + 4, new int[] {0, 1, 2, 3}, null) + , false); - // TODO: We may not really need this value... - // What we need is the number of pixels packed into each green sample (byte) - int widthBits = colorTableSize > 16 ? 0 : - colorTableSize > 4 ? 1 : - colorTableSize > 2 ? 2 : 3; + + //resolve subtraction code + for (int i = 4; i < colorTable.length; i++) { + colorTable[i] += colorTable[i - 4]; + } + + // The number of pixels packed into each green sample (byte) + byte widthBits = (byte) (colorTableSize > 16 ? 0 : + colorTableSize > 4 ? 1 : + colorTableSize > 2 ? 2 : 3); xSize = subSampleSize(xSize, widthBits); - /* - // TODO: read ARGB - int argb = 0; - - // Inverse transform - // TODO: Expand to mutliple pixels? - argb = colorTable[GREEN(argb)]; - */ - + // The colors components are stored in ARGB order at 4*index, 4*index + 1, 4*index + 2, 4*index + 3 // TODO: Can we use this to produce an image with IndexColorModel instead of expanding the values in-memory? - transforms.add(new Transform(transformType, colorTable)); + transforms.add(0, new ColorIndexingTransform(colorTable, widthBits)); break; } diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorIndexingTransform.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorIndexingTransform.java new file mode 100644 index 00000000..32d16009 --- /dev/null +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorIndexingTransform.java @@ -0,0 +1,18 @@ +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; + +import java.awt.image.*; + +public class ColorIndexingTransform implements Transform { + + private final byte[] colorTable; + private final byte bits; + + public ColorIndexingTransform(byte[] colorTable, byte bits) { + this.colorTable = colorTable; + this.bits = bits; + } + + @Override + public void applyInverse(WritableRaster raster) { + } +} diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorTransform.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorTransform.java new file mode 100644 index 00000000..6ecb8e73 --- /dev/null +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/ColorTransform.java @@ -0,0 +1,17 @@ +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; + +import java.awt.image.*; + +public class ColorTransform implements Transform { + private final Raster data; + private final byte bits; + + public ColorTransform(Raster raster, byte bits) { + this.data = raster; + this.bits = bits; + } + + @Override + public void applyInverse(WritableRaster raster) { + } +} diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/PredictorMode.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorMode.java similarity index 97% rename from imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/PredictorMode.java rename to imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorMode.java index 907c4ed2..d3e0bca1 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/PredictorMode.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorMode.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.twelvemonkeys.imageio.plugins.webp.lossless; +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; /** * PredictorMode. diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorTransform.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorTransform.java new file mode 100644 index 00000000..10d80911 --- /dev/null +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/PredictorTransform.java @@ -0,0 +1,17 @@ +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; + +import java.awt.image.*; + +public class PredictorTransform implements Transform { + private final Raster data; + private final byte bits; + + public PredictorTransform(Raster raster, byte bits) { + this.data = raster; + this.bits = bits; + } + + @Override + public void applyInverse(WritableRaster raster) { + } +} diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/SubtractGreenTransform.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/SubtractGreenTransform.java new file mode 100644 index 00000000..63a5b982 --- /dev/null +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/SubtractGreenTransform.java @@ -0,0 +1,11 @@ +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; + +import java.awt.image.*; + +public class SubtractGreenTransform implements Transform { + + + @Override + public void applyInverse(WritableRaster raster) { + } +} diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/Transform.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/Transform.java similarity index 82% rename from imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/Transform.java rename to imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/Transform.java index d4aafa74..98394f1e 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/Transform.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/Transform.java @@ -29,27 +29,16 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.twelvemonkeys.imageio.plugins.webp.lossless; +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; + +import java.awt.image.WritableRaster; /** * Transform. * * @author Harald Kuhr */ -final class Transform { - final int type; - final Object data; +public interface Transform { - Transform(final int type, final Object data) { - this.type = type; - this.data = data; - } - - byte[] getData() { - return (byte[]) data; - } - - int[] getColorMap() { - return (int[]) data; - } + void applyInverse(WritableRaster raster); } diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/TransformType.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/TransformType.java similarity index 94% rename from imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/TransformType.java rename to imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/TransformType.java index 525a6fa8..18ba23e6 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/TransformType.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/transform/TransformType.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.twelvemonkeys.imageio.plugins.webp.lossless; +package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; /** * TransformType. @@ -37,7 +37,7 @@ package com.twelvemonkeys.imageio.plugins.webp.lossless; * @author Harald Kuhr */ // Hmm.. Why doesn't SUBTRACT_GREEN follow the convention? -interface TransformType { +public interface TransformType { int PREDICTOR_TRANSFORM = 0; int COLOR_TRANSFORM = 1; int SUBTRACT_GREEN = 2;