Browse Source
Merge pull request #2823 from SixLabors/js/issue-2801
WEBP : Use Correct Width With AlphaDecoder
pull/2835/head
James Jackson-South
2 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with
36 additions and
8 deletions
src/ImageSharp/Formats/Webp/AlphaDecoder.cs
src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs
src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs
tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
tests/ImageSharp.Tests/TestImages.cs
tests/Images/Input/Webp/issues/Issue2801.webp
@ -183,7 +183,7 @@ internal class AlphaDecoder : IDisposable
else
{
this . LosslessDecoder . DecodeImageData ( this . Vp8LDec , this . Vp8LDec . Pixels . Memory . Span ) ;
this . ExtractAlphaRows ( this . Vp8LDec ) ;
this . ExtractAlphaRows ( this . Vp8LDec , this . Width ) ;
}
}
@ -257,14 +257,15 @@ internal class AlphaDecoder : IDisposable
/// Once the image-stream is decoded into ARGB color values, the transparency information will be extracted from the green channel of the ARGB quadruplet.
/// </summary>
/// <param name="dec">The VP8L decoder.</param>
private void ExtractAlphaRows ( Vp8LDecoder dec )
/// <param name="width">The image width.</param>
private void ExtractAlphaRows ( Vp8LDecoder dec , int width )
{
int numRowsToProcess = dec . Height ;
int width = dec . Width ;
Span < uint > input = dec . Pixels . Memory . Span ;
Span < byte > output = this . Alpha . Memory . Span ;
// Extract alpha (which is stored in the green plane).
// the final width (!= dec->width_)
int pixelCount = width * numRowsToProcess ;
WebpLosslessDecoder . ApplyInverseTransforms ( dec , input , this . memoryAllocator ) ;
ExtractGreen ( input , output , pixelCount ) ;
@ -269,7 +269,11 @@ internal static unsafe class LosslessUtils
/// </summary>
/// <param name="transform">The transform data contains color table size and the entries in the color table.</param>
/// <param name="pixelData">The pixel data to apply the reverse transform on.</param>
public static void ColorIndexInverseTransform ( Vp8LTransform transform , Span < uint > pixelData )
/// <param name="outputSpan">The resulting pixel data with the reversed transformation data.</param>
public static void ColorIndexInverseTransform (
Vp8LTransform transform ,
Span < uint > pixelData ,
Span < uint > outputSpan )
{
int bitsPerPixel = 8 > > transform . Bits ;
int width = transform . XSize ;
@ -282,7 +286,6 @@ internal static unsafe class LosslessUtils
int countMask = pixelsPerByte - 1 ;
int bitMask = ( 1 < < bitsPerPixel ) - 1 ;
uint [ ] decodedPixelData = new uint [ width * height ] ;
int pixelDataPos = 0 ;
for ( int y = 0 ; y < height ; y + + )
{
@ -298,12 +301,12 @@ internal static unsafe class LosslessUtils
packedPixels = GetArgbIndex ( pixelData [ pixelDataPos + + ] ) ;
}
decodedPixelData [ decodedPixels + + ] = colorMap [ ( int ) ( packedPixels & bitMask ) ] ;
outputSpan [ decodedPixels + + ] = colorMap [ ( int ) ( packedPixels & bitMask ) ] ;
packedPixels > > = bitsPerPixel ;
}
}
decodedPixelData . AsSpan ( ) . CopyTo ( pixelData ) ;
outputSpan . CopyTo ( pixelData ) ;
}
else
{
@ -684,6 +684,7 @@ internal sealed class WebpLosslessDecoder
List < Vp8LTransform > transforms = decoder . Transforms ;
for ( int i = transforms . Count - 1 ; i > = 0 ; i - - )
{
// TODO: Review these 1D allocations. They could conceivably exceed limits.
Vp8LTransform transform = transforms [ i ] ;
switch ( transform . TransformType )
{
@ -701,7 +702,11 @@ internal sealed class WebpLosslessDecoder
LosslessUtils . ColorSpaceInverseTransform ( transform , pixelData ) ;
break ;
case Vp8LTransformType . ColorIndexingTransform :
LosslessUtils . ColorIndexInverseTransform ( transform , pixelData ) ;
using ( IMemoryOwner < uint > output = memoryAllocator . Allocate < uint > ( transform . XSize * transform . YSize , AllocationOptions . Clean ) )
{
LosslessUtils . ColorIndexInverseTransform ( transform , pixelData , output . GetSpan ( ) ) ;
}
break ;
}
}
@ -516,6 +516,21 @@ public class WebpEncoderTests
image . VerifyEncoder ( provider , "webp" , string . Empty , encoder ) ;
}
// https://github.com/SixLabors/ImageSharp/issues/2801
[Theory]
[WithFile(Lossy.Issue2801, PixelTypes.Rgba32)]
public void WebpDecoder_CanDecode_Issue2801 < TPixel > ( TestImageProvider < TPixel > provider )
where TPixel : unmanaged , IPixel < TPixel >
{
WebpEncoder encoder = new ( )
{
Quality = 1 0 0
} ;
using Image < TPixel > image = provider . GetImage ( ) ;
image . VerifyEncoder ( provider , "webp" , string . Empty , encoder , ImageComparer . TolerantPercentage ( 0.0994F ) ) ;
}
public static void RunEncodeLossy_WithPeakImage ( )
{
TestImageProvider < Rgba32 > provider = TestImageProvider < Rgba32 > . File ( TestImageLossyFullPath ) ;
@ -827,6 +827,7 @@ public static class TestImages
public const string Issue2257 = "Webp/issues/Issue2257.webp" ;
public const string Issue2670 = "Webp/issues/Issue2670.webp" ;
public const string Issue2763 = "Webp/issues/Issue2763.png" ;
public const string Issue2801 = "Webp/issues/Issue2801.webp" ;
}
}
@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e90a0d853ddf70d823d8da44eb6c57081e955b1fb7f436a1fd88ca5e5c75a003
size 261212