JCPREPCT.c
上传用户:qiutianh
上传日期:2022-08-08
资源大小:939k
文件大小:13k
源码类别:

图形图象

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////
  2. //
  3. // Note : this file is included as part of the Smaller Animals Software
  4. // JpegFile package. Though this file has not been modified from it's 
  5. // original IJG 6a form, it is not the responsibility on the Independent
  6. // JPEG Group to answer questions regarding this code.
  7. //
  8. // Any questions you have about this code should be addressed to :
  9. //
  10. // CHRISDL@PAGESZ.NET - the distributor of this package.
  11. //
  12. // Remember, by including this code in the JpegFile package, Smaller 
  13. // Animals Software assumes all responsibilities for answering questions
  14. // about it. If we (SA Software) can't answer your questions ourselves, we 
  15. // will direct you to people who can.
  16. //
  17. // Thanks, CDL.
  18. //
  19. ////////////////////////////////////////////////////////////////////////
  20. /*
  21.  * jcprepct.c
  22.  *
  23.  * Copyright (C) 1994-1996, Thomas G. Lane.
  24.  * This file is part of the Independent JPEG Group's software.
  25.  * For conditions of distribution and use, see the accompanying README file.
  26.  *
  27.  * This file contains the compression preprocessing controller.
  28.  * This controller manages the color conversion, downsampling,
  29.  * and edge expansion steps.
  30.  *
  31.  * Most of the complexity here is associated with buffering input rows
  32.  * as required by the downsampler.  See the comments at the head of
  33.  * jcsample.c for the downsampler's needs.
  34.  */
  35. #define JPEG_INTERNALS
  36. #include "jinclude.h"
  37. #include "jpeglib.h"
  38. /* At present, jcsample.c can request context rows only for smoothing.
  39.  * In the future, we might also need context rows for CCIR601 sampling
  40.  * or other more-complex downsampling procedures.  The code to support
  41.  * context rows should be compiled only if needed.
  42.  */
  43. #ifdef INPUT_SMOOTHING_SUPPORTED
  44. #define CONTEXT_ROWS_SUPPORTED
  45. #endif
  46. /*
  47.  * For the simple (no-context-row) case, we just need to buffer one
  48.  * row group's worth of pixels for the downsampling step.  At the bottom of
  49.  * the image, we pad to a full row group by replicating the last pixel row.
  50.  * The downsampler's last output row is then replicated if needed to pad
  51.  * out to a full iMCU row.
  52.  *
  53.  * When providing context rows, we must buffer three row groups' worth of
  54.  * pixels.  Three row groups are physically allocated, but the row pointer
  55.  * arrays are made five row groups high, with the extra pointers above and
  56.  * below "wrapping around" to point to the last and first real row groups.
  57.  * This allows the downsampler to access the proper context rows.
  58.  * At the top and bottom of the image, we create dummy context rows by
  59.  * copying the first or last real pixel row.  This copying could be avoided
  60.  * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
  61.  * trouble on the compression side.
  62.  */
  63. /* Private buffer controller object */
  64. typedef struct {
  65.   struct jpeg_c_prep_controller pub; /* public fields */
  66.   /* Downsampling input buffer.  This buffer holds color-converted data
  67.    * until we have enough to do a downsample step.
  68.    */
  69.   JSAMPARRAY color_buf[MAX_COMPONENTS];
  70.   JDIMENSION rows_to_go; /* counts rows remaining in source image */
  71.   int next_buf_row; /* index of next row to store in color_buf */
  72. #ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
  73.   int this_row_group; /* starting row index of group to process */
  74.   int next_buf_stop; /* downsample when we reach this index */
  75. #endif
  76. } my_prep_controller;
  77. typedef my_prep_controller * my_prep_ptr;
  78. /*
  79.  * Initialize for a processing pass.
  80.  */
  81. METHODDEF(void)
  82. start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
  83. {
  84.   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
  85.   if (pass_mode != JBUF_PASS_THRU)
  86.     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
  87.   /* Initialize total-height counter for detecting bottom of image */
  88.   prep->rows_to_go = cinfo->image_height;
  89.   /* Mark the conversion buffer empty */
  90.   prep->next_buf_row = 0;
  91. #ifdef CONTEXT_ROWS_SUPPORTED
  92.   /* Preset additional state variables for context mode.
  93.    * These aren't used in non-context mode, so we needn't test which mode.
  94.    */
  95.   prep->this_row_group = 0;
  96.   /* Set next_buf_stop to stop after two row groups have been read in. */
  97.   prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
  98. #endif
  99. }
  100. /*
  101.  * Expand an image vertically from height input_rows to height output_rows,
  102.  * by duplicating the bottom row.
  103.  */
  104. LOCAL(void)
  105. expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
  106.     int input_rows, int output_rows)
  107. {
  108.   register int row;
  109.   for (row = input_rows; row < output_rows; row++) {
  110.     jcopy_sample_rows(image_data, input_rows-1, image_data, row,
  111.       1, num_cols);
  112.   }
  113. }
  114. /*
  115.  * Process some data in the simple no-context case.
  116.  *
  117.  * Preprocessor output data is counted in "row groups".  A row group
  118.  * is defined to be v_samp_factor sample rows of each component.
  119.  * Downsampling will produce this much data from each max_v_samp_factor
  120.  * input rows.
  121.  */
  122. METHODDEF(void)
  123. pre_process_data (j_compress_ptr cinfo,
  124.   JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
  125.   JDIMENSION in_rows_avail,
  126.   JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
  127.   JDIMENSION out_row_groups_avail)
  128. {
  129.   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
  130.   int numrows, ci;
  131.   JDIMENSION inrows;
  132.   jpeg_component_info * compptr;
  133.   while (*in_row_ctr < in_rows_avail &&
  134.  *out_row_group_ctr < out_row_groups_avail) {
  135.     /* Do color conversion to fill the conversion buffer. */
  136.     inrows = in_rows_avail - *in_row_ctr;
  137.     numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
  138.     numrows = (int) MIN((JDIMENSION) numrows, inrows);
  139.     (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
  140.        prep->color_buf,
  141.        (JDIMENSION) prep->next_buf_row,
  142.        numrows);
  143.     *in_row_ctr += numrows;
  144.     prep->next_buf_row += numrows;
  145.     prep->rows_to_go -= numrows;
  146.     /* If at bottom of image, pad to fill the conversion buffer. */
  147.     if (prep->rows_to_go == 0 &&
  148. prep->next_buf_row < cinfo->max_v_samp_factor) {
  149.       for (ci = 0; ci < cinfo->num_components; ci++) {
  150. expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
  151.    prep->next_buf_row, cinfo->max_v_samp_factor);
  152.       }
  153.       prep->next_buf_row = cinfo->max_v_samp_factor;
  154.     }
  155.     /* If we've filled the conversion buffer, empty it. */
  156.     if (prep->next_buf_row == cinfo->max_v_samp_factor) {
  157.       (*cinfo->downsample->downsample) (cinfo,
  158. prep->color_buf, (JDIMENSION) 0,
  159. output_buf, *out_row_group_ctr);
  160.       prep->next_buf_row = 0;
  161.       (*out_row_group_ctr)++;
  162.     }
  163.     /* If at bottom of image, pad the output to a full iMCU height.
  164.      * Note we assume the caller is providing a one-iMCU-height output buffer!
  165.      */
  166.     if (prep->rows_to_go == 0 &&
  167. *out_row_group_ctr < out_row_groups_avail) {
  168.       for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
  169.    ci++, compptr++) {
  170. expand_bottom_edge(output_buf[ci],
  171.    compptr->width_in_blocks * DCTSIZE,
  172.    (int) (*out_row_group_ctr * compptr->v_samp_factor),
  173.    (int) (out_row_groups_avail * compptr->v_samp_factor));
  174.       }
  175.       *out_row_group_ctr = out_row_groups_avail;
  176.       break; /* can exit outer loop without test */
  177.     }
  178.   }
  179. }
  180. #ifdef CONTEXT_ROWS_SUPPORTED
  181. /*
  182.  * Process some data in the context case.
  183.  */
  184. METHODDEF(void)
  185. pre_process_context (j_compress_ptr cinfo,
  186.      JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
  187.      JDIMENSION in_rows_avail,
  188.      JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
  189.      JDIMENSION out_row_groups_avail)
  190. {
  191.   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
  192.   int numrows, ci;
  193.   int buf_height = cinfo->max_v_samp_factor * 3;
  194.   JDIMENSION inrows;
  195.   while (*out_row_group_ctr < out_row_groups_avail) {
  196.     if (*in_row_ctr < in_rows_avail) {
  197.       /* Do color conversion to fill the conversion buffer. */
  198.       inrows = in_rows_avail - *in_row_ctr;
  199.       numrows = prep->next_buf_stop - prep->next_buf_row;
  200.       numrows = (int) MIN((JDIMENSION) numrows, inrows);
  201.       (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
  202.  prep->color_buf,
  203.  (JDIMENSION) prep->next_buf_row,
  204.  numrows);
  205.       /* Pad at top of image, if first time through */
  206.       if (prep->rows_to_go == cinfo->image_height) {
  207. for (ci = 0; ci < cinfo->num_components; ci++) {
  208.   int row;
  209.   for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
  210.     jcopy_sample_rows(prep->color_buf[ci], 0,
  211.       prep->color_buf[ci], -row,
  212.       1, cinfo->image_width);
  213.   }
  214. }
  215.       }
  216.       *in_row_ctr += numrows;
  217.       prep->next_buf_row += numrows;
  218.       prep->rows_to_go -= numrows;
  219.     } else {
  220.       /* Return for more data, unless we are at the bottom of the image. */
  221.       if (prep->rows_to_go != 0)
  222. break;
  223.       /* When at bottom of image, pad to fill the conversion buffer. */
  224.       if (prep->next_buf_row < prep->next_buf_stop) {
  225. for (ci = 0; ci < cinfo->num_components; ci++) {
  226.   expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
  227.      prep->next_buf_row, prep->next_buf_stop);
  228. }
  229. prep->next_buf_row = prep->next_buf_stop;
  230.       }
  231.     }
  232.     /* If we've gotten enough data, downsample a row group. */
  233.     if (prep->next_buf_row == prep->next_buf_stop) {
  234.       (*cinfo->downsample->downsample) (cinfo,
  235. prep->color_buf,
  236. (JDIMENSION) prep->this_row_group,
  237. output_buf, *out_row_group_ctr);
  238.       (*out_row_group_ctr)++;
  239.       /* Advance pointers with wraparound as necessary. */
  240.       prep->this_row_group += cinfo->max_v_samp_factor;
  241.       if (prep->this_row_group >= buf_height)
  242. prep->this_row_group = 0;
  243.       if (prep->next_buf_row >= buf_height)
  244. prep->next_buf_row = 0;
  245.       prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
  246.     }
  247.   }
  248. }
  249. /*
  250.  * Create the wrapped-around downsampling input buffer needed for context mode.
  251.  */
  252. LOCAL(void)
  253. create_context_buffer (j_compress_ptr cinfo)
  254. {
  255.   my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
  256.   int rgroup_height = cinfo->max_v_samp_factor;
  257.   int ci, i;
  258.   jpeg_component_info * compptr;
  259.   JSAMPARRAY true_buffer, fake_buffer;
  260.   /* Grab enough space for fake row pointers for all the components;
  261.    * we need five row groups' worth of pointers for each component.
  262.    */
  263.   fake_buffer = (JSAMPARRAY)
  264.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  265. (cinfo->num_components * 5 * rgroup_height) *
  266. SIZEOF(JSAMPROW));
  267.   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
  268.        ci++, compptr++) {
  269.     /* Allocate the actual buffer space (3 row groups) for this component.
  270.      * We make the buffer wide enough to allow the downsampler to edge-expand
  271.      * horizontally within the buffer, if it so chooses.
  272.      */
  273.     true_buffer = (*cinfo->mem->alloc_sarray)
  274.       ((j_common_ptr) cinfo, JPOOL_IMAGE,
  275.        (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
  276.       cinfo->max_h_samp_factor) / compptr->h_samp_factor),
  277.        (JDIMENSION) (3 * rgroup_height));
  278.     /* Copy true buffer row pointers into the middle of the fake row array */
  279.     MEMCOPY(fake_buffer + rgroup_height, true_buffer,
  280.     3 * rgroup_height * SIZEOF(JSAMPROW));
  281.     /* Fill in the above and below wraparound pointers */
  282.     for (i = 0; i < rgroup_height; i++) {
  283.       fake_buffer[i] = true_buffer[2 * rgroup_height + i];
  284.       fake_buffer[4 * rgroup_height + i] = true_buffer[i];
  285.     }
  286.     prep->color_buf[ci] = fake_buffer + rgroup_height;
  287.     fake_buffer += 5 * rgroup_height; /* point to space for next component */
  288.   }
  289. }
  290. #endif /* CONTEXT_ROWS_SUPPORTED */
  291. /*
  292.  * Initialize preprocessing controller.
  293.  */
  294. GLOBAL(void)
  295. jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
  296. {
  297.   my_prep_ptr prep;
  298.   int ci;
  299.   jpeg_component_info * compptr;
  300.   if (need_full_buffer) /* safety check */
  301.     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
  302.   prep = (my_prep_ptr)
  303.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  304. SIZEOF(my_prep_controller));
  305.   cinfo->prep = (struct jpeg_c_prep_controller *) prep;
  306.   prep->pub.start_pass = start_pass_prep;
  307.   /* Allocate the color conversion buffer.
  308.    * We make the buffer wide enough to allow the downsampler to edge-expand
  309.    * horizontally within the buffer, if it so chooses.
  310.    */
  311.   if (cinfo->downsample->need_context_rows) {
  312.     /* Set up to provide context rows */
  313. #ifdef CONTEXT_ROWS_SUPPORTED
  314.     prep->pub.pre_process_data = pre_process_context;
  315.     create_context_buffer(cinfo);
  316. #else
  317.     ERREXIT(cinfo, JERR_NOT_COMPILED);
  318. #endif
  319.   } else {
  320.     /* No context, just make it tall enough for one row group */
  321.     prep->pub.pre_process_data = pre_process_data;
  322.     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
  323.  ci++, compptr++) {
  324.       prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
  325. ((j_common_ptr) cinfo, JPOOL_IMAGE,
  326.  (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
  327. cinfo->max_h_samp_factor) / compptr->h_samp_factor),
  328.  (JDIMENSION) cinfo->max_v_samp_factor);
  329.     }
  330.   }
  331. }