ImportYUVAFromRGBA: use relative pointer offsets

avoids int rollover when working with large input

BUG=webp:312

Change-Id: I3d7b689be8d5751248a82d1021243d80d3f67203
(cherry picked from commit deb1b83199)
This commit is contained in:
James Zern 2016-11-04 07:04:18 +00:00
parent c284780f0a
commit 9daad4598b

View File

@ -830,10 +830,10 @@ static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb,
} }
} }
static int ImportYUVAFromRGBA(const uint8_t* const r_ptr, static int ImportYUVAFromRGBA(const uint8_t* r_ptr,
const uint8_t* const g_ptr, const uint8_t* g_ptr,
const uint8_t* const b_ptr, const uint8_t* b_ptr,
const uint8_t* const a_ptr, const uint8_t* a_ptr,
int step, // bytes per pixel int step, // bytes per pixel
int rgb_stride, // bytes per scanline int rgb_stride, // bytes per scanline
float dithering, float dithering,
@ -900,36 +900,34 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
// Downsample Y/U/V planes, two rows at a time // Downsample Y/U/V planes, two rows at a time
for (y = 0; y < (height >> 1); ++y) { for (y = 0; y < (height >> 1); ++y) {
int rows_have_alpha = has_alpha; int rows_have_alpha = has_alpha;
const int off1 = (2 * y + 0) * rgb_stride;
const int off2 = (2 * y + 1) * rgb_stride;
if (use_dsp) { if (use_dsp) {
if (is_rgb) { if (is_rgb) {
WebPConvertRGB24ToY(r_ptr + off1, dst_y, width); WebPConvertRGB24ToY(r_ptr, dst_y, width);
WebPConvertRGB24ToY(r_ptr + off2, dst_y + picture->y_stride, width); WebPConvertRGB24ToY(r_ptr + rgb_stride,
dst_y + picture->y_stride, width);
} else { } else {
WebPConvertBGR24ToY(b_ptr + off1, dst_y, width); WebPConvertBGR24ToY(b_ptr, dst_y, width);
WebPConvertBGR24ToY(b_ptr + off2, dst_y + picture->y_stride, width); WebPConvertBGR24ToY(b_ptr + rgb_stride,
dst_y + picture->y_stride, width);
} }
} else { } else {
ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step, ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
dst_y, width, rg); ConvertRowToY(r_ptr + rgb_stride,
ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step, g_ptr + rgb_stride,
b_ptr + rgb_stride, step,
dst_y + picture->y_stride, width, rg); dst_y + picture->y_stride, width, rg);
} }
dst_y += 2 * picture->y_stride; dst_y += 2 * picture->y_stride;
if (has_alpha) { if (has_alpha) {
rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride, rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2,
width, 2,
dst_a, picture->a_stride); dst_a, picture->a_stride);
dst_a += 2 * picture->a_stride; dst_a += 2 * picture->a_stride;
} }
// Collect averaged R/G/B(/A) // Collect averaged R/G/B(/A)
if (!rows_have_alpha) { if (!rows_have_alpha) {
AccumulateRGB(r_ptr + off1, g_ptr + off1, b_ptr + off1, AccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, width);
step, rgb_stride, tmp_rgb, width);
} else { } else {
AccumulateRGBA(r_ptr + off1, g_ptr + off1, b_ptr + off1, a_ptr + off1, AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, width);
rgb_stride, tmp_rgb, width);
} }
// Convert to U/V // Convert to U/V
if (rg == NULL) { if (rg == NULL) {
@ -939,31 +937,33 @@ static int ImportYUVAFromRGBA(const uint8_t* const r_ptr,
} }
dst_u += picture->uv_stride; dst_u += picture->uv_stride;
dst_v += picture->uv_stride; dst_v += picture->uv_stride;
r_ptr += 2 * rgb_stride;
b_ptr += 2 * rgb_stride;
g_ptr += 2 * rgb_stride;
if (has_alpha) a_ptr += 2 * rgb_stride;
} }
if (height & 1) { // extra last row if (height & 1) { // extra last row
const int off = 2 * y * rgb_stride;
int row_has_alpha = has_alpha; int row_has_alpha = has_alpha;
if (use_dsp) { if (use_dsp) {
if (r_ptr < b_ptr) { if (r_ptr < b_ptr) {
WebPConvertRGB24ToY(r_ptr + off, dst_y, width); WebPConvertRGB24ToY(r_ptr, dst_y, width);
} else { } else {
WebPConvertBGR24ToY(b_ptr + off, dst_y, width); WebPConvertBGR24ToY(b_ptr, dst_y, width);
} }
} else { } else {
ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step, ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
dst_y, width, rg);
} }
if (row_has_alpha) { if (row_has_alpha) {
row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0); row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0);
} }
// Collect averaged R/G/B(/A) // Collect averaged R/G/B(/A)
if (!row_has_alpha) { if (!row_has_alpha) {
// Collect averaged R/G/B // Collect averaged R/G/B
AccumulateRGB(r_ptr + off, g_ptr + off, b_ptr + off, AccumulateRGB(r_ptr, g_ptr, b_ptr, step, /* rgb_stride = */ 0,
step, /* rgb_stride = */ 0, tmp_rgb, width); tmp_rgb, width);
} else { } else {
AccumulateRGBA(r_ptr + off, g_ptr + off, b_ptr + off, a_ptr + off, AccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /* rgb_stride = */ 0,
/* rgb_stride = */ 0, tmp_rgb, width); tmp_rgb, width);
} }
if (rg == NULL) { if (rg == NULL) {
WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width); WebPConvertRGBA32ToUV(tmp_rgb, dst_u, dst_v, uv_width);