From 008e57a7cebca5cc0d88c23f083060e4c9e64933 Mon Sep 17 00:00:00 2001 From: Simon Kammermeier Date: Mon, 29 Aug 2022 17:31:57 +0200 Subject: [PATCH] Move helper methods to transforms needing them --- .../plugins/webp/lossless/VP8LDecoder.java | 137 ------------------ .../lossless/transform/ColorTransform.java | 72 +++++++++ .../transform/PredictorTransform.java | 55 +++++++ .../transform/SubtractGreenTransform.java | 5 + 4 files changed, 132 insertions(+), 137 deletions(-) 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 23bd8444..bde0bb5e 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 @@ -46,7 +46,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import static java.lang.Math.*; /** * VP8LDecoder. @@ -196,143 +195,7 @@ public final class VP8LDecoder { } - //// - - // FROM the spec - private static int divRoundUp(final int numerator, final int denominator) { - return (numerator + denominator - 1) / denominator; - } - private static int subSampleSize(final int size, final int samplingBits) { return (size + (1 << samplingBits) - 1) >> samplingBits; } - - private static int ALPHA(final int ARGB) { - return ARGB >>> 24; - } - - private static int RED(final int ARGB) { - return (ARGB >> 16) & 0xff; - } - - private static int GREEN(final int ARGB) { - return (ARGB >> 8) & 0xff; - } - - private static int BLUE(final int ARGB) { - return ARGB & 0xff; - } - - private static int select(final int L, final int T, final int TL) { - // L = left pixel, T = top pixel, TL = top left pixel. - - // ARGB component estimates for prediction. - int pAlpha = ALPHA(L) + ALPHA(T) - ALPHA(TL); - int pRed = RED(L) + RED(T) - RED(TL); - int pGreen = GREEN(L) + GREEN(T) - GREEN(TL); - int pBlue = BLUE(L) + BLUE(T) - BLUE(TL); - - // Manhattan distances to estimates for left and top pixels. - int pL = abs(pAlpha - ALPHA(L)) + abs(pRed - RED(L)) + - abs(pGreen - GREEN(L)) + abs(pBlue - BLUE(L)); - int pT = abs(pAlpha - ALPHA(T)) + abs(pRed - RED(T)) + - abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T)); - - // Return either left or top, the one closer to the prediction. - return pL < pT ? L : T; - } - - private static int average2(final int a, final int b) { - return (a + b) / 2; - } - - // Clamp the input value between 0 and 255. - private static int clamp(final int a) { - return max(0, min(a, 255)); - } - - private static int clampAddSubtractFull(final int a, final int b, final int c) { - return clamp(a + b - c); - } - - private static int clampAddSubtractHalf(final int a, final int b) { - return clamp(a + (a - b) / 2); - } - - static final class ColorTransformElement { - final int green_to_red; - final int green_to_blue; - final int red_to_blue; - - ColorTransformElement(final int green_to_red, final int green_to_blue, final int red_to_blue) { - this.green_to_red = green_to_red; - this.green_to_blue = green_to_blue; - this.red_to_blue = red_to_blue; - } - } - - // NOTE: For encoding! - private static void colorTransform(final int red, final int blue, final int green, - final ColorTransformElement trans, - final int[] newRedBlue) { - // Transformed values of red and blue components - int tmp_red = red; - int tmp_blue = blue; - - // Applying transform is just adding the transform deltas - tmp_red += colorTransformDelta((byte) trans.green_to_red, (byte) green); - tmp_blue += colorTransformDelta((byte) trans.green_to_blue, (byte) green); - tmp_blue += colorTransformDelta((byte) trans.red_to_blue, (byte) red); - - // No pointer dereferences in Java... - // TODO: Consider passing an offset too, so we can modify in-place - newRedBlue[0] = tmp_red & 0xff; - newRedBlue[1] = tmp_blue & 0xff; - } - - // A conversion from the 8-bit unsigned representation (uint8) to the 8-bit - // signed one (int8) is required before calling ColorTransformDelta(). It - // should be performed using 8-bit two's complement (that is: uint8 range - // [128-255] is mapped to the [-128, -1] range of its converted int8 - // value). - private static byte colorTransformDelta(final byte t, final byte c) { - return (byte) ((t * c) >> 5); - } - - private static void inverseTransform(final byte red, final byte green, final byte blue, - final ColorTransformElement trans, - final int[] newRedBlue) { - // Applying inverse transform is just subtracting the - // color transform deltas - // Transformed values of red and blue components - int tmp_red = red; - int tmp_blue = blue; - - tmp_red -= colorTransformDelta((byte) trans.green_to_red, green); - tmp_blue -= colorTransformDelta((byte) trans.green_to_blue, green); - tmp_blue -= colorTransformDelta((byte) trans.red_to_blue, red); // Spec has red & 0xff - - newRedBlue[0] = tmp_red & 0xff; - newRedBlue[1] = tmp_blue & 0xff; - } - - private static void inverseTransform(final byte[] rgb, final ColorTransformElement trans) { - // Applying inverse transform is just subtracting the - // color transform deltas - // Transformed values of red and blue components - int tmp_red = rgb[0]; - int tmp_blue = rgb[2]; - - tmp_red -= colorTransformDelta((byte) trans.green_to_red, rgb[1]); - tmp_blue -= colorTransformDelta((byte) trans.green_to_blue, rgb[1]); - tmp_blue -= colorTransformDelta((byte) trans.red_to_blue, rgb[0]); // Spec has red & 0xff - - rgb[0] = (byte) (tmp_red & 0xff); - rgb[2] = (byte) (tmp_blue & 0xff); - } - - private static void addGreenToBlueAndRed(byte[] rgb) { - rgb[0] = (byte) ((rgb[0] + rgb[1]) & 0xff); - rgb[2] = (byte) ((rgb[2] + rgb[1]) & 0xff); - } } 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 index 6ecb8e73..2623e946 100644 --- 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 @@ -14,4 +14,76 @@ public class ColorTransform implements Transform { @Override public void applyInverse(WritableRaster raster) { } + + // NOTE: For encoding! + private static void colorTransform(final int red, final int blue, final int green, + final ColorTransformElement trans, + final int[] newRedBlue) { + // Transformed values of red and blue components + int tmp_red = red; + int tmp_blue = blue; + + // Applying transform is just adding the transform deltas + tmp_red += colorTransformDelta((byte) trans.green_to_red, (byte) green); + tmp_blue += colorTransformDelta((byte) trans.green_to_blue, (byte) green); + tmp_blue += colorTransformDelta((byte) trans.red_to_blue, (byte) red); + + // No pointer dereferences in Java... + // TODO: Consider passing an offset too, so we can modify in-place + newRedBlue[0] = tmp_red & 0xff; + newRedBlue[1] = tmp_blue & 0xff; + } + + // A conversion from the 8-bit unsigned representation (uint8) to the 8-bit + // signed one (int8) is required before calling ColorTransformDelta(). It + // should be performed using 8-bit two's complement (that is: uint8 range + // [128-255] is mapped to the [-128, -1] range of its converted int8 + // value). + private static byte colorTransformDelta(final byte t, final byte c) { + return (byte) ((t * c) >> 5); + } + + private static void inverseTransform(final byte red, final byte green, final byte blue, + final ColorTransformElement trans, + final int[] newRedBlue) { + // Applying inverse transform is just subtracting the + // color transform deltas + // Transformed values of red and blue components + int tmp_red = red; + int tmp_blue = blue; + + tmp_red -= colorTransformDelta((byte) trans.green_to_red, green); + tmp_blue -= colorTransformDelta((byte) trans.green_to_blue, green); + tmp_blue -= colorTransformDelta((byte) trans.red_to_blue, red); // Spec has red & 0xff + + newRedBlue[0] = tmp_red & 0xff; + newRedBlue[1] = tmp_blue & 0xff; + } + + private static void inverseTransform(final byte[] rgb, final ColorTransformElement trans) { + // Applying inverse transform is just subtracting the + // color transform deltas + // Transformed values of red and blue components + int tmp_red = rgb[0]; + int tmp_blue = rgb[2]; + + tmp_red -= colorTransformDelta((byte) trans.green_to_red, rgb[1]); + tmp_blue -= colorTransformDelta((byte) trans.green_to_blue, rgb[1]); + tmp_blue -= colorTransformDelta((byte) trans.red_to_blue, rgb[0]); // Spec has red & 0xff + + rgb[0] = (byte) (tmp_red & 0xff); + rgb[2] = (byte) (tmp_blue & 0xff); + } + + static final class ColorTransformElement { + final int green_to_red; + final int green_to_blue; + final int red_to_blue; + + ColorTransformElement(final int green_to_red, final int green_to_blue, final int red_to_blue) { + this.green_to_red = green_to_red; + this.green_to_blue = green_to_blue; + this.red_to_blue = red_to_blue; + } + } } 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 index 10d80911..711e1cf3 100644 --- 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 @@ -2,6 +2,8 @@ package com.twelvemonkeys.imageio.plugins.webp.lossless.transform; import java.awt.image.*; +import static java.lang.Math.*; + public class PredictorTransform implements Transform { private final Raster data; private final byte bits; @@ -14,4 +16,57 @@ public class PredictorTransform implements Transform { @Override public void applyInverse(WritableRaster raster) { } + + private static int ALPHA(final int ARGB) { + return ARGB >>> 24; + } + + private static int RED(final int ARGB) { + return (ARGB >> 16) & 0xff; + } + + private static int GREEN(final int ARGB) { + return (ARGB >> 8) & 0xff; + } + + private static int BLUE(final int ARGB) { + return ARGB & 0xff; + } + + private static int select(final int L, final int T, final int TL) { + // L = left pixel, T = top pixel, TL = top left pixel. + + // ARGB component estimates for prediction. + int pAlpha = ALPHA(L) + ALPHA(T) - ALPHA(TL); + int pRed = RED(L) + RED(T) - RED(TL); + int pGreen = GREEN(L) + GREEN(T) - GREEN(TL); + int pBlue = BLUE(L) + BLUE(T) - BLUE(TL); + + // Manhattan distances to estimates for left and top pixels. + int pL = abs(pAlpha - ALPHA(L)) + abs(pRed - RED(L)) + + abs(pGreen - GREEN(L)) + abs(pBlue - BLUE(L)); + int pT = abs(pAlpha - ALPHA(T)) + abs(pRed - RED(T)) + + abs(pGreen - GREEN(T)) + abs(pBlue - BLUE(T)); + + // Return either left or top, the one closer to the prediction. + return pL < pT ? L : T; + } + + private static int average2(final int a, final int b) { + return (a + b) / 2; + } + + // Clamp the input value between 0 and 255. + private static int clamp(final int a) { + return max(0, min(a, 255)); + } + + private static int clampAddSubtractFull(final int a, final int b, final int c) { + return clamp(a + b - c); + } + + private static int clampAddSubtractHalf(final int a, final int b) { + return clamp(a + (a - b) / 2); + } + } 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 index 63a5b982..157f723b 100644 --- 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 @@ -5,6 +5,11 @@ import java.awt.image.*; public class SubtractGreenTransform implements Transform { + private static void addGreenToBlueAndRed(byte[] rgb) { + rgb[0] = (byte) ((rgb[0] + rgb[1]) & 0xff); + rgb[2] = (byte) ((rgb[2] + rgb[1]) & 0xff); + } + @Override public void applyInverse(WritableRaster raster) { }