home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / jlib / jdmerge.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-16  |  14.2 KB  |  420 lines

  1. //-------------------------------------------------------------------------//
  2. //          Windows Graphics Programming: Win32 GDI and DirectDraw         //
  3. //                        ISBN  0-13-086985-6                              //
  4. //                                                                         //
  5. //  Modified by: Yuan, Feng                             www.fengyuan.com   //
  6. //  Changes    : C++, exception, in-memory source, BGR byte order          //
  7. //  Version    : 1.00.000, May 31, 2000                                    //
  8. //-------------------------------------------------------------------------//
  9.  
  10. /*
  11.  * jdmerge.c
  12.  *
  13.  * Copyright (C) 1994-1996, Thomas G. Lane.
  14.  * This file is part of the Independent JPEG Group's software.
  15.  * For conditions of distribution and use, see the accompanying README file.
  16.  *
  17.  * This file contains code for merged upsampling/color conversion.
  18.  *
  19.  * This file combines functions from jdsample.c and jdcolor.c;
  20.  * read those files first to understand what's going on.
  21.  *
  22.  * When the chroma components are to be upsampled by simple replication
  23.  * (ie, box filtering), we can save some work in color conversion by
  24.  * calculating all the output pixels corresponding to a pair of chroma
  25.  * samples at one time.  In the conversion equations
  26.  *    R = Y           + K1 * Cr
  27.  *    G = Y + K2 * Cb + K3 * Cr
  28.  *    B = Y + K4 * Cb
  29.  * only the Y term varies among the group of pixels corresponding to a pair
  30.  * of chroma samples, so the rest of the terms can be calculated just once.
  31.  * At typical sampling ratios, this eliminates half or three-quarters of the
  32.  * multiplications needed for color conversion.
  33.  *
  34.  * This file currently provides implementations for the following cases:
  35.  *    YCbCr => RGB color conversion only.
  36.  *    Sampling ratios of 2h1v or 2h2v.
  37.  *    No scaling needed at upsample time.
  38.  *    Corner-aligned (non-CCIR601) sampling alignment.
  39.  * Other special cases could be added, but in most applications these are
  40.  * the only common cases.  (For uncommon cases we fall back on the more
  41.  * general code in jdsample.c and jdcolor.c.)
  42.  */
  43.  
  44. #define JPEG_INTERNALS
  45. #include "jinclude.h"
  46. #include "jpeglib.h"
  47.  
  48. #ifdef UPSAMPLE_MERGING_SUPPORTED
  49.  
  50.  
  51. /* Private subobject */
  52.  
  53. typedef struct {
  54.   struct jpeg_upsampler pub;    /* public fields */
  55.  
  56.   /* Pointer to routine to do actual upsampling/conversion of one row group */
  57.   JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
  58.                JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
  59.                JSAMPARRAY output_buf));
  60.  
  61.   /* Private state for YCC->RGB conversion */
  62.   int * Cr_r_tab;        /* => table for Cr to R conversion */
  63.   int * Cb_b_tab;        /* => table for Cb to B conversion */
  64.   long * Cr_g_tab;        /* => table for Cr to G conversion */
  65.   long * Cb_g_tab;        /* => table for Cb to G conversion */
  66.  
  67.   /* For 2:1 vertical sampling, we produce two output rows at a time.
  68.    * We need a "spare" row buffer to hold the second output row if the
  69.    * application provides just a one-row buffer; we also use the spare
  70.    * to discard the dummy last row if the image height is odd.
  71.    */
  72.   JSAMPROW spare_row;
  73.   boolean spare_full;        /* T if spare buffer is occupied */
  74.  
  75.   JDIMENSION out_row_width;    /* samples per output row */
  76.   JDIMENSION rows_to_go;    /* counts rows remaining in image */
  77. } my_upsampler;
  78.  
  79. typedef my_upsampler * my_upsample_ptr;
  80.  
  81. #define SCALEBITS    16    /* speediest right-shift on some machines */
  82. #define ONE_HALF    ((long) 1 << (SCALEBITS-1))
  83. #define FIX(x)        ((long) ((x) * (1L<<SCALEBITS) + 0.5))
  84.  
  85.  
  86. /*
  87.  * Initialize tables for YCC->RGB colorspace conversion.
  88.  * This is taken directly from jdcolor.c; see that file for more info.
  89.  */
  90.  
  91. LOCAL(void)
  92. build_ycc_rgb_table (j_decompress_ptr cinfo)
  93. {
  94.   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  95.   int i;
  96.   long x;
  97.   SHIFT_TEMPS
  98.  
  99.   upsample->Cr_r_tab = (int *)   cinfo->mem->alloc_small(JPOOL_IMAGE, (MAXJSAMPLE+1) * sizeof(int));
  100.   upsample->Cb_b_tab = (int *)   cinfo->mem->alloc_small(JPOOL_IMAGE, (MAXJSAMPLE+1) * sizeof(int));
  101.   upsample->Cr_g_tab = (long *) cinfo->mem->alloc_small(JPOOL_IMAGE, (MAXJSAMPLE+1) * sizeof(long));
  102.   upsample->Cb_g_tab = (long *) cinfo->mem->alloc_small(JPOOL_IMAGE, (MAXJSAMPLE+1) * sizeof(long));
  103.  
  104.   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
  105.     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
  106.     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
  107.     /* Cr=>R value is nearest int to 1.40200 * x */
  108.     upsample->Cr_r_tab[i] = (int)
  109.             RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
  110.     /* Cb=>B value is nearest int to 1.77200 * x */
  111.     upsample->Cb_b_tab[i] = (int)
  112.             RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
  113.     /* Cr=>G value is scaled-up -0.71414 * x */
  114.     upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
  115.     /* Cb=>G value is scaled-up -0.34414 * x */
  116.     /* We also add in ONE_HALF so that need not do it in inner loop */
  117.     upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
  118.   }
  119. }
  120.  
  121.  
  122. /*
  123.  * Initialize for an upsampling pass.
  124.  */
  125.  
  126. void
  127. start_pass_merged_upsample (j_decompress_ptr cinfo)
  128. {
  129.   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  130.  
  131.   /* Mark the spare buffer empty */
  132.   upsample->spare_full = FALSE;
  133.   /* Initialize total-height counter for detecting bottom of image */
  134.   upsample->rows_to_go = cinfo->output_height;
  135. }
  136.  
  137.  
  138. /*
  139.  * Control routine to do upsampling (and color conversion).
  140.  *
  141.  * The control routine just handles the row buffering considerations.
  142.  */
  143.  
  144. void
  145. merged_2v_upsample (j_decompress_ptr cinfo,
  146.             JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
  147.             JDIMENSION in_row_groups_avail,
  148.             JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
  149.             JDIMENSION out_rows_avail)
  150. /* 2:1 vertical sampling case: may need a spare row. */
  151. {
  152.   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  153.   JSAMPROW work_ptrs[2];
  154.   JDIMENSION num_rows;        /* number of rows returned to caller */
  155.  
  156.   if (upsample->spare_full) {
  157.     /* If we have a spare row saved from a previous cycle, just return it. */
  158.     jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
  159.               1, upsample->out_row_width);
  160.     num_rows = 1;
  161.     upsample->spare_full = FALSE;
  162.   } else {
  163.     /* Figure number of rows to return to caller. */
  164.     num_rows = 2;
  165.     /* Not more than the distance to the end of the image. */
  166.     if (num_rows > upsample->rows_to_go)
  167.       num_rows = upsample->rows_to_go;
  168.     /* And not more than what the client can accept: */
  169.     out_rows_avail -= *out_row_ctr;
  170.     if (num_rows > out_rows_avail)
  171.       num_rows = out_rows_avail;
  172.     /* Create output pointer array for upsampler. */
  173.     work_ptrs[0] = output_buf[*out_row_ctr];
  174.     if (num_rows > 1) {
  175.       work_ptrs[1] = output_buf[*out_row_ctr + 1];
  176.     } else {
  177.       work_ptrs[1] = upsample->spare_row;
  178.       upsample->spare_full = TRUE;
  179.     }
  180.     /* Now do the upsampling. */
  181.     (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
  182.   }
  183.  
  184.   /* Adjust counts */
  185.   *out_row_ctr += num_rows;
  186.   upsample->rows_to_go -= num_rows;
  187.   /* When the buffer is emptied, declare this input row group consumed */
  188.   if (! upsample->spare_full)
  189.     (*in_row_group_ctr)++;
  190. }
  191.  
  192.  
  193. void
  194. merged_1v_upsample (j_decompress_ptr cinfo,
  195.             JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
  196.             JDIMENSION in_row_groups_avail,
  197.             JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
  198.             JDIMENSION out_rows_avail)
  199. /* 1:1 vertical sampling case: much easier, never need a spare row. */
  200. {
  201.   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  202.  
  203.   /* Just do the upsampling. */
  204.   (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
  205.              output_buf + *out_row_ctr);
  206.   /* Adjust counts */
  207.   (*out_row_ctr)++;
  208.   (*in_row_group_ctr)++;
  209. }
  210.  
  211.  
  212. /*
  213.  * These are the routines invoked by the control routines to do
  214.  * the actual upsampling/conversion.  One row group is processed per call.
  215.  *
  216.  * Note: since we may be writing directly into application-supplied buffers,
  217.  * we have to be honest about the output width; we can't assume the buffer
  218.  * has been rounded up to an even width.
  219.  */
  220.  
  221.  
  222. /*
  223.  * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
  224.  */
  225.  
  226. void
  227. h2v1_merged_upsample (j_decompress_ptr cinfo,
  228.               JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
  229.               JSAMPARRAY output_buf)
  230. {
  231.     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  232.     register int y, cred, cgreen, cblue;
  233.     int cb, cr;
  234.     register JSAMPROW outptr;
  235.     JSAMPROW inptr0, inptr1, inptr2;
  236.     JDIMENSION col;
  237.     
  238.     /* copy these pointers into registers if possible */
  239.     register JSAMPLE * range_limit = cinfo->sample_range_limit;
  240.     int * Crrtab = upsample->Cr_r_tab;
  241.     int * Cbbtab = upsample->Cb_b_tab;
  242.     long * Crgtab = upsample->Cr_g_tab;
  243.     long * Cbgtab = upsample->Cb_g_tab;
  244.     SHIFT_TEMPS
  245.  
  246.     inptr0 = input_buf[0][in_row_group_ctr];
  247.     inptr1 = input_buf[1][in_row_group_ctr];
  248.     inptr2 = input_buf[2][in_row_group_ctr];
  249.     outptr = output_buf[0];
  250.   
  251.     /* Loop for each pair of output pixels */
  252.     for (col = cinfo->output_width >> 1; col > 0; col--) 
  253.     {
  254.         /* Do the chroma part of the calculation */
  255.         cb = GETJSAMPLE(*inptr1++);
  256.         cr = GETJSAMPLE(*inptr2++);
  257.         cred = Crrtab[cr];
  258.         cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
  259.         cblue = Cbbtab[cb];
  260.     
  261.         /* Fetch 2 Y values and emit 2 pixels */
  262.         y  = GETJSAMPLE(*inptr0++);
  263.         outptr[RGB_RED] =   range_limit[y + cred];
  264.         outptr[RGB_GREEN] = range_limit[y + cgreen];
  265.         outptr[RGB_BLUE] =  range_limit[y + cblue];
  266.         outptr += RGB_PIXELSIZE;
  267.     
  268.         y  = GETJSAMPLE(*inptr0++);
  269.         outptr[RGB_RED] =   range_limit[y + cred];
  270.         outptr[RGB_GREEN] = range_limit[y + cgreen];
  271.         outptr[RGB_BLUE] =  range_limit[y + cblue];
  272.         outptr += RGB_PIXELSIZE;
  273.     }
  274.   
  275.     /* If image width is odd, do the last output column separately */
  276.     if (cinfo->output_width & 1) 
  277.     {
  278.         cb = GETJSAMPLE(*inptr1);
  279.         cr = GETJSAMPLE(*inptr2);
  280.         cred = Crrtab[cr];
  281.         cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
  282.         cblue = Cbbtab[cb];
  283.         
  284.         y  = GETJSAMPLE(*inptr0);
  285.         outptr[RGB_RED] =   range_limit[y + cred];
  286.         outptr[RGB_GREEN] = range_limit[y + cgreen];
  287.         outptr[RGB_BLUE] =  range_limit[y + cblue];
  288.     }
  289. }
  290.  
  291.  
  292. /*
  293.  * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
  294.  */
  295.  
  296. void h2v2_merged_upsample (j_decompress_ptr cinfo,
  297.               JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
  298.               JSAMPARRAY output_buf)
  299. {
  300.     my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
  301.     register int y, cred, cgreen, cblue;
  302.     int cb, cr;
  303.     register JSAMPROW outptr0, outptr1;
  304.     JSAMPROW inptr00, inptr01, inptr1, inptr2;
  305.     JDIMENSION col;
  306.   
  307.     /* copy these pointers into registers if possible */
  308.     register JSAMPLE * range_limit = cinfo->sample_range_limit;
  309.     int * Crrtab = upsample->Cr_r_tab;
  310.     int * Cbbtab = upsample->Cb_b_tab;
  311.     long * Crgtab = upsample->Cr_g_tab;
  312.     long * Cbgtab = upsample->Cb_g_tab;
  313.     SHIFT_TEMPS
  314.  
  315.     inptr00 = input_buf[0][in_row_group_ctr*2];
  316.     inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
  317.     inptr1 = input_buf[1][in_row_group_ctr];
  318.     inptr2 = input_buf[2][in_row_group_ctr];
  319.     outptr0 = output_buf[0];
  320.     outptr1 = output_buf[1];
  321.   
  322.     /* Loop for each group of output pixels */
  323.     for (col = cinfo->output_width >> 1; col > 0; col--) 
  324.     {
  325.         /* Do the chroma part of the calculation */
  326.         cb = GETJSAMPLE(*inptr1++);
  327.         cr = GETJSAMPLE(*inptr2++);
  328.         cred = Crrtab[cr];
  329.         cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
  330.         cblue = Cbbtab[cb];
  331.     
  332.         /* Fetch 4 Y values and emit 4 pixels */
  333.         y  = GETJSAMPLE(*inptr00++);
  334.         outptr0[RGB_RED]   = range_limit[y + cred];
  335.         outptr0[RGB_GREEN] = range_limit[y + cgreen];
  336.         outptr0[RGB_BLUE]  = range_limit[y + cblue];
  337.         outptr0 += RGB_PIXELSIZE;
  338.     
  339.         y  = GETJSAMPLE(*inptr00++);
  340.         outptr0[RGB_RED]   = range_limit[y + cred];
  341.         outptr0[RGB_GREEN] = range_limit[y + cgreen];
  342.         outptr0[RGB_BLUE]  = range_limit[y + cblue];
  343.         outptr0 += RGB_PIXELSIZE;
  344.     
  345.         y  = GETJSAMPLE(*inptr01++);
  346.         outptr1[RGB_RED] =   range_limit[y + cred];
  347.         outptr1[RGB_GREEN] = range_limit[y + cgreen];
  348.         outptr1[RGB_BLUE] =  range_limit[y + cblue];
  349.         outptr1 += RGB_PIXELSIZE;
  350.     
  351.         y  = GETJSAMPLE(*inptr01++);
  352.         outptr1[RGB_RED]   = range_limit[y + cred];
  353.         outptr1[RGB_GREEN] = range_limit[y + cgreen];
  354.         outptr1[RGB_BLUE]  = range_limit[y + cblue];
  355.         outptr1 += RGB_PIXELSIZE;
  356.     }
  357.   
  358.     /* If image width is odd, do the last output column separately */
  359.     if (cinfo->output_width & 1) 
  360.     {
  361.         cb = GETJSAMPLE(*inptr1);
  362.         cr = GETJSAMPLE(*inptr2);
  363.         cred = Crrtab[cr];
  364.         cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
  365.         cblue = Cbbtab[cb];
  366.     
  367.         y  = GETJSAMPLE(*inptr00);
  368.         outptr0[RGB_RED]   = range_limit[y + cred];
  369.         outptr0[RGB_GREEN] = range_limit[y + cgreen];
  370.         outptr0[RGB_BLUE]  = range_limit[y + cblue];
  371.         
  372.         y  = GETJSAMPLE(*inptr01);
  373.         outptr1[RGB_RED]   = range_limit[y + cred];
  374.         outptr1[RGB_GREEN] = range_limit[y + cgreen];
  375.         outptr1[RGB_BLUE]  = range_limit[y + cblue];
  376.     }
  377. }
  378.  
  379.  
  380. /*
  381.  * Module initialization routine for merged upsampling/color conversion.
  382.  *
  383.  * NB: this is called under the conditions determined by use_merged_upsample()
  384.  * in jdmaster.c.  That routine MUST correspond to the actual capabilities
  385.  * of this module; no safety checks are made here.
  386.  */
  387.  
  388. GLOBAL(void) jinit_merged_upsampler (j_decompress_ptr cinfo)
  389. {
  390.     my_upsample_ptr upsample;
  391.  
  392.     upsample = (my_upsample_ptr) cinfo->mem->alloc_small(JPOOL_IMAGE, sizeof(my_upsampler));
  393.     cinfo->upsample = (struct jpeg_upsampler *) upsample;
  394.     upsample->pub.start_pass = start_pass_merged_upsample;
  395.     upsample->pub.need_context_rows = FALSE;
  396.  
  397.     upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
  398.  
  399.     if (cinfo->max_v_samp_factor == 2) 
  400.     {
  401.         upsample->pub.upsample = merged_2v_upsample;
  402.         upsample->upmethod = h2v2_merged_upsample;
  403.         
  404.         /* Allocate a spare row buffer */
  405.         upsample->spare_row = (JSAMPROW) cinfo->mem->alloc_large(JPOOL_IMAGE,
  406.                                         (size_t) (upsample->out_row_width * sizeof(JSAMPLE)));
  407.     } 
  408.     else 
  409.     {
  410.         upsample->pub.upsample = merged_1v_upsample;
  411.         upsample->upmethod = h2v1_merged_upsample;
  412.         /* No spare row needed */
  413.         upsample->spare_row = NULL;
  414.     }
  415.  
  416.     build_ycc_rgb_table(cinfo);
  417. }
  418.  
  419. #endif /* UPSAMPLE_MERGING_SUPPORTED */
  420.