Browse Source

Fix bug in PredictorInverseTransform

pull/1147/head
Brian Popow 6 years ago
parent
commit
2bd350e558
  1. 60
      src/ImageSharp/Formats/WebP/LosslessUtils.cs
  2. 1
      tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs
  3. 1
      tests/ImageSharp.Tests/TestImages.cs
  4. BIN
      tests/Images/Input/WebP/bike_lossless.webp

60
src/ImageSharp/Formats/WebP/LosslessUtils.cs

@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
// decrementing a counter. // decrementing a counter.
if ((x & countMask) is 0) if ((x & countMask) is 0)
{ {
packedPixels = GetARGBIndex(pixelData[pixelDataPos++]); packedPixels = GetArgbIndex(pixelData[pixelDataPos++]);
} }
decodedPixelData[decodedPixels++] = colorMap[packedPixels & bitMask]; decodedPixelData[decodedPixels++] = colorMap[packedPixels & bitMask];
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
for (int x = 0; x < width; ++x) for (int x = 0; x < width; ++x)
{ {
uint colorMapIndex = GetARGBIndex(pixelData[decodedPixels]); uint colorMapIndex = GetArgbIndex(pixelData[decodedPixels]);
pixelData[decodedPixels] = colorMap[colorMapIndex]; pixelData[decodedPixels] = colorMap[colorMapIndex];
decodedPixels++; decodedPixels++;
} }
@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
++y; ++y;
if ((y & mask) == 0) if ((y & mask) is 0)
{ {
predRowIdxStart += tilesPerRow; predRowIdxStart += tilesPerRow;
} }
@ -501,35 +501,37 @@ namespace SixLabors.ImageSharp.Formats.WebP
private static uint ClampedAddSubtractFull(uint c0, uint c1, uint c2) private static uint ClampedAddSubtractFull(uint c0, uint c1, uint c2)
{ {
int a = AddSubtractComponentFull(c0 >> 24, c1 >> 24, c2 >> 24); int a = AddSubtractComponentFull((int)(c0 >> 24), (int)(c1 >> 24), (int)(c2 >> 24));
int r = AddSubtractComponentFull((c0 >> 16) & 0xff, int r = AddSubtractComponentFull(
(c1 >> 16) & 0xff, (int)((c0 >> 16) & 0xff),
(c2 >> 16) & 0xff); (int)((c1 >> 16) & 0xff),
int g = AddSubtractComponentFull((c0 >> 8) & 0xff, (int)((c2 >> 16) & 0xff));
(c1 >> 8) & 0xff, int g = AddSubtractComponentFull(
(c2 >> 8) & 0xff); (int)((c0 >> 8) & 0xff),
int b = AddSubtractComponentFull(c0 & 0xff, c1 & 0xff, c2 & 0xff); (int)((c1 >> 8) & 0xff),
(int)((c2 >> 8) & 0xff));
int b = AddSubtractComponentFull((int)(c0 & 0xff), (int)(c1 & 0xff), (int)(c2 & 0xff));
return (uint)(((uint)a << 24) | (r << 16) | (g << 8) | b); return (uint)(((uint)a << 24) | (r << 16) | (g << 8) | b);
} }
private static uint ClampedAddSubtractHalf(uint c0, uint c1, uint c2) private static uint ClampedAddSubtractHalf(uint c0, uint c1, uint c2)
{ {
uint ave = Average2(c0, c1); uint ave = Average2(c0, c1);
int a = AddSubtractComponentHalf(ave >> 24, c2 >> 24); int a = AddSubtractComponentHalf((int)(ave >> 24), (int)(c2 >> 24));
int r = AddSubtractComponentHalf((ave >> 16) & 0xff, (c2 >> 16) & 0xff); int r = AddSubtractComponentHalf((int)((ave >> 16) & 0xff), (int)((c2 >> 16) & 0xff));
int g = AddSubtractComponentHalf((ave >> 8) & 0xff, (c2 >> 8) & 0xff); int g = AddSubtractComponentHalf((int)((ave >> 8) & 0xff), (int)((c2 >> 8) & 0xff));
int b = AddSubtractComponentHalf((ave >> 0) & 0xff, (c2 >> 0) & 0xff); int b = AddSubtractComponentHalf((int)(ave & 0xff), (int)(c2 & 0xff));
return (uint)(((uint)a << 24) | (r << 16) | (g << 8) | b); return (uint)(((uint)a << 24) | (r << 16) | (g << 8) | b);
} }
private static int AddSubtractComponentHalf(uint a, uint b) private static int AddSubtractComponentHalf(int a, int b)
{ {
return (int)Clip255(a + ((a - b) / 2)); return (int)Clip255((uint)(a + ((a - b) / 2)));
} }
private static int AddSubtractComponentFull(uint a, uint b, uint c) private static int AddSubtractComponentFull(int a, int b, int c)
{ {
return (int)Clip255(a + b - c); return (int)Clip255((uint)(a + b - c));
} }
private static uint Clip255(uint a) private static uint Clip255(uint a)
@ -539,26 +541,24 @@ namespace SixLabors.ImageSharp.Formats.WebP
return a; return a;
} }
// return 0, when a is a negative integer.
// return 255, when a is positive.
return ~a >> 24; return ~a >> 24;
} }
private static uint Select(uint a, uint b, uint c) private static uint Select(uint a, uint b, uint c)
{ {
int paMinusPb = int paMinusPb =
Sub3(a >> 24, b >> 24, c >> 24) + Sub3((int)(a >> 24), (int)(b >> 24), (int)(c >> 24)) +
Sub3((a >> 16) & 0xff, (b >> 16) & 0xff, (c >> 16) & 0xff) + Sub3((int)((a >> 16) & 0xff), (int)((b >> 16) & 0xff), (int)((c >> 16) & 0xff)) +
Sub3((a >> 8) & 0xff, (b >> 8) & 0xff, (c >> 8) & 0xff) + Sub3((int)((a >> 8) & 0xff), (int)((b >> 8) & 0xff), (int)((c >> 8) & 0xff)) +
Sub3( a & 0xff, b & 0xff, c & 0xff); Sub3((int)(a & 0xff), (int)(b & 0xff), (int)(c & 0xff));
return (paMinusPb <= 0) ? a : b; return (paMinusPb <= 0) ? a : b;
} }
private static int Sub3(uint a, uint b, uint c) private static int Sub3(int a, int b, int c)
{ {
uint pb = b - c; int pb = b - c;
uint pa = a - c; int pa = a - c;
return (int)(Math.Abs(pb) - Math.Abs(pa)); return Math.Abs(pb) - Math.Abs(pa);
} }
private static uint Average2(uint a0, uint a1) private static uint Average2(uint a0, uint a1)
@ -605,7 +605,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
return (alphaAndGreen & 0xff00ff00u) | (redAndBlue & 0x00ff00ffu); return (alphaAndGreen & 0xff00ff00u) | (redAndBlue & 0x00ff00ffu);
} }
private static uint GetARGBIndex(uint idx) private static uint GetArgbIndex(uint idx)
{ {
return (idx >> 8) & 0xff; return (idx >> 8) & 0xff;
} }

1
tests/ImageSharp.Tests/Formats/WebP/WebPDecoderTests.cs

@ -162,6 +162,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP
[WithFile(Lossless.ThreeTransforms5, PixelTypes.Rgba32)] [WithFile(Lossless.ThreeTransforms5, PixelTypes.Rgba32)]
[WithFile(Lossless.ThreeTransforms6, PixelTypes.Rgba32)] [WithFile(Lossless.ThreeTransforms6, PixelTypes.Rgba32)]
[WithFile(Lossless.ThreeTransforms7, PixelTypes.Rgba32)] [WithFile(Lossless.ThreeTransforms7, PixelTypes.Rgba32)]
[WithFile(Lossless.ThreeTransforms8, PixelTypes.Rgba32)]
public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms<TPixel>(TestImageProvider<TPixel> provider) public void WebpDecoder_CanDecode_Lossless_WithThreeTransforms<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {

1
tests/ImageSharp.Tests/TestImages.cs

@ -416,6 +416,7 @@ namespace SixLabors.ImageSharp.Tests
public const string ThreeTransforms5 = "Webp/lossless_vec_2_11.webp"; // color_indexing, predictor, cross_color public const string ThreeTransforms5 = "Webp/lossless_vec_2_11.webp"; // color_indexing, predictor, cross_color
public const string ThreeTransforms6 = "Webp/lossless_vec_2_14.webp"; // substract_green, predictor, cross_color public const string ThreeTransforms6 = "Webp/lossless_vec_2_14.webp"; // substract_green, predictor, cross_color
public const string ThreeTransforms7 = "Webp/lossless_vec_2_15.webp"; // color_indexing, predictor, cross_color public const string ThreeTransforms7 = "Webp/lossless_vec_2_15.webp"; // color_indexing, predictor, cross_color
public const string ThreeTransforms8 = "Webp/bike_lossless.webp"; // substract_green, predictor, cross_color
// Invalid / corrupted images // Invalid / corrupted images
// Below images have errors according to webpinfo. The error message webpinfo gives is "Truncated data detected when parsing RIFF payload." // Below images have errors according to webpinfo. The error message webpinfo gives is "Truncated data detected when parsing RIFF payload."

BIN
tests/Images/Input/WebP/bike_lossless.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Loading…
Cancel
Save