Skip to content

Commit a87f781

Browse files
committed
Fixing edge case
See phoboslab/qoi#258 and previous commit
1 parent bca998d commit a87f781

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
146146
{
147147
Rgba32[] previouslySeenPixels = new Rgba32[64];
148148
Rgba32 previousPixel = new (0,0,0,255);
149+
150+
// We save the pixel to avoid loosing the fully opaque black pixel
151+
// See https://github.com/phoboslab/qoi/issues/258
152+
int pixelArrayPosition = this.GetArrayPosition(previousPixel);
153+
previouslySeenPixels[pixelArrayPosition] = previousPixel;
154+
149155
for (int i = 0; i < this.header.Height; i++)
150156
{
151157
for (int j = 0; j < this.header.Width; j++)
@@ -154,9 +160,9 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
154160
byte[] pixelBytes;
155161
Rgba32 readPixel;
156162
TPixel pixel = new();
157-
int pixelArrayPosition;
158163
switch ((QoiChunkEnum)operationByte)
159164
{
165+
// Reading one pixel with previous alpha intact
160166
case QoiChunkEnum.QOI_OP_RGB:
161167
pixelBytes = new byte[3];
162168
if (stream.Read(pixelBytes) < 3)
@@ -170,6 +176,7 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
170176
previouslySeenPixels[pixelArrayPosition] = readPixel;
171177
break;
172178

179+
// Reading one pixel with new alpha
173180
case QoiChunkEnum.QOI_OP_RGBA:
174181
pixelBytes = new byte[4];
175182
if (stream.Read(pixelBytes) < 4)
@@ -186,12 +193,14 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
186193
default:
187194
switch ((QoiChunkEnum)(operationByte & 0b11000000))
188195
{
196+
// Getting one pixel from previously seen pixels
189197
case QoiChunkEnum.QOI_OP_INDEX:
190198
readPixel = previouslySeenPixels[operationByte];
191199
pixel.FromRgba32(readPixel);
192200
break;
201+
202+
// Get one pixel from the difference (-2..1) of the previous pixel
193203
case QoiChunkEnum.QOI_OP_DIFF:
194-
// Get each value
195204
byte redDifference = (byte)((operationByte & 0b00110000) >> 4),
196205
greenDifference = (byte)((operationByte & 0b00001100) >> 2),
197206
blueDifference = (byte)(operationByte & 0b00000011);
@@ -205,8 +214,10 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
205214
pixelArrayPosition = this.GetArrayPosition(readPixel);
206215
previouslySeenPixels[pixelArrayPosition] = readPixel;
207216
break;
217+
218+
// Get green difference in 6 bits and red and blue differences
219+
// depending on the green one
208220
case QoiChunkEnum.QOI_OP_LUMA:
209-
// Get difference green channel
210221
byte diffGreen = (byte)(operationByte & 0b00111111),
211222
currentGreen = (byte)((previousPixel.G + (diffGreen - 32)) % 256),
212223
nextByte = (byte)stream.ReadByte(),
@@ -219,6 +230,8 @@ private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> p
219230
pixelArrayPosition = this.GetArrayPosition(readPixel);
220231
previouslySeenPixels[pixelArrayPosition] = readPixel;
221232
break;
233+
234+
// Repeating the previous pixel 1..63 times
222235
case QoiChunkEnum.QOI_OP_RUN:
223236
byte repetitions = (byte)(operationByte & 0b00111111);
224237
if(repetitions is 62 or 63)
Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)