LOCAL void noninterleaved_scan_setup (compress_info_ptr cinfo) /* Compute all derived info for a noninterleaved (single-component) scan */ /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */ { jpeg_component_info *compptr = cinfo->cur_comp_info[0]; /* for noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) DCTSIZE); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) DCTSIZE); cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE; cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row; cinfo->restart_interval = (UINT16) MIN(nominal, 65535L); } (*cinfo->methods->c_per_scan_method_selection) (cinfo); }
LOCAL void noninterleaved_scan_setup (decompress_info_ptr cinfo) /* Compute all derived info for a noninterleaved (single-component) scan */ /* On entry, cinfo->comps_in_scan = 1 and cinfo->cur_comp_info[0] is set up */ { jpeg_component_info *compptr = cinfo->cur_comp_info[0]; /* for noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) DCTSIZE); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) DCTSIZE); cinfo->MCUs_per_row = compptr->downsampled_width / DCTSIZE; cinfo->MCU_rows_in_scan = compptr->downsampled_height / DCTSIZE; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; (*cinfo->methods->d_per_scan_method_selection) (cinfo); }
jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec; d_diff_ptr diff; int ci; jpeg_component_info *compptr; diff = (d_diff_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(d_diff_controller)); losslsd->diff_private = (void *) diff; losslsd->diff_start_input_pass = start_input_pass; losslsd->pub.start_output_pass = start_output_pass; /* Create the [un]difference buffers. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) compptr->v_samp_factor); diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) compptr->v_samp_factor); } if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component. */ int access_rows; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_data_units, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } losslsd->pub.consume_data = consume_data; losslsd->pub.decompress_data = output_data; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { losslsd->pub.consume_data = dummy_consume_data; losslsd->pub.decompress_data = decompress_data; diff->whole_image[0] = NULL; /* flag for no virtual arrays */ } }
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; __boundcheck_metadata_store((void *)(&coef),(void *)((size_t)(&coef)+sizeof(coef)*8-1)); coef = (my_coef_ptr) (*(void *(*)(j_common_ptr, int, size_t))(__boundcheck_ptr_reference(409,19,"jinit_c_coef_controller",(void *)(cinfo->mem->alloc_small),(void *)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; /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ int ci; __boundcheck_metadata_store((void *)(&ci),(void *)((size_t)(&ci)+sizeof(ci)*8-1)); jpeg_component_info *compptr; __boundcheck_metadata_store((void *)(&compptr),(void *)((size_t)(&compptr)+sizeof(compptr)*8-1)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[_RV_insert_check(0,10,424,7,"jinit_c_coef_controller",ci)] = (*(jvirt_barray_ptr (*)(j_common_ptr, int, boolean, JDIMENSION, JDIMENSION, JDIMENSION))(__boundcheck_ptr_reference(424,45,"jinit_c_coef_controller",(void *)(cinfo->mem->request_virt_barray),(void *)cinfo->mem->request_virt_barray))) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; __boundcheck_metadata_store((void *)(&buffer),(void *)((size_t)(&buffer)+sizeof(buffer)*8-1)); int i; __boundcheck_metadata_store((void *)(&i),(void *)((size_t)(&i)+sizeof(i)*8-1)); buffer = (JBLOCKROW) (*(void *(*)(j_common_ptr, int, size_t))(__boundcheck_ptr_reference(441,21,"jinit_c_coef_controller",(void *)(cinfo->mem->alloc_large),(void *)cinfo->mem->alloc_large))) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[_RV_insert_check(0,10,444,7,"jinit_c_coef_controller",i)] = buffer + i; } coef->whole_image[_RV_insert_check(0,10,446,5,"jinit_c_coef_controller",0)] = NULL; /* flag for no virtual arrays */ } }
LOCAL void interleaved_scan_setup (compress_info_ptr cinfo) /* Compute all derived info for an interleaved (multi-component) scan */ /* On entry, cinfo->comps_in_scan and cinfo->cur_comp_info[] are set up */ { short ci, mcublks; jpeg_component_info *compptr; if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->MCUs_per_row = (cinfo->image_width + cinfo->max_h_samp_factor*DCTSIZE - 1) / (cinfo->max_h_samp_factor*DCTSIZE); cinfo->MCU_rows_in_scan = (cinfo->image_height + cinfo->max_v_samp_factor*DCTSIZE - 1) / (cinfo->max_v_samp_factor*DCTSIZE); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* for interleaved scan, sampling factors give # of blocks per component */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; /* compute physical dimensions of component */ compptr->downsampled_width = jround_up(compptr->true_comp_width, (long) (compptr->MCU_width*DCTSIZE)); compptr->downsampled_height = jround_up(compptr->true_comp_height, (long) (compptr->MCU_height*DCTSIZE)); /* Sanity check */ if (compptr->downsampled_width != (cinfo->MCUs_per_row * (compptr->MCU_width*DCTSIZE))) ERREXIT(cinfo->emethods, "I'm confused about the image width"); /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo->emethods, "Sampling factors too large for interleaved scan"); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = cinfo->restart_in_rows * cinfo->MCUs_per_row; cinfo->restart_interval = (UINT16) MIN(nominal, 65535L); } (*cinfo->methods->c_per_scan_method_selection) (cinfo); }
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ /* Note we ask for a pre-zeroed array. */ int ci, access_rows; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } coef->pub.consume_data = consume_data; coef->pub.decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data = dummy_consume_data; coef->pub.decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } }
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; 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; /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ int ci; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); coef->whole_image_uq[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->whole_image[0] = NULL; /* flag for no virtual arrays */ } }
jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; 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; if (need_full_buffer) { #ifdef FULL_COEF_BUFFER_SUPPORTED int ci; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->whole_image[0] = NULL; } }
jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr my_main; int ci; jpeg_component_info *compptr; my_main = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_c_main_controller *) my_main; my_main->pub.start_pass = start_pass_main; /* We don't need to create a buffer in raw-data mode. */ if (cinfo->raw_data_in) return; /* Create the buffer. It holds downsampled data, so each component * may be of a different size. */ if (need_full_buffer) { #ifdef FULL_MAIN_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component */ /* Note we pad the bottom to a multiple of the iMCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { my_main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor) * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { #ifdef FULL_MAIN_BUFFER_SUPPORTED my_main->whole_image[0] = NULL; /* flag for no virtual arrays */ #endif /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { my_main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } } }
GLOBAL void jinit_d_post_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; post = (my_post_ptr) (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->whole_image = NULL; /* flag for no virtual arrays */ post->buffer = NULL; /* flag for no strip buffer */ /* Create the quantization buffer, if needed */ if(cinfo->quantize_colors) { /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) */ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; if(need_full_buffer) { /* Two-pass color quantization: need full-image storage. */ /* We round up the number of rows to a multiple of the strip height. */ #ifdef QUANT_2PASS_SUPPORTED post->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, cinfo->output_width * cinfo->out_color_components, (JDIMENSION) jround_up((long) cinfo->output_height, (long) post->strip_height), post->strip_height); #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ post->buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } } }
GLOBAL void jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; int ci, i; jpeg_component_info *compptr; JBLOCKROW buffer; coef = (my_coef_ptr)alloc_small_wrapper((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller_d)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_pass = start_pass_coef; /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ /* Note memmgr implicitly pads the vertical direction. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), compptr->height_in_blocks, (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else { /* We only need a single-MCU buffer. */ buffer = (JBLOCKROW)alloc_large_wrapper((j_common_ptr) cinfo, JPOOL_IMAGE, MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->whole_image[0] = NULL; /* flag for no virtual arrays */ } }
jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer) { j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; c_diff_ptr diff; int ci, row; jpeg_component_info *compptr; diff = (c_diff_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_diff_controller)); losslsc->diff_private = (void *) diff; losslsc->diff_start_pass = start_pass_diff; /* Create the prediction row buffers. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) 1); diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) 1); } /* Create the difference buffer. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { diff->diff_buf[ci] = (*cinfo->mem->alloc_darray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) compptr->v_samp_factor); /* Prefill difference rows with zeros. We do this because only actual * data is placed in the buffers during prediction/differencing, leaving * any dummy differences at the right edge as zeros, which will encode * to the smallest amount of data. */ for (row = 0; row < compptr->v_samp_factor; row++) MEMZERO(diff->diff_buf[ci][row], jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor) * SIZEOF(JDIFF)); } /* Create the sample buffer. */ if (need_full_buffer) { #ifdef FULL_SAMP_BUFFER_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor differences in each direction. */ int ci; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_data_units, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_data_units, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif } else diff->whole_image[0] = NULL; /* flag for no virtual arrays */ }
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; }
jtransform_request_workspace (j_decompress_ptr srcinfo, jpeg_transform_info *info) { jvirt_barray_ptr *coef_arrays = NULL; jpeg_component_info *compptr; int ci; if (info->force_grayscale && srcinfo->jpeg_color_space == JCS_YCbCr && srcinfo->num_components == 3) { /* We'll only process the first component */ info->num_components = 1; } else { /* Process all the components */ info->num_components = srcinfo->num_components; } switch (info->transform) { case JXFORM_NONE: case JXFORM_FLIP_H: /* Don't need a workspace array */ break; case JXFORM_FLIP_V: case JXFORM_ROT_180: /* Need workspace arrays having same dimensions as source image. * Note that we allocate arrays padded out to the next iMCU boundary, * so that transform routines need not worry about missing edge blocks. */ coef_arrays = (jvirt_barray_ptr *) (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) * info->num_components); for (ci = 0; ci < info->num_components; ci++) { compptr = srcinfo->comp_info + ci; coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) compptr->v_samp_factor); } break; case JXFORM_TRANSPOSE: case JXFORM_TRANSVERSE: case JXFORM_ROT_90: case JXFORM_ROT_270: /* Need workspace arrays having transposed dimensions. * Note that we allocate arrays padded out to the next iMCU boundary, * so that transform routines need not worry about missing edge blocks. */ coef_arrays = (jvirt_barray_ptr *) (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE, SIZEOF(jvirt_barray_ptr) * info->num_components); for (ci = 0; ci < info->num_components; ci++) { compptr = srcinfo->comp_info + ci; coef_arrays[ci] = (*srcinfo->mem->request_virt_barray) ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) compptr->h_samp_factor); } break; } info->workspace_coef_arrays = coef_arrays; }
jinit_upsampler(j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; jpeg_component_info* compptr; boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr)(*cinfo->mem->alloc_small)( (j_common_ptr)cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler*)upsample; upsample->pub.start_pass = start_pass_upsample; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, * so don't ask for it. */ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Compute size of an "input group" after IDCT scaling. This many * samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ need_buffer = TRUE; if (!compptr->component_needed) { /* Don't bother to upsample an uninteresting component. */ upsample->methods[ci] = noop_upsample; need_buffer = FALSE; } else if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; need_buffer = FALSE; } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special cases for 2h1v upsampling */ if (do_fancy && compptr->downsampled_width > 2) upsample->methods[ci] = h2v1_fancy_upsample; else upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { /* Special cases for 2h2v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; } else upsample->methods[ci] = h2v2_upsample; } else if ( (h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ upsample->methods[ci] = int_upsample; upsample->h_expand[ci] = (UINT8)(h_out_group / h_in_group); upsample->v_expand[ci] = (UINT8)(v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); if (need_buffer) { upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)( (j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)jround_up( (long)cinfo->output_width, (long)cinfo->max_h_samp_factor), (JDIMENSION)cinfo->max_v_samp_factor); } } }
METHODDEF void single_eopt_ccontroller (compress_info_ptr cinfo) { int rows_in_mem; /* # of sample rows in full-size buffers */ long fullsize_width; /* # of samples per row in full-size buffers */ long cur_pixel_row; /* counts # of pixel rows processed */ long mcu_rows_output; /* # of MCU rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for pre-downsampling data (see comments at head of file) */ JSAMPIMAGE fullsize_data[2]; /* Work buffer for downsampled data */ JSAMPIMAGE sampled_data; int rows_this_time; int blocks_in_big_row; short ci, whichss, i; /* Prepare for single scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT(cinfo->emethods, "Too many components for interleaved scan"); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Vk block rows constitute the same number of MCU rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row contains Vk block rows */ mcu_rows_per_loop = 1; } cinfo->total_passes += 2; /* entropy encoder must add # passes it uses */ /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate working memory: */ /* fullsize_data is sample data before downsampling */ alloc_sampling_buffer(cinfo, fullsize_data, fullsize_width); /* sampled_data is sample data after downsampling */ sampled_data = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); for (ci = 0; ci < cinfo->num_components; ci++) { sampled_data[ci] = (*cinfo->emethods->alloc_small_sarray) (cinfo->comp_info[ci].downsampled_width, (long) (cinfo->comp_info[ci].v_samp_factor * DCTSIZE)); } /* Figure # of MCUs to be packed in a row of whole_scan_MCUs */ MCUs_in_big_row = MAX_WHOLE_ROW_BLOCKS / cinfo->blocks_in_MCU; blocks_in_big_row = MCUs_in_big_row * cinfo->blocks_in_MCU; /* Request a big array: whole_scan_MCUs saves the MCU data for the scan */ whole_scan_MCUs = (*cinfo->emethods->request_big_barray) ((long) blocks_in_big_row, (long) (cinfo->MCUs_per_row * cinfo->MCU_rows_in_scan + MCUs_in_big_row-1) / MCUs_in_big_row, 1L); /* unit height is 1 row */ next_whole_row = 0; /* init output ptr for MCU_output_catcher */ next_MCU_index = MCUs_in_big_row; /* forces access on first call! */ /* Tell the memory manager to instantiate big arrays */ (*cinfo->emethods->alloc_big_arrays) ((long) 0, /* no more small sarrays */ (long) 0, /* no more small barrays */ (long) 0); /* no more "medium" objects */ /* Do per-scan object init */ (*cinfo->methods->downsample_init) (cinfo); (*cinfo->methods->extract_init) (cinfo); /* Loop over input image: rows_in_mem pixel rows are processed per loop */ /* MCU data goes into whole_scan_MCUs, not to the entropy encoder */ mcu_rows_output = 0; whichss = 1; /* arrange to start with fullsize_data[0] */ for (cur_pixel_row = 0; cur_pixel_row < cinfo->image_height; cur_pixel_row += rows_in_mem) { (*cinfo->methods->progress_monitor) (cinfo, cur_pixel_row, cinfo->image_height); whichss ^= 1; /* switch to other fullsize_data buffer */ /* Obtain rows_this_time pixel rows and expand to rows_in_mem rows. */ /* Then we have exactly DCTSIZE row groups for downsampling. */ rows_this_time = (int) MIN((long) rows_in_mem, cinfo->image_height - cur_pixel_row); (*cinfo->methods->get_sample_rows) (cinfo, rows_this_time, fullsize_data[whichss]); (*cinfo->methods->edge_expand) (cinfo, cinfo->image_width, rows_this_time, fullsize_width, rows_in_mem, fullsize_data[whichss]); /* Downsample the data (all components) */ /* First time through is a special case */ if (cur_pixel_row) { /* Downsample last row group of previous set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* and dump the previous set's downsampled data */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, mcu_rows_per_loop, MCU_output_catcher); mcu_rows_output += mcu_rows_per_loop; /* Downsample first row group of this set */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Downsample first row group with dummy above-context */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Downsample second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of outer loop */ /* Downsample the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ downsample(cinfo, fullsize_data[whichss], sampled_data, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* Dump the remaining data (may be less than full height if uninterleaved) */ (*cinfo->methods->extract_MCUs) (cinfo, sampled_data, (int) (cinfo->MCU_rows_in_scan - mcu_rows_output), MCU_output_catcher); /* Clean up after that stuff, then find the optimal entropy parameters */ (*cinfo->methods->extract_term) (cinfo); (*cinfo->methods->downsample_term) (cinfo); cinfo->completed_passes++; (*cinfo->methods->entropy_optimize) (cinfo, dump_scan_MCUs); /* Emit scan to output file */ /* Note: we can't do write_scan_header until entropy parameters are set! */ (*cinfo->methods->write_scan_header) (cinfo); cinfo->methods->entropy_output = cinfo->methods->write_jpeg_data; (*cinfo->methods->entropy_encode_init) (cinfo); dump_scan_MCUs(cinfo, cinfo->methods->entropy_encode); (*cinfo->methods->entropy_encode_term) (cinfo); (*cinfo->methods->write_scan_trailer) (cinfo); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ }
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; }
jinit_d_coef_controller(j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; coef = (my_coef_ptr) (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_input_pass = start_input_pass; coef->pub.start_output_pass = start_output_pass; coef->pub.column_left_boundary = 0; coef->pub.column_right_boundary = 0; coef->pub.MCU_columns_to_skip = 0; #ifdef BLOCK_SMOOTHING_SUPPORTED coef->coef_bits_latch = NULL; #endif #ifdef ANDROID_TILE_BASED_DECODE if (cinfo->tile_decode) { if (cinfo->progressive_mode) { /* Allocate one iMCU row virtual array, coef->whole_image[ci], * for each color component, padded to a multiple of h_samp_factor * DCT blocks in the horizontal direction. */ int ci, access_rows; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) compptr->v_samp_factor, // one iMCU row (JDIMENSION) access_rows); } coef->pub.consume_data_build_huffman_index = consume_data_build_huffman_index_progressive; coef->pub.consume_data = consume_data_multi_scan; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ coef->pub.decompress_data = decompress_onepass; } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data_build_huffman_index = consume_data_build_huffman_index_baseline; coef->pub.consume_data = dummy_consume_data; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ coef->pub.decompress_data = decompress_onepass; } return; } #endif /* Create the coefficient buffer. */ if (need_full_buffer) { #ifdef D_MULTISCAN_FILES_SUPPORTED /* Allocate a full-image virtual array for each component, */ /* padded to a multiple of samp_factor DCT blocks in each direction. */ /* Note we ask for a pre-zeroed array. */ int ci, access_rows; jpeg_component_info *compptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { access_rows = compptr->v_samp_factor; #ifdef BLOCK_SMOOTHING_SUPPORTED /* If block smoothing could be used, need a bigger window */ if (cinfo->progressive_mode) access_rows *= 3; #endif coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE, (JDIMENSION) jround_up((long) compptr->width_in_blocks, (long) compptr->h_samp_factor), (JDIMENSION) jround_up((long) compptr->height_in_blocks, (long) compptr->v_samp_factor), (JDIMENSION) access_rows); } coef->pub.consume_data = consume_data; coef->pub.decompress_data = decompress_data; coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { /* We only need a single-MCU buffer. */ JBLOCKROW buffer; int i; buffer = (JBLOCKROW) (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } coef->pub.consume_data = dummy_consume_data; coef->pub.decompress_data = decompress_onepass; coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */ } }
METHODDEF void complex_dcontroller (decompress_info_ptr cinfo) { long fullsize_width; /* # of samples per row in full-size buffers */ long cur_mcu_row; /* counts # of MCU rows processed */ long pixel_rows_output; /* # of pixel rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for dequantized coefficients (IDCT input) */ JBLOCKIMAGE coeff_data; /* Work buffer for cross-block smoothing input */ #ifdef BLOCK_SMOOTHING_SUPPORTED JBLOCKIMAGE bsmooth[3]; /* this is optional */ int whichb; #endif /* Work buffer for downsampled image data (see comments at head of file) */ JSAMPIMAGE sampled_data[2]; int whichss, ri; short ci, i; boolean single_scan; /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Allocate all working memory that doesn't depend on scan info */ /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); prepare_range_limit_table(cinfo); /* Get a big image: fullsize_image is sample data after upsampling. */ fullsize_image = (big_sarray_ptr *) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(big_sarray_ptr)); for (ci = 0; ci < cinfo->num_components; ci++) { fullsize_image[ci] = (*cinfo->emethods->request_big_sarray) (fullsize_width, jround_up(cinfo->image_height, (long) rows_in_mem), (long) rows_in_mem); } /* Also get an area for pointers to currently accessible chunks */ fullsize_ptrs = (JSAMPIMAGE) (*cinfo->emethods->alloc_small) (cinfo->num_components * SIZEOF(JSAMPARRAY)); /* Tell the memory manager to instantiate big arrays */ (*cinfo->emethods->alloc_big_arrays) /* extra sarray space is for downsampled-data buffers: */ ((long) (fullsize_width /* max width in samples */ * cinfo->max_v_samp_factor*(DCTSIZE+2) /* max height */ * cinfo->num_components), /* max components per scan */ /* extra barray space is for MCU-row buffers: */ (long) ((fullsize_width / DCTSIZE) /* max width in blocks */ * cinfo->max_v_samp_factor /* max height */ * cinfo->num_components /* max components per scan */ * (cinfo->do_block_smoothing ? 4 : 1)),/* how many of these we need */ /* no extra "medium"-object space */ (long) 0); /* NB: if quantizer needs any "medium" size objects, it must get them */ /* at color_quant_init time */ /* If file is single-scan, we can do color quantization prescan on-the-fly * during the scan (we must be doing 2-pass quantization, else this method * would not have been selected). If it is multiple scans, we have to make * a separate pass after we've collected all the components. (We could save * some I/O by doing CQ prescan during the last scan, but the extra logic * doesn't seem worth the trouble.) */ single_scan = (cinfo->comps_in_scan == cinfo->num_components); /* Account for passes needed (color quantizer adds its passes separately). * If multiscan file, we guess that each component has its own scan, * and increment completed_passes by the number of components in the scan. */ if (single_scan) cinfo->total_passes++; /* the single scan */ else { cinfo->total_passes += cinfo->num_components; /* guessed # of scans */ if (cinfo->two_pass_quantize) cinfo->total_passes++; /* account for separate CQ prescan pass */ } if (! cinfo->two_pass_quantize) cinfo->total_passes++; /* count output pass unless quantizer does it */ /* Loop over scans in file */ do { /* Prepare for this scan */ if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Need to read Vk MCU rows to obtain Vk block rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row provides Vk block rows */ mcu_rows_per_loop = 1; } /* Allocate scan-local working memory */ /* coeff_data holds a single MCU row of coefficient blocks */ coeff_data = alloc_MCU_row(cinfo); /* if doing cross-block smoothing, need extra space for its input */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { bsmooth[0] = alloc_MCU_row(cinfo); bsmooth[1] = alloc_MCU_row(cinfo); bsmooth[2] = alloc_MCU_row(cinfo); } #endif /* sampled_data is sample data before upsampling */ alloc_sampling_buffer(cinfo, sampled_data); /* line up the big buffers for components in this scan */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray) (fullsize_image[cinfo->cur_comp_info[ci]->component_index], (long) 0, TRUE); } /* Initialize to read scan data */ (*cinfo->methods->entropy_decode_init) (cinfo); (*cinfo->methods->upsample_init) (cinfo); (*cinfo->methods->disassemble_init) (cinfo); /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */ pixel_rows_output = 0; whichss = 1; /* arrange to start with sampled_data[0] */ for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan; cur_mcu_row += mcu_rows_per_loop) { (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row, cinfo->MCU_rows_in_scan); whichss ^= 1; /* switch to other downsampled-data buffer */ /* Obtain v_samp_factor block rows of each component in the scan. */ /* This is a single MCU row if interleaved, multiple MCU rows if not. */ /* In the noninterleaved case there might be fewer than v_samp_factor */ /* block rows remaining; if so, pad with copies of the last pixel row */ /* so that upsampling doesn't have to treat it as a special case. */ for (ri = 0; ri < mcu_rows_per_loop; ri++) { if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) { /* OK to actually read an MCU row. */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) get_smoothed_row(cinfo, coeff_data, bsmooth, &whichb, cur_mcu_row + ri); else #endif (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data); (*cinfo->methods->reverse_DCT) (cinfo, coeff_data, sampled_data[whichss], ri * DCTSIZE); } else { /* Need to pad out with copies of the last downsampled row. */ /* This can only happen if there is just one component. */ duplicate_row(sampled_data[whichss][0], cinfo->cur_comp_info[0]->downsampled_width, ri * DCTSIZE - 1, DCTSIZE); } } /* Upsample the data */ /* First time through is a special case */ if (cur_mcu_row) { /* Expand last row group of previous set */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* If single scan, can do color quantization prescan on-the-fly */ if (single_scan) (*cinfo->methods->color_quant_prescan) (cinfo, rows_in_mem, fullsize_ptrs, output_workspace[0]); /* Realign the big buffers */ pixel_rows_output += rows_in_mem; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { fullsize_ptrs[ci] = (*cinfo->emethods->access_big_sarray) (fullsize_image[cinfo->cur_comp_info[ci]->component_index], pixel_rows_output, TRUE); } /* Expand first row group of this set */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Expand first row group with dummy above-context */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Expand second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of loop over scan's data */ /* Expand the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ expand(cinfo, sampled_data[whichss], fullsize_ptrs, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* If single scan, finish on-the-fly color quantization prescan */ if (single_scan) (*cinfo->methods->color_quant_prescan) (cinfo, (int) (cinfo->image_height - pixel_rows_output), fullsize_ptrs, output_workspace[0]); /* Clean up after the scan */ (*cinfo->methods->disassemble_term) (cinfo); (*cinfo->methods->upsample_term) (cinfo); (*cinfo->methods->entropy_decode_term) (cinfo); (*cinfo->methods->read_scan_trailer) (cinfo); if (single_scan) cinfo->completed_passes++; else cinfo->completed_passes += cinfo->comps_in_scan; /* Release scan-local working memory */ free_MCU_row(cinfo, coeff_data); #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { free_MCU_row(cinfo, bsmooth[0]); free_MCU_row(cinfo, bsmooth[1]); free_MCU_row(cinfo, bsmooth[2]); } #endif free_sampling_buffer(cinfo, sampled_data); /* Repeat if there is another scan */ } while ((!single_scan) && (*cinfo->methods->read_scan_header) (cinfo)); if (single_scan) { /* If we expected just one scan, make SURE there's just one */ if ((*cinfo->methods->read_scan_header) (cinfo)) WARNMS(cinfo->emethods, "Didn't expect more than one scan"); /* We did the CQ prescan on-the-fly, so we are all set. */ } else { /* For multiple-scan file, do the CQ prescan as a separate pass. */ /* The main reason why prescan is passed the output_workspace is */ /* so that we can use scan_big_image to call it... */ if (cinfo->two_pass_quantize) scan_big_image(cinfo, cinfo->methods->color_quant_prescan); } /* Now that we've collected the data, do color processing and output */ if (cinfo->two_pass_quantize) (*cinfo->methods->color_quant_doit) (cinfo, scan_big_image); else scan_big_image(cinfo, emit_1pass); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ }
METHODDEF void simple_dcontroller (decompress_info_ptr cinfo) { long fullsize_width; /* # of samples per row in full-size buffers */ long cur_mcu_row; /* counts # of MCU rows processed */ long pixel_rows_output; /* # of pixel rows actually emitted */ int mcu_rows_per_loop; /* # of MCU rows processed per outer loop */ /* Work buffer for dequantized coefficients (IDCT input) */ JBLOCKIMAGE coeff_data; /* Work buffer for cross-block smoothing input */ #ifdef BLOCK_SMOOTHING_SUPPORTED JBLOCKIMAGE bsmooth[3]; /* this is optional */ int whichb; #endif /* Work buffer for downsampled image data (see comments at head of file) */ JSAMPIMAGE sampled_data[2]; /* Work buffer for upsampled data */ JSAMPIMAGE fullsize_data; int whichss, ri; short i; /* Compute dimensions of full-size pixel buffers */ /* Note these are the same whether interleaved or not. */ rows_in_mem = cinfo->max_v_samp_factor * DCTSIZE; fullsize_width = jround_up(cinfo->image_width, (long) (cinfo->max_h_samp_factor * DCTSIZE)); /* Prepare for single scan containing all components */ if (cinfo->comps_in_scan == 1) { noninterleaved_scan_setup(cinfo); /* Need to read Vk MCU rows to obtain Vk block rows */ mcu_rows_per_loop = cinfo->cur_comp_info[0]->v_samp_factor; } else { interleaved_scan_setup(cinfo); /* in an interleaved scan, one MCU row provides Vk block rows */ mcu_rows_per_loop = 1; } cinfo->total_passes++; /* Allocate working memory: */ /* coeff_data holds a single MCU row of coefficient blocks */ coeff_data = alloc_MCU_row(cinfo); /* if doing cross-block smoothing, need extra space for its input */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) { bsmooth[0] = alloc_MCU_row(cinfo); bsmooth[1] = alloc_MCU_row(cinfo); bsmooth[2] = alloc_MCU_row(cinfo); } #endif /* sampled_data is sample data before upsampling */ alloc_sampling_buffer(cinfo, sampled_data); /* fullsize_data is sample data after upsampling */ fullsize_data = alloc_sampimage(cinfo, (int) cinfo->num_components, (long) rows_in_mem, fullsize_width); /* output_workspace is the color-processed data */ output_workspace = alloc_sampimage(cinfo, (int) cinfo->final_out_comps, (long) rows_in_mem, fullsize_width); prepare_range_limit_table(cinfo); /* Tell the memory manager to instantiate big arrays. * We don't need any big arrays in this controller, * but some other module (like the output file writer) may need one. */ (*cinfo->emethods->alloc_big_arrays) ((long) 0, /* no more small sarrays */ (long) 0, /* no more small barrays */ (long) 0); /* no more "medium" objects */ /* NB: if quantizer needs any "medium" size objects, it must get them */ /* at color_quant_init time */ /* Initialize to read scan data */ (*cinfo->methods->entropy_decode_init) (cinfo); (*cinfo->methods->upsample_init) (cinfo); (*cinfo->methods->disassemble_init) (cinfo); /* Loop over scan's data: rows_in_mem pixel rows are processed per loop */ pixel_rows_output = 0; whichss = 1; /* arrange to start with sampled_data[0] */ for (cur_mcu_row = 0; cur_mcu_row < cinfo->MCU_rows_in_scan; cur_mcu_row += mcu_rows_per_loop) { (*cinfo->methods->progress_monitor) (cinfo, cur_mcu_row, cinfo->MCU_rows_in_scan); whichss ^= 1; /* switch to other downsampled-data buffer */ /* Obtain v_samp_factor block rows of each component in the scan. */ /* This is a single MCU row if interleaved, multiple MCU rows if not. */ /* In the noninterleaved case there might be fewer than v_samp_factor */ /* block rows remaining; if so, pad with copies of the last pixel row */ /* so that upsampling doesn't have to treat it as a special case. */ for (ri = 0; ri < mcu_rows_per_loop; ri++) { if (cur_mcu_row + ri < cinfo->MCU_rows_in_scan) { /* OK to actually read an MCU row. */ #ifdef BLOCK_SMOOTHING_SUPPORTED if (cinfo->do_block_smoothing) get_smoothed_row(cinfo, coeff_data, bsmooth, &whichb, cur_mcu_row + ri); else #endif (*cinfo->methods->disassemble_MCU) (cinfo, coeff_data); (*cinfo->methods->reverse_DCT) (cinfo, coeff_data, sampled_data[whichss], ri * DCTSIZE); } else { /* Need to pad out with copies of the last downsampled row. */ /* This can only happen if there is just one component. */ duplicate_row(sampled_data[whichss][0], cinfo->cur_comp_info[0]->downsampled_width, ri * DCTSIZE - 1, DCTSIZE); } } /* Upsample the data */ /* First time through is a special case */ if (cur_mcu_row) { /* Expand last row group of previous set */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) DCTSIZE, (short) (DCTSIZE+1), (short) 0, (short) (DCTSIZE-1)); /* and dump the previous set's expanded data */ emit_1pass (cinfo, rows_in_mem, fullsize_data, (JSAMPARRAY) NULL); pixel_rows_output += rows_in_mem; /* Expand first row group of this set */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (DCTSIZE+1), (short) 0, (short) 1, (short) 0); } else { /* Expand first row group with dummy above-context */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (-1), (short) 0, (short) 1, (short) 0); } /* Expand second through next-to-last row groups of this set */ for (i = 1; i <= DCTSIZE-2; i++) { expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (i-1), (short) i, (short) (i+1), (short) i); } } /* end of outer loop */ /* Expand the last row group with dummy below-context */ /* Note whichss points to last buffer side used */ expand(cinfo, sampled_data[whichss], fullsize_data, fullsize_width, (short) (DCTSIZE-2), (short) (DCTSIZE-1), (short) (-1), (short) (DCTSIZE-1)); /* and dump the remaining data (may be less than full height) */ emit_1pass (cinfo, (int) (cinfo->image_height - pixel_rows_output), fullsize_data, (JSAMPARRAY) NULL); /* Clean up after the scan */ (*cinfo->methods->disassemble_term) (cinfo); (*cinfo->methods->upsample_term) (cinfo); (*cinfo->methods->entropy_decode_term) (cinfo); (*cinfo->methods->read_scan_trailer) (cinfo); cinfo->completed_passes++; /* Verify that we've seen the whole input file */ if ((*cinfo->methods->read_scan_header) (cinfo)) WARNMS(cinfo->emethods, "Didn't expect more than one scan"); /* Release working memory */ /* (no work -- we let free_all release what's needful) */ }