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); } }
get_8bit_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 8-bit colormap indexes */ { bmp_source_ptr source = (bmp_source_ptr)sinfo; register JSAMPARRAY colormap = source->colormap; int cmaplen = source->cmap_length; JSAMPARRAY image_ptr; register int t; register JSAMPROW inptr, outptr; register JDIMENSION col; if (source->use_inversion_array) { /* Fetch next row from virtual array */ source->source_row--; image_ptr = (*cinfo->mem->access_virt_sarray) ((j_common_ptr)cinfo, source->whole_image, source->source_row, (JDIMENSION)1, FALSE); inptr = image_ptr[0]; } else { if (!ReadOK(source->pub.input_file, source->iobuffer, source->row_width)) ERREXIT(cinfo, JERR_INPUT_EOF); inptr = source->iobuffer; } /* Expand the colormap indexes to real data */ outptr = source->pub.buffer[0]; if (cinfo->in_color_space == JCS_GRAYSCALE) { for (col = cinfo->image_width; col > 0; col--) { t = GETJSAMPLE(*inptr++); if (t >= cmaplen) ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); *outptr++ = colormap[0][t]; } } else if (cinfo->in_color_space == JCS_CMYK) { for (col = cinfo->image_width; col > 0; col--) { t = GETJSAMPLE(*inptr++); if (t >= cmaplen) ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); rgb_to_cmyk(colormap[0][t], colormap[1][t], colormap[2][t], outptr, outptr + 1, outptr + 2, outptr + 3); outptr += 4; } } else { register int rindex = rgb_red[cinfo->in_color_space]; register int gindex = rgb_green[cinfo->in_color_space]; register int bindex = rgb_blue[cinfo->in_color_space]; register int aindex = alpha_index[cinfo->in_color_space]; register int ps = rgb_pixelsize[cinfo->in_color_space]; if (aindex >= 0) { for (col = cinfo->image_width; col > 0; col--) { t = GETJSAMPLE(*inptr++); if (t >= cmaplen) ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); outptr[rindex] = colormap[0][t]; outptr[gindex] = colormap[1][t]; outptr[bindex] = colormap[2][t]; outptr[aindex] = 0xFF; outptr += ps; } } else { for (col = cinfo->image_width; col > 0; col--) { t = GETJSAMPLE(*inptr++); if (t >= cmaplen) ERREXIT(cinfo, JERR_BMP_OUTOFRANGE); outptr[rindex] = colormap[0][t]; outptr[gindex] = colormap[1][t]; outptr[bindex] = colormap[2][t]; outptr += ps; } } } return 1; }
LOCAL void extract_block (JSAMPARRAY input_data, int start_row, long start_col, JBLOCK output_data, QUANT_TBL_PTR quanttbl) /* Extract one 8x8 block from the specified location in the sample array; */ /* perform forward DCT, quantization scaling, and zigzag reordering on it. */ { /* This routine is heavily used, so it's worth coding it tightly. */ DCTBLOCK block; #ifdef DCT_ERR_STATS DCTBLOCK svblock; /* saves input data for comparison */ #endif { register JSAMPROW elemptr; register DCTELEM *localblkptr = block; register int elemr; for (elemr = DCTSIZE; elemr > 0; elemr--) { elemptr = input_data[start_row++] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *localblkptr++ = (DCTELEM) (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); } } #endif } } #ifdef DCT_ERR_STATS MEMCOPY(svblock, block, SIZEOF(DCTBLOCK)); #endif j_fwd_dct(block); { register JCOEF temp; register QUANT_VAL qval; register int i; for (i = 0; i < DCTSIZE2; i++) { qval = *quanttbl++; temp = (JCOEF) block[ZAG[i]]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) (a >= b) ? (a /= b) : (a = 0) #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } *output_data++ = temp; }
finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { rle_dest_ptr dest = (rle_dest_ptr) dinfo; rle_hdr header; /* Output file information */ rle_pixel **rle_row, *red, *green, *blue; JSAMPROW output_row; char cmapcomment[80]; int row, col; int ci; #ifdef LIBJPEG_PROGRESS_REPORT cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; #endif /* Initialize the header info */ header = *rle_hdr_init(NULL); header.rle_file = dest->pub.output_file; header.xmin = 0; header.xmax = cinfo->output_width - 1; header.ymin = 0; header.ymax = cinfo->output_height - 1; header.alpha = 0; header.ncolors = cinfo->output_components; for (ci = 0; ci < cinfo->output_components; ci++) { RLE_SET_BIT(header, ci); } if (cinfo->quantize_colors) { header.ncmap = cinfo->out_color_components; header.cmaplen = CMAPBITS; header.cmap = dest->colormap; /* Add a comment to the output image with the true colormap length. */ sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors); rle_putcom(cmapcomment, &header); } /* Emit the RLE header and color map (if any) */ rle_put_setup(&header); /* Now output the RLE data from our virtual array. * We assume here that (a) rle_pixel is represented the same as JSAMPLE, * and (b) we are not on a machine where FAR pointers differ from regular. */ #ifdef LIBJPEG_PROGRESS_REPORT if (progress != NULL) { progress->pub.pass_limit = cinfo->output_height; progress->pub.pass_counter = 0; (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); } #endif if (cinfo->output_components == 1) { for (row = cinfo->output_height-1; row >= 0; row--) { rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, dest->image, (JDIMENSION) row, (JDIMENSION) 1, FALSE); rle_putrow(rle_row, (int) cinfo->output_width, &header); #ifdef LIBJPEG_PROGRESS_REPORT if (progress != NULL) { progress->pub.pass_counter++; (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); } #endif } } else { for (row = cinfo->output_height-1; row >= 0; row--) { rle_row = (rle_pixel **) dest->rle_row; output_row = * (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, dest->image, (JDIMENSION) row, (JDIMENSION) 1, FALSE); red = rle_row[0]; green = rle_row[1]; blue = rle_row[2]; for (col = cinfo->output_width; col > 0; col--) { *red++ = GETJSAMPLE(*output_row++); *green++ = GETJSAMPLE(*output_row++); *blue++ = GETJSAMPLE(*output_row++); } rle_putrow(rle_row, (int) cinfo->output_width, &header); #ifdef LIBJPEG_PROGRESS_REPORT if (progress != NULL) { progress->pub.pass_counter++; (*progress->pub.progress_monitor) ((j_common_ptr) cinfo); } #endif } } #ifdef LIBJPEG_PROGRESS_REPORT if (progress != NULL) progress->completed_extra_passes++; #endif /* Emit file trailer */ rle_puteof(&header); fflush(dest->pub.output_file); if (ferror(dest->pub.output_file)) ERREXIT(cinfo, JERR_FILE_WRITE); }
start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { rle_dest_ptr dest = (rle_dest_ptr) dinfo; size_t cmapsize; int i, ci; #ifdef LIBJPEG_PROGRESS_REPORT cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; #endif /* * Make sure the image can be stored in RLE format. * * - RLE stores image dimensions as *signed* 16 bit integers. JPEG * uses unsigned, so we have to check the width. * * - Colorspace is expected to be grayscale or RGB. * * - The number of channels (components) is expected to be 1 (grayscale/ * pseudocolor) or 3 (truecolor/directcolor). * (could be 2 or 4 if using an alpha channel, but we aren't) */ if (cinfo->output_width > 32767 || cinfo->output_height > 32767) ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width, cinfo->output_height); if (cinfo->out_color_space != JCS_GRAYSCALE && cinfo->out_color_space != JCS_RGB) ERREXIT(cinfo, JERR_RLE_COLORSPACE); if (cinfo->output_components != 1 && cinfo->output_components != 3) ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components); /* Convert colormap, if any, to RLE format. */ dest->colormap = NULL; if (cinfo->quantize_colors) { /* Allocate storage for RLE-style cmap, zero any extra entries */ cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map); dest->colormap = (rle_map *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize); MEMZERO(dest->colormap, cmapsize); /* Save away data in RLE format --- note 8-bit left shift! */ /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */ for (ci = 0; ci < cinfo->out_color_components; ci++) { for (i = 0; i < cinfo->actual_number_of_colors; i++) { dest->colormap[ci * CMAPLENGTH + i] = GETJSAMPLE(cinfo->colormap[ci][i]) << 8; } } } /* Set the output buffer to the first row */ dest->pub.buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE); dest->pub.buffer_height = 1; dest->pub.put_pixel_rows = rle_put_pixel_rows; #ifdef LIBJPEG_PROGRESS_REPORT if (progress != NULL) { progress->total_extra_passes++; /* count file writing as separate pass */ } #endif }
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); }
METHODDEF void fullsize_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols); /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for(outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; above_ptr = input_data[outrow - 1]; below_ptr = input_data[outrow + 1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for(colctr = output_cols - 2; colctr > 0; colctr--) { membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE)((membersum + 32768) >> 16); } }
jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) { DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; DCTELEM tmp10, tmp11, tmp12, tmp13; DCTELEM z1, z2, z3, z4, z5, z11, z13; DCTELEM *dataptr; JSAMPROW elemptr; int ctr; SHIFT_TEMPS /* Pass 1: process rows. */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Load data into workspace */ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]); tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]); tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]); tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]); tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]); tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]); tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]); tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]); /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Apply unsigned->signed conversion */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } }
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; INT32 * Crgtab = upsample->Cr_g_tab; INT32 * 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; } }
METHODDEF void h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 register int thiscolsum, lastcolsum, nextcolsum; #else register INT32 thiscolsum, lastcolsum, nextcolsum; #endif register JDIMENSION colctr; int inrow, outrow, v; inrow = outrow = 0; while(outrow < cinfo->max_v_samp_factor) { for(v = 0; v < 2; v++) { /* inptr0 points to nearest input row, inptr1 points to next nearest */ inptr0 = input_data[inrow]; if(v == 0) /* next nearest is row above */ { inptr1 = input_data[inrow - 1]; } else /* next nearest is row below */ { inptr1 = input_data[inrow + 1]; } outptr = output_data[outrow++]; /* Special case for first column */ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE)((thiscolsum * 4 + 8) >> 4); *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for(colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ *outptr++ = (JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE)((thiscolsum * 4 + 7) >> 4); } inrow++; } }
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; } }
write_colormap_buf (j_decompress_ptr cinfo, bmp_dest_ptr dest, int map_colors, int map_entry_size,char *buf) { JSAMPARRAY colormap = cinfo->colormap; int num_colors = cinfo->actual_number_of_colors; FILE * outfile = dest->pub.output_file; JSAMPARRAY outbuffer= dest->pub.buffer; int i,k=54; if (colormap != NULL) { if (cinfo->out_color_components == 3) { /* Normal case with RGB colormap */ for (i = 0; i < num_colors; i++) { *(buf+k)=GETJSAMPLE(colormap[2][i]); k++; *(buf+k)=GETJSAMPLE(colormap[1][i]); k++; *(buf+k)=GETJSAMPLE(colormap[0][i]); k++; if (map_entry_size == 4){ //putc(0, outfile); *(buf+k)=0; k++; } } } else { /* Grayscale colormap (only happens with grayscale quantization) */ for (i = 0; i < num_colors; i++) { *(buf+k)=GETJSAMPLE(colormap[0][i]); k++; *(buf+k)=GETJSAMPLE(colormap[0][i]); k++; *(buf+k)=GETJSAMPLE(colormap[0][i]); k++; if (map_entry_size == 4) { *(buf+k)=0; k++; } } } } else { /* If no colormap, must be grayscale data. Generate a linear "map". */ for (i = 0; i < 256; i++) { *(buf+k)=i; k++; *(buf+k)=i; k++; *(buf+k)=i; k++; if (map_entry_size == 4) { //putc(0, outfile); *(buf+k)=0; k++; } } } /* Pad colormap with zeros to ensure specified number of colormap entries */ if (i > map_colors) ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i); for (; i < map_colors; i++) { *(buf+k)=0; k++; *(buf+k)=0; k++; *(buf+k)=0; k++; if (map_entry_size == 4) { //putc(0, outfile); *(buf+k)=0; k++; } } }
quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with ordered dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; int * dither; /* points to active row of dither matrix */ int row_index, col_index; /* current indexes into dither matrix */ int nc = cinfo->out_color_components; int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ 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))); row_index = cquantize->row_index; #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; colorindex_ci = cquantize->colorindex[ci]; dither = cquantize->odither[ci][row_index]; col_index = 0; #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ for (col = width; col > 0; col--) { /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE, * select output value, accumulate into output code for this pixel. * Range-limiting need not be done explicitly, as we have extended * the colorindex table to produce the right answers for out-of-range * inputs. The maximum dither is +- MAXJSAMPLE; this sets the * required amount of padding. */ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]]; input_ptr += nc; output_ptr++; col_index = (col_index + 1) & ODITHER_MASK; } } /* Advance row index for next row */ row_index = (row_index + 1) & ODITHER_MASK; cquantize->row_index = row_index; } }
jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col) { FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; FAST_FLOAT tmp10, tmp11, tmp12, tmp13; FAST_FLOAT z1, z2, z3, z4, z5, z11, z13; FAST_FLOAT *dataptr; JSAMPROW elemptr; int ctr; /* Pass 1: process rows. */ dataptr = data; for (ctr = 0; ctr < DCTSIZE; ctr++) { elemptr = sample_data[ctr] + start_col; /* Load data into workspace */ tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7])); tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7])); tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6])); tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6])); tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5])); tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5])); tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4])); tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4])); /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Apply unsigned->signed conversion. */ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */ dataptr[4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[2] = tmp13 + z1; /* phase 5 */ dataptr[6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[5] = z13 + z2; /* phase 6 */ dataptr[3] = z13 - z2; dataptr[1] = z11 + z4; dataptr[7] = z11 - z4; dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ dataptr = data; for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part */ tmp10 = tmp0 + tmp3; /* phase 2 */ tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ dataptr[DCTSIZE*4] = tmp10 - tmp11; z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ dataptr[DCTSIZE*6] = tmp13 - z1; /* Odd part */ tmp10 = tmp4 + tmp5; /* phase 2 */ tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; /* The rotator is modified from fig 4-8 to avoid extra negations. */ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */ z11 = tmp7 + z3; /* phase 5 */ z13 = tmp7 - z3; dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ dataptr[DCTSIZE*3] = z13 - z2; dataptr[DCTSIZE*1] = z11 + z4; dataptr[DCTSIZE*7] = z11 - z4; dataptr++; /* advance pointer to next column */ } }
METHODDEF void h2v2_smooth_downsample(j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols * 2); /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four * smoothed values. Each of the four member pixels contributes a fraction * (1-8*SF) to its own smoothed image and a fraction SF to each of the three * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final * output. The four corner-adjacent neighbor pixels contribute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for(outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow + 1]; above_ptr = input_data[inrow - 1]; below_ptr = input_data[inrow + 2]; /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for(colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ *outptr++ = (JSAMPLE)((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE)((membersum + 32768) >> 16); inrow += 2; } }
forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) /* This version is used for integer DCT implementations. */ { /* This routine is heavily used, so it's worth coding it tightly. */ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private; forward_DCT_method_ptr do_dct = fdct->do_dct; DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { /* Load data into workspace, applying unsigned->signed conversion */ { register DCTELEM *workspaceptr; register JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; } } #endif } } /* Perform the DCT */ (*do_dct) (workspace); /* Quantize/descale the coefficients, and store into coef_blocks[] */ { register DCTELEM temp, qval; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { qval = divisors[i]; temp = workspace[i]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } output_ptr[i] = (JCOEF) temp; } }
static int bmJpegRememberScanline( JSAMPARRAY pixel_data, struct jpeg_decompress_struct * cinfo ) { BmJpegInputSource * bjis= (BmJpegInputSource *)cinfo->src; unsigned char * to; register JSAMPROW ptr0; long col; switch( cinfo->out_color_space ) { case JCS_GRAYSCALE: switch( bjis->bjisBd.bdBitsPerSample ) { case 8: to= bjis->bjisBitmapBuffer+ bjis->bjisBd.bdBytesPerRow* (bjis->bjisRowsReceived++); ptr0 = pixel_data[0]; for ( col = 0; col < cinfo->image_width; col++ ) { *(to++)= GETJSAMPLE(*(ptr0++)); } break; default: LDEB(bjis->bjisBd.bdBitsPerSample); return -1; } break; case JCS_RGB: switch( bjis->bjisBd.bdBitsPerSample ) { case 8: to= bjis->bjisBitmapBuffer+ bjis->bjisBd.bdBytesPerRow* (bjis->bjisRowsReceived++); ptr0 = pixel_data[0]; for ( col = 0; col < cinfo->image_width; col++ ) { *(to++)= GETJSAMPLE(*(ptr0++)); /* red */ *(to++)= GETJSAMPLE(*(ptr0++)); /* green */ *(to++)= GETJSAMPLE(*(ptr0++)); /* blue */ } break; default: LDEB(bjis->bjisBd.bdBitsPerSample); return -1; } break; case JCS_UNKNOWN: case JCS_YCbCr: case JCS_YCCK: case JCS_CMYK: LDEB(cinfo->out_color_space); return -1; break; default: LDEB(cinfo->out_color_space); return -1; break; } return 0; }