Browse Source

Fix bug in ColorSpaceInverseTransform

pull/1147/head
Brian Popow 6 years ago
parent
commit
541aa858fc
  1. 33
      src/ImageSharp/Formats/WebP/LosslessUtils.cs
  2. 3
      src/ImageSharp/Formats/WebP/Vp8LTransform.cs
  3. 4
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

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

@ -89,25 +89,27 @@ namespace SixLabors.ImageSharp.Formats.WebP
int remainingWidth = width - safeWidth; int remainingWidth = width - safeWidth;
int tilesPerRow = SubSampleSize(width, transform.Bits); int tilesPerRow = SubSampleSize(width, transform.Bits);
int y = 0; int y = 0;
uint predRow = transform.Data[(y >> transform.Bits) * tilesPerRow]; int predRowIdxStart = (y >> transform.Bits) * tilesPerRow;
int pixelPos = 0; int pixelPos = 0;
while (y < yEnd) while (y < yEnd)
{ {
uint pred = predRow; int predRowIdx = predRowIdxStart;
Vp8LMultipliers m = default(Vp8LMultipliers); Vp8LMultipliers m = default(Vp8LMultipliers);
int srcSafeEnd = pixelPos + safeWidth; int srcSafeEnd = pixelPos + safeWidth;
int srcEnd = pixelPos + width; int srcEnd = pixelPos + width;
while (pixelPos < srcSafeEnd) while (pixelPos < srcSafeEnd)
{ {
ColorCodeToMultipliers(pred++, ref m); uint colorCode = transform.Data[predRowIdx++];
ColorCodeToMultipliers(colorCode, ref m);
TransformColorInverse(m, pixelData, pixelPos, tileWidth); TransformColorInverse(m, pixelData, pixelPos, tileWidth);
pixelPos += tileWidth; pixelPos += tileWidth;
} }
if (pixelPos < srcEnd) if (pixelPos < srcEnd)
{ {
ColorCodeToMultipliers(pred++, ref m); uint colorCode = transform.Data[predRowIdx];
ColorCodeToMultipliers(colorCode, ref m);
TransformColorInverse(m, pixelData, pixelPos, remainingWidth); TransformColorInverse(m, pixelData, pixelPos, remainingWidth);
pixelPos += remainingWidth; pixelPos += remainingWidth;
} }
@ -115,7 +117,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
++y; ++y;
if ((y & mask) == 0) if ((y & mask) == 0)
{ {
predRow += (uint)tilesPerRow; predRowIdxStart += tilesPerRow;
} }
} }
} }
@ -130,13 +132,13 @@ namespace SixLabors.ImageSharp.Formats.WebP
uint red = argb >> 16; uint red = argb >> 16;
int newRed = (int)(red & 0xff); int newRed = (int)(red & 0xff);
int newBlue = (int)argb & 0xff; int newBlue = (int)argb & 0xff;
newRed += ColorTransformDelta(m.GreenToRed, (sbyte)green); newRed += ColorTransformDelta((sbyte)m.GreenToRed, (sbyte)green);
newRed &= 0xff; newRed &= 0xff;
newBlue += ColorTransformDelta(m.GreenToBlue, (sbyte)green); newBlue += ColorTransformDelta((sbyte)m.GreenToBlue, (sbyte)green);
newBlue += ColorTransformDelta(m.RedToBlue, (sbyte)newRed); newBlue += ColorTransformDelta((sbyte)m.RedToBlue, (sbyte)newRed);
newBlue &= 0xff; newBlue &= 0xff;
// uint pixelValue = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue); uint pixelValue = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue);
pixelData[i] = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue); pixelData[i] = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue);
} }
} }
@ -612,23 +614,24 @@ namespace SixLabors.ImageSharp.Formats.WebP
private static int ColorTransformDelta(sbyte colorPred, sbyte color) private static int ColorTransformDelta(sbyte colorPred, sbyte color)
{ {
var delta = ((sbyte)colorPred * color) >> 5;
return ((int)colorPred * color) >> 5; return ((int)colorPred * color) >> 5;
} }
private static void ColorCodeToMultipliers(uint colorCode, ref Vp8LMultipliers m) private static void ColorCodeToMultipliers(uint colorCode, ref Vp8LMultipliers m)
{ {
m.GreenToRed = (sbyte)(colorCode & 0xff); m.GreenToRed = (byte)(colorCode & 0xff);
m.GreenToBlue = (sbyte)((colorCode >> 8) & 0xff); m.GreenToBlue = (byte)((colorCode >> 8) & 0xff);
m.RedToBlue = (sbyte)((colorCode >> 16) & 0xff); m.RedToBlue = (byte)((colorCode >> 16) & 0xff);
} }
internal struct Vp8LMultipliers internal struct Vp8LMultipliers
{ {
public sbyte GreenToRed; public byte GreenToRed;
public sbyte GreenToBlue; public byte GreenToBlue;
public sbyte RedToBlue; public byte RedToBlue;
} }
} }
} }

3
src/ImageSharp/Formats/WebP/Vp8LTransform.cs

@ -1,11 +1,14 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Diagnostics;
namespace SixLabors.ImageSharp.Formats.WebP namespace SixLabors.ImageSharp.Formats.WebP
{ {
/// <summary> /// <summary>
/// Data associated with a VP8L transformation to reduce the entropy. /// Data associated with a VP8L transformation to reduce the entropy.
/// </summary> /// </summary>
[DebuggerDisplay("Transformtype: {TransformType}")]
internal class Vp8LTransform internal class Vp8LTransform
{ {
public Vp8LTransform(Vp8LTransformType transformType, int xSize, int ySize) public Vp8LTransform(Vp8LTransformType transformType, int xSize, int ySize)

4
src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

@ -306,7 +306,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
else else
{ {
// Error // TODO: throw appropriate error msg
} }
} }
@ -750,7 +750,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
int xOffset = 8 - (distCode & 0xf); int xOffset = 8 - (distCode & 0xf);
int dist = (yOffset * xSize) + xOffset; int dist = (yOffset * xSize) + xOffset;
// dist < 1 can happen if xsize is very small. // dist < 1 can happen if xSize is very small.
return (dist >= 1) ? dist : 1; return (dist >= 1) ? dist : 1;
} }

Loading…
Cancel
Save