diff --git a/png.c b/png.c index c99c40d9c..605f50e9b 100644 --- a/png.c +++ b/png.c @@ -2402,12 +2402,14 @@ png_max_pixel_block(png_const_structrp png_ptr) void /* PRIVATE */ png_copy_row(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp, png_uint_32 x/*in INPUT*/, png_uint_32 width/*of INPUT*/, - unsigned int pixel_depth, int clear/*clear the final byte*/) + unsigned int pixel_depth, int clear/*clear the final byte*/, int x_in_dest) /* Copy the row in row_buffer; this is the non-interlaced copy used in both - * the read and write code. + * the read and write code. 'x_in_dest' specifies whether the 'x' applies to + * the destination (sp->dp[x], x_in_dest tru) or the source (sp[x]->dp, + * x_in_dest false). */ { - png_alloc_size_t cb; + png_alloc_size_t cb, offset; unsigned int remaining; /* remaining bits in a partial byte */ /* Copy 'cb' pixels, but take care with the last byte because it may @@ -2419,28 +2421,34 @@ png_copy_row(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp, case 1U: remaining = width & 7U; debug((x & 7U) == 0U); cb = width >> 3; - dp += x >> 3; + offset = x >> 3; break; case 2U: remaining = (width << 1) & 6U; debug((x & 3U) == 0U); cb = width >> 2; - dp += x >> 2; + offset = x >> 2; break; case 4U: remaining = (width << 2) & 4U; debug((x & 1U) == 0U); cb = width >> 1; - dp += x >> 1; + offset = x >> 1; break; case 8U: remaining = 0U; cb = width; - dp += x; + offset = x; break; default: remaining = 0U; cb = png_calc_rowbytes(png_ptr, pixel_depth, width); - dp += png_calc_rowbytes(png_ptr, pixel_depth, x); + offset = png_calc_rowbytes(png_ptr, pixel_depth, x); break; } + if (x_in_dest) + dp += offset; + + else + sp += offset; + memcpy(dp, sp, cb); if (remaining > 0U) diff --git a/pngpriv.h b/pngpriv.h index 10b4bb9c4..a7c222ce8 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -943,13 +943,15 @@ PNG_INTERNAL_FUNCTION(png_alloc_size_t,png_calc_rowbytes, PNG_INTERNAL_FUNCTION(unsigned int,png_max_pixel_block, (png_const_structrp png_ptr),PNG_EMPTY); -/* Copy the row in row_buffer; this is the non-interlaced copy used in both - * the read and write code. +/* Copy the row in row_buffer; this is the non-interlaced copy used in both the + * read and write code. 'x_in_dest' specifies whether the 'x' applies to + * the destination (sp->dp[x], x_in_dest tru) or the source (sp[x]->dp, + * x_in_dest false). */ PNG_INTERNAL_FUNCTION(void, png_copy_row,(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp, png_uint_32 x/*in INPUT*/, png_uint_32 width/*of INPUT*/, unsigned int pixel_depth, - int clear/*clear the final byte*/),PNG_EMPTY); + int clear/*clear the final byte*/, int x_in_dest),PNG_EMPTY); /* Zlib support */ #define PNG_UNEXPECTED_ZLIB_RETURN (-7) diff --git a/pngrutil.c b/pngrutil.c index 7bb53bafa..42d3ea48d 100644 --- a/pngrutil.c +++ b/pngrutil.c @@ -3114,7 +3114,7 @@ copy_row(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp, # else PNG_PIXEL_DEPTH(*png_ptr), # endif - clear/*clear partial byte at end of row*/); + clear/*clear partial byte at end of row*/, 1/*sp -> dp[x]*/); } #ifdef PNG_READ_INTERLACING_SUPPORTED diff --git a/pngwrite.c b/pngwrite.c index 3a1ffbb98..e41dbb873 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -720,7 +720,8 @@ copy_row(png_const_structrp png_ptr, png_bytep row_buffer, unsigned int pixel_depth) { /* Copy row[x..x+count] pixels to row_buffer. */ - png_copy_row(png_ptr, row_buffer, row, x, count, pixel_depth, 1/*clear*/); + png_copy_row(png_ptr, row_buffer, row, x, count, pixel_depth, 1/*clear*/, + 0/* x_in_dest; row[x]->row_buffer */); } #endif /* WRITE_TRANSFORMS */