mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 03:55:28 -04:00
Move helper methods to transforms needing them
This commit is contained in:
parent
28270b4d5b
commit
008e57a7ce
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user