mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 03:55:28 -04:00
WebP source subsampling.
This commit is contained in:
parent
4dedf76ebc
commit
3bb312e9e1
@ -428,7 +428,7 @@ final class WebPImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
private void readVP8Lossless(final WritableRaster raster, final ImageReadParam param) throws IOException {
|
||||
VP8LDecoder decoder = new VP8LDecoder(imageInput);
|
||||
VP8LDecoder decoder = new VP8LDecoder(imageInput, DEBUG);
|
||||
decoder.readVP8Lossless(raster, true);
|
||||
}
|
||||
|
||||
@ -443,7 +443,6 @@ final class WebPImageReader extends ImageReaderBase {
|
||||
});
|
||||
|
||||
if (!frame.decode(raster, param)) {
|
||||
// TODO: Does this make any sense? Only happens if frame type is not still (0)
|
||||
processWarningOccurred("Nothing to decode");
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.twelvemonkeys.imageio.plugins.webp.RasterUtils.asByteRaster;
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.*;
|
||||
|
||||
/**
|
||||
* VP8LDecoder.
|
||||
@ -49,14 +49,13 @@ import static java.lang.Math.abs;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
*/
|
||||
public final class VP8LDecoder {
|
||||
|
||||
private final ImageInputStream imageInput;
|
||||
private final LSBBitReader lsbBitReader;
|
||||
|
||||
private final List<Transform> transforms = new ArrayList<>();
|
||||
private ColorCache colorCache;
|
||||
|
||||
public VP8LDecoder(final ImageInputStream imageInput) {
|
||||
public VP8LDecoder(final ImageInputStream imageInput, final boolean debug) {
|
||||
this.imageInput = imageInput;
|
||||
lsbBitReader = new LSBBitReader(imageInput);
|
||||
}
|
||||
@ -275,7 +274,7 @@ public final class VP8LDecoder {
|
||||
|
||||
// Clamp the input value between 0 and 255.
|
||||
private static int clamp(final int a) {
|
||||
return a < 0 ? 0 : a > 255 ? 255 : a;
|
||||
return max(0, min(a, 255));
|
||||
}
|
||||
|
||||
private static int clampAddSubtractFull(final int a, final int b, final int c) {
|
||||
|
@ -499,8 +499,7 @@ final class Globals {
|
||||
for (int i = 0; i < vp8DefaultCoefProbs.length; i++)
|
||||
for (int j = 0; j < vp8DefaultCoefProbs[0].length; j++)
|
||||
for (int k = 0; k < vp8DefaultCoefProbs[0][0].length; k++)
|
||||
for (int l = 0; l < vp8DefaultCoefProbs[0][0][0].length; l++)
|
||||
r[i][j][k][l] = vp8DefaultCoefProbs[i][j][k][l];
|
||||
r[i][j][k] = vp8DefaultCoefProbs[i][j][k].clone();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -145,16 +145,6 @@ final class LoopFilter {
|
||||
return abs(p1 - p0) > threshold || abs(q1 - q0) > threshold;
|
||||
}
|
||||
|
||||
// public static void loopFilter(VP8Frame frame) {
|
||||
// if (frame.getFilterType() == 2) {
|
||||
// loopFilterUV(frame);
|
||||
// loopFilterY(frame);
|
||||
// }
|
||||
// else if (frame.getFilterType() == 1) {
|
||||
// loopFilterSimple(frame);
|
||||
// }
|
||||
// }
|
||||
|
||||
static void loopFilterBlock(final MacroBlock cmb, final MacroBlock lmb, final MacroBlock tmb, int frameType, boolean simpleFilter, int sharpness) {
|
||||
if (simpleFilter) {
|
||||
loopFilterSimpleBlock(cmb, lmb, tmb, sharpness);
|
||||
@ -165,23 +155,7 @@ final class LoopFilter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void loopFilterSimple(VP8Frame frame) {
|
||||
for (int y = 0; y < frame.getMacroBlockRows(); y++) {
|
||||
// frame.fireLFProgressUpdate((100.0f * ((float) (y + 1) / (float) (frame
|
||||
// .getMacroBlockRows()))));
|
||||
for (int x = 0; x < frame.getMacroBlockCols(); x++) {
|
||||
loopFilterSimpleBlock(frame.getMacroBlock(x, y),
|
||||
x > 0 ? frame.getMacroBlock(x - 1, y) : null,
|
||||
y > 0 ? frame.getMacroBlock(x, y - 1) : null,
|
||||
frame.getSharpnessLevel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void loopFilterSimpleBlock(final MacroBlock cmb, final MacroBlock lmb, final MacroBlock tmb, final int sharpnessLevel) {
|
||||
// System.out.println("x: "+x+" y: "+y);
|
||||
// MacroBlock bmb = frame.getMacroBlock(x, y); // TODO: Same..?
|
||||
int loop_filter_level = cmb.getFilterLevel();
|
||||
if (loop_filter_level != 0) {
|
||||
int interior_limit = cmb.getFilterLevel();
|
||||
@ -277,18 +251,6 @@ final class LoopFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loopFilterUV(VP8Frame frame) {
|
||||
for (int y = 0; y < frame.getMacroBlockRows(); y++) {
|
||||
for (int x = 0; x < frame.getMacroBlockCols(); x++) {
|
||||
loopFilterUVBlock(frame.getMacroBlock(x, y),
|
||||
x > 0 ? frame.getMacroBlock(x - 1, y) : null,
|
||||
y > 0 ? frame.getMacroBlock(x, y - 1) : null,
|
||||
frame.getSharpnessLevel(), frame.getFrameType()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void loopFilterUVBlock(final MacroBlock cmb, final MacroBlock lmb, final MacroBlock tmb, final int sharpnessLevel, final int frameType) {
|
||||
int loop_filter_level = cmb.getFilterLevel();
|
||||
if (loop_filter_level != 0) {
|
||||
@ -407,17 +369,6 @@ final class LoopFilter {
|
||||
}
|
||||
}
|
||||
|
||||
private static void loopFilterY(VP8Frame frame) {
|
||||
for (int y = 0; y < frame.getMacroBlockRows(); y++) {
|
||||
for (int x = 0; x < frame.getMacroBlockCols(); x++) {
|
||||
loopFilterYBlock(frame.getMacroBlock(x, y),
|
||||
x > 0 ? frame.getMacroBlock(x - 1, y) : null,
|
||||
y > 0 ? frame.getMacroBlock(x, y - 1) : null,
|
||||
frame.getSharpnessLevel(), frame.getFrameType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void loopFilterYBlock(final MacroBlock cmb, final MacroBlock lmb, final MacroBlock tmb, final int sharpnessLevel, final int frameType) {
|
||||
int loop_filter_level = cmb.getFilterLevel();
|
||||
|
||||
@ -587,9 +538,6 @@ final class LoopFilter {
|
||||
if ((abs(seg.P0 - seg.Q0) * 2 + abs(seg.P1 - seg.Q1) / 2) <= edge_limit) {
|
||||
common_adjust(true, seg); // use outer taps
|
||||
}
|
||||
else {
|
||||
// TODO?
|
||||
}
|
||||
}
|
||||
|
||||
private static void subblock_filter(int hev_threshold, // detect high edge variance
|
||||
@ -605,9 +553,6 @@ final class LoopFilter {
|
||||
seg.P1 = s2u(p1 + a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TODO?
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert pixel value (0 <= v <= 255) to an 8-bit signed number. */
|
||||
|
@ -236,7 +236,6 @@ final class SubBlock {
|
||||
}
|
||||
|
||||
public SubBlock getAbove() {
|
||||
|
||||
return above;
|
||||
}
|
||||
|
||||
@ -247,6 +246,7 @@ final class SubBlock {
|
||||
&& plane == Plane.Y1) {
|
||||
r = r + "\n " + Globals.getSubBlockModeAsString(mode);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -260,12 +260,10 @@ final class SubBlock {
|
||||
}
|
||||
|
||||
public int[][] getDiff() {
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
public SubBlock getLeft() {
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
|
@ -1060,22 +1060,24 @@ public final class VP8Frame {
|
||||
private final byte[] rgb = new byte[4]; // Allow decoding into RGBA, leaving the alpha out.
|
||||
|
||||
private void copyBlock(final MacroBlock macroBlock, final WritableRaster byteRGBRaster, final ImageReadParam param) {
|
||||
// TODO: Consider doing YCbCr -> RGB in reader instead, or pass a flag to allow readRaster reading direct YUV/YCbCr values
|
||||
int sourceYSubsampling = param != null ? param.getSourceYSubsampling() : 1;
|
||||
int sourceXSubsampling = param != null ? param.getSourceXSubsampling() : 1;
|
||||
|
||||
// We might be copying into a smaller raster
|
||||
int yStart = macroBlock.getY() * 16;
|
||||
int yEnd = Math.min(16, byteRGBRaster.getHeight() - yStart);
|
||||
int yEnd = Math.min(16, byteRGBRaster.getHeight() * sourceYSubsampling - yStart);
|
||||
int xStart = macroBlock.getX() * 16;
|
||||
int xEnd = Math.min(16, byteRGBRaster.getWidth() - xStart);
|
||||
int xEnd = Math.min(16, byteRGBRaster.getWidth() * sourceXSubsampling - xStart);
|
||||
|
||||
for (int y = 0; y < yEnd; y++) {
|
||||
for (int x = 0; x < xEnd; x++) {
|
||||
for (int y = 0; y < yEnd; y += sourceYSubsampling) {
|
||||
for (int x = 0; x < xEnd; x += sourceXSubsampling) {
|
||||
yuv[0] = (byte) macroBlock.getSubBlock(SubBlock.Plane.Y1, x / 4, y / 4).getDest()[x % 4][y % 4];
|
||||
yuv[1] = (byte) macroBlock.getSubBlock(SubBlock.Plane.U, (x / 2) / 4, (y / 2) / 4).getDest()[(x / 2) % 4][(y / 2) % 4];
|
||||
yuv[2] = (byte) macroBlock.getSubBlock(SubBlock.Plane.V, (x / 2) / 4, (y / 2) / 4).getDest()[(x / 2) % 4][(y / 2) % 4];
|
||||
|
||||
// TODO: Consider doing YCbCr -> RGB in reader instead, or pass a flag to allow readRaster reading direct YUV/YCbCr values
|
||||
convertYCbCr2RGB(yuv, rgb, 0);
|
||||
byteRGBRaster.setDataElements(xStart + x, yStart + y, rgb);
|
||||
byteRGBRaster.setDataElements((xStart + x) / sourceXSubsampling, (yStart + y) / sourceYSubsampling, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user