Browse Source

Implemented ColorSpaceInverseTransform

pull/1147/head
Brian Popow 7 years ago
parent
commit
89bdf89f55
  1. 78
      src/ImageSharp/Formats/WebP/LosslessUtils.cs
  2. 9
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

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

@ -22,46 +22,65 @@ namespace SixLabors.ImageSharp.Formats.WebP
} }
} }
public static void ColorSpaceInverseTransform(Vp8LTransform transform, uint[] pixelData, int yEnd) public static void ColorSpaceInverseTransform(Vp8LTransform transform, uint[] pixelData)
{ {
int width = transform.XSize; int width = transform.XSize;
int yEnd = transform.YSize;
int tileWidth = 1 << transform.Bits; int tileWidth = 1 << transform.Bits;
int mask = tileWidth - 1; int mask = tileWidth - 1;
int safeWidth = width & ~mask; int safeWidth = width & ~mask;
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];
/*uint[] predRow = transform.Data + (y >> transform.Bits) * tilesPerRow; int pixelPos = 0;
while (y < yEnd) while (y < yEnd)
{ {
uint[] pred = predRow; uint pred = predRow;
VP8LMultipliers m = { 0, 0, 0 }; Vp8LMultipliers m = default(Vp8LMultipliers);
const uint32_t* const src_safe_end = src + safeWidth; int srcSafeEnd = pixelPos + safeWidth;
const uint32_t* const src_end = src + width; int srcEnd = pixelPos + width;
while (src<src_safe_end) while (pixelPos < srcSafeEnd)
{ {
ColorCodeToMultipliers(*pred++, &m); ColorCodeToMultipliers(pred++, ref m);
VP8LTransformColorInverse(&m, src, tileWidth, dst); TransformColorInverse(m, pixelData, pixelPos, tileWidth);
src += tileWidth; pixelPos += tileWidth;
dst += tileWidth;
} }
if (src < src_end) if (pixelPos < srcEnd)
{ {
ColorCodeToMultipliers(*pred++, &m); ColorCodeToMultipliers(pred++, ref m);
VP8LTransformColorInverse(&m, src, remainingWidth, dst); TransformColorInverse(m, pixelData, pixelPos, remainingWidth);
src += remaining_width; pixelPos += remainingWidth;
dst += remaining_width;
} }
++y; ++y;
if ((y & mask) == 0) if ((y & mask) == 0)
{ {
predRow += tilesPerRow; predRow += (uint)tilesPerRow;
} }
}*/ }
}
public static void TransformColorInverse(Vp8LMultipliers m, uint[] pixelData, int start, int numPixels)
{
int end = start + numPixels;
for (int i = start; i < end; i++)
{
uint argb = pixelData[i];
sbyte green = (sbyte)(argb >> 8);
uint red = argb >> 16;
int newRed = (int)(red & 0xff);
int newBlue = (int)argb & 0xff;
newRed += ColorTransformDelta(m.GreenToRed, (sbyte)green);
newRed &= 0xff;
newBlue += ColorTransformDelta(m.GreenToBlue, (sbyte)green);
newBlue += ColorTransformDelta(m.RedToBlue, (sbyte)newRed);
newBlue &= 0xff;
var pixelValue = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue);
pixelData[i] = (uint)((argb & 0xff00ff00u) | (newRed << 16) | newBlue);
}
} }
/// <summary> /// <summary>
@ -71,5 +90,26 @@ namespace SixLabors.ImageSharp.Formats.WebP
{ {
return (size + (1 << samplingBits) - 1) >> samplingBits; return (size + (1 << samplingBits) - 1) >> samplingBits;
} }
private static int ColorTransformDelta(sbyte colorPred, sbyte color)
{
return ((int)colorPred * color) >> 5;
}
private static void ColorCodeToMultipliers(uint colorCode, ref Vp8LMultipliers m)
{
m.GreenToRed = (sbyte)(colorCode & 0xff);
m.GreenToBlue = (sbyte)((colorCode >> 8) & 0xff);
m.RedToBlue = (sbyte)((colorCode >> 16) & 0xff);
}
internal struct Vp8LMultipliers
{
public sbyte GreenToRed;
public sbyte GreenToBlue;
public sbyte RedToBlue;
}
} }
} }

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

@ -630,14 +630,17 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void ApplyInverseTransforms(Vp8LDecoder decoder, uint[] pixelData) private void ApplyInverseTransforms(Vp8LDecoder decoder, uint[] pixelData)
{ {
List<Vp8LTransform> transforms = decoder.Transforms; List<Vp8LTransform> transforms = decoder.Transforms;
for (int i = transforms.Count; i > 0; i--) for (int i = transforms.Count - 1; i >= 0; i--)
{ {
Vp8LTransformType transform = transforms[0].TransformType; Vp8LTransformType transformType = transforms[i].TransformType;
switch (transform) switch (transformType)
{ {
case Vp8LTransformType.SubtractGreen: case Vp8LTransformType.SubtractGreen:
LosslessUtils.AddGreenToBlueAndRed(pixelData); LosslessUtils.AddGreenToBlueAndRed(pixelData);
break; break;
case Vp8LTransformType.CrossColorTransform:
LosslessUtils.ColorSpaceInverseTransform(transforms[i], pixelData);
break;
} }
} }
} }

Loading…
Cancel
Save