start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; coef->iMCU_row_num = 0; start_iMCU_row(cinfo); switch (pass_mode) { case JBUF_PASS_THRU: if (coef->whole_image[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_data; break; #ifdef FULL_COEF_BUFFER_SUPPORTED case JBUF_SAVE_AND_PASS: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_first_pass; break; case JBUF_CRANK_DEST: if (coef->whole_image[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->pub.compress_data = compress_output; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } }
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->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. */ } /* 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++) { /* 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)) { /* 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_output (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 */ int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; ( void ) input_buf; /* Align the virtual buffers for the components used in this scan. * NB: during first pass, this is safe only because the buffers will * already be aligned properly, so jmemmgr.c won't need to do any I/O. */ 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->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* 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++) { /* 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 write the MCU. */ 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; }
start_pass_coef(j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; if (pass_mode != JBUF_CRANK_DEST) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->iMCU_row_num = 0; start_iMCU_row(cinfo); }
start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private; if (pass_mode != JBUF_CRANK_DEST) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); coef->iMCU_row_num = 0; start_iMCU_row(cinfo); }
consume_data_build_huffman_index_baseline(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 ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKROW buffer_ptr; huffman_scan_header *scan_header = index->scan + current_scan; scan_header->MCU_rows_per_iMCU_row = coef->MCU_rows_per_iMCU_row; size_t allocate_size = coef->MCU_rows_per_iMCU_row * jdiv_round_up(cinfo->MCUs_per_row, index->MCU_sample_size) * 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]; /* 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++) { // Record huffman bit offset if (MCU_col_num % index->MCU_sample_size == 0) { (*cinfo->entropy->get_huffman_decoder_configuration) (cinfo, offset_data); ++offset_data; } /* Try to fetch the MCU. */ if (!(*cinfo->entropy->decode_mcu_discard_coef)(cinfo)) { /* 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_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; int blkn, ci, xindex, yindex, yoffset; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; 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->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } 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++) { blkn = 0; 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++; } } } 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; }
start_input_pass (j_decompress_ptr cinfo) { j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; /* Check that the restart interval is an integer multiple of the number * of MCU in an MCU-row. */ if (cinfo->restart_interval % cinfo->MCUs_per_row != 0) ERREXIT2(cinfo, JERR_BAD_RESTART, cinfo->restart_interval, cinfo->MCUs_per_row); /* Initialize restart counter */ diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row; cinfo->input_iMCU_row = 0; start_iMCU_row(cinfo); }
compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) { j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION MCU_count; /* number of MCUs encoded */ /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int comp, ci, yoffset, samp_row, samp_rows, samps_across; jpeg_component_info *compptr; /* Loop to write as much as one whole iMCU row */ for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row; yoffset++) { MCU_col_num = diff->mcu_ctr; /* Scale and predict each scanline of the MCU-row separately. * * Note: We only do this if we are at the start of a MCU-row, ie, * we don't want to reprocess a row suspended by the output. */ if (MCU_col_num == 0) { for (comp = 0; comp < cinfo->comps_in_scan; comp++) { compptr = cinfo->cur_comp_info[comp]; ci = compptr->component_index; if (diff->iMCU_row_num < last_iMCU_row) samp_rows = compptr->v_samp_factor; else { /* NB: can't use last_row_height here, since may not be set! */ samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor); if (samp_rows == 0) samp_rows = compptr->v_samp_factor; else { /* Fill dummy difference rows at the bottom edge with zeros, which * will encode to the smallest amount of data. */ for (samp_row = samp_rows; samp_row < compptr->v_samp_factor; samp_row++) MEMZERO(diff->diff_buf[ci][samp_row], jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); } } samps_across = compptr->width_in_data_units; for (samp_row = 0; samp_row < samp_rows; samp_row++) { (*losslsc->scaler_scale) (cinfo, input_buf[ci][samp_row], diff->cur_row[ci], samps_across); (*losslsc->predict_difference[ci]) (cinfo, ci, diff->cur_row[ci], diff->prev_row[ci], diff->diff_buf[ci][samp_row], samps_across); SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]); } } } /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */ MCU_count = (*losslsc->entropy_encode_mcus) (cinfo, diff->diff_buf, yoffset, MCU_col_num, cinfo->MCUs_per_row - MCU_col_num); if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { /* Suspension forced; update state counters and exit */ diff->MCU_vert_offset = yoffset; diff->mcu_ctr += MCU_col_num; return FALSE; } /* Completed an MCU row, but perhaps not an iMCU row */ diff->mcu_ctr = 0; } /* Completed the iMCU row, advance counters for next one */ diff->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; 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_output (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, ci, xindex, yindex, yoffset, blockcnt; JDIMENSION start_col; JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; JBLOCKROW buffer_ptr; jpeg_component_info *compptr; (void)input_buf; /* 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->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* 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++) { /* 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; blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width : compptr->last_col_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->iMCU_row_num < last_iMCU_row || yindex+yoffset < compptr->last_row_height) { /* Fill in pointers to real blocks in this row */ buffer_ptr = buffer[ci][yindex+yoffset] + start_col; for (xindex = 0; xindex < blockcnt; xindex++) MCU_buffer[blkn++] = buffer_ptr++; } else { /* At bottom of image, need a whole row of dummy blocks */ xindex = 0; } /* Fill in any dummy blocks needed in this row. * Dummy blocks are filled in the same way as in jccoefct.c: * all zeroes in the AC entries, DC entries equal to previous * block's DC value. The init routine has already zeroed the * AC entries, so we need only set the DC entries correctly. */ for (; xindex < compptr->MCU_width; xindex++) { MCU_buffer[blkn] = coef->dummy_buffer[blkn]; MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; blkn++; } } } /* Try to write the MCU. */ if (! (*cinfo->entropy->encode_mcu) (cinfo, 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; }
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; }
METHODDEF void start_input_pass( j_decompress_ptr cinfo ) { cinfo->input_iMCU_row = 0; start_iMCU_row( cinfo ); }
decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION MCU_count; /* number of MCUs decoded */ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; int comp, ci, yoffset, row, prev_row; jpeg_component_info *compptr; /* Loop to process as much as one whole iMCU row */ for (yoffset = diff->MCU_vert_offset; yoffset < (int)diff->MCU_rows_per_iMCU_row; yoffset++) { /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (diff->restart_rows_to_go == 0) if (! process_restart(cinfo)) return JPEG_SUSPENDED; } MCU_col_num = diff->MCU_ctr; /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */ MCU_count = (*losslsd->entropy_decode_mcus) (cinfo, diff->diff_buf, yoffset, MCU_col_num, cinfo->MCUs_per_row - MCU_col_num); if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) { /* Suspension forced; update state counters and exit */ diff->MCU_vert_offset = yoffset; diff->MCU_ctr += MCU_count; return JPEG_SUSPENDED; } /* Account for restart interval (no-op if not using restarts) */ diff->restart_rows_to_go--; /* Completed an MCU row, but perhaps not an iMCU row */ diff->MCU_ctr = 0; } /* * Undifference and scale each scanline of the disassembled MCU-row * separately. We do not process dummy samples at the end of a scanline * or dummy rows at the end of the image. */ for (comp = 0; comp < cinfo->comps_in_scan; comp++) { compptr = cinfo->cur_comp_info[comp]; ci = compptr->component_index; for (row = 0, prev_row = compptr->v_samp_factor - 1; row < (cinfo->input_iMCU_row == last_iMCU_row ? compptr->last_row_height : compptr->v_samp_factor); prev_row = row, row++) { (*losslsd->predict_undifference[ci]) (cinfo, ci, diff->diff_buf[ci][row], diff->undiff_buf[ci][prev_row], diff->undiff_buf[ci][row], compptr->width_in_data_units); (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row], output_buf[ci][row], compptr->width_in_data_units); } } /* Completed the iMCU row, advance counters for next one. * * NB: output_data will increment output_iMCU_row. * This counter is not needed for the single-pass case * or the input side of the multi-pass case. */ 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; }
jpeg_skip_scanlines (j_decompress_ptr cinfo, JDIMENSION num_lines) { my_main_ptr main_ptr = (my_main_ptr) cinfo->main; my_coef_ptr coef = (my_coef_ptr) cinfo->coef; my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JDIMENSION i, x; int y; JDIMENSION lines_per_iMCU_row, lines_left_in_iMCU_row, lines_after_iMCU_row; JDIMENSION lines_to_skip, lines_to_read; if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Do not skip past the bottom of the image. */ if (cinfo->output_scanline + num_lines >= cinfo->output_height) { cinfo->output_scanline = cinfo->output_height; return cinfo->output_height - cinfo->output_scanline; } if (num_lines == 0) return 0; lines_per_iMCU_row = cinfo->_min_DCT_scaled_size * cinfo->max_v_samp_factor; lines_left_in_iMCU_row = (lines_per_iMCU_row - (cinfo->output_scanline % lines_per_iMCU_row)) % lines_per_iMCU_row; lines_after_iMCU_row = num_lines - lines_left_in_iMCU_row; /* Skip the lines remaining in the current iMCU row. When upsampling * requires context rows, we need the previous and next rows in order to read * the current row. This adds some complexity. */ if (cinfo->upsample->need_context_rows) { /* If the skipped lines would not move us past the current iMCU row, we * read the lines and ignore them. There might be a faster way of doing * this, but we are facing increasing complexity for diminishing returns. * The increasing complexity would be a by-product of meddling with the * state machine used to skip context rows. Near the end of an iMCU row, * the next iMCU row may have already been entropy-decoded. In this unique * case, we will read the next iMCU row if we cannot skip past it as well. */ if ((num_lines < lines_left_in_iMCU_row + 1) || (lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full && lines_after_iMCU_row < lines_per_iMCU_row + 1)) { read_and_discard_scanlines(cinfo, num_lines); return num_lines; } /* If the next iMCU row has already been entropy-decoded, make sure that * we do not skip too far. */ if (lines_left_in_iMCU_row <= 1 && main_ptr->buffer_full) { cinfo->output_scanline += lines_left_in_iMCU_row + lines_per_iMCU_row; lines_after_iMCU_row -= lines_per_iMCU_row; } else { cinfo->output_scanline += lines_left_in_iMCU_row; } /* If we have just completed the first block, adjust the buffer pointers */ if (main_ptr->iMCU_row_ctr == 0 || (main_ptr->iMCU_row_ctr == 1 && lines_left_in_iMCU_row > 2)) set_wraparound_pointers(cinfo); main_ptr->buffer_full = FALSE; main_ptr->rowgroup_ctr = 0; main_ptr->context_state = CTX_PREPARE_FOR_IMCU; upsample->next_row_out = cinfo->max_v_samp_factor; upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; } /* Skipping is much simpler when context rows are not required. */ else { if (num_lines < lines_left_in_iMCU_row) { increment_simple_rowgroup_ctr(cinfo, num_lines); return num_lines; } else { cinfo->output_scanline += lines_left_in_iMCU_row; main_ptr->buffer_full = FALSE; main_ptr->rowgroup_ctr = 0; upsample->next_row_out = cinfo->max_v_samp_factor; upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; } } /* Calculate how many full iMCU rows we can skip. */ if (cinfo->upsample->need_context_rows) lines_to_skip = ((lines_after_iMCU_row - 1) / lines_per_iMCU_row) * lines_per_iMCU_row; else lines_to_skip = (lines_after_iMCU_row / lines_per_iMCU_row) * lines_per_iMCU_row; /* Calculate the number of lines that remain to be skipped after skipping all * of the full iMCU rows that we can. We will not read these lines unless we * have to. */ lines_to_read = lines_after_iMCU_row - lines_to_skip; /* For images requiring multiple scans (progressive, non-interleaved, etc.), * all of the entropy decoding occurs in jpeg_start_decompress(), assuming * that the input data source is non-suspending. This makes skipping easy. */ if (cinfo->inputctl->has_multiple_scans) { if (cinfo->upsample->need_context_rows) { cinfo->output_scanline += lines_to_skip; cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row; main_ptr->iMCU_row_ctr += lines_after_iMCU_row / lines_per_iMCU_row; /* It is complex to properly move to the middle of a context block, so * read the remaining lines instead of skipping them. */ read_and_discard_scanlines(cinfo, lines_to_read); } else { cinfo->output_scanline += lines_to_skip; cinfo->output_iMCU_row += lines_to_skip / lines_per_iMCU_row; increment_simple_rowgroup_ctr(cinfo, lines_to_read); } upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; return num_lines; } /* Skip the iMCU rows that we can safely skip. */ for (i = 0; i < lines_to_skip; i += lines_per_iMCU_row) { for (y = 0; y < coef->MCU_rows_per_iMCU_row; y++) { for (x = 0; x < cinfo->MCUs_per_row; x++) { /* Calling decode_mcu() with a NULL pointer causes it to discard the * decoded coefficients. This is ~5% faster for large subsets, but * it's tough to tell a difference for smaller images. */ (*cinfo->entropy->decode_mcu) (cinfo, NULL); } } cinfo->input_iMCU_row++; cinfo->output_iMCU_row++; if (cinfo->input_iMCU_row < cinfo->total_iMCU_rows) start_iMCU_row(cinfo); else (*cinfo->inputctl->finish_input_pass) (cinfo); } cinfo->output_scanline += lines_to_skip; if (cinfo->upsample->need_context_rows) { /* Context-based upsampling keeps track of iMCU rows. */ main_ptr->iMCU_row_ctr += lines_to_skip / lines_per_iMCU_row; /* It is complex to properly move to the middle of a context block, so * read the remaining lines instead of skipping them. */ read_and_discard_scanlines(cinfo, lines_to_read); } else { increment_simple_rowgroup_ctr(cinfo, lines_to_read); } /* Since skipping lines involves skipping the upsampling step, the value of * "rows_to_go" will become invalid unless we set it here. NOTE: This is a * bit odd, since "rows_to_go" seems to be redundantly keeping track of * output_scanline. */ upsample->rows_to_go = cinfo->output_height - cinfo->output_scanline; /* Always skip the requested number of lines. */ return num_lines; }
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; }
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; }
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_output (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 */ int blkn; __boundcheck_metadata_store((void *)(&blkn),(void *)((size_t)(&blkn)+sizeof(blkn)*8-1)); int ci; __boundcheck_metadata_store((void *)(&ci),(void *)((size_t)(&ci)+sizeof(ci)*8-1)); int xindex; __boundcheck_metadata_store((void *)(&xindex),(void *)((size_t)(&xindex)+sizeof(xindex)*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)); JDIMENSION start_col; __boundcheck_metadata_store((void *)(&start_col),(void *)((size_t)(&start_col)+sizeof(start_col)*8-1)); JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];__boundcheck_metadata_store(&buffer[0],&buffer[4-1]); JBLOCKROW buffer_ptr; __boundcheck_metadata_store((void *)(&buffer_ptr),(void *)((size_t)(&buffer_ptr)+sizeof(buffer_ptr)*8-1)); jpeg_component_info *compptr; __boundcheck_metadata_store((void *)(&compptr),(void *)((size_t)(&compptr)+sizeof(compptr)*8-1)); /* Align the virtual buffers for the components used in this scan. * NB: during first pass, this is safe only because the buffers will * already be aligned properly, so jmemmgr.c won't need to do any I/O. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[_RV_insert_check(0,4,355,15,"compress_output",ci)]; buffer[_RV_insert_check(0,4,356,5,"compress_output",ci)] = (*(JBLOCKARRAY (*)(j_common_ptr, jvirt_barray_ptr, JDIMENSION, JDIMENSION, boolean))(__boundcheck_ptr_reference(356,32,"compress_output",(void *)(cinfo->mem->access_virt_barray),(void *)cinfo->mem->access_virt_barray))) ((j_common_ptr) cinfo, coef->whole_image[_RV_insert_check(0,10,357,30,"compress_output",compptr->component_index)], coef->iMCU_row_num * compptr->v_samp_factor, (JDIMENSION) compptr->v_samp_factor, FALSE); } /* 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++) { /* 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[_RV_insert_check(0,4,370,12,"compress_output",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[_RV_insert_check(0,10,375,6,"compress_output",blkn++)] = buffer_ptr++; } } } /* Try to write the MCU. */ if (! (*(boolean (*)(j_compress_ptr, JBLOCKROW *))(__boundcheck_ptr_reference(380,31,"compress_output",(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_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; }