Move helper methods to transforms needing them

This commit is contained in:
Simon Kammermeier 2022-08-29 17:31:57 +02:00
parent 28270b4d5b
commit 008e57a7ce
4 changed files with 132 additions and 137 deletions

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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) {
}