home *** CD-ROM | disk | FTP | other *** search
/ Encyclopedia of Graphics File Formats Companion / GFF_CD.ISO / software / unix / jpeg / jpegv4a.tar / jcsample.c < prev    next >
C/C++ Source or Header  |  1992-11-05  |  16KB  |  461 lines

  1. /*
  2.  * jcsample.c
  3.  *
  4.  * Copyright (C) 1991, 1992, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains downsampling routines.
  9.  * These routines are invoked via the downsample and
  10.  * downsample_init/term methods.
  11.  *
  12.  * An excellent reference for image resampling is
  13.  *   Digital Image Warping, George Wolberg, 1990.
  14.  *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
  15.  *
  16.  * The downsampling algorithm used here is a simple average of the source
  17.  * pixels covered by the output pixel.  The hi-falutin sampling literature
  18.  * refers to this as a "box filter".  In general the characteristics of a box
  19.  * filter are not very good, but for the specific cases we normally use (1:1
  20.  * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
  21.  * nearly so bad.  If you intend to use other sampling ratios, you'd be well
  22.  * advised to improve this code.
  23.  *
  24.  * A simple input-smoothing capability is provided.  This is mainly intended
  25.  * for cleaning up color-dithered GIF input files (if you find it inadequate,
  26.  * we suggest using an external filtering program such as pnmconvol).  When
  27.  * enabled, each input pixel P is replaced by a weighted sum of itself and its
  28.  * eight neighbors.  P's weight is 1-8*SF and each neighbor's weight is SF,
  29.  * where SF = (smoothing_factor / 1024).
  30.  * Currently, smoothing is only supported for 2h2v sampling factors.
  31.  */
  32.  
  33. #include "jinclude.h"
  34.  
  35.  
  36. /*
  37.  * Initialize for downsampling a scan.
  38.  */
  39.  
  40. METHODDEF void
  41. downsample_init (compress_info_ptr cinfo)
  42. {
  43.   /* no work for now */
  44. }
  45.  
  46.  
  47. /*
  48.  * Downsample pixel values of a single component.
  49.  * This version handles arbitrary integral sampling ratios, without smoothing.
  50.  * Note that this version is not actually used for customary sampling ratios.
  51.  */
  52.  
  53. METHODDEF void
  54. int_downsample (compress_info_ptr cinfo, int which_component,
  55.         long input_cols, int input_rows,
  56.         long output_cols, int output_rows,
  57.         JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  58.         JSAMPARRAY output_data)
  59. {
  60.   jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
  61.   int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
  62.   long outcol, outcol_h;    /* outcol_h == outcol*h_expand */
  63.   JSAMPROW inptr, outptr;
  64.   INT32 outvalue;
  65.  
  66. #ifdef DEBUG            /* for debugging pipeline controller */
  67.   if (output_rows != compptr->v_samp_factor ||
  68.       input_rows != cinfo->max_v_samp_factor ||
  69.       (output_cols % compptr->h_samp_factor) != 0 ||
  70.       (input_cols % cinfo->max_h_samp_factor) != 0 ||
  71.       input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
  72.     ERREXIT(cinfo->emethods, "Bogus downsample parameters");
  73. #endif
  74.  
  75.   h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
  76.   v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
  77.   numpix = h_expand * v_expand;
  78.   numpix2 = numpix/2;
  79.  
  80.   inrow = 0;
  81.   for (outrow = 0; outrow < output_rows; outrow++) {
  82.     outptr = output_data[outrow];
  83.     for (outcol = 0, outcol_h = 0; outcol < output_cols;
  84.      outcol++, outcol_h += h_expand) {
  85.       outvalue = 0;
  86.       for (v = 0; v < v_expand; v++) {
  87.     inptr = input_data[inrow+v] + outcol_h;
  88.     for (h = 0; h < h_expand; h++) {
  89.       outvalue += (INT32) GETJSAMPLE(*inptr++);
  90.     }
  91.       }
  92.       *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
  93.     }
  94.     inrow += v_expand;
  95.   }
  96. }
  97.  
  98.  
  99. /*
  100.  * Downsample pixel values of a single component.
  101.  * This version handles the common case of 2:1 horizontal and 1:1 vertical,
  102.  * without smoothing.
  103.  */
  104.  
  105. METHODDEF void
  106. h2v1_downsample (compress_info_ptr cinfo, int which_component,
  107.          long input_cols, int input_rows,
  108.          long output_cols, int output_rows,
  109.          JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  110.          JSAMPARRAY output_data)
  111. {
  112.   int outrow;
  113.   long outcol;
  114.   register JSAMPROW inptr, outptr;
  115.  
  116. #ifdef DEBUG            /* for debugging pipeline controller */
  117.   jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
  118.   if (output_rows != compptr->v_samp_factor ||
  119.       input_rows != cinfo->max_v_samp_factor ||
  120.       (output_cols % compptr->h_samp_factor) != 0 ||
  121.       (input_cols % cinfo->max_h_samp_factor) != 0 ||
  122.       input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
  123.     ERREXIT(cinfo->emethods, "Bogus downsample parameters");
  124. #endif
  125.  
  126.   for (outrow = 0; outrow < output_rows; outrow++) {
  127.     outptr = output_data[outrow];
  128.     inptr = input_data[outrow];
  129.     for (outcol = 0; outcol < output_cols; outcol++) {
  130.       *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
  131.                   + 1) >> 1);
  132.       inptr += 2;
  133.     }
  134.   }
  135. }
  136.  
  137.  
  138. /*
  139.  * Downsample pixel values of a single component.
  140.  * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
  141.  * without smoothing.
  142.  */
  143.  
  144. METHODDEF void
  145. h2v2_downsample (compress_info_ptr cinfo, int which_component,
  146.          long input_cols, int input_rows,
  147.          long output_cols, int output_rows,
  148.          JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  149.          JSAMPARRAY output_data)
  150. {
  151.   int inrow, outrow;
  152.   long outcol;
  153.   register JSAMPROW inptr0, inptr1, outptr;
  154.  
  155. #ifdef DEBUG            /* for debugging pipeline controller */
  156.   jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
  157.   if (output_rows != compptr->v_samp_factor ||
  158.       input_rows != cinfo->max_v_samp_factor ||
  159.       (output_cols % compptr->h_samp_factor) != 0 ||
  160.       (input_cols % cinfo->max_h_samp_factor) != 0 ||
  161.       input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
  162.     ERREXIT(cinfo->emethods, "Bogus downsample parameters");
  163. #endif
  164.  
  165.   inrow = 0;
  166.   for (outrow = 0; outrow < output_rows; outrow++) {
  167.     outptr = output_data[outrow];
  168.     inptr0 = input_data[inrow];
  169.     inptr1 = input_data[inrow+1];
  170.     for (outcol = 0; outcol < output_cols; outcol++) {
  171.       *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
  172.                   GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
  173.                   + 2) >> 2);
  174.       inptr0 += 2; inptr1 += 2;
  175.     }
  176.     inrow += 2;
  177.   }
  178. }
  179.  
  180.  
  181. /*
  182.  * Downsample pixel values of a single component.
  183.  * This version handles the special case of a full-size component,
  184.  * without smoothing.
  185.  */
  186.  
  187. METHODDEF void
  188. fullsize_downsample (compress_info_ptr cinfo, int which_component,
  189.              long input_cols, int input_rows,
  190.              long output_cols, int output_rows,
  191.              JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  192.              JSAMPARRAY output_data)
  193. {
  194. #ifdef DEBUG            /* for debugging pipeline controller */
  195.   if (input_cols != output_cols || input_rows != output_rows)
  196.     ERREXIT(cinfo->emethods, "Pipeline controller messed up");
  197. #endif
  198.  
  199.   jcopy_sample_rows(input_data, 0, output_data, 0, output_rows, output_cols);
  200. }
  201.  
  202.  
  203. #ifdef INPUT_SMOOTHING_SUPPORTED
  204.  
  205. /*
  206.  * Downsample pixel values of a single component.
  207.  * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
  208.  * with smoothing.
  209.  */
  210.  
  211. METHODDEF void
  212. h2v2_smooth_downsample (compress_info_ptr cinfo, int which_component,
  213.             long input_cols, int input_rows,
  214.             long output_cols, int output_rows,
  215.             JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  216.             JSAMPARRAY output_data)
  217. {
  218.   int inrow, outrow;
  219.   long colctr;
  220.   register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
  221.   INT32 membersum, neighsum, memberscale, neighscale;
  222.  
  223. #ifdef DEBUG            /* for debugging pipeline controller */
  224.   jpeg_component_info * compptr = cinfo->cur_comp_info[which_component];
  225.   if (output_rows != compptr->v_samp_factor ||
  226.       input_rows != cinfo->max_v_samp_factor ||
  227.       (output_cols % compptr->h_samp_factor) != 0 ||
  228.       (input_cols % cinfo->max_h_samp_factor) != 0 ||
  229.       input_cols*compptr->h_samp_factor != output_cols*cinfo->max_h_samp_factor)
  230.     ERREXIT(cinfo->emethods, "Bogus downsample parameters");
  231. #endif
  232.  
  233.   /* We don't bother to form the individual "smoothed" input pixel values;
  234.    * we can directly compute the output which is the average of the four
  235.    * smoothed values.  Each of the four member pixels contributes a fraction
  236.    * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
  237.    * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
  238.    * output.  The four corner-adjacent neighbor pixels contribute a fraction
  239.    * SF to just one smoothed pixel, or SF/4 to the final output; while the
  240.    * eight edge-adjacent neighbors contribute SF to each of two smoothed
  241.    * pixels, or SF/2 overall.  In order to use integer arithmetic, these
  242.    * factors are scaled by 2^16 = 65536.
  243.    * Also recall that SF = smoothing_factor / 1024.
  244.    */
  245.  
  246.   memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
  247.   neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
  248.  
  249.   inrow = 0;
  250.   for (outrow = 0; outrow < output_rows; outrow++) {
  251.     outptr = output_data[outrow];
  252.     inptr0 = input_data[inrow];
  253.     inptr1 = input_data[inrow+1];
  254.     if (inrow == 0)
  255.       above_ptr = above[input_rows-1];
  256.     else
  257.       above_ptr = input_data[inrow-1];
  258.     if (inrow >= input_rows-2)
  259.       below_ptr = below[0];
  260.     else
  261.       below_ptr = input_data[inrow+2];
  262.  
  263.     /* Special case for first column: pretend column -1 is same as column 0 */
  264.     membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
  265.         GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
  266.     neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
  267.            GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
  268.            GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
  269.            GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
  270.     neighsum += neighsum;
  271.     neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
  272.         GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
  273.     membersum = membersum * memberscale + neighsum * neighscale;
  274.     *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
  275.     inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
  276.  
  277.     for (colctr = output_cols - 2; colctr > 0; colctr--) {
  278.       /* sum of pixels directly mapped to this output element */
  279.       membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
  280.           GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
  281.       /* sum of edge-neighbor pixels */
  282.       neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
  283.          GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
  284.          GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
  285.          GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
  286.       /* The edge-neighbors count twice as much as corner-neighbors */
  287.       neighsum += neighsum;
  288.       /* Add in the corner-neighbors */
  289.       neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
  290.           GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
  291.       /* form final output scaled up by 2^16 */
  292.       membersum = membersum * memberscale + neighsum * neighscale;
  293.       /* round, descale and output it */
  294.       *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
  295.       inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
  296.     }
  297.  
  298.     /* Special case for last column */
  299.     membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
  300.         GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
  301.     neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
  302.            GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
  303.            GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
  304.            GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
  305.     neighsum += neighsum;
  306.     neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
  307.         GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
  308.     membersum = membersum * memberscale + neighsum * neighscale;
  309.     *outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
  310.  
  311.     inrow += 2;
  312.   }
  313. }
  314.  
  315.  
  316. /*
  317.  * Downsample pixel values of a single component.
  318.  * This version handles the special case of a full-size component,
  319.  * with smoothing.
  320.  */
  321.  
  322. METHODDEF void
  323. fullsize_smooth_downsample (compress_info_ptr cinfo, int which_component,
  324.                 long input_cols, int input_rows,
  325.                 long output_cols, int output_rows,
  326.                 JSAMPARRAY above, JSAMPARRAY input_data, JSAMPARRAY below,
  327.                 JSAMPARRAY output_data)
  328. {
  329.   int outrow;
  330.   long colctr;
  331.   register JSAMPROW inptr, above_ptr, below_ptr, outptr;
  332.   INT32 membersum, neighsum, memberscale, neighscale;
  333.   int colsum, lastcolsum, nextcolsum;
  334.  
  335. #ifdef DEBUG            /* for debugging pipeline controller */
  336.   if (input_cols != output_cols || input_rows != output_rows)
  337.     ERREXIT(cinfo->emethods, "Pipeline controller messed up");
  338. #endif
  339.  
  340.   /* Each of the eight neighbor pixels contributes a fraction SF to the
  341.    * smoothed pixel, while the main pixel contributes (1-8*SF).  In order
  342.    * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
  343.    * Also recall that SF = smoothing_factor / 1024.
  344.    */
  345.  
  346.   memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
  347.   neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
  348.  
  349.   for (outrow = 0; outrow < output_rows; outrow++) {
  350.     outptr = output_data[outrow];
  351.     inptr = input_data[outrow];
  352.     if (outrow == 0)
  353.       above_ptr = above[input_rows-1];
  354.     else
  355.       above_ptr = input_data[outrow-1];
  356.     if (outrow >= input_rows-1)
  357.       below_ptr = below[0];
  358.     else
  359.       below_ptr = input_data[outrow+1];
  360.  
  361.     /* Special case for first column */
  362.     colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
  363.          GETJSAMPLE(*inptr);
  364.     membersum = GETJSAMPLE(*inptr++);
  365.     nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
  366.          GETJSAMPLE(*inptr);
  367.     neighsum = colsum + (colsum - membersum) + nextcolsum;
  368.     membersum = membersum * memberscale + neighsum * neighscale;
  369.     *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
  370.     lastcolsum = colsum; colsum = nextcolsum;
  371.  
  372.     for (colctr = output_cols - 2; colctr > 0; colctr--) {
  373.       membersum = GETJSAMPLE(*inptr++);
  374.       above_ptr++; below_ptr++;
  375.       nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
  376.            GETJSAMPLE(*inptr);
  377.       neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
  378.       membersum = membersum * memberscale + neighsum * neighscale;
  379.       *outptr++ = (JSAMPLE) ((membersum + 32768L) >> 16);
  380.       lastcolsum = colsum; colsum = nextcolsum;
  381.     }
  382.  
  383.     /* Special case for last column */
  384.     membersum = GETJSAMPLE(*inptr);
  385.     neighsum = lastcolsum + (colsum - membersum) + colsum;
  386.     membersum = membersum * memberscale + neighsum * neighscale;
  387.     *outptr = (JSAMPLE) ((membersum + 32768L) >> 16);
  388.  
  389.   }
  390. }
  391.  
  392. #endif /* INPUT_SMOOTHING_SUPPORTED */
  393.  
  394.  
  395. /*
  396.  * Clean up after a scan.
  397.  */
  398.  
  399. METHODDEF void
  400. downsample_term (compress_info_ptr cinfo)
  401. {
  402.   /* no work for now */
  403. }
  404.  
  405.  
  406.  
  407. /*
  408.  * The method selection routine for downsampling.
  409.  * Note that we must select a routine for each component.
  410.  */
  411.  
  412. GLOBAL void
  413. jseldownsample (compress_info_ptr cinfo)
  414. {
  415.   short ci;
  416.   jpeg_component_info * compptr;
  417.   boolean smoothok = TRUE;
  418.  
  419.   if (cinfo->CCIR601_sampling)
  420.     ERREXIT(cinfo->emethods, "CCIR601 downsampling not implemented yet");
  421.  
  422.   for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
  423.     compptr = cinfo->cur_comp_info[ci];
  424.     if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
  425.     compptr->v_samp_factor == cinfo->max_v_samp_factor) {
  426. #ifdef INPUT_SMOOTHING_SUPPORTED
  427.       if (cinfo->smoothing_factor)
  428.     cinfo->methods->downsample[ci] = fullsize_smooth_downsample;
  429.       else
  430. #endif
  431.     cinfo->methods->downsample[ci] = fullsize_downsample;
  432.     } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
  433.          compptr->v_samp_factor == cinfo->max_v_samp_factor) {
  434.       smoothok = FALSE;
  435.       cinfo->methods->downsample[ci] = h2v1_downsample;
  436.     } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
  437.          compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
  438. #ifdef INPUT_SMOOTHING_SUPPORTED
  439.       if (cinfo->smoothing_factor)
  440.     cinfo->methods->downsample[ci] = h2v2_smooth_downsample;
  441.       else
  442. #endif
  443.     cinfo->methods->downsample[ci] = h2v2_downsample;
  444.     } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
  445.          (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
  446.       smoothok = FALSE;
  447.       cinfo->methods->downsample[ci] = int_downsample;
  448.     } else
  449.       ERREXIT(cinfo->emethods, "Fractional downsampling not implemented yet");
  450.   }
  451.  
  452. #ifdef INPUT_SMOOTHING_SUPPORTED
  453.   if (cinfo->smoothing_factor && !smoothok)
  454.     TRACEMS(cinfo->emethods, 0,
  455.         "Smoothing not supported with nonstandard sampling ratios");
  456. #endif
  457.  
  458.   cinfo->methods->downsample_init = downsample_init;
  459.   cinfo->methods->downsample_term = downsample_term;
  460. }
  461.