Browse Source

Fixing edge case

See https://github.com/phoboslab/qoi/issues/258 and previous commit
qoi
LuisAlfredo92 3 years ago
parent
commit
a87f78123f
No known key found for this signature in database GPG Key ID: 13A8436905993B8F
  1. 19
      src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs
  2. 4
      tests/Images/External/ReferenceOutput/QoiDecoderTests/Decode_Rgba32_edgecase.png

19
src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs

@ -146,6 +146,12 @@ internal class QoiDecoderCore : IImageDecoderInternals
{
Rgba32[] previouslySeenPixels = new Rgba32[64];
Rgba32 previousPixel = new (0,0,0,255);
// We save the pixel to avoid loosing the fully opaque black pixel
// See https://github.com/phoboslab/qoi/issues/258
int pixelArrayPosition = this.GetArrayPosition(previousPixel);
previouslySeenPixels[pixelArrayPosition] = previousPixel;
for (int i = 0; i < this.header.Height; i++)
{
for (int j = 0; j < this.header.Width; j++)
@ -154,9 +160,9 @@ internal class QoiDecoderCore : IImageDecoderInternals
byte[] pixelBytes;
Rgba32 readPixel;
TPixel pixel = new();
int pixelArrayPosition;
switch ((QoiChunkEnum)operationByte)
{
// Reading one pixel with previous alpha intact
case QoiChunkEnum.QOI_OP_RGB:
pixelBytes = new byte[3];
if (stream.Read(pixelBytes) < 3)
@ -170,6 +176,7 @@ internal class QoiDecoderCore : IImageDecoderInternals
previouslySeenPixels[pixelArrayPosition] = readPixel;
break;
// Reading one pixel with new alpha
case QoiChunkEnum.QOI_OP_RGBA:
pixelBytes = new byte[4];
if (stream.Read(pixelBytes) < 4)
@ -186,12 +193,14 @@ internal class QoiDecoderCore : IImageDecoderInternals
default:
switch ((QoiChunkEnum)(operationByte & 0b11000000))
{
// Getting one pixel from previously seen pixels
case QoiChunkEnum.QOI_OP_INDEX:
readPixel = previouslySeenPixels[operationByte];
pixel.FromRgba32(readPixel);
break;
// Get one pixel from the difference (-2..1) of the previous pixel
case QoiChunkEnum.QOI_OP_DIFF:
// Get each value
byte redDifference = (byte)((operationByte & 0b00110000) >> 4),
greenDifference = (byte)((operationByte & 0b00001100) >> 2),
blueDifference = (byte)(operationByte & 0b00000011);
@ -205,8 +214,10 @@ internal class QoiDecoderCore : IImageDecoderInternals
pixelArrayPosition = this.GetArrayPosition(readPixel);
previouslySeenPixels[pixelArrayPosition] = readPixel;
break;
// Get green difference in 6 bits and red and blue differences
// depending on the green one
case QoiChunkEnum.QOI_OP_LUMA:
// Get difference green channel
byte diffGreen = (byte)(operationByte & 0b00111111),
currentGreen = (byte)((previousPixel.G + (diffGreen - 32)) % 256),
nextByte = (byte)stream.ReadByte(),
@ -219,6 +230,8 @@ internal class QoiDecoderCore : IImageDecoderInternals
pixelArrayPosition = this.GetArrayPosition(readPixel);
previouslySeenPixels[pixelArrayPosition] = readPixel;
break;
// Repeating the previous pixel 1..63 times
case QoiChunkEnum.QOI_OP_RUN:
byte repetitions = (byte)(operationByte & 0b00111111);
if(repetitions is 62 or 63)

4
tests/Images/External/ReferenceOutput/QoiDecoderTests/Decode_Rgba32_edgecase.png

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1b39ab87da8d615f1ebb1348789a767b6421771dfcf11cd0b7cac618a0b8d6f1
size 918
oid sha256:12c966382b318c58578e3823ac066c597ce1e16ce7c2315b0f9d66451803a082
size 1245

Loading…
Cancel
Save