diff options
author | Robin Watts <robin.watts@artifex.com> | 2013-08-15 12:23:23 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2013-08-16 10:25:23 +0100 |
commit | dde6d480e632eefbe5ccd42bc52b456582514a2a (patch) | |
tree | 9790f3ef9ec73f1b3810ac381c77d398f972b553 | |
parent | fd89aa38fb8a8af11ac6100ee5eebd9ce61091e3 (diff) | |
download | ghostpdl-dde6d480e632eefbe5ccd42bc52b456582514a2a.tar.gz |
Bug 694451: Solve problems with interpolated landscape images.
The portrait image code accumulates pixels into scanlines, and then
plots the whole scanline at once. The landscape image code follows
this lead by accumulating pixels into 'scancolumns' and then plots
the whole column at once.
Unfortunately this accumulation for columns goes wrong in the case
where we are working at < 8 bpp (as the transposition of rows to
columns fails). This causes images with runs of identical pixels in
to be 'squished' vertically.
We work around this here in the < 8 bpp case by repeating the writes
of each pixel so whole bytes are filled. This is suboptimal, but
doing anything else is tricky with the macros the way they are.
-rw-r--r-- | gs/base/gxiscale.c | 221 |
1 files changed, 161 insertions, 60 deletions
diff --git a/gs/base/gxiscale.c b/gs/base/gxiscale.c index 9ddd0a03b..921ef1e3b 100644 --- a/gs/base/gxiscale.c +++ b/gs/base/gxiscale.c @@ -1168,6 +1168,7 @@ image_render_interpolate_landscape(gx_image_enum * penum, const gs_color_space *pactual_cs; int bpp = dev->color_info.depth; uint raster = (bpp+7)>>3; + int bpp_rep = 8/bpp; bool device_color; if (penum->matrix.yx > 0) @@ -1273,38 +1274,88 @@ image_render_interpolate_landscape(gx_image_enum * penum, if (color_is_pure(&devc)) { /* Just pack colors into a scan line. */ gx_color_index color = devc.colors.pure; - /* Skip runs quickly for the common cases. */ - switch (spp_decode) { - case 1: - do { + if (bpp >= 8) { + /* Skip runs quickly for the common cases. */ + switch (spp_decode) { + case 1: + do { + LINE_ACCUM(color, bpp); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, psrc += 1; + } while (x < xe && psrc[-1] == psrc[0]); + break; + case 3: + do { + LINE_ACCUM(color, bpp); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, psrc += 3; + } while (x < xe && + psrc[-3] == psrc[0] && + psrc[-2] == psrc[1] && + psrc[-1] == psrc[2]); + break; + case 4: + do { + LINE_ACCUM(color, bpp); + x++, psrc += 4; + } while (x < xe && + psrc[-4] == psrc[0] && + psrc[-3] == psrc[1] && + psrc[-2] == psrc[2] && + psrc[-1] == psrc[3]); + break; + default: LINE_ACCUM(color, bpp); - vd_pixel(int2fixed(x), int2fixed(ry), color); - x++, psrc += 1; - } while (x < xe && psrc[-1] == psrc[0]); - break; - case 3: - do { - LINE_ACCUM(color, bpp); - vd_pixel(int2fixed(x), int2fixed(ry), color); - x++, psrc += 3; - } while (x < xe && - psrc[-3] == psrc[0] && - psrc[-2] == psrc[1] && - psrc[-1] == psrc[2]); - break; - case 4: - do { - LINE_ACCUM(color, bpp); - x++, psrc += 4; - } while (x < xe && - psrc[-4] == psrc[0] && - psrc[-3] == psrc[1] && - psrc[-2] == psrc[2] && - psrc[-1] == psrc[3]); - break; - default: - LINE_ACCUM(color, bpp); - x++, psrc += spp_decode; + x++, psrc += spp_decode; + } + } else { + /* Skip runs quickly for the common cases. */ + switch (spp_decode) { + case 1: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, psrc += 1; + } while (x < xe && psrc[-1] == psrc[0]); + break; + case 3: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, psrc += 3; + } while (x < xe && + psrc[-3] == psrc[0] && + psrc[-2] == psrc[1] && + psrc[-1] == psrc[2]); + break; + case 4: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + x++, psrc += 4; + } while (x < xe && + psrc[-4] == psrc[0] && + psrc[-3] == psrc[1] && + psrc[-2] == psrc[2] && + psrc[-1] == psrc[3]); + break; + default: + { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + x++, psrc += spp_decode; + } + } } } else { int rcode; @@ -1381,6 +1432,7 @@ image_render_interpolate_landscape_icc(gx_image_enum * penum, int dy; int bpp = dev->color_info.depth; uint raster = (bpp+7)>>3; + int bpp_rep = 8/bpp; unsigned short *p_cm_interp; byte *p_cm_buff = NULL; byte *psrc; @@ -1511,36 +1563,85 @@ image_render_interpolate_landscape_icc(gx_image_enum * penum, if (color_is_pure(&devc)) { /* Just pack colors into a scan line. */ gx_color_index color = devc.colors.pure; - /* Skip runs quickly for the common cases. */ - switch (spp_cm) { - case 1: - do { + if (bpp >= 8) + { + /* Skip runs quickly for the common cases. */ + switch (spp_cm) { + case 1: + do { + LINE_ACCUM(color, bpp); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, p_cm_interp += 1; + } while (x < xe && p_cm_interp[-1] == p_cm_interp[0]); + break; + case 3: + do { + LINE_ACCUM(color, bpp); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, p_cm_interp += 3; + } while (x < xe && p_cm_interp[-3] == p_cm_interp[0] && + p_cm_interp[-2] == p_cm_interp[1] && + p_cm_interp[-1] == p_cm_interp[2]); + break; + case 4: + do { + LINE_ACCUM(color, bpp); + x++, p_cm_interp += 4; + } while (x < xe && p_cm_interp[-4] == p_cm_interp[0] && + p_cm_interp[-3] == p_cm_interp[1] && + p_cm_interp[-2] == p_cm_interp[2] && + p_cm_interp[-1] == p_cm_interp[3]); + break; + default: LINE_ACCUM(color, bpp); - vd_pixel(int2fixed(x), int2fixed(ry), color); - x++, p_cm_interp += 1; - } while (x < xe && p_cm_interp[-1] == p_cm_interp[0]); - break; - case 3: - do { - LINE_ACCUM(color, bpp); - vd_pixel(int2fixed(x), int2fixed(ry), color); - x++, p_cm_interp += 3; - } while (x < xe && p_cm_interp[-3] == p_cm_interp[0] && - p_cm_interp[-2] == p_cm_interp[1] && - p_cm_interp[-1] == p_cm_interp[2]); - break; - case 4: - do { - LINE_ACCUM(color, bpp); - x++, p_cm_interp += 4; - } while (x < xe && p_cm_interp[-4] == p_cm_interp[0] && - p_cm_interp[-3] == p_cm_interp[1] && - p_cm_interp[-2] == p_cm_interp[2] && - p_cm_interp[-1] == p_cm_interp[3]); - break; - default: - LINE_ACCUM(color, bpp); - x++, p_cm_interp += spp_cm; + x++, p_cm_interp += spp_cm; + } + } else { + /* Skip runs quickly for the common cases. */ + switch (spp_cm) { + case 1: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, p_cm_interp += 1; + } while (x < xe && p_cm_interp[-1] == p_cm_interp[0]); + break; + case 3: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + vd_pixel(int2fixed(x), int2fixed(ry), color); + x++, p_cm_interp += 3; + } while (x < xe && p_cm_interp[-3] == p_cm_interp[0] && + p_cm_interp[-2] == p_cm_interp[1] && + p_cm_interp[-1] == p_cm_interp[2]); + break; + case 4: + do { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + x++, p_cm_interp += 4; + } while (x < xe && p_cm_interp[-4] == p_cm_interp[0] && + p_cm_interp[-3] == p_cm_interp[1] && + p_cm_interp[-2] == p_cm_interp[2] && + p_cm_interp[-1] == p_cm_interp[3]); + break; + default: + { + int count = bpp_rep; + do { + LINE_ACCUM(color, bpp); + } while (--count); + x++, p_cm_interp += spp_cm; + } + } } } else { int rcode; |