Process rows properly in case of YUV cropping on odd lines.

Bug: 447845730,447958064,448792425,449246999,449546226,449781448
Change-Id: Ie8a855b5410019ec1f618fa4d4705ae3984db444
This commit is contained in:
Vincent Rabaud
2025-10-10 11:03:26 +02:00
parent 61791c774a
commit 23359a1039

View File

@@ -822,7 +822,10 @@ static WEBP_INLINE HTreeGroup* GetHtreeGroupForPos(VP8LMetadata* const hdr,
//------------------------------------------------------------------------------
// Main loop, with custom row-processing function
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row);
// If 'wait_for_biggest_batch' is true, wait for enough data to fill the
// argb_cache as much as possible (usually NUM_ARGB_CACHE_ROWS).
typedef void (*ProcessRowsFunc)(VP8LDecoder* const dec, int row,
int wait_for_biggest_batch);
static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row,
int num_rows, const uint32_t* const rows) {
@@ -846,16 +849,26 @@ static void ApplyInverseTransforms(VP8LDecoder* const dec, int start_row,
// Processes (transforms, scales & color-converts) the rows decoded after the
// last call.
static void ProcessRows(VP8LDecoder* const dec, int row) {
static void ProcessRows(VP8LDecoder* const dec, int row,
int wait_for_biggest_batch) {
const uint32_t* const rows = dec->pixels + dec->width * dec->last_row;
int num_rows;
// In case of YUV conversion and if we do not need to get to the last row.
if (!WebPIsRGBMode(dec->output->colorspace) && row >= dec->io->crop_top &&
row < dec->io->crop_bottom) {
// Make sure the number of rows to process is even.
if ((row - dec->io->crop_top) % 2 == 1) {
--row;
if (wait_for_biggest_batch) {
// In case of YUV conversion, and if we do not use the whole cropping
// region.
if (!WebPIsRGBMode(dec->output->colorspace) && row >= dec->io->crop_top &&
row < dec->io->crop_bottom) {
// Make sure the number of rows to process is even.
if ((row - dec->io->crop_top) % 2 != 0) return;
// Make sure the cache is as full as possible.
if (row % NUM_ARGB_CACHE_ROWS != 0 &&
(row + 1) % NUM_ARGB_CACHE_ROWS != 0) {
return;
}
} else {
if (row % NUM_ARGB_CACHE_ROWS != 0) return;
}
}
num_rows = row - dec->last_row;
@@ -1249,8 +1262,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
col = 0;
++row;
if (process_func != NULL) {
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
process_func(dec, row);
if (row <= last_row) {
process_func(dec, row, /*wait_for_biggest_batch=*/1);
}
}
if (color_cache != NULL) {
@@ -1280,8 +1293,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
col -= width;
++row;
if (process_func != NULL) {
if (row <= last_row && (row % NUM_ARGB_CACHE_ROWS == 0)) {
process_func(dec, row);
if (row <= last_row) {
process_func(dec, row, /*wait_for_biggest_batch=*/1);
}
}
}
@@ -1324,7 +1337,8 @@ static int DecodeImageData(VP8LDecoder* const dec, uint32_t* const data,
} else if ((dec->incremental && src >= src_last) || !br->eos) {
// Process the remaining rows corresponding to last row-block.
if (process_func != NULL) {
process_func(dec, row > last_row ? last_row : row);
process_func(dec, row > last_row ? last_row : row,
/*wait_for_biggest_batch=*/0);
}
dec->status = VP8_STATUS_OK;
dec->last_pixel = (int)(src - data); // end-of-scan marker
@@ -1634,11 +1648,15 @@ static int AllocateInternalBuffers8b(VP8LDecoder* const dec) {
//------------------------------------------------------------------------------
// Special row-processing that only stores the alpha data.
static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row) {
static void ExtractAlphaRows(VP8LDecoder* const dec, int last_row,
int wait_for_biggest_batch) {
int cur_row = dec->last_row;
int num_rows = last_row - cur_row;
const uint32_t* in = dec->pixels + dec->width * cur_row;
if (wait_for_biggest_batch && last_row % NUM_ARGB_CACHE_ROWS != 0) {
return;
}
assert(last_row <= dec->io->crop_bottom);
while (num_rows > 0) {
const int num_rows_to_process =