vrshoot
diff libs/libjpeg/jcprepct.c @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/libjpeg/jcprepct.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,354 @@ 1.4 +/* 1.5 + * jcprepct.c 1.6 + * 1.7 + * Copyright (C) 1994-1996, Thomas G. Lane. 1.8 + * This file is part of the Independent JPEG Group's software. 1.9 + * For conditions of distribution and use, see the accompanying README file. 1.10 + * 1.11 + * This file contains the compression preprocessing controller. 1.12 + * This controller manages the color conversion, downsampling, 1.13 + * and edge expansion steps. 1.14 + * 1.15 + * Most of the complexity here is associated with buffering input rows 1.16 + * as required by the downsampler. See the comments at the head of 1.17 + * jcsample.c for the downsampler's needs. 1.18 + */ 1.19 + 1.20 +#define JPEG_INTERNALS 1.21 +#include "jinclude.h" 1.22 +#include "jpeglib.h" 1.23 + 1.24 + 1.25 +/* At present, jcsample.c can request context rows only for smoothing. 1.26 + * In the future, we might also need context rows for CCIR601 sampling 1.27 + * or other more-complex downsampling procedures. The code to support 1.28 + * context rows should be compiled only if needed. 1.29 + */ 1.30 +#ifdef INPUT_SMOOTHING_SUPPORTED 1.31 +#define CONTEXT_ROWS_SUPPORTED 1.32 +#endif 1.33 + 1.34 + 1.35 +/* 1.36 + * For the simple (no-context-row) case, we just need to buffer one 1.37 + * row group's worth of pixels for the downsampling step. At the bottom of 1.38 + * the image, we pad to a full row group by replicating the last pixel row. 1.39 + * The downsampler's last output row is then replicated if needed to pad 1.40 + * out to a full iMCU row. 1.41 + * 1.42 + * When providing context rows, we must buffer three row groups' worth of 1.43 + * pixels. Three row groups are physically allocated, but the row pointer 1.44 + * arrays are made five row groups high, with the extra pointers above and 1.45 + * below "wrapping around" to point to the last and first real row groups. 1.46 + * This allows the downsampler to access the proper context rows. 1.47 + * At the top and bottom of the image, we create dummy context rows by 1.48 + * copying the first or last real pixel row. This copying could be avoided 1.49 + * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the 1.50 + * trouble on the compression side. 1.51 + */ 1.52 + 1.53 + 1.54 +/* Private buffer controller object */ 1.55 + 1.56 +typedef struct { 1.57 + struct jpeg_c_prep_controller pub; /* public fields */ 1.58 + 1.59 + /* Downsampling input buffer. This buffer holds color-converted data 1.60 + * until we have enough to do a downsample step. 1.61 + */ 1.62 + JSAMPARRAY color_buf[MAX_COMPONENTS]; 1.63 + 1.64 + JDIMENSION rows_to_go; /* counts rows remaining in source image */ 1.65 + int next_buf_row; /* index of next row to store in color_buf */ 1.66 + 1.67 +#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */ 1.68 + int this_row_group; /* starting row index of group to process */ 1.69 + int next_buf_stop; /* downsample when we reach this index */ 1.70 +#endif 1.71 +} my_prep_controller; 1.72 + 1.73 +typedef my_prep_controller * my_prep_ptr; 1.74 + 1.75 + 1.76 +/* 1.77 + * Initialize for a processing pass. 1.78 + */ 1.79 + 1.80 +METHODDEF(void) 1.81 +start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) 1.82 +{ 1.83 + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; 1.84 + 1.85 + if (pass_mode != JBUF_PASS_THRU) 1.86 + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); 1.87 + 1.88 + /* Initialize total-height counter for detecting bottom of image */ 1.89 + prep->rows_to_go = cinfo->image_height; 1.90 + /* Mark the conversion buffer empty */ 1.91 + prep->next_buf_row = 0; 1.92 +#ifdef CONTEXT_ROWS_SUPPORTED 1.93 + /* Preset additional state variables for context mode. 1.94 + * These aren't used in non-context mode, so we needn't test which mode. 1.95 + */ 1.96 + prep->this_row_group = 0; 1.97 + /* Set next_buf_stop to stop after two row groups have been read in. */ 1.98 + prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; 1.99 +#endif 1.100 +} 1.101 + 1.102 + 1.103 +/* 1.104 + * Expand an image vertically from height input_rows to height output_rows, 1.105 + * by duplicating the bottom row. 1.106 + */ 1.107 + 1.108 +LOCAL(void) 1.109 +expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, 1.110 + int input_rows, int output_rows) 1.111 +{ 1.112 + register int row; 1.113 + 1.114 + for (row = input_rows; row < output_rows; row++) { 1.115 + jcopy_sample_rows(image_data, input_rows-1, image_data, row, 1.116 + 1, num_cols); 1.117 + } 1.118 +} 1.119 + 1.120 + 1.121 +/* 1.122 + * Process some data in the simple no-context case. 1.123 + * 1.124 + * Preprocessor output data is counted in "row groups". A row group 1.125 + * is defined to be v_samp_factor sample rows of each component. 1.126 + * Downsampling will produce this much data from each max_v_samp_factor 1.127 + * input rows. 1.128 + */ 1.129 + 1.130 +METHODDEF(void) 1.131 +pre_process_data (j_compress_ptr cinfo, 1.132 + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, 1.133 + JDIMENSION in_rows_avail, 1.134 + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, 1.135 + JDIMENSION out_row_groups_avail) 1.136 +{ 1.137 + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; 1.138 + int numrows, ci; 1.139 + JDIMENSION inrows; 1.140 + jpeg_component_info * compptr; 1.141 + 1.142 + while (*in_row_ctr < in_rows_avail && 1.143 + *out_row_group_ctr < out_row_groups_avail) { 1.144 + /* Do color conversion to fill the conversion buffer. */ 1.145 + inrows = in_rows_avail - *in_row_ctr; 1.146 + numrows = cinfo->max_v_samp_factor - prep->next_buf_row; 1.147 + numrows = (int) MIN((JDIMENSION) numrows, inrows); 1.148 + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, 1.149 + prep->color_buf, 1.150 + (JDIMENSION) prep->next_buf_row, 1.151 + numrows); 1.152 + *in_row_ctr += numrows; 1.153 + prep->next_buf_row += numrows; 1.154 + prep->rows_to_go -= numrows; 1.155 + /* If at bottom of image, pad to fill the conversion buffer. */ 1.156 + if (prep->rows_to_go == 0 && 1.157 + prep->next_buf_row < cinfo->max_v_samp_factor) { 1.158 + for (ci = 0; ci < cinfo->num_components; ci++) { 1.159 + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, 1.160 + prep->next_buf_row, cinfo->max_v_samp_factor); 1.161 + } 1.162 + prep->next_buf_row = cinfo->max_v_samp_factor; 1.163 + } 1.164 + /* If we've filled the conversion buffer, empty it. */ 1.165 + if (prep->next_buf_row == cinfo->max_v_samp_factor) { 1.166 + (*cinfo->downsample->downsample) (cinfo, 1.167 + prep->color_buf, (JDIMENSION) 0, 1.168 + output_buf, *out_row_group_ctr); 1.169 + prep->next_buf_row = 0; 1.170 + (*out_row_group_ctr)++; 1.171 + } 1.172 + /* If at bottom of image, pad the output to a full iMCU height. 1.173 + * Note we assume the caller is providing a one-iMCU-height output buffer! 1.174 + */ 1.175 + if (prep->rows_to_go == 0 && 1.176 + *out_row_group_ctr < out_row_groups_avail) { 1.177 + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 1.178 + ci++, compptr++) { 1.179 + expand_bottom_edge(output_buf[ci], 1.180 + compptr->width_in_blocks * DCTSIZE, 1.181 + (int) (*out_row_group_ctr * compptr->v_samp_factor), 1.182 + (int) (out_row_groups_avail * compptr->v_samp_factor)); 1.183 + } 1.184 + *out_row_group_ctr = out_row_groups_avail; 1.185 + break; /* can exit outer loop without test */ 1.186 + } 1.187 + } 1.188 +} 1.189 + 1.190 + 1.191 +#ifdef CONTEXT_ROWS_SUPPORTED 1.192 + 1.193 +/* 1.194 + * Process some data in the context case. 1.195 + */ 1.196 + 1.197 +METHODDEF(void) 1.198 +pre_process_context (j_compress_ptr cinfo, 1.199 + JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, 1.200 + JDIMENSION in_rows_avail, 1.201 + JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, 1.202 + JDIMENSION out_row_groups_avail) 1.203 +{ 1.204 + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; 1.205 + int numrows, ci; 1.206 + int buf_height = cinfo->max_v_samp_factor * 3; 1.207 + JDIMENSION inrows; 1.208 + 1.209 + while (*out_row_group_ctr < out_row_groups_avail) { 1.210 + if (*in_row_ctr < in_rows_avail) { 1.211 + /* Do color conversion to fill the conversion buffer. */ 1.212 + inrows = in_rows_avail - *in_row_ctr; 1.213 + numrows = prep->next_buf_stop - prep->next_buf_row; 1.214 + numrows = (int) MIN((JDIMENSION) numrows, inrows); 1.215 + (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, 1.216 + prep->color_buf, 1.217 + (JDIMENSION) prep->next_buf_row, 1.218 + numrows); 1.219 + /* Pad at top of image, if first time through */ 1.220 + if (prep->rows_to_go == cinfo->image_height) { 1.221 + for (ci = 0; ci < cinfo->num_components; ci++) { 1.222 + int row; 1.223 + for (row = 1; row <= cinfo->max_v_samp_factor; row++) { 1.224 + jcopy_sample_rows(prep->color_buf[ci], 0, 1.225 + prep->color_buf[ci], -row, 1.226 + 1, cinfo->image_width); 1.227 + } 1.228 + } 1.229 + } 1.230 + *in_row_ctr += numrows; 1.231 + prep->next_buf_row += numrows; 1.232 + prep->rows_to_go -= numrows; 1.233 + } else { 1.234 + /* Return for more data, unless we are at the bottom of the image. */ 1.235 + if (prep->rows_to_go != 0) 1.236 + break; 1.237 + /* When at bottom of image, pad to fill the conversion buffer. */ 1.238 + if (prep->next_buf_row < prep->next_buf_stop) { 1.239 + for (ci = 0; ci < cinfo->num_components; ci++) { 1.240 + expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, 1.241 + prep->next_buf_row, prep->next_buf_stop); 1.242 + } 1.243 + prep->next_buf_row = prep->next_buf_stop; 1.244 + } 1.245 + } 1.246 + /* If we've gotten enough data, downsample a row group. */ 1.247 + if (prep->next_buf_row == prep->next_buf_stop) { 1.248 + (*cinfo->downsample->downsample) (cinfo, 1.249 + prep->color_buf, 1.250 + (JDIMENSION) prep->this_row_group, 1.251 + output_buf, *out_row_group_ctr); 1.252 + (*out_row_group_ctr)++; 1.253 + /* Advance pointers with wraparound as necessary. */ 1.254 + prep->this_row_group += cinfo->max_v_samp_factor; 1.255 + if (prep->this_row_group >= buf_height) 1.256 + prep->this_row_group = 0; 1.257 + if (prep->next_buf_row >= buf_height) 1.258 + prep->next_buf_row = 0; 1.259 + prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; 1.260 + } 1.261 + } 1.262 +} 1.263 + 1.264 + 1.265 +/* 1.266 + * Create the wrapped-around downsampling input buffer needed for context mode. 1.267 + */ 1.268 + 1.269 +LOCAL(void) 1.270 +create_context_buffer (j_compress_ptr cinfo) 1.271 +{ 1.272 + my_prep_ptr prep = (my_prep_ptr) cinfo->prep; 1.273 + int rgroup_height = cinfo->max_v_samp_factor; 1.274 + int ci, i; 1.275 + jpeg_component_info * compptr; 1.276 + JSAMPARRAY true_buffer, fake_buffer; 1.277 + 1.278 + /* Grab enough space for fake row pointers for all the components; 1.279 + * we need five row groups' worth of pointers for each component. 1.280 + */ 1.281 + fake_buffer = (JSAMPARRAY) 1.282 + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 1.283 + (cinfo->num_components * 5 * rgroup_height) * 1.284 + SIZEOF(JSAMPROW)); 1.285 + 1.286 + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 1.287 + ci++, compptr++) { 1.288 + /* Allocate the actual buffer space (3 row groups) for this component. 1.289 + * We make the buffer wide enough to allow the downsampler to edge-expand 1.290 + * horizontally within the buffer, if it so chooses. 1.291 + */ 1.292 + true_buffer = (*cinfo->mem->alloc_sarray) 1.293 + ((j_common_ptr) cinfo, JPOOL_IMAGE, 1.294 + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * 1.295 + cinfo->max_h_samp_factor) / compptr->h_samp_factor), 1.296 + (JDIMENSION) (3 * rgroup_height)); 1.297 + /* Copy true buffer row pointers into the middle of the fake row array */ 1.298 + MEMCOPY(fake_buffer + rgroup_height, true_buffer, 1.299 + 3 * rgroup_height * SIZEOF(JSAMPROW)); 1.300 + /* Fill in the above and below wraparound pointers */ 1.301 + for (i = 0; i < rgroup_height; i++) { 1.302 + fake_buffer[i] = true_buffer[2 * rgroup_height + i]; 1.303 + fake_buffer[4 * rgroup_height + i] = true_buffer[i]; 1.304 + } 1.305 + prep->color_buf[ci] = fake_buffer + rgroup_height; 1.306 + fake_buffer += 5 * rgroup_height; /* point to space for next component */ 1.307 + } 1.308 +} 1.309 + 1.310 +#endif /* CONTEXT_ROWS_SUPPORTED */ 1.311 + 1.312 + 1.313 +/* 1.314 + * Initialize preprocessing controller. 1.315 + */ 1.316 + 1.317 +GLOBAL(void) 1.318 +jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) 1.319 +{ 1.320 + my_prep_ptr prep; 1.321 + int ci; 1.322 + jpeg_component_info * compptr; 1.323 + 1.324 + if (need_full_buffer) /* safety check */ 1.325 + ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); 1.326 + 1.327 + prep = (my_prep_ptr) 1.328 + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 1.329 + SIZEOF(my_prep_controller)); 1.330 + cinfo->prep = (struct jpeg_c_prep_controller *) prep; 1.331 + prep->pub.start_pass = start_pass_prep; 1.332 + 1.333 + /* Allocate the color conversion buffer. 1.334 + * We make the buffer wide enough to allow the downsampler to edge-expand 1.335 + * horizontally within the buffer, if it so chooses. 1.336 + */ 1.337 + if (cinfo->downsample->need_context_rows) { 1.338 + /* Set up to provide context rows */ 1.339 +#ifdef CONTEXT_ROWS_SUPPORTED 1.340 + prep->pub.pre_process_data = pre_process_context; 1.341 + create_context_buffer(cinfo); 1.342 +#else 1.343 + ERREXIT(cinfo, JERR_NOT_COMPILED); 1.344 +#endif 1.345 + } else { 1.346 + /* No context, just make it tall enough for one row group */ 1.347 + prep->pub.pre_process_data = pre_process_data; 1.348 + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 1.349 + ci++, compptr++) { 1.350 + prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) 1.351 + ((j_common_ptr) cinfo, JPOOL_IMAGE, 1.352 + (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * 1.353 + cinfo->max_h_samp_factor) / compptr->h_samp_factor), 1.354 + (JDIMENSION) cinfo->max_v_samp_factor); 1.355 + } 1.356 + } 1.357 +}