h2v2_merged_upsample_internal (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr0, outptr1; JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; JLONG * Crgtab = upsample->Cr_g_tab; JLONG * Cbgtab = upsample->Cb_g_tab; SHIFT_TEMPS inptr00 = input_buf[0][in_row_group_ctr*2]; inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr0 = output_buf[0]; outptr1 = output_buf[1]; /* Loop for each group of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr0[RGB_ALPHA] = 0xFF; #endif outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr00++); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr0[RGB_ALPHA] = 0xFF; #endif outptr0 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr1[RGB_ALPHA] = 0xFF; #endif outptr1 += RGB_PIXELSIZE; y = GETJSAMPLE(*inptr01++); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr1[RGB_ALPHA] = 0xFF; #endif outptr1 += RGB_PIXELSIZE; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr00); outptr0[RGB_RED] = range_limit[y + cred]; outptr0[RGB_GREEN] = range_limit[y + cgreen]; outptr0[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr0[RGB_ALPHA] = 0xFF; #endif y = GETJSAMPLE(*inptr01); outptr1[RGB_RED] = range_limit[y + cred]; outptr1[RGB_GREEN] = range_limit[y + cgreen]; outptr1[RGB_BLUE] = range_limit[y + cblue]; #ifdef RGB_ALPHA outptr1[RGB_ALPHA] = 0xFF; #endif } }
h2v2_merged_upsample_565D (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr0, outptr1; JSAMPROW inptr00, inptr01, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; INT32 d1 = dither_matrix[(cinfo->output_scanline+1) & DITHER_MASK]; unsigned int r, g, b; INT32 rgb; SHIFT_TEMPS inptr00 = input_buf[0][in_row_group_ctr*2]; inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr0 = output_buf[0]; outptr1 = output_buf[1]; /* Loop for each group of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; /* Fetch 4 Y values and emit 4 pixels */ y = GETJSAMPLE(*inptr00++); r = range_limit[DITHER_565_R(y + cred, d0)]; g = range_limit[DITHER_565_G(y + cgreen, d0)]; b = range_limit[DITHER_565_B(y + cblue, d0)]; d0 = DITHER_ROTATE(d0); rgb = PACK_SHORT_565(r, g, b); y = GETJSAMPLE(*inptr00++); r = range_limit[DITHER_565_R(y + cred, d1)]; g = range_limit[DITHER_565_G(y + cgreen, d1)]; b = range_limit[DITHER_565_B(y + cblue, d1)]; d1 = DITHER_ROTATE(d1); rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b)); WRITE_TWO_PIXELS(outptr0, rgb); outptr0 += 4; y = GETJSAMPLE(*inptr01++); r = range_limit[DITHER_565_R(y + cred, d0)]; g = range_limit[DITHER_565_G(y + cgreen, d0)]; b = range_limit[DITHER_565_B(y + cblue, d0)]; d0 = DITHER_ROTATE(d0); rgb = PACK_SHORT_565(r, g, b); y = GETJSAMPLE(*inptr01++); r = range_limit[DITHER_565_R(y + cred, d1)]; g = range_limit[DITHER_565_G(y + cgreen, d1)]; b = range_limit[DITHER_565_B(y + cblue, d1)]; d1 = DITHER_ROTATE(d1); rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b)); WRITE_TWO_PIXELS(outptr1, rgb); outptr1 += 4; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr00); r = range_limit[DITHER_565_R(y + cred, d0)]; g = range_limit[DITHER_565_G(y + cgreen, d0)]; b = range_limit[DITHER_565_B(y + cblue, d0)]; rgb = PACK_SHORT_565(r, g, b); *(INT16*)outptr0 = rgb; y = GETJSAMPLE(*inptr01); r = range_limit[DITHER_565_R(y + cred, d1)]; g = range_limit[DITHER_565_G(y + cgreen, d1)]; b = range_limit[DITHER_565_B(y + cblue, d1)]; rgb = PACK_SHORT_565(r, g, b); *(INT16*)outptr1 = rgb; } }
quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register LOCFSERROR cur; /* current error or pixel value */ LOCFSERROR belowerr; /* error for pixel below cur */ LOCFSERROR bpreverr; /* error for below/prev col */ LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ int dirnc; /* dir * nc */ int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ jzero_far((void FAR *) output_buf[row], (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ input_ptr += (width-1) * nc; /* so point to rightmost pixel */ output_ptr += width-1; dir = -1; dirnc = -nc; errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ } else { /* work left to right in this row */ dir = 1; dirnc = nc; errorptr = cquantize->fserrors[ci]; /* => entry before first column */ } colorindex_ci = cquantize->colorindex[ci]; colormap_ci = cquantize->sv_colormap[ci]; /* Preset error values: no error propagated to first pixel from left */ cur = 0; /* and no error propagated to row below yet */ belowerr = bpreverr = 0; for (col = width; col > 0; col--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr + cur); cur += delta; /* form error * 5 */ bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ input_ptr += dirnc; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); } }
h2v1_merged_upsample_565 (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, JSAMPARRAY output_buf) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; register int y, cred, cgreen, cblue; int cb, cr; register JSAMPROW outptr; JSAMPROW inptr0, inptr1, inptr2; JDIMENSION col; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; int * Crrtab = upsample->Cr_r_tab; int * Cbbtab = upsample->Cb_b_tab; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * Cbgtab = upsample->Cb_g_tab; unsigned int r, g, b; INT32 rgb; SHIFT_TEMPS inptr0 = input_buf[0][in_row_group_ctr]; inptr1 = input_buf[1][in_row_group_ctr]; inptr2 = input_buf[2][in_row_group_ctr]; outptr = output_buf[0]; /* Loop for each pair of output pixels */ for (col = cinfo->output_width >> 1; col > 0; col--) { /* Do the chroma part of the calculation */ cb = GETJSAMPLE(*inptr1++); cr = GETJSAMPLE(*inptr2++); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; /* Fetch 2 Y values and emit 2 pixels */ y = GETJSAMPLE(*inptr0++); r = range_limit[y + cred]; g = range_limit[y + cgreen]; b = range_limit[y + cblue]; rgb = PACK_SHORT_565(r, g, b); y = GETJSAMPLE(*inptr0++); r = range_limit[y + cred]; g = range_limit[y + cgreen]; b = range_limit[y + cblue]; rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b)); WRITE_TWO_PIXELS(outptr, rgb); outptr += 4; } /* If image width is odd, do the last output column separately */ if (cinfo->output_width & 1) { cb = GETJSAMPLE(*inptr1); cr = GETJSAMPLE(*inptr2); cred = Crrtab[cr]; cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); cblue = Cbbtab[cb]; y = GETJSAMPLE(*inptr0); r = range_limit[y + cred]; g = range_limit[y + cgreen]; b = range_limit[y + cblue]; rgb = PACK_SHORT_565(r, g, b); *(INT16*)outptr = rgb; } }
void il_quantize_fs_dither(il_container *ic, const uint8 *mask, const uint8 *input_buf, int x_offset, uint8 XP_HUGE *output_buf, int width) { my_cquantize_ptr cquantize; register LOCFSERROR r_cur, g_cur, b_cur; /* current error or pixel value */ LOCFSERROR r_belowerr, g_belowerr, b_belowerr; /* error for pixel below cur */ LOCFSERROR r_bpreverr, g_bpreverr, b_bpreverr; /* error for below/prev col */ LOCFSERROR r_bnexterr, g_bnexterr, b_bnexterr; /* error for below/next col */ LOCFSERROR delta; FSERRPTR r_errorptr, g_errorptr, b_errorptr; /* fserrors[] at column before current */ const JSAMPLE* input_ptr; JSAMPLE XP_HUGE * output_ptr; IL_ColorMap *cmap = &ic->image->header.color_space->cmap; IL_RGB *map = cmap->map; /* The colormap array. */ IL_RGB *map_entry; /* Current entry in the colormap. */ uint8 *lookup_table = cmap->table; /* Lookup table for the colormap. */ const uint8 *maskp; uint8 map_index; int dir; /* 1 for left-to-right, -1 for right-to-left */ JDIMENSION col; JSAMPLE *range_limit = the_sample_range_limit; SHIFT_TEMPS cquantize = (my_cquantize_ptr) ic->quantize; output_buf += x_offset; /* Initialize output values to 0 so can process components separately */ if (mask) { output_ptr = output_buf; maskp = mask; for (col = width; col > 0; col--) *output_ptr++ &= ~*maskp++; } else { XP_BZERO((void XP_HUGE *) output_buf, (size_t) (width * SIZEOF(JSAMPLE))); } input_ptr = input_buf; output_ptr = output_buf; maskp = mask; if (cquantize->on_odd_row) { int total_offset; /* work right to left in this row */ input_ptr += 3 * width - 1; /* so point to the blue sample of the rightmost pixel */ output_ptr += width-1; dir = -1; /* => entry after last column */ total_offset = x_offset + (width + 1); r_errorptr = cquantize->fserrors[0] + total_offset; g_errorptr = cquantize->fserrors[1] + total_offset; b_errorptr = cquantize->fserrors[2] + total_offset; maskp += (width - 1); } else { /* work left to right in this row */ dir = 1; /* => entry before first column */ r_errorptr = cquantize->fserrors[0] + x_offset; g_errorptr = cquantize->fserrors[1] + x_offset; b_errorptr = cquantize->fserrors[2] + x_offset; } /* Preset error values: no error propagated to first pixel from left */ r_cur = g_cur = b_cur = 0; /* and no error propagated to row below yet */ r_belowerr = g_belowerr = b_belowerr = 0; r_bpreverr = g_bpreverr = b_bpreverr = 0; for (col = width; col > 0; col--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ r_cur = RIGHT_SHIFT(r_cur + r_errorptr[dir] + 8, 4); g_cur = RIGHT_SHIFT(g_cur + g_errorptr[dir] + 8, 4); b_cur = RIGHT_SHIFT(b_cur + b_errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ if (dir > 0) { r_cur += GETJSAMPLE(*input_ptr); r_cur = GETJSAMPLE(range_limit[r_cur]); input_ptr++; g_cur += GETJSAMPLE(*input_ptr); g_cur = GETJSAMPLE(range_limit[g_cur]); input_ptr++; b_cur += GETJSAMPLE(*input_ptr); b_cur = GETJSAMPLE(range_limit[b_cur]); input_ptr++; } else { b_cur += GETJSAMPLE(*input_ptr); b_cur = GETJSAMPLE(range_limit[b_cur]); input_ptr--; g_cur += GETJSAMPLE(*input_ptr); g_cur = GETJSAMPLE(range_limit[g_cur]); input_ptr--; r_cur += GETJSAMPLE(*input_ptr); r_cur = GETJSAMPLE(range_limit[r_cur]); input_ptr--; } /* Select output value, accumulate into output code for this pixel */ map_index = COLORMAP_INDEX(lookup_table, r_cur, g_cur, b_cur); if (mask) { if (*maskp) *output_ptr = map_index; maskp += dir; } else { *output_ptr = map_index; } /* Compute the actual representation error at this pixel */ map_entry = map + map_index; r_cur -= GETJSAMPLE(map_entry->red); g_cur -= GETJSAMPLE(map_entry->green); b_cur -= GETJSAMPLE(map_entry->blue); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ r_bnexterr = r_cur; delta = r_cur * 2; r_cur += delta; /* form error * 3 */ r_errorptr[0] = (FSERROR) (r_bpreverr + r_cur); r_cur += delta; /* form error * 5 */ r_bpreverr = r_belowerr + r_cur; r_belowerr = r_bnexterr; r_cur += delta; /* form error * 7 */ g_bnexterr = g_cur; delta = g_cur * 2; g_cur += delta; /* form error * 3 */ g_errorptr[0] = (FSERROR) (g_bpreverr + g_cur); g_cur += delta; /* form error * 5 */ g_bpreverr = g_belowerr + g_cur; g_belowerr = g_bnexterr; g_cur += delta; /* form error * 7 */ b_bnexterr = b_cur; delta = b_cur * 2; b_cur += delta; /* form error * 3 */ b_errorptr[0] = (FSERROR) (b_bpreverr + b_cur); b_cur += delta; /* form error * 5 */ b_bpreverr = b_belowerr + b_cur; b_belowerr = b_bnexterr; b_cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. * Note: the input_ptr has already been advanced. */ output_ptr += dir; /* advance output ptr to next column */ r_errorptr += dir; /* advance errorptr to current column */ g_errorptr += dir; /* advance errorptr to current column */ b_errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ r_errorptr[0] = (FSERROR) r_bpreverr; /* unload prev err into array */ g_errorptr[0] = (FSERROR) g_bpreverr; /* unload prev err into array */ b_errorptr[0] = (FSERROR) b_bpreverr; /* unload prev err into array */ cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); }