transencode_coef_controller (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; c_coef_ptr coef; JBLOCKROW buffer; int i; coef = (c_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_coef_controller)); lossyc->coef_private = (struct jpeg_c_coef_controller *) coef; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) { coef->dummy_buffer[i] = buffer + i; } }
transencode_coef_controller (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) { my_coef_ptr coef; JBLOCKROW buffer; int i; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; coef->pub.compress_data = compress_output; /* Save pointer to virtual arrays */ coef->whole_image = coef_arrays; /* Allocate and pre-zero space for dummy DCT blocks. */ buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->dummy_buffer[i] = buffer + i; } }
start_pass_1_quant (j_decompress_ptr cinfo, wxjpeg_boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; size_t arraysize; int i; /* Install my colormap. */ cinfo->colormap = cquantize->sv_colormap; cinfo->actual_number_of_colors = cquantize->sv_actual; /* Initialize for desired dithering mode. */ switch (cinfo->dither_mode) { case JDITHER_NONE: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = color_quantize3; else cquantize->pub.color_quantize = color_quantize; break; case JDITHER_ORDERED: if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = quantize3_ord_dither; else cquantize->pub.color_quantize = quantize_ord_dither; cquantize->row_index = 0; /* initialize state for ordered dither */ /* If user changed to ordered dither from another mode, * we must recreate the color index table with padding. * This will cost extra space, but probably isn't very likely. */ if (! cquantize->is_padded) create_colorindex(cinfo); /* Create ordered-dither tables if we didn't already. */ if (cquantize->odither[0] == NULL) create_odither_tables(cinfo); break; case JDITHER_FS: cquantize->pub.color_quantize = quantize_fs_dither; cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */ /* Allocate Floyd-Steinberg workspace if didn't already. */ if (cquantize->fserrors[0] == NULL) alloc_fs_workspace(cinfo); /* Initialize the propagated errors to zero. */ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); #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 (i = 0; i < cinfo->out_color_components; i++) jzero_far((void FAR *) cquantize->fserrors[i], arraysize); break; default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } }
/*METHODDEF*/static void 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; 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; 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; 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; } }
METHODDEF void disassemble_noninterleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[1]; long mcuindex; /* this is pretty easy since there is one component and one block per MCU */ /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ jzero_far((void FAR *) image_data[0][0], (size_t) (cinfo->MCUs_per_row * SIZEOF(JBLOCK))); for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spot in the image array for this MCU */ MCU_data[0] = image_data[0][0] + mcuindex; /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } }
METHODDEF void disassemble_interleaved_MCU (decompress_info_ptr cinfo, JBLOCKIMAGE image_data) { JBLOCKROW MCU_data[MAX_BLOCKS_IN_MCU]; long mcuindex; short blkn, ci, xpos, ypos; jpeg_component_info * compptr; JBLOCKROW image_ptr; /* Pre-zero the target area to speed up entropy decoder */ /* (we assume wholesale zeroing is faster than retail) */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { jzero_far((void FAR *) image_data[ci][ypos], (size_t) (cinfo->MCUs_per_row * compptr->MCU_width * SIZEOF(JBLOCK))); } } for (mcuindex = 0; mcuindex < cinfo->MCUs_per_row; mcuindex++) { /* Point to the proper spots in the image array for this MCU */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; for (ypos = 0; ypos < compptr->MCU_height; ypos++) { image_ptr = image_data[ci][ypos] + (mcuindex * compptr->MCU_width); for (xpos = 0; xpos < compptr->MCU_width; xpos++) { MCU_data[blkn] = image_ptr; image_ptr++; blkn++; } } } /* Fetch the coefficient data */ (*cinfo->methods->entropy_decode) (cinfo, MCU_data); } }
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; __boundcheck_metadata_store((void *)(&coef),(void *)((size_t)(&coef)+sizeof(coef)*8-1)); JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; __boundcheck_metadata_store((void *)(&last_iMCU_row),(void *)((size_t)(&last_iMCU_row)+sizeof(last_iMCU_row)*8-1)); JDIMENSION blocks_across; __boundcheck_metadata_store((void *)(&blocks_across),(void *)((size_t)(&blocks_across)+sizeof(blocks_across)*8-1)); JDIMENSION MCUs_across; __boundcheck_metadata_store((void *)(&MCUs_across),(void *)((size_t)(&MCUs_across)+sizeof(MCUs_across)*8-1)); JDIMENSION MCUindex; __boundcheck_metadata_store((void *)(&MCUindex),(void *)((size_t)(&MCUindex)+sizeof(MCUindex)*8-1)); int bi; __boundcheck_metadata_store((void *)(&bi),(void *)((size_t)(&bi)+sizeof(bi)*8-1)); int ci; __boundcheck_metadata_store((void *)(&ci),(void *)((size_t)(&ci)+sizeof(ci)*8-1)); int h_samp_factor; __boundcheck_metadata_store((void *)(&h_samp_factor),(void *)((size_t)(&h_samp_factor)+sizeof(h_samp_factor)*8-1)); int block_row; __boundcheck_metadata_store((void *)(&block_row),(void *)((size_t)(&block_row)+sizeof(block_row)*8-1)); int block_rows; __boundcheck_metadata_store((void *)(&block_rows),(void *)((size_t)(&block_rows)+sizeof(block_rows)*8-1)); int ndummy; __boundcheck_metadata_store((void *)(&ndummy),(void *)((size_t)(&ndummy)+sizeof(ndummy)*8-1)); JCOEF lastDC; __boundcheck_metadata_store((void *)(&lastDC),(void *)((size_t)(&lastDC)+sizeof(lastDC)*8-1)); jpeg_component_info *compptr; __boundcheck_metadata_store((void *)(&compptr),(void *)((size_t)(&compptr)+sizeof(compptr)*8-1)); JBLOCKARRAY buffer; __boundcheck_metadata_store((void *)(&buffer),(void *)((size_t)(&buffer)+sizeof(buffer)*8-1)); JBLOCKROW thisblockrow; __boundcheck_metadata_store((void *)(&thisblockrow),(void *)((size_t)(&thisblockrow)+sizeof(thisblockrow)*8-1)); JBLOCKROW lastblockrow; __boundcheck_metadata_store((void *)(&lastblockrow),(void *)((size_t)(&lastblockrow)+sizeof(lastblockrow)*8-1)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Align the virtual buffer for this component. */ buffer = (*(JBLOCKARRAY (*)(j_common_ptr, jvirt_barray_ptr, JDIMENSION, JDIMENSION, boolean))(__boundcheck_ptr_reference(258,28,"compress_first_pass",(void *)(cinfo->mem->access_virt_barray),(void *)cinfo->mem->access_virt_barray))) ((j_common_ptr) cinfo, coef->whole_image[_RV_insert_check(0,10,259,30,"compress_first_pass",ci)], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Count non-dummy DCT block rows in this iMCU row. */ if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = (*(JBLOCKROW *)(__boundcheck_ptr_reference(280,22,"compress_first_pass",(void *)(&buffer[0]),(void *)(&buffer[block_row])))); (*(void (*)(j_compress_ptr, jpeg_component_info *, JSAMPARRAY, JBLOCKROW, JDIMENSION, JDIMENSION, JDIMENSION))(__boundcheck_ptr_reference(281,22,"compress_first_pass",(void *)(cinfo->fdct->forward_DCT),(void *)cinfo->fdct->forward_DCT))) (cinfo, compptr, (*(JSAMPARRAY *)(__boundcheck_ptr_reference(282,8,"compress_first_pass",(void *)(&input_buf[0]),(void *)(&input_buf[ci])))), thisblockrow, (JDIMENSION) (block_row * DCTSIZE), (JDIMENSION) 0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = (*(JCOEF *)(__boundcheck_ptr_reference(289,11,"compress_first_pass",(void *)(&thisblockrow[-1][0]),(void *)(&thisblockrow[-1][0])))); for (bi = 0; bi < ndummy; bi++) { (*(JCOEF *)(__boundcheck_ptr_reference(291,4,"compress_first_pass",(void *)(&thisblockrow[bi][0]),(void *)(&thisblockrow[bi][0])))) = lastDC; } } } /* If at end of image, create dummy block rows as needed. * The tricky part here is that within each MCU, we want the DC values * of the dummy blocks to match the last real block's DC value. * This squeezes a few more bytes out of the resulting file... */ if (coef->iMCU_row_num == last_iMCU_row) { blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = (*(JBLOCKROW *)(__boundcheck_ptr_reference(305,17,"compress_first_pass",(void *)(&buffer[0]),(void *)(&buffer[block_row])))); lastblockrow = (*(JBLOCKROW *)(__boundcheck_ptr_reference(306,17,"compress_first_pass",(void *)(&buffer[0]),(void *)(&buffer[block_row - 1])))); jzero_far((void FAR *) thisblockrow, (size_t) (blocks_across * SIZEOF(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = (*(JCOEF *)(__boundcheck_ptr_reference(310,13,"compress_first_pass",(void *)(&lastblockrow[h_samp_factor - 1][0]),(void *)(&lastblockrow[h_samp_factor - 1][0])))); for (bi = 0; bi < h_samp_factor; bi++) { (*(JCOEF *)(__boundcheck_ptr_reference(312,6,"compress_first_pass",(void *)(&thisblockrow[bi][0]),(void *)(&thisblockrow[bi][0])))) = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } } } } /* NB: compress_output will increment iMCU_row_num if successful. * A suspension return will result in redoing all the work above next time. */ /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); }
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); } }
METHODDEF int decompress_onepass( j_decompress_ptr cinfo, JSAMPIMAGE output_buf ) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, ci, xindex, yindex, yoffset, useful_width; JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info * compptr; inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole iMCU row */ for ( yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++ ) { for ( MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++ ) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ jzero_far( (void FAR *) coef->MCU_buffer[0], (size_t) ( cinfo->blocks_in_MCU * SIZEOF( JBLOCK ) ) ); if ( !( *cinfo->entropy->decode_mcu )( cinfo, coef->MCU_buffer ) ) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkn gets * incremented past them!). Note the inner loop relies on having * allocated the MCU_buffer[] blocks sequentially. */ blkn = 0; /* index of current DCT block within MCU */ for ( ci = 0; ci < cinfo->comps_in_scan; ci++ ) { compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if ( !compptr->component_needed ) { blkn += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; useful_width = ( MCU_col_num < last_MCU_col ) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[ci] + yoffset * compptr->DCT_scaled_size; start_col = MCU_col_num * compptr->MCU_sample_width; for ( yindex = 0; yindex < compptr->MCU_height; yindex++ ) { if ( ( cinfo->input_iMCU_row < last_iMCU_row ) || ( yoffset + yindex < compptr->last_row_height ) ) { output_col = start_col; for ( xindex = 0; xindex < useful_width; xindex++ ) { ( *inverse_DCT )( cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn + xindex], output_ptr, output_col ); output_col += compptr->DCT_scaled_size; } } blkn += compptr->MCU_width; output_ptr += compptr->DCT_scaled_size; } } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ cinfo->output_iMCU_row++; if ( ++ ( cinfo->input_iMCU_row ) < cinfo->total_iMCU_rows ) { start_iMCU_row( cinfo ); return JPEG_ROW_COMPLETED; } /* Completed the scan */ ( *cinfo->inputctl->finish_input_pass )( cinfo ); return JPEG_SCAN_COMPLETED; }
JBLOCKARRAY my_memory_mgr::access_virt_barray(jvirt_barray_ptr ptr, JDIMENSION start_row, JDIMENSION num_rows, boolean writable) /* Access the part of a virtual block array starting at start_row */ /* and extending for num_rows rows. writable is true if */ /* caller intends to modify the accessed area. */ { JDIMENSION end_row = start_row + num_rows; JDIMENSION undef_row; /* debugging check */ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess || ptr->mem_buffer == NULL) cinfo->ERREXIT(JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || end_row > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) cinfo->ERREXIT(JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_barray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) end_row - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* Read in the selected part of the array. * During the initial write pass, we will do no actual read * because the selected part is all undefined. */ do_barray_io(cinfo, ptr, FALSE); } /* Ensure the accessed part of the array is defined; prezero if needed. * To improve locality of access, we only prezero the part of the array * that the caller is about to access, not the entire in-memory array. */ if (ptr->first_undef_row < end_row) { if (ptr->first_undef_row < start_row) { if (writable) /* writer skipped over a section of array */ cinfo->ERREXIT(JERR_BAD_VIRTUAL_ACCESS); undef_row = start_row; /* but reader is allowed to read ahead */ } else { undef_row = ptr->first_undef_row; } if (writable) ptr->first_undef_row = end_row; if (ptr->pre_zero) { size_t bytesperrow = (size_t) ptr->blocksperrow * sizeof(JBLOCK); undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */ end_row -= ptr->cur_start_row; while (undef_row < end_row) { jzero_far((void *) ptr->mem_buffer[undef_row], bytesperrow); undef_row++; } } else { if (! writable) /* reader looking at undefined data */ cinfo->ERREXIT(JERR_BAD_VIRTUAL_ACCESS); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); }
METHODDEF boolean decompress_read (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { // sm: this is a downcast from a pointer to jpeg_d_coef_controller // to a pointer to my_coef_controller_d, whose first field isa // jpeg_d_coef_controller structure; but there is no tag field.. my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset, num_MCU_rows; JDIMENSION total_width, remaining_rows, start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->MCU_row_num * compptr->v_samp_factor, TRUE); /* Entropy decoder expects buffer to be zeroed. */ total_width = (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor); for (yindex = 0; yindex < compptr->v_samp_factor; yindex++) { jzero_far((void FAR *) buffer[ci][yindex], (size_t) (total_width * SIZEOF(JBLOCK))); } } /* In an interleaved scan, we process exactly one MCU row. * In a noninterleaved scan, we need to process v_samp_factor MCU rows, * each of which contains a single block row. */ if (cinfo->comps_in_scan == 1) { compptr = cinfo->cur_comp_info[0]; num_MCU_rows = compptr->v_samp_factor; /* but watch out for the bottom of the image */ remaining_rows = cinfo->MCU_rows_in_scan - coef->MCU_row_num * compptr->v_samp_factor; if (remaining_rows < (JDIMENSION) num_MCU_rows) num_MCU_rows = (int) remaining_rows; } else { num_MCU_rows = 1; } /* Loop to process one whole iMCU row */ for (yoffset = 0; yoffset < num_MCU_rows; yoffset++) { for (MCU_col_num = 0; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { coef->MCU_buffer[blkn++] = buffer_ptr++; } } } /* Try to fetch the MCU. */ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { ERREXIT(cinfo, JERR_CANT_SUSPEND); /* not supported */ } } } coef->MCU_row_num++; return TRUE; }
METHODDEF boolean decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_MCU_row = cinfo->MCU_rows_in_scan - 1; int blkn, ci, xindex, yindex, useful_width; JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole MCU row */ for (MCU_col_num = coef->MCU_col_num; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ jzero_far((void FAR *) coef->MCU_buffer[0], (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; return with row unfinished */ coef->MCU_col_num = MCU_col_num; /* update my state */ return FALSE; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkn gets * incremented past them!). Note the inner loop relies on having * allocated the MCU_buffer[] blocks sequentially. */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { blkn += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; output_ptr = output_buf[ci]; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->MCU_row_num < last_MCU_row || yindex < compptr->last_row_height) { output_col = start_col; for (xindex = 0; xindex < useful_width; xindex++) { (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) coef->MCU_buffer[blkn+xindex], output_ptr, output_col); output_col += compptr->DCT_scaled_size; } } blkn += compptr->MCU_width; output_ptr += compptr->DCT_scaled_size; } } } /* We finished the row successfully */ coef->MCU_col_num = 0; /* prepare for next row */ coef->MCU_row_num++; return TRUE; }
consume_data_build_huffman_index_progressive(j_decompress_ptr cinfo, huffman_index *index, int current_scan) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; int factor = 4; // maximum factor is 4. for (ci = 0; ci < cinfo->comps_in_scan; ci++) factor = jmin(factor, cinfo->cur_comp_info[ci]->h_samp_factor); int sample_size = index->MCU_sample_size * factor; huffman_scan_header *scan_header = index->scan + current_scan; scan_header->MCU_rows_per_iMCU_row = coef->MCU_rows_per_iMCU_row; scan_header->MCUs_per_row = jdiv_round_up(cinfo->MCUs_per_row, sample_size); scan_header->comps_in_scan = cinfo->comps_in_scan; size_t allocate_size = coef->MCU_rows_per_iMCU_row * scan_header->MCUs_per_row * sizeof(huffman_offset_data); scan_header->offset[cinfo->input_iMCU_row] = (huffman_offset_data *) malloc(allocate_size); index->mem_used += allocate_size; huffman_offset_data *offset_data = scan_header->offset[cinfo->input_iMCU_row]; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], 0, // Only need one row buffer (JDIMENSION) compptr->v_samp_factor, TRUE); } /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row; MCU_col_num++) { /* For each MCU, we loop through different color components. * Then, for each color component we will get a list of pointers to DCT * blocks in the virtual buffer. */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; /* Get the list of pointers to DCT blocks in * the virtual buffer in a color component of the MCU. */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex + yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { coef->MCU_buffer[blkn++] = buffer_ptr++; if (cinfo->input_scan_number == 0) { // need to do pre-zero by ourself. jzero_far((void FAR *) coef->MCU_buffer[blkn - 1], (size_t)(SIZEOF(JBLOCK))); } } } } // Record huffman bit offset if (MCU_col_num % sample_size == 0) { (*cinfo->entropy->get_huffman_decoder_configuration) (cinfo, offset_data); ++offset_data; } /* Try to fetch the MCU. */ if (!(*cinfo->entropy->decode_mcu)(cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } (*cinfo->entropy->get_huffman_decoder_configuration) (cinfo, &scan_header->prev_MCU_offset); /* Completed the iMCU row, advance counters for next one */ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass)(cinfo); return JPEG_SCAN_COMPLETED; }
consume_data(j_decompress_ptr cinfo) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; /* Align the virtual buffers for the components used in this scan. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; buffer[ci] = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], cinfo->tile_decode ? 0 : cinfo->input_iMCU_row * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Note: entropy decoder expects buffer to be zeroed, * but this is handled automatically by the memory manager * because we requested a pre-zeroed array. */ } unsigned int MCUs_per_row = cinfo->MCUs_per_row; #ifdef ANDROID_TILE_BASED_DECODE if (cinfo->tile_decode) { int iMCU_width_To_MCU_width; if (cinfo->comps_in_scan > 1) { // Interleaved iMCU_width_To_MCU_width = 1; } else { // Non-intervleaved iMCU_width_To_MCU_width = cinfo->cur_comp_info[0]->h_samp_factor; } MCUs_per_row = jmin(MCUs_per_row, (cinfo->coef->column_right_boundary - cinfo->coef->column_left_boundary) * cinfo->entropy->index->MCU_sample_size * iMCU_width_To_MCU_width); } #endif /* Loop to process one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { // configure huffman decoder #ifdef ANDROID_TILE_BASED_DECODE if (cinfo->tile_decode) { huffman_scan_header scan_header = cinfo->entropy->index->scan[cinfo->input_scan_number]; int col_offset = cinfo->coef->column_left_boundary; (*cinfo->entropy->configure_huffman_decoder) (cinfo, scan_header.offset[cinfo->input_iMCU_row] [col_offset + yoffset * scan_header.MCUs_per_row]); } #endif // zero all blocks for (MCU_col_num = coef->MCU_ctr; MCU_col_num < MCUs_per_row; MCU_col_num++) { /* Construct list of pointers to DCT blocks belonging to this MCU */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; start_col = MCU_col_num * compptr->MCU_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { buffer_ptr = buffer[ci][yindex + yoffset] + start_col; for (xindex = 0; xindex < compptr->MCU_width; xindex++) { coef->MCU_buffer[blkn++] = buffer_ptr++; #ifdef ANDROID_TILE_BASED_DECODE if (cinfo->tile_decode && cinfo->input_scan_number == 0) { // need to do pre-zero ourselves. jzero_far((void FAR *) coef->MCU_buffer[blkn-1], (size_t) (SIZEOF(JBLOCK))); } #endif } } } /* Try to fetch the MCU. */ if (!(*cinfo->entropy->decode_mcu)(cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->MCU_ctr = MCU_col_num; return JPEG_SUSPENDED; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->MCU_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) { start_iMCU_row(cinfo); return JPEG_ROW_COMPLETED; } /* Completed the scan */ (*cinfo->inputctl->finish_input_pass)(cinfo); return JPEG_SCAN_COMPLETED; }
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, bi, ci, yindex, yoffset, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks * sequentially. Dummy blocks at the right or bottom edge are filled in * specially. The data in them does not matter for image reconstruction, * so we fill them with values that will encode to the smallest amount of * data, viz: all zeroes in the AC entries, DC entries equal to previous * block's DC value. (Thanks to Thomas Kinsman for this idea.) */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[compptr->component_index], coef->MCU_buffer[blkn], ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; } } } else { /* Create a row of dummy blocks at the bottom of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn], compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; } } blkn += compptr->MCU_width; ypos += DCTSIZE; } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; }
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; __boundcheck_metadata_store((void *)(&coef),(void *)((size_t)(&coef)+sizeof(coef)*8-1)); JDIMENSION MCU_col_num; __boundcheck_metadata_store((void *)(&MCU_col_num),(void *)((size_t)(&MCU_col_num)+sizeof(MCU_col_num)*8-1)); /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; __boundcheck_metadata_store((void *)(&last_MCU_col),(void *)((size_t)(&last_MCU_col)+sizeof(last_MCU_col)*8-1)); JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; __boundcheck_metadata_store((void *)(&last_iMCU_row),(void *)((size_t)(&last_iMCU_row)+sizeof(last_iMCU_row)*8-1)); int blkn; __boundcheck_metadata_store((void *)(&blkn),(void *)((size_t)(&blkn)+sizeof(blkn)*8-1)); int bi; __boundcheck_metadata_store((void *)(&bi),(void *)((size_t)(&bi)+sizeof(bi)*8-1)); int ci; __boundcheck_metadata_store((void *)(&ci),(void *)((size_t)(&ci)+sizeof(ci)*8-1)); int yindex; __boundcheck_metadata_store((void *)(&yindex),(void *)((size_t)(&yindex)+sizeof(yindex)*8-1)); int yoffset; __boundcheck_metadata_store((void *)(&yoffset),(void *)((size_t)(&yoffset)+sizeof(yoffset)*8-1)); int blockcnt; __boundcheck_metadata_store((void *)(&blockcnt),(void *)((size_t)(&blockcnt)+sizeof(blockcnt)*8-1)); JDIMENSION ypos; __boundcheck_metadata_store((void *)(&ypos),(void *)((size_t)(&ypos)+sizeof(ypos)*8-1)); JDIMENSION xpos; __boundcheck_metadata_store((void *)(&xpos),(void *)((size_t)(&xpos)+sizeof(xpos)*8-1)); jpeg_component_info *compptr; __boundcheck_metadata_store((void *)(&compptr),(void *)((size_t)(&compptr)+sizeof(compptr)*8-1)); /* Loop to write as much as one whole iMCU row */ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks * sequentially. Dummy blocks at the right or bottom edge are filled in * specially. The data in them does not matter for image reconstruction, * so we fill them with values that will encode to the smallest amount of * data, viz: all zeroes in the AC entries, DC entries equal to previous * block's DC value. (Thanks to Thomas Kinsman for this idea.) */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[_RV_insert_check(0,4,169,12,"compress_data",ci)]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { (*(void (*)(j_compress_ptr, jpeg_component_info *, JSAMPARRAY, JBLOCKROW, JDIMENSION, JDIMENSION, JDIMENSION))(__boundcheck_ptr_reference(177,21,"compress_data",(void *)(cinfo->fdct->forward_DCT),(void *)cinfo->fdct->forward_DCT))) (cinfo, compptr, (*(JSAMPARRAY *)(__boundcheck_ptr_reference(178,7,"compress_data",(void *)(&input_buf[0]),(void *)(&input_buf[ci])))), coef->MCU_buffer[_RV_insert_check(0,10,178,22,"compress_data",blkn)], ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void FAR *) coef->MCU_buffer[_RV_insert_check(0,10,182,31,"compress_data",blkn + blockcnt)], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[_RV_insert_check(0,10,185,3,"compress_data",blkn+bi)][_RV_insert_check(0,10,185,3,"compress_data",0)][_RV_insert_check(0,10,185,3,"compress_data",0)] = coef->MCU_buffer[_RV_insert_check(0,10,185,37,"compress_data",blkn+bi-1)][_RV_insert_check(0,10,185,37,"compress_data",0)][_RV_insert_check(0,10,185,37,"compress_data",0)]; } } } else { /* Create a row of dummy blocks at the bottom of the image. */ jzero_far((void FAR *) coef->MCU_buffer[_RV_insert_check(0,10,190,29,"compress_data",blkn)], compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[_RV_insert_check(0,10,193,8,"compress_data",blkn+bi)][_RV_insert_check(0,10,193,8,"compress_data",0)][_RV_insert_check(0,10,193,8,"compress_data",0)] = coef->MCU_buffer[_RV_insert_check(0,10,193,42,"compress_data",blkn-1)][_RV_insert_check(0,10,193,42,"compress_data",0)][_RV_insert_check(0,10,193,42,"compress_data",0)]; } } blkn += compptr->MCU_width; ypos += DCTSIZE; } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*(boolean (*)(j_compress_ptr, JBLOCKROW *))(__boundcheck_ptr_reference(203,31,"compress_data",(void *)(cinfo->entropy->encode_mcu),(void *)cinfo->entropy->encode_mcu))) (cinfo, coef->MCU_buffer)) { /* Suspension forced; update state counters and exit */ coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } /* Completed an MCU row, but perhaps not an iMCU row */ coef->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; }
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; JCOEF lastDC; jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, (JDIMENSION) (block_row * DCTSIZE), (JDIMENSION) 0, blocks_across); if (ndummy > 0) { thisblockrow += blocks_across; jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } } } if (coef->iMCU_row_num == last_iMCU_row) { blocks_across += ndummy; MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; jzero_far((void FAR *) thisblockrow, (size_t) (blocks_across * SIZEOF(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; lastblockrow += h_samp_factor; } } } } return compress_output(cinfo, input_buf); }
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int blkn, bi, ci, yindex, yoffset, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; yoffset++) { for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; ypos = yoffset * DCTSIZE; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yoffset+yindex < compptr->last_row_height) { (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[compptr->component_index], coef->MCU_buffer[blkn], ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; } } } else { jzero_far((void FAR *) coef->MCU_buffer[blkn], compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; } } blkn += compptr->MCU_width; ypos += DCTSIZE; } } if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { coef->MCU_vert_offset = yoffset; coef->mcu_ctr = MCU_col_num; return FALSE; } } coef->mcu_ctr = 0; } coef->iMCU_row_num++; start_iMCU_row(cinfo); return TRUE; }
compress_trellis_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; JCOEF lastDC; jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; JBLOCKARRAY buffer_dst; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { c_derived_tbl dctbl_data; c_derived_tbl *dctbl = &dctbl_data; c_derived_tbl actbl_data; c_derived_tbl *actbl = &actbl_data; #ifdef C_ARITH_CODING_SUPPORTED arith_rates arith_r_data; arith_rates *arith_r = &arith_r_data; #endif compptr = cinfo->cur_comp_info[ci]; #ifdef C_ARITH_CODING_SUPPORTED if (cinfo->arith_code) jget_arith_rates(cinfo, compptr->dc_tbl_no, compptr->ac_tbl_no, arith_r); else #endif { jpeg_make_c_derived_tbl(cinfo, TRUE, compptr->dc_tbl_no, &dctbl); jpeg_make_c_derived_tbl(cinfo, FALSE, compptr->ac_tbl_no, &actbl); } /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); buffer_dst = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image_uq[compptr->component_index], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Count non-dummy DCT block rows in this iMCU row. */ if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; lastDC = 0; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = (block_row > 0) ? buffer[block_row-1] : NULL; #ifdef C_ARITH_CODING_SUPPORTED if (cinfo->arith_code) quantize_trellis_arith(cinfo, arith_r, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->master->norm_src[compptr->quant_tbl_no], cinfo->master->norm_coef[compptr->quant_tbl_no], &lastDC, lastblockrow, buffer_dst[block_row-1]); else #endif quantize_trellis(cinfo, dctbl, actbl, thisblockrow, buffer_dst[block_row], blocks_across, cinfo->quant_tbl_ptrs[compptr->quant_tbl_no], cinfo->master->norm_src[compptr->quant_tbl_no], cinfo->master->norm_coef[compptr->quant_tbl_no], &lastDC, lastblockrow, buffer_dst[block_row-1]); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ jzero_far((void *) thisblockrow, ndummy * sizeof(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } } } /* If at end of image, create dummy block rows as needed. * The tricky part here is that within each MCU, we want the DC values * of the dummy blocks to match the last real block's DC value. * This squeezes a few more bytes out of the resulting file... */ if (coef->iMCU_row_num == last_iMCU_row) { blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; jzero_far((void *) thisblockrow, (size_t) (blocks_across * sizeof(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } } } } /* NB: compress_output will increment iMCU_row_num if successful. * A suspension return will result in redoing all the work above next time. */ /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); }
compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; JDIMENSION blocks_across, MCUs_across, MCUindex; int bi, ci, h_samp_factor, block_row, block_rows, ndummy; JCOEF lastDC; jpeg_component_info *compptr; JBLOCKARRAY buffer; JBLOCKROW thisblockrow, lastblockrow; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Align the virtual buffer for this component. */ buffer = (*cinfo->mem->access_virt_barray) ((j_common_ptr) cinfo, coef->whole_image[ci], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, TRUE); /* Count non-dummy DCT block rows in this iMCU row. */ if (coef->iMCU_row_num < last_iMCU_row) block_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (block_rows == 0) block_rows = compptr->v_samp_factor; } blocks_across = compptr->width_in_blocks; h_samp_factor = compptr->h_samp_factor; /* Count number of dummy blocks to be added at the right margin. */ ndummy = (int) (blocks_across % h_samp_factor); if (ndummy > 0) ndummy = h_samp_factor - ndummy; /* Perform DCT for all non-dummy blocks in this iMCU row. Each call * on forward_DCT processes a complete horizontal row of DCT blocks. */ for (block_row = 0; block_row < block_rows; block_row++) { thisblockrow = buffer[block_row]; (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow, (JDIMENSION) (block_row * DCTSIZE), (JDIMENSION) 0, blocks_across); if (ndummy > 0) { /* Create dummy blocks at the right edge of the image. */ thisblockrow += blocks_across; /* => first dummy block */ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); lastDC = thisblockrow[-1][0]; for (bi = 0; bi < ndummy; bi++) { thisblockrow[bi][0] = lastDC; } } } /* If at end of image, create dummy block rows as needed. * The tricky part here is that within each MCU, we want the DC values * of the dummy blocks to match the last real block's DC value. * This squeezes a few more bytes out of the resulting file... */ if (coef->iMCU_row_num == last_iMCU_row) { blocks_across += ndummy; /* include lower right corner */ MCUs_across = blocks_across / h_samp_factor; for (block_row = block_rows; block_row < compptr->v_samp_factor; block_row++) { thisblockrow = buffer[block_row]; lastblockrow = buffer[block_row-1]; jzero_far((void FAR *) thisblockrow, (size_t) (blocks_across * SIZEOF(JBLOCK))); for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { lastDC = lastblockrow[h_samp_factor-1][0]; for (bi = 0; bi < h_samp_factor; bi++) { thisblockrow[bi][0] = lastDC; } thisblockrow += h_samp_factor; /* advance to next MCU in row */ lastblockrow += h_samp_factor; } } } } /* NB: compress_output will increment iMCU_row_num if successful. * A suspension return will result in redoing all the work above next time. */ /* Emit data to the entropy encoder, sharing code with subsequent passes */ return compress_output(cinfo, input_buf); }
decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf, JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU) { j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private; unsigned int mcu_num; int sampn, ci, yoffset, MCU_width, ptrn; BITREAD_STATE_VARS; /* Set output pointer locations based on MCU_col_num */ for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) { ci = entropy->output_ptr_info[ptrn].ci; yoffset = entropy->output_ptr_info[ptrn].yoffset; MCU_width = entropy->output_ptr_info[ptrn].MCU_width; entropy->output_ptr[ptrn] = diff_buf[ci][MCU_row_num + (JDIMENSION)yoffset] + MCU_col_num * (JDIMENSION)MCU_width; } /* * If we've run out of data, zero out the buffers and return. * By resetting the undifferencer, the output samples will be CENTERJSAMPLE. * * NB: We should find a way to do this without interacting with the * undifferencer module directly. */ if (entropy->insufficient_data) { for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) jzero_far((void FAR *) entropy->output_ptr[ptrn], nMCU * (size_t)entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF)); (*losslsd->predict_process_restart) (cinfo); } else { /* Load up working state */ BITREAD_LOAD_STATE(cinfo,entropy->bitstate); /* Outer loop handles the number of MCU requested */ for (mcu_num = 0; mcu_num < nMCU; mcu_num++) { /* Inner loop handles the samples in the MCU */ for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) { d_derived_tbl * dctbl = entropy->cur_tbls[sampn]; register int s, r; /* Section H.2.2: decode the sample difference */ HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1); if (s) { if (s == 16) /* special case: always output 32768 */ s = 32768; else { /* normal case: fetch subsequent bits */ CHECK_BIT_BUFFER(br_state, s, return mcu_num); r = GET_BITS(s); s = HUFF_EXTEND(r, s); } } /* Output the sample difference */ *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s; } /* Completed MCU, so update state */ BITREAD_SAVE_STATE(cinfo,entropy->bitstate); } } return nMCU; }