summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Cherepanov <alex.cherepanov@artifex.com>2012-02-23 01:25:59 -0500
committerChris Liddell <chris.liddell@artifex.com>2012-03-15 11:54:23 +0000
commit4c24e6805399d1ba304a0ae86307f71e8bec7f61 (patch)
tree955c0dbfccd23044d06d831abb43f858d91bbb85
parent9e526e8d747a1f7bdb00093174af7d725b255918 (diff)
Bug 692851: Fix OpenJpeg JPX with components > 1, and bps < 8
Fix packing of multi-component color values with bps < 8 into the output stream. This results in progressions on Bug691843.pdf, and minor differences in Bug690147.pdf
-rw-r--r--gs/base/sjpx_openjpeg.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/gs/base/sjpx_openjpeg.c b/gs/base/sjpx_openjpeg.c
index 4afd544e5..4e5fd619a 100644
--- a/gs/base/sjpx_openjpeg.c
+++ b/gs/base/sjpx_openjpeg.c
@@ -158,7 +158,7 @@ s_jpxd_ycc_to_rgb(stream_jpxd_state *state)
static int decode_image(stream_jpxd_state * const state)
{
opj_cio_t *cio = NULL;
- int numprimcomp = 0, alpha_comp = -1, compno;
+ int numprimcomp = 0, alpha_comp = -1, compno, rowbytes;
/* open a byte stream */
cio = opj_cio_open((opj_common_ptr)state->opj_dinfo_p, state->inbuf, state->inbuf_fill);
@@ -246,12 +246,13 @@ static int decode_image(stream_jpxd_state * const state)
else
state->out_numcomps = numprimcomp;
- /* round up bpp to multiple of 8, eg 12->16 */
- if ((state->colorspace != gs_jpx_cs_gray && !state->image->has_palette) || state->bpp>8)
- state->bpp = (state->bpp+7)/8*8;
+ /* round up bpp 12->16 */
+ if (state->bpp == 12)
+ state->bpp = 16;
/* calculate total data */
- state->totalbytes = state->width*state->height*state->bpp*state->out_numcomps/8;
+ rowbytes = (state->width*state->bpp*state->out_numcomps+7)/8;
+ state->totalbytes = rowbytes*state->height;
/* convert input from YCC to RGB */
if (state->image->color_space == CLRSPC_SYCC || state->image->color_space == CLRSPC_EYCC)
@@ -282,7 +283,7 @@ static int process_one_trunk(stream_jpxd_state * const state, stream_cursor_writ
/* read data from image to pw */
unsigned long out_size = pw->limit - pw->ptr;
int bytepp1 = state->bpp/8; /* bytes / pixel for one output component */
- int bytepp = state->out_numcomps*state->bpp/8; /* bytes / pixel all compoments */
+ int bytepp = state->out_numcomps*state->bpp/8; /* bytes / pixel all components */
unsigned long write_size = min(out_size-(bytepp?(out_size%bytepp):0), state->totalbytes-state->out_offset);
unsigned long in_offset = state->out_offset*8/state->bpp/state->out_numcomps; /* component data offset */
int shift_bit = state->bpp-state->image->comps[0].prec; /*difference between input and output bit-depth*/
@@ -335,21 +336,55 @@ static int process_one_trunk(stream_jpxd_state * const state, stream_cursor_writ
}
else
{
- /* only grayscale can have such bit-depth, also shift_bit = 0, bpp < 8 */
+ /* shift_bit = 0, bpp < 8 */
unsigned long image_total = state->width*state->height;
+ int bt=0; int bit_pos = 0;
+ int rowbytes = (state->width*state->bpp*state->out_numcomps+7)/8; /*row bytes */
+ int currowcnt = state->out_offset % rowbytes; /* number of bytes filled in current row */
+ int start_comp = (currowcnt*8) % img_numcomps; /* starting component for this round of output*/
+ if (start_comp != 0)
+ {
+ for (compno=start_comp; compno<img_numcomps; compno++)
+ {
+ if (state->img_offset < image_total)
+ {
+ bt <<= state->bpp;
+ bt += *(state->pdata[compno]-1) + state->sign_comps[compno];
+ }
+ bit_pos += state->bpp;
+ if (bit_pos >= 8)
+ {
+ *(pw->ptr++) = bt >> (bit_pos-8);
+ bit_pos -= 8;
+ bt &= (1<<(bit_pos-8))-1;
+ }
+ }
+ }
while (pw->ptr < pend)
{
- int bt=0;
- for (i=0; i<8/state->bpp; i++)
+ for (compno=0; compno<img_numcomps; compno++)
{
- bt = bt<<state->bpp;
- if (state->img_offset < image_total && !(i!=0 && state->img_offset % state->width == 0))
+ if (state->img_offset < image_total)
{
- bt += *(state->pdata[0]++) + state->sign_comps[0];
- state->img_offset++;
+ bt <<= state->bpp;
+ bt += *(state->pdata[compno]++) + state->sign_comps[compno];
}
- }
- *(pw->ptr++) = bt;
+ bit_pos += state->bpp;
+ if (bit_pos >= 8)
+ {
+ *(pw->ptr++) = bt >> (bit_pos-8);
+ bit_pos -= 8;
+ bt &= (1<<(bit_pos-8))-1;
+ }
+ }
+ state->img_offset++;
+ if (bit_pos != 0 && state->img_offset % state->width == 0)
+ {
+ /* row padding */
+ *(pw->ptr++) = bt << (8 - bit_pos);
+ bit_pos = 0;
+ bt = 0;
+ }
}
}
}