GLOBAL boolean jpeg_start_decompress (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_READY) { /* First call: initialize master control, select active modules */ jinit_master_decompress(cinfo); if (cinfo->buffered_image) { /* No more work here; expecting jpeg_start_output next */ cinfo->global_state = DSTATE_BUFIMAGE; return TRUE; } cinfo->global_state = DSTATE_PRELOAD; } if (cinfo->global_state == DSTATE_PRELOAD) { /* If file has multiple scans, absorb them all into the coef buffer */ if (cinfo->inputctl->has_multiple_scans) { #ifdef D_MULTISCAN_FILES_SUPPORTED for (;;) { int retcode; /* Call progress monitor hook if present */ if (cinfo->progress != NULL) (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); /* Absorb some more input */ retcode = (*cinfo->inputctl->consume_input) (cinfo); if (retcode == JPEG_SUSPENDED) return FALSE; if (retcode == JPEG_REACHED_EOI) break; /* Advance progress counter if appropriate */ if (cinfo->progress != NULL && (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { /* jdmaster underestimated number of scans; ratchet up one scan */ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; } } } #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif /* D_MULTISCAN_FILES_SUPPORTED */ } cinfo->output_scan_number = cinfo->input_scan_number; } else if (cinfo->global_state != DSTATE_PRESCAN) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any dummy output passes, and set up for the final pass */ return output_pass_setup(cinfo); }
METHODDEF(void) start_pass (j_decompress_ptr cinfo) { my_idct_ptr idct = (my_idct_ptr) cinfo->idct; int ci, i; jpeg_component_info *compptr; int method = 0; inverse_DCT_method_ptr method_ptr = NULL; JQUANT_TBL * qtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Select the proper IDCT routine for this component's scaling */ switch (compptr->DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case 1: method_ptr = jpeg_idct_1x1; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 2: method_ptr = jpeg_idct_2x2; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; case 4: method_ptr = jpeg_idct_4x4; method = JDCT_ISLOW; /* jidctred uses islow-style table */ break; #endif case DCTSIZE: switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: method_ptr = jpeg_idct_islow; method = JDCT_ISLOW; break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: method_ptr = jpeg_idct_ifast; method = JDCT_IFAST; break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: method_ptr = jpeg_idct_float; method = JDCT_FLOAT; break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } break; default: ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); break; } idct->pub.inverse_DCT[ci] = method_ptr; /* Create multiplier table from quant table. * However, we can skip this if the component is uninteresting * or if we already built the table. Also, if no quant table * has yet been saved for the component, we leave the * multiplier table all-zero; we'll be reading zeroes from the * coefficient controller's buffer anyway. */ if (! compptr->component_needed || idct->cur_method[ci] == method) continue; qtbl = compptr->quant_table; if (qtbl == NULL) /* happens if no data yet for component */ continue; idct->cur_method[ci] = method; switch (method) { #ifdef PROVIDE_ISLOW_TABLES case JDCT_ISLOW: { /* For LL&M IDCT method, multipliers are equal to raw quantization * coefficients, but are stored as ints to ensure access efficiency. */ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table; for (i = 0; i < DCTSIZE2; i++) { ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i]; } } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * For integer operation, the multiplier table is to be scaled by * IFAST_SCALE_BITS. */ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table; #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS for (i = 0; i < DCTSIZE2; i++) { ifmtbl[i] = (IFAST_MULT_TYPE) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), CONST_BITS-IFAST_SCALE_BITS); } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, multipliers are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 */ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fmtbl[i] = (FLOAT_MULT_TYPE) ((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col]); i++; } } } break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } }
jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) { jpeg_component_info * compptr; __boundcheck_metadata_store((void *)(&compptr),(void *)((size_t)(&compptr)+sizeof(compptr)*8-1)); int ci; __boundcheck_metadata_store((void *)(&ci),(void *)((size_t)(&ci)+sizeof(ci)*8-1)); #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ (compptr = &cinfo->comp_info[index], \ compptr->component_id = (id), \ compptr->h_samp_factor = (hsamp), \ compptr->v_samp_factor = (vsamp), \ compptr->quant_tbl_no = (quant), \ compptr->dc_tbl_no = (dctbl), \ compptr->ac_tbl_no = (actbl) ) /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* For all colorspaces, we use Q and Huff tables 0 for luminance components, * tables 1 for chrominance components. */ cinfo->jpeg_color_space = colorspace; cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ SET_COMP(0, 1, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ /* We default to 2x2 subsamples of chrominance */ SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ cinfo->num_components = 4; SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); break; case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); SET_COMP(3, 4, 2,2, 0, 0,0); break; case JCS_UNKNOWN: cinfo->num_components = cinfo->input_components; if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); for (ci = 0; ci < cinfo->num_components; ci++) { SET_COMP(ci, ci, 1,1, 0, 0,0); } break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } }
start_pass_fdctmgr (j_compress_ptr cinfo) { my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; int ci, qtblno, i; jpeg_component_info *compptr; JQUANT_TBL * qtbl; DCTELEM * dtbl; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { qtblno = compptr->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); qtbl = cinfo->quant_tbl_ptrs[qtblno]; /* Compute divisors for this quant table */ /* We may do this more than once for same table, but it's not a big deal */ switch (cinfo->dct_method) { #ifdef DCT_ISLOW_SUPPORTED case JDCT_ISLOW: /* For LL&M IDCT method, divisors are equal to raw quantization * coefficients multiplied by 8 (to counteract scaling). */ if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; } break; #endif #ifdef DCT_IFAST_SUPPORTED case JDCT_IFAST: { /* For AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. */ #define CONST_BITS 14 static const INT16 aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 }; SHIFT_TEMPS if (fdct->divisors[qtblno] == NULL) { fdct->divisors[qtblno] = (DCTELEM *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(DCTELEM)); } dtbl = fdct->divisors[qtblno]; for (i = 0; i < DCTSIZE2; i++) { dtbl[i] = (DCTELEM) DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], (INT32) aanscales[i]), CONST_BITS-3); } } break; #endif #ifdef DCT_FLOAT_SUPPORTED case JDCT_FLOAT: { /* For float AA&N IDCT method, divisors are equal to quantization * coefficients scaled by scalefactor[row]*scalefactor[col], where * scalefactor[0] = 1 * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 * We apply a further scale factor of 8. * What's actually stored is 1/divisor so that the inner loop can * use a multiplication rather than a division. */ FAST_FLOAT * fdtbl; int row, col; static const double aanscalefactor[DCTSIZE] = { 1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379 }; if (fdct->float_divisors[qtblno] == NULL) { fdct->float_divisors[qtblno] = (FAST_FLOAT *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, DCTSIZE2 * SIZEOF(FAST_FLOAT)); } fdtbl = fdct->float_divisors[qtblno]; i = 0; for (row = 0; row < DCTSIZE; row++) { for (col = 0; col < DCTSIZE; col++) { fdtbl[i] = (FAST_FLOAT) (1.0 / (((double) qtbl->quantval[i] * aanscalefactor[row] * aanscalefactor[col] * 8.0))); i++; } } } break; #endif default: ERREXIT(cinfo, JERR_NOT_COMPILED); break; } } }
initial_setup (j_decompress_ptr cinfo) /* Called once, when first SOS marker is reached */ { int ci; jpeg_component_info *compptr; /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. * In the full decompressor, this will be overridden by jdmaster.c; * but in the transcoder, jdmaster.c is not used, so we must do it here. */ cinfo->min_DCT_scaled_size = DCTSIZE; /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->DCT_scaled_size = DCTSIZE; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* downsampled_width and downsampled_height will also be overridden by * jdmaster.c if we are doing full decompression. The transcoder library * doesn't use these values, but the calling application might. */ /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed, until color conversion says otherwise */ compptr->component_needed = true; /* Mark no quantization table yet saved for component */ compptr->quant_table = NULL; } /* Compute number of fully interleaved MCU rows. */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); /* Decide whether file contains multiple scans */ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode) cinfo->inputctl->has_multiple_scans = true; else cinfo->inputctl->has_multiple_scans = FALSE; }
parse_switches (j_decompress_ptr cinfo, int argc, char **argv, int last_file_arg_seen, boolean for_real) /* Parse optional switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) * for_real is FALSE on the first (dummy) pass; we may skip any expensive * processing. */ { int argn; char * arg; /* Set up default JPEG parameters. */ requested_fmt = DEFAULT_FMT; /* set default output file format */ outfilename = NULL; cinfo->err->trace_level = 0; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processed */ } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ if (keymatch(arg, "bmp", 1)) { /* BMP output format. */ requested_fmt = FMT_BMP; } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { /* Do color quantization. */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); cinfo->desired_number_of_colors = val; cinfo->quantize_colors = TRUE; } else if (keymatch(arg, "dct", 2)) { /* Select IDCT algorithm. */ if (++argn >= argc) /* advance to next argument */ usage(); if (keymatch(argv[argn], "int", 1)) { cinfo->dct_method = JDCT_ISLOW; } else if (keymatch(argv[argn], "fast", 2)) { cinfo->dct_method = JDCT_IFAST; } else if (keymatch(argv[argn], "float", 2)) { cinfo->dct_method = JDCT_FLOAT; } else usage(); } else if (keymatch(arg, "dither", 2)) { /* Select dithering algorithm. */ if (++argn >= argc) /* advance to next argument */ usage(); if (keymatch(argv[argn], "fs", 2)) { cinfo->dither_mode = JDITHER_FS; } else if (keymatch(argv[argn], "none", 2)) { cinfo->dither_mode = JDITHER_NONE; } else if (keymatch(argv[argn], "ordered", 2)) { cinfo->dither_mode = JDITHER_ORDERED; } else usage(); } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ static boolean printed_version = FALSE; if (! printed_version) { fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", JVERSION, JCOPYRIGHT); printed_version = TRUE; } cinfo->err->trace_level++; } else if (keymatch(arg, "fast", 1)) { /* Select recommended processing options for quick-and-dirty output. */ cinfo->two_pass_quantize = FALSE; cinfo->dither_mode = JDITHER_ORDERED; if (! cinfo->quantize_colors) /* don't override an earlier -colors */ cinfo->desired_number_of_colors = 216; cinfo->dct_method = JDCT_FASTEST; cinfo->do_fancy_upsampling = FALSE; } else if (keymatch(arg, "gif", 1)) { /* GIF output format. */ requested_fmt = FMT_GIF; } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { /* Force monochrome output. */ cinfo->out_color_space = JCS_GRAYSCALE; } else if (keymatch(arg, "map", 3)) { /* Quantize to a color map taken from an input file. */ if (++argn >= argc) /* advance to next argument */ usage(); if (for_real) { /* too expensive to do twice! */ #ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */ FILE * mapfile; if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]); exit(EXIT_FAILURE); } read_color_map(cinfo, mapfile); fclose(mapfile); cinfo->quantize_colors = TRUE; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } } else if (keymatch(arg, "maxmemory", 3)) { /* Maximum memory in Kb (or Mb with 'm'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (ch == 'm' || ch == 'M') lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nosmooth", 3)) { /* Suppress fancy upsampling */ cinfo->do_fancy_upsampling = FALSE; } else if (keymatch(arg, "onepass", 3)) { /* Use fast one-pass quantization. */ cinfo->two_pass_quantize = FALSE; } else if (keymatch(arg, "os2", 3)) { /* BMP output format (OS/2 flavor). */ requested_fmt = FMT_OS2; } else if (keymatch(arg, "outfile", 4)) { /* Set output file name. */ if (++argn >= argc) /* advance to next argument */ usage(); outfilename = argv[argn]; /* save it away for later use */ } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { /* PPM/PGM output format. */ requested_fmt = FMT_PPM; } else if (keymatch(arg, "rle", 1)) { /* RLE output format. */ requested_fmt = FMT_RLE; } else if (keymatch(arg, "scale", 1)) { /* Scale the output image by a fraction M/N. */ if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d/%d", &cinfo->scale_num, &cinfo->scale_denom) != 2) usage(); } else if (keymatch(arg, "targa", 1)) { /* Targa output format. */ requested_fmt = FMT_TARGA; } else { usage(); /* bogus switch */ } } return argn; /* return index of next arg (file name) */ }
jtransform_adjust_parameters (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, jvirt_barray_ptr *src_coef_arrays, jpeg_transform_info *info) { /* If force-to-grayscale is requested, adjust destination parameters */ if (info->force_grayscale) { /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed * properly. Among other things, the target h_samp_factor & v_samp_factor * will get set to 1, which typically won't match the source. * In fact we do this even if the source is already grayscale; that * provides an easy way of coercing a grayscale JPEG with funny sampling * factors to the customary 1,1. (Some decoders fail on other factors.) */ if ((dstinfo->jpeg_color_space == JCS_YCbCr && dstinfo->num_components == 3) || (dstinfo->jpeg_color_space == JCS_GRAYSCALE && dstinfo->num_components == 1)) { /* We have to preserve the source's quantization table number. */ int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no; jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE); dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no; } else { /* Sorry, can't do it */ ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL); } } /* Correct the destination's image dimensions etc if necessary */ switch (info->transform) { case JXFORM_NONE: /* Nothing to do */ break; case JXFORM_FLIP_H: if (info->trim) trim_right_edge(dstinfo); break; case JXFORM_FLIP_V: if (info->trim) trim_bottom_edge(dstinfo); break; case JXFORM_TRANSPOSE: transpose_critical_parameters(dstinfo); /* transpose does NOT have to trim anything */ break; case JXFORM_TRANSVERSE: transpose_critical_parameters(dstinfo); if (info->trim) { trim_right_edge(dstinfo); trim_bottom_edge(dstinfo); } break; case JXFORM_ROT_90: transpose_critical_parameters(dstinfo); if (info->trim) trim_right_edge(dstinfo); break; case JXFORM_ROT_180: if (info->trim) { trim_right_edge(dstinfo); trim_bottom_edge(dstinfo); } break; case JXFORM_ROT_270: transpose_critical_parameters(dstinfo); if (info->trim) trim_bottom_edge(dstinfo); break; } /* Return the appropriate output data set */ if (info->workspace_coef_arrays != NULL) return info->workspace_coef_arrays; return src_coef_arrays; }
jinit_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; boolean need_buffer; 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); /* 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_h_scaled_size) / cinfo->min_DCT_h_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / cinfo->min_DCT_v_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 case for 2h1v upsampling */ upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { /* Special case for 2h2v upsampling */ 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); } } }
LOCAL void per_scan_setup (j_compress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = DCTSIZE; compptr->last_col_width = 1; compptr->last_row_height = 1; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (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]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); 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 = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); } }
/*{{{ histogram(transform_info_ptr tinfo) {*/ METHODDEF DATATYPE * histogram(transform_info_ptr tinfo) { struct histogram_local_struct *localp=(struct histogram_local_struct *)tinfo->methods->local_storage; transform_argument *args=tinfo->methods->arguments; HIST_TYPE *histogram_data=localp->boundaries.histogram; DATATYPE hist_min=localp->boundaries.hist_min, hist_resolution=localp->boundaries.hist_resolution; int nr_of_bins=localp->boundaries.nr_of_bins; int from_x=localp->from_x, to_x=localp->to_x; int outliers=args[ARGS_ASSIGN_OUTLIERS].is_set; int channels=tinfo->nr_of_channels, itemsize=tinfo->itemsize; int channelskip, freqskip, channel, point, points, freq, nfreq; int out_binskip, out_freqskip, out_pointskip, out_channelskip, out_shifts; int start_freq, end_freq, start_point, end_point; int freq_offset, channel_offset, point_offset; array tsdata; if (itemsize>1) { ERREXIT(tinfo->emethods, "histogram: Can't handle multiple items in input data.\n"); } /*{{{ Set up tsdata array: elements=points, vectors=items*/ tsdata.vector_skip=1; tsdata.nr_of_vectors=itemsize; if (from_x<0) from_x=0; if (tinfo->data_type==FREQ_DATA) { nfreq=tinfo->nroffreq; freqskip=itemsize; channelskip=nfreq*itemsize; tsdata.element_skip=channels*channelskip; out_shifts=points=tinfo->nrofshifts; if (to_x<0 || to_x>nfreq) to_x=nfreq; start_freq=from_x; end_freq=to_x; start_point=0; end_point=points; if (args[ARGS_COLLAPSE_POINTS].is_set) { out_pointskip=0; } else { out_pointskip=(end_freq-start_freq)*nr_of_bins*(args[ARGS_COLLAPSE_CHANNELS].is_set ? 1 : channels); } } else { nfreq=1; freqskip=0; points=tinfo->nr_of_points; if (tinfo->multiplexed) { tsdata.element_skip=channels*itemsize; channelskip=itemsize; } else { tsdata.element_skip=itemsize; channelskip=tinfo->nr_of_points*itemsize; } if (to_x<0 || to_x>points) to_x=points; start_freq=0; end_freq=1; start_point=from_x; end_point=to_x; out_shifts=1; out_pointskip=(args[ARGS_COLLAPSE_POINTS].is_set ? 0: 1); } tsdata.nr_of_elements=points; array_setreadwrite(&tsdata); if (to_x<=from_x) { ERREXIT(tinfo->emethods, "histogram: minx>=maxx. Please respecify these parameters.\n"); } out_binskip=(args[ARGS_COLLAPSE_POINTS].is_set ? 1 : to_x-from_x); out_channelskip=(args[ARGS_COLLAPSE_CHANNELS].is_set ? 0 : out_binskip*nr_of_bins); out_freqskip=1; /*}}} */ if (histogram_data==(HIST_TYPE *)NULL) { /*{{{ First incoming epoch: Initialize working memory*/ memcpy(&localp->tinfo, tinfo, sizeof(struct transform_info_struct)); /* Protect the memory spaces we may need: */ tinfo->comment=NULL; tinfo->probepos=NULL; if (args[ARGS_COLLAPSE_CHANNELS].is_set) { localp->tinfo.length_of_output_region=out_binskip*nr_of_bins*out_shifts; localp->tinfo.nr_of_channels=1; } else { tinfo->channelnames=NULL; localp->tinfo.length_of_output_region=channels*out_channelskip*out_shifts; } if ((histogram_data=(HIST_TYPE *)calloc(localp->tinfo.length_of_output_region, sizeof(DATATYPE)))==NULL) { ERREXIT(tinfo->emethods, "histogram: Error allocating epoch memory\n"); } localp->tinfo.tsdata=(DATATYPE *)(localp->boundaries.histogram=histogram_data); localp->tinfo.itemsize=out_binskip; localp->tinfo.leaveright=0; if (tinfo->data_type==FREQ_DATA) { localp->tinfo.nroffreq=nr_of_bins; /* nrofshifts remains unmodified */ } else { localp->tinfo.nr_of_points=nr_of_bins; } localp->tinfo.multiplexed=FALSE; localp->to_x=to_x; localp->from_x=from_x; /*}}} */ } /*{{{ Register the input data*/ freq_offset=0; for (freq=start_freq; freq<end_freq; freq++) { tsdata.start=tinfo->tsdata+freq*freqskip; channel_offset=freq_offset; for (channel=0; channel<channels; channel++) { array_setreadwrite(&tsdata); array_reset(&tsdata); tsdata.current_element=start_point; point_offset=channel_offset; for (point=start_point; point<end_point; point++) { int bin=(int)rint((array_scan(&tsdata)-hist_min)/hist_resolution); if (bin>=0 && bin<nr_of_bins) { histogram_data[point_offset+bin*out_binskip]++; } else if (outliers) { if (bin<0) histogram_data[point_offset]++; else histogram_data[point_offset+(nr_of_bins-1)*out_binskip]++; } point_offset+=out_pointskip; } tsdata.start+=channelskip; channel_offset+=out_channelskip; } freq_offset+=out_freqskip; } /*}}} */ free_tinfo(tinfo); /* Free everything from the old epoch */ tinfo->nrofaverages++; return localp->tinfo.tsdata; }
GLOBAL void jpeg_finish_compress (j_compress_ptr cinfo) { JDIMENSION iMCU_row; if (cinfo->global_state == CSTATE_SCANNING || cinfo->global_state == CSTATE_RAW_OK) { /* Terminate first pass */ if (cinfo->next_scanline < cinfo->image_height) ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); (*cinfo->master->finish_pass) (cinfo); } else if (cinfo->global_state != CSTATE_WRCOEFS) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform any remaining passes */ while (! cinfo->master->is_last_pass) { (*cinfo->master->prepare_for_pass) (cinfo); for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) iMCU_row; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* We bypass the main controller and invoke coef controller directly; * all work is being done from the coefficient buffer. */ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } (*cinfo->master->finish_pass) (cinfo); } /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); }
jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, c_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; c_derived_tbl *dtbl; int p, i, l, lastp, si, maxsymbol; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (c_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(c_derived_tbl)); dtbl = *pdtbl; /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. * BUG FIX 2001-09-03: Comparison must be >, not >= */ if (((IJG_INT32) code) > (((IJG_INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set all codeless symbols to have code length 0; * this lets us detect duplicate VAL entries here, and later * allows emit_bits to detect any attempt to emit such symbols. */ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); /* This is also a convenient place to check for out-of-range * and duplicated VAL entries. We allow 0..255 for AC symbols * but only 0..16 for DC. (We could constrain them further * based on data depth and mode, but this seems enough.) */ maxsymbol = isDC ? 16 : 255; for (p = 0; p < lastp; p++) { i = htbl->huffval[p]; if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); dtbl->ehufco[i] = huffcode[p]; dtbl->ehufsi[i] = huffsize[p]; } }
jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ int codesize[257]; /* codesize[k] = code length of symbol k */ int others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; long v; /* This algorithm is explained in section K.2 of the JPEG standard */ MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ freq[256] = 1; /* make sure 256 has a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 * will be placed last in the largest codeword category. */ /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { /* Find the smallest nonzero frequency, set c1 = its symbol */ /* In case of ties, take the larger symbol number */ c1 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; } } /* Find the next smallest nonzero frequency, set c2 = its symbol */ /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } others[c1] = c2; /* chain c2 onto c1's tree branch */ /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. * Here is what the JPEG spec says about how this next bit works: * Since symbols are paired for the longest Huffman code, the symbols are * removed from this length category two at a time. The prefix for the pair * (which is one bit shorter) is allocated to one of the pair; then, * skipping the BITS entry for that prefix length, a code word from the next * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) j--; bits[i] = (UINT8)(bits[i] - 2); /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] = (UINT8)(bits[j+1] + 2); /* two new symbols in this length */ bits[j]--; /* symbol of this length is now a prefix */ } } /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. */ p = 0; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { htbl->huffval[p] = (UINT8) j; p++; } } } /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; }
jpeg_open_backing_store (j_common_ptr cinfo, struct backing_store_struct *, long ) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); }
master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; boolean use_c_buffer; long samplesperrow; JDIMENSION jd_samplesperrow; /* Initialize dimensions and other stuff */ jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); /* Width of an output scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* Initialize my private state */ master->pass_number = 0; master->using_merged_upsample = use_merged_upsample(cinfo); /* Color quantizer selection */ master->quantizer_1pass = NULL; master->quantizer_2pass = NULL; /* No mode changes if not using buffered-image mode. */ if (! cinfo->quantize_colors || ! cinfo->buffered_image) { cinfo->enable_1pass_quant = FALSE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; } if (cinfo->quantize_colors) { if (cinfo->raw_data_out) ERREXIT(cinfo, JERR_NOTIMPL); /* 2-pass quantizer only works in 3-component color space. */ if (cinfo->out_color_components != 3) { cinfo->enable_1pass_quant = TRUE; cinfo->enable_external_quant = FALSE; cinfo->enable_2pass_quant = FALSE; cinfo->colormap = NULL; } else if (cinfo->colormap != NULL) { cinfo->enable_external_quant = TRUE; } else if (cinfo->two_pass_quantize) { cinfo->enable_2pass_quant = TRUE; } else { cinfo->enable_1pass_quant = TRUE; } if (cinfo->enable_1pass_quant) { #ifdef QUANT_1PASS_SUPPORTED jinit_1pass_quantizer(cinfo); master->quantizer_1pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* We use the 2-pass code to map to external colormaps. */ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) { #ifdef QUANT_2PASS_SUPPORTED jinit_2pass_quantizer(cinfo); master->quantizer_2pass = cinfo->cquantize; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } /* If both quantizers are initialized, the 2-pass one is left active; * this is necessary for starting with quantization to an external map. */ } /* Post-processing: in particular, color conversion first */ if (! cinfo->raw_data_out) { if (master->using_merged_upsample) { #ifdef UPSAMPLE_MERGING_SUPPORTED jinit_merged_upsampler(cinfo); /* does color conversion too */ #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { jinit_color_deconverter(cinfo); jinit_upsampler(cinfo); } jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant); } /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { #ifdef D_ARITH_CODING_SUPPORTED jinit_arith_decoder(cinfo); #else ERREXIT(cinfo, JERR_ARITH_NOTIMPL); #endif } else { if (cinfo->progressive_mode) { #ifdef D_PROGRESSIVE_SUPPORTED jinit_phuff_decoder(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else jinit_huff_decoder(cinfo); } /* Initialize principal buffer controllers. */ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image; jinit_d_coef_controller(cinfo, use_c_buffer); if (! cinfo->raw_data_out) jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Initialize input side of decompressor to consume first scan. */ (*cinfo->inputctl->start_input_pass) (cinfo); #ifdef D_MULTISCAN_FILES_SUPPORTED /* If jpeg_start_decompress will read the whole file, initialize * progress monitoring appropriately. The input step is counted * as one pass. */ if (cinfo->progress != NULL && ! cinfo->buffered_image && cinfo->inputctl->has_multiple_scans) { int nscans; /* Estimate number of scans to set pass_limit. */ if (cinfo->progressive_mode) { /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */ nscans = 2 + 3 * cinfo->num_components; } else { /* For a nonprogressive multiscan file, estimate 1 scan per component. */ nscans = cinfo->num_components; } cinfo->progress->pass_counter = 0L; cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans; cinfo->progress->completed_passes = 0; cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2); /* Count the input pass as done */ master->pass_number++; } #endif /* D_MULTISCAN_FILES_SUPPORTED */ }
LOCAL void initial_setup (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { int ci; jpeg_component_info *compptr; long samplesperrow; JDIMENSION jd_samplesperrow; /* Sanity check on image dimensions */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0 || cinfo->input_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); /* Width of an input scanline must be representable as JDIMENSION. */ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; jd_samplesperrow = (JDIMENSION) samplesperrow; if ((long) jd_samplesperrow != samplesperrow) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* For compression, we never do DCT scaling. */ compptr->DCT_scaled_size = DCTSIZE; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed (this flag isn't actually used for compression) */ compptr->component_needed = TRUE; } /* Compute number of fully interleaved MCU rows (number of times that * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); }
METHODDEF int start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { tga_source_ptr source = (tga_source_ptr) sinfo; U_CHAR targaheader[18]; int idlen, cmaptype, subtype, flags, interlace_type, components; unsigned int width, height, maplen; boolean is_bottom_up; #define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \ (((unsigned int) UCH(targaheader[offset+1])) << 8)) if (! ReadOK(source->pub.input_file, targaheader, 18)) ERREXIT(cinfo, JERR_INPUT_EOF); /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ if (targaheader[16] == 15) targaheader[16] = 16; idlen = UCH(targaheader[0]); cmaptype = UCH(targaheader[1]); subtype = UCH(targaheader[2]); maplen = GET_2B(5); width = GET_2B(12); height = GET_2B(14); source->pixel_size = UCH(targaheader[16]) >> 3; flags = UCH(targaheader[17]); /* Image Descriptor byte */ is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ interlace_type = flags >> 6; /* bits 6/7 are interlace code */ if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ source->pixel_size < 1 || source->pixel_size > 4 || (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ interlace_type != 0) /* currently don't allow interlaced image */ ERREXIT(cinfo, JERR_TGA_BADPARMS); if (subtype > 8) { /* It's an RLE-coded file */ source->read_pixel = read_rle_pixel; source->block_count = source->dup_pixel_count = 0; subtype -= 8; } else { /* Non-RLE file */ source->read_pixel = read_non_rle_pixel; } /* Now should have subtype 1, 2, or 3 */ components = 3; /* until proven different */ cinfo->in_color_space = JCS_RGB; switch (subtype) { case 1: /* Colormapped image */ if (source->pixel_size == 1 && cmaptype == 1) source->get_pixel_rows = get_8bit_row; else ERREXIT(cinfo, JERR_TGA_BADPARMS); TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height); break; case 2: /* RGB image */ switch (source->pixel_size) { case 2: source->get_pixel_rows = get_16bit_row; break; case 3: source->get_pixel_rows = get_24bit_row; break; case 4: printf(" is 32bpp!"); return 1; // no 32bpp support // source->get_pixel_rows = get_32bit_row; break; default: ERREXIT(cinfo, JERR_TGA_BADPARMS); break; } TRACEMS2(cinfo, 1, JTRC_TGA, width, height); break; case 3: /* Grayscale image */ components = 1; cinfo->in_color_space = JCS_GRAYSCALE; if (source->pixel_size == 1) source->get_pixel_rows = get_8bit_gray_row; else ERREXIT(cinfo, JERR_TGA_BADPARMS); TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height); break; default: ERREXIT(cinfo, JERR_TGA_BADPARMS); break; } if (is_bottom_up) { /* Create a virtual array to buffer the upside-down image. */ source->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1); if (cinfo->progress != NULL) { cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; progress->total_extra_passes++; /* count file input as separate pass */ } /* source->pub.buffer will point to the virtual array. */ source->pub.buffer_height = 1; /* in case anyone looks at it */ source->pub.get_pixel_rows = preload_image; } else { /* Don't need a virtual array, but do need a one-row input buffer. */ source->whole_image = NULL; source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) width * components, (JDIMENSION) 1); source->pub.buffer_height = 1; source->pub.get_pixel_rows = source->get_pixel_rows; } while (idlen--) /* Throw away ID field */ (void) read_byte(source); if (maplen > 0) { if (maplen > 256 || GET_2B(3) != 0) ERREXIT(cinfo, JERR_TGA_BADCMAP); /* Allocate space to store the colormap */ source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3); /* and read it from the file */ read_colormap(source, (int) maplen, UCH(targaheader[7])); } else { if (cmaptype) /* but you promised a cmap! */ ERREXIT(cinfo, JERR_TGA_BADPARMS); source->colormap = NULL; } cinfo->input_components = components; cinfo->data_precision = 8; cinfo->image_width = width; cinfo->image_height = height; return 0; }
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) */ }
int main (int argc, char **argv) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; #ifdef PROGRESS_REPORT struct cdjpeg_progress_mgr progress; #endif int file_index; djpeg_dest_ptr dest_mgr = NULL; FILE * input_file; FILE * output_file; JDIMENSION num_scanlines; /* On Mac, fetch a command line. */ #ifdef USE_CCOMMAND argc = ccommand(&argv); #endif progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "djpeg"; /* in case C library doesn't provide it */ /* Initialize the JPEG decompression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = cdjpeg_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; jerr.last_addon_message = JMSG_LASTADDONCODE; /* Insert custom COM marker processor. */ jpeg_set_marker_processor(&cinfo, JPEG_COM, COM_handler); /* Now safe to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER enable_signal_catcher((j_common_ptr) &cinfo); #endif /* Scan command line to find file names. */ /* It is convenient to use just one switch-parsing routine, but the switch * values read here are ignored; we will rescan the switches after opening * the input file. * (Exception: tracing level set here controls verbosity for COM markers * found during jpeg_read_header...) */ file_index = parse_switches(&cinfo, argc, argv, 0, FALSE); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ input_file = read_stdin(); } /* Open the output file. */ if (outfilename != NULL) { if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ output_file = write_stdout(); } #ifdef PROGRESS_REPORT start_progress_monitor((j_common_ptr) &cinfo, &progress); #endif /* Specify data source for decompression */ jpeg_stdio_src(&cinfo, input_file); /* Read file header, set default decompression parameters */ (void) jpeg_read_header(&cinfo, TRUE); /* Adjust default decompression parameters by re-parsing the options */ file_index = parse_switches(&cinfo, argc, argv, 0, TRUE); /* Initialize the output module now to let it override any crucial * option settings (for instance, GIF wants to force color quantization). */ switch (requested_fmt) { #ifdef BMP_SUPPORTED case FMT_BMP: dest_mgr = jinit_write_bmp(&cinfo, FALSE); break; case FMT_OS2: dest_mgr = jinit_write_bmp(&cinfo, TRUE); break; #endif #ifdef GIF_SUPPORTED case FMT_GIF: dest_mgr = jinit_write_gif(&cinfo); break; #endif #ifdef PPM_SUPPORTED case FMT_PPM: dest_mgr = jinit_write_ppm(&cinfo); break; #endif #ifdef RLE_SUPPORTED case FMT_RLE: dest_mgr = jinit_write_rle(&cinfo); break; #endif #ifdef TARGA_SUPPORTED case FMT_TARGA: dest_mgr = jinit_write_targa(&cinfo); break; #endif default: ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); break; } dest_mgr->output_file = output_file; /* Start decompressor */ (void) jpeg_start_decompress(&cinfo); /* Write output file header */ (*dest_mgr->start_output) (&cinfo, dest_mgr); /* Process data */ while (cinfo.output_scanline < cinfo.output_height) { num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, dest_mgr->buffer_height); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); } #ifdef PROGRESS_REPORT /* Hack: count final pass as done in case finish_output does an extra pass. * The library won't have updated completed_passes. */ progress.pub.completed_passes = progress.pub.total_passes; #endif /* Finish decompression and release memory. * I must do it in this order because output module has allocated memory * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory. */ (*dest_mgr->finish_output) (&cinfo, dest_mgr); (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); /* Close files, if we opened them */ if (input_file != stdin) fclose(input_file); if (output_file != stdout) fclose(output_file); #ifdef PROGRESS_REPORT end_progress_monitor((j_common_ptr) &cinfo); #endif /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ }
METHODDEF void multi_eopt_ccontroller (compress_info_ptr cinfo) { ERREXIT(cinfo->emethods, "Not implemented yet"); }
jinit_color_deconverter (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; cconvert->pub.start_pass = start_pass_dcolor; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->num_components < 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; } /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->comp_info[ci].component_needed = FALSE; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: cinfo->out_color_components = RGB_PIXELSIZE; if (cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { cconvert->pub.color_convert = gray_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { cconvert->pub.color_convert = ycck_cmyk_convert; build_ycc_rgb_table(cinfo); } else if (cinfo->jpeg_color_space == JCS_CMYK) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; cconvert->pub.color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; } if (cinfo->quantize_colors) cinfo->output_components = 1; /* single colormapped output component */ else cinfo->output_components = cinfo->out_color_components; }
GLOBAL void jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); }
per_scan_setup (j_decompress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ { int ci, mcublks, tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->DCT_scaled_size; compptr->last_col_width = 1; /* For noninterleaved scans, it is convenient to define last_row_height * as the number of block rows present in the last iMCU row. */ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); if (tmp == 0) tmp = compptr->v_samp_factor; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (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]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = tmp; tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } }
start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { bmp_source_ptr source = (bmp_source_ptr) sinfo; U_CHAR bmpfileheader[14]; U_CHAR bmpinfoheader[64]; #define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \ (((unsigned int) UCH(array[offset+1])) << 8)) #define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \ (((INT32) UCH(array[offset+1])) << 8) + \ (((INT32) UCH(array[offset+2])) << 16) + \ (((INT32) UCH(array[offset+3])) << 24)) INT32 bfOffBits; INT32 headerSize; INT32 biWidth; INT32 biHeight; unsigned int biPlanes; INT32 biCompression; INT32 biXPelsPerMeter,biYPelsPerMeter; INT32 biClrUsed = 0; int mapentrysize = 0; /* 0 indicates no colormap */ INT32 bPad; JDIMENSION row_width; /* Read and verify the bitmap file header */ if (! ReadOK(source->pub.input_file, bmpfileheader, 14)) ERREXIT(cinfo, JERR_INPUT_EOF); if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */ ERREXIT(cinfo, JERR_BMP_NOT); bfOffBits = (INT32) GET_4B(bmpfileheader,10); /* We ignore the remaining fileheader fields */ /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows), * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which. */ if (! ReadOK(source->pub.input_file, bmpinfoheader, 4)) ERREXIT(cinfo, JERR_INPUT_EOF); headerSize = (INT32) GET_4B(bmpinfoheader,0); if (headerSize < 12 || headerSize > 64) ERREXIT(cinfo, JERR_BMP_BADHEADER); if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4)) ERREXIT(cinfo, JERR_INPUT_EOF); switch ((int) headerSize) { case 12: /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */ biWidth = (INT32) GET_2B(bmpinfoheader,4); biHeight = (INT32) GET_2B(bmpinfoheader,6); biPlanes = GET_2B(bmpinfoheader,8); source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10); switch (source->bits_per_pixel) { case 8: /* colormapped image */ mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */ TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight); break; case 24: /* RGB image */ TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight); break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } break; case 40: case 64: /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */ /* or OS/2 2.x header, which has additional fields that we ignore */ biWidth = GET_4B(bmpinfoheader,4); biHeight = GET_4B(bmpinfoheader,8); biPlanes = GET_2B(bmpinfoheader,12); source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14); biCompression = GET_4B(bmpinfoheader,16); biXPelsPerMeter = GET_4B(bmpinfoheader,24); biYPelsPerMeter = GET_4B(bmpinfoheader,28); biClrUsed = GET_4B(bmpinfoheader,32); /* biSizeImage, biClrImportant fields are ignored */ switch (source->bits_per_pixel) { case 8: /* colormapped image */ mapentrysize = 4; /* Windows uses RGBQUAD colormap */ TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight); break; case 24: /* RGB image */ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); break; case 32: /* RGB image + Alpha channel */ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); break; default: ERREXIT(cinfo, JERR_BMP_BADDEPTH); break; } if (biCompression != 0) ERREXIT(cinfo, JERR_BMP_COMPRESSED); if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) { /* Set JFIF density parameters from the BMP data */ cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */ cinfo->Y_density = (UINT16) (biYPelsPerMeter/100); cinfo->density_unit = 2; /* dots/cm */ } break; default: ERREXIT(cinfo, JERR_BMP_BADHEADER); return; } if (biWidth <= 0 || biHeight <= 0) ERREXIT(cinfo, JERR_BMP_EMPTY); if (biPlanes != 1) ERREXIT(cinfo, JERR_BMP_BADPLANES); /* Compute distance to bitmap data --- will adjust for colormap below */ bPad = bfOffBits - (headerSize + 14); /* Read the colormap, if any */ if (mapentrysize > 0) { if (biClrUsed <= 0) biClrUsed = 256; /* assume it's 256 */ else if (biClrUsed > 256) ERREXIT(cinfo, JERR_BMP_BADCMAP); /* Allocate space to store the colormap */ source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) biClrUsed, (JDIMENSION) 3); /* and read it from the file */ read_colormap(source, (int) biClrUsed, mapentrysize); /* account for size of colormap */ bPad -= biClrUsed * mapentrysize; } /* Skip any remaining pad bytes */ if (bPad < 0) /* incorrect bfOffBits value? */ ERREXIT(cinfo, JERR_BMP_BADHEADER); while (--bPad >= 0) { (void) read_byte(source); } /* Compute row width in file, including padding to 4-byte boundary */ if (source->bits_per_pixel == 24) row_width = (JDIMENSION) (biWidth * 3); else if (source->bits_per_pixel == 32) row_width = (JDIMENSION) (biWidth * 4); else row_width = (JDIMENSION) biWidth; while ((row_width & 3) != 0) row_width++; source->row_width = row_width; /* Allocate space for inversion array, prepare for preload pass */ source->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, row_width, (JDIMENSION) biHeight, (JDIMENSION) 1); source->pub.get_pixel_rows = preload_image; if (cinfo->progress != NULL) { cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress; progress->total_extra_passes++; /* count file input as separate pass */ } /* Allocate one-row buffer for returned data */ source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (biWidth * 3), (JDIMENSION) 1); source->pub.buffer_height = 1; cinfo->in_color_space = JCS_RGB; cinfo->input_components = 3; cinfo->data_precision = 8; cinfo->image_width = (JDIMENSION) biWidth; cinfo->image_height = (JDIMENSION) biHeight; }
METHODDEF void new_color_map_1_quant(j_decompress_ptr cinfo) { ERREXIT(cinfo, JERR_MODE_CHANGE); }
write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest) /* Write a Windows-style BMP file header, including colormap if needed */ { char bmpfileheader[14]; char bmpinfoheader[40]; #define PUT_2B(array,offset,value) \ (array[offset] = (char) ((value) & 0xFF), \ array[offset+1] = (char) (((value) >> 8) & 0xFF)) #define PUT_4B(array,offset,value) \ (array[offset] = (char) ((value) & 0xFF), \ array[offset+1] = (char) (((value) >> 8) & 0xFF), \ array[offset+2] = (char) (((value) >> 16) & 0xFF), \ array[offset+3] = (char) (((value) >> 24) & 0xFF)) INT32 headersize, bfSize; int bits_per_pixel, cmap_entries; /* Compute colormap size and total file size */ if (cinfo->out_color_space == JCS_RGB) { if (cinfo->quantize_colors) { /* Colormapped RGB */ bits_per_pixel = 8; cmap_entries = 256; } else { /* Unquantized, full color RGB */ bits_per_pixel = 24; cmap_entries = 0; } } else { /* Grayscale output. We need to fake a 256-entry colormap. */ bits_per_pixel = 8; cmap_entries = 256; } /* File size */ headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height; /* Set unused fields of header to 0 */ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader)); MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader)); /* Fill the file header */ bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */ bmpfileheader[1] = 0x4D; PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */ /* we leave bfReserved1 & bfReserved2 = 0 */ PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */ /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */ PUT_2B(bmpinfoheader, 0, 40); /* biSize */ PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */ PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */ PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */ PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */ /* we leave biCompression = 0, for none */ /* we leave biSizeImage = 0; this is correct for uncompressed data */ if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */ PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */ PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */ } PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */ /* we leave biClrImportant = 0 */ if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14) ERREXIT(cinfo, JERR_FILE_WRITE); if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40) ERREXIT(cinfo, JERR_FILE_WRITE); if (cmap_entries > 0) write_colormap(cinfo, dest, cmap_entries, 4); }
static boolean fill_input_buffer (j_decompress_ptr cinfo) { ERREXIT(cinfo, JERR_INPUT_EMPTY); return TRUE; }
static int scan_JPEG_header (int verbose, int raw) { int marker; /* Expect SOI at start of file */ if (first_marker() != M_SOI) ERREXIT("Expected SOI marker first"); /* Scan miscellaneous markers until we reach SOS. */ for (;;) { marker = next_marker(); switch (marker) { /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be, * treated as SOFn. C4 in particular is actually DHT. */ case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ case M_SOF2: /* Progressive, Huffman */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_SOF9: /* Extended sequential, arithmetic */ case M_SOF10: /* Progressive, arithmetic */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ if (verbose) process_SOFn(marker); else skip_variable(); break; case M_SOS: /* stop before hitting compressed data */ return marker; case M_EOI: /* in case it's a tables-only JPEG stream */ return marker; case M_COM: process_COM(raw); break; case M_APP12: /* Some digital camera makers put useful textual information into * APP12 markers, so we print those out too when in -verbose mode. */ if (verbose) { printf("APP12 contains:\n"); process_COM(raw); } else skip_variable(); break; default: /* Anything else just gets skipped */ skip_variable(); /* we assume it has a parameter count... */ break; } } /* end loop */ }
jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno, d_derived_tbl ** pdtbl) { JHUFF_TBL *htbl; d_derived_tbl *dtbl; int p, i, l, si, numsymbols; int lookbits, ctr; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Note that huffsize[] and huffcode[] are filled in code-length order, * paralleling the order of the symbols themselves in htbl->huffval[]. */ /* Find the input Huffman table */ if (tblno < 0 || tblno >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); htbl = isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); /* Allocate a workspace if we haven't already done so. */ if (*pdtbl == NULL) *pdtbl = (d_derived_tbl *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(d_derived_tbl)); dtbl = *pdtbl; dtbl->pub = htbl; /* fill in back link */ /* Figure C.1: make table of Huffman code length for each symbol */ p = 0; for (l = 1; l <= 16; l++) { i = (int) htbl->bits[l]; if (i < 0 || p + i > 256) /* protect against table overrun */ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); while (i--) huffsize[p++] = (char) l; } huffsize[p] = 0; numsymbols = p; /* Figure C.2: generate the codes themselves */ /* We also validate that the counts represent a legal Huffman code tree. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } /* code is now 1 more than the last code used for codelength si; but * it must still fit in si bits, since no code is allowed to be all ones. */ if (((INT32) code) >= (((INT32) 1) << si)) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); code <<= 1; si++; } /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->bits[l]) { /* valoffset[l] = huffval[] index of 1st symbol of code length l, * minus the minimum code of length l */ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p]; p += htbl->bits[l]; dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { dtbl->maxcode[l] = -1; /* -1 if no codes of this length */ } } dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */ /* Compute lookahead tables to speed up decoding. * First we set all the table entries to 0, indicating "too long"; * then we iterate through the Huffman codes that are short enough and * fill in all the entries that correspond to bit sequences starting * with that code. */ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { for (i = 1; i <= (int) htbl->bits[l]; i++, p++) { /* l = current code's length, p = its index in huffcode[] & huffval[]. */ /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { dtbl->look_nbits[lookbits] = l; dtbl->look_sym[lookbits] = htbl->huffval[p]; lookbits++; } } } /* Validate symbols as being reasonable. * For AC tables, we make no check, but accept all byte values 0..255. * For DC tables, we require the symbols to be in range 0..15. * (Tighter bounds could be applied depending on the data depth and mode, * but this is sufficient to ensure safe decoding.) */ if (isDC) { for (i = 0; i < numsymbols; i++) { int sym = htbl->huffval[i]; if (sym < 0 || sym > 15) ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); } } }
GLOBAL JDIMENSION jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, JDIMENSION max_lines) { JDIMENSION lines_per_iMCU_row; if (cinfo->global_state != DSTATE_RAW_OK) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (cinfo->output_scanline >= cinfo->output_height) { WARNMS(cinfo, JWRN_TOO_MUCH_DATA); return 0; } /* Call progress monitor hook if present */ if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) cinfo->output_scanline; cinfo->progress->pass_limit = (long) cinfo->output_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } /* Verify that at least one iMCU row can be returned. */ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; if (max_lines < lines_per_iMCU_row) ERREXIT(cinfo, JERR_BUFFER_SIZE); /* Decompress directly into user's buffer. */ if (! (*cinfo->coef->decompress_data) (cinfo, data)) return 0; /* suspension forced, can do nothing more */ /* OK, we processed one iMCU row. */ cinfo->output_scanline += lines_per_iMCU_row; return lines_per_iMCU_row; }