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.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.Math.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VP8LDecoder.
|
* 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) {
|
private static int subSampleSize(final int size, final int samplingBits) {
|
||||||
return (size + (1 << samplingBits) - 1) >> 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
|
@Override
|
||||||
public void applyInverse(WritableRaster raster) {
|
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 java.awt.image.*;
|
||||||
|
|
||||||
|
import static java.lang.Math.*;
|
||||||
|
|
||||||
public class PredictorTransform implements Transform {
|
public class PredictorTransform implements Transform {
|
||||||
private final Raster data;
|
private final Raster data;
|
||||||
private final byte bits;
|
private final byte bits;
|
||||||
@ -14,4 +16,57 @@ public class PredictorTransform implements Transform {
|
|||||||
@Override
|
@Override
|
||||||
public void applyInverse(WritableRaster raster) {
|
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 {
|
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
|
@Override
|
||||||
public void applyInverse(WritableRaster raster) {
|
public void applyInverse(WritableRaster raster) {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user