Skip to content

Commit

Permalink
Fixed decoding of progressive images (PNG)
Browse files Browse the repository at this point in the history
  * Progressive flag was not properly propagated by the decoder,
    which means that the decoding failed as progressive data is
    stored differently
  * Relaxed strict checking of PNG filters as it's not done by
    libpng's reference implementation. Unknown filters are just
    ignored and threated as PNG_FILTER_NONE
  • Loading branch information
kobalicek committed Jun 26, 2024
1 parent c966273 commit a9e8f40
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/blend2d/codec/pngcodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ static BLResult decoderReadInfoInternal(BLPngDecoderImpl* decoderI, const uint8_
decoderI->imageInfo.size.reset(int(w), int(h));
decoderI->imageInfo.depth = uint16_t(sampleDepth * uint32_t(decoderI->sampleCount));
decoderI->imageInfo.frameCount = 1;
decoderI->imageInfo.flags = progressive ? BL_IMAGE_INFO_FLAG_PROGRESSIVE : BL_IMAGE_INFO_FLAG_NO_FLAGS;

decoderI->bufferIndex = (size_t)(p - start);
return BL_SUCCESS;
Expand Down
19 changes: 11 additions & 8 deletions src/blend2d/codec/pngops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,16 @@ BLResult BL_CDECL inverseFilterImpl(uint8_t* p, uint32_t bpp, uint32_t bpl, uint
// First row uses a special filter that doesn't access the previous row,
// which is assumed to contain all zeros.
uint32_t filterType = *p++;
if (BL_UNLIKELY(filterType >= BL_PNG_FILTER_TYPE_COUNT))
return blTraceError(BL_ERROR_INVALID_DATA);

if (filterType >= BL_PNG_FILTER_TYPE_COUNT)
filterType = BL_PNG_FILTER_TYPE_NONE;

filterType = simplifyFilterOfFirstRow(filterType);

for (;;) {
uint32_t i;

switch (filterType) {
case BL_PNG_FILTER_TYPE_NONE:
p += bpl;
break;

case BL_PNG_FILTER_TYPE_SUB: {
for (i = bpl - bpp; i != 0; i--, p++)
p[bpp] = applySumFilter(p[bpp], p[0]);
Expand Down Expand Up @@ -88,6 +86,11 @@ BLResult BL_CDECL inverseFilterImpl(uint8_t* p, uint32_t bpp, uint32_t bpl, uint
p += bpp;
break;
}

case BL_PNG_FILTER_TYPE_NONE:
default:
p += bpl;
break;
}

if (--y == 0)
Expand All @@ -96,8 +99,8 @@ BLResult BL_CDECL inverseFilterImpl(uint8_t* p, uint32_t bpp, uint32_t bpl, uint
u = p - bpl;
filterType = *p++;

if (BL_UNLIKELY(filterType >= BL_PNG_FILTER_TYPE_COUNT))
return blTraceError(BL_ERROR_INVALID_DATA);
if (filterType >= BL_PNG_FILTER_TYPE_COUNT)
filterType = BL_PNG_FILTER_TYPE_NONE;
}

return BL_SUCCESS;
Expand Down
19 changes: 11 additions & 8 deletions src/blend2d/codec/pngops_sse2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ BLResult BL_CDECL inverseFilterImpl_SSE2(uint8_t* p, uint32_t bpp, uint32_t bpl,
// First row uses a special filter that doesn't access the previous row,
// which is assumed to contain all zeros.
uint32_t filterType = *p++;
if (BL_UNLIKELY(filterType >= BL_PNG_FILTER_TYPE_COUNT))
return blTraceError(BL_ERROR_INVALID_DATA);

if (filterType >= BL_PNG_FILTER_TYPE_COUNT)
filterType = BL_PNG_FILTER_TYPE_NONE;

filterType = simplifyFilterOfFirstRow(filterType);

#define BL_PNG_PAETH(DST, A, B, C) \
Expand Down Expand Up @@ -68,10 +70,6 @@ BLResult BL_CDECL inverseFilterImpl_SSE2(uint8_t* p, uint32_t bpp, uint32_t bpl,
uint32_t i;

switch (filterType) {
case BL_PNG_FILTER_TYPE_NONE:
p += bpl;
break;

// This is one of the easiest filters to parallelize. Although it looks like the data dependency
// is too high, it's simply additions, which are really easy to parallelize. The following formula:
//
Expand Down Expand Up @@ -1029,6 +1027,11 @@ BLResult BL_CDECL inverseFilterImpl_SSE2(uint8_t* p, uint32_t bpp, uint32_t bpl,
p += bpp;
break;
}

case BL_PNG_FILTER_TYPE_NONE:
default:
p += bpl;
break;
}

if (--y == 0)
Expand All @@ -1037,8 +1040,8 @@ BLResult BL_CDECL inverseFilterImpl_SSE2(uint8_t* p, uint32_t bpp, uint32_t bpl,
u = p - bpl;
filterType = *p++;

if (BL_UNLIKELY(filterType >= BL_PNG_FILTER_TYPE_COUNT))
return blTraceError(BL_ERROR_INVALID_DATA);
if (filterType >= BL_PNG_FILTER_TYPE_COUNT)
filterType = BL_PNG_FILTER_TYPE_NONE;
}

#undef BL_PNG_PAETH
Expand Down

0 comments on commit a9e8f40

Please sign in to comment.