home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / compresn / jpegv3sr / jccolor.c < prev    next >
C/C++ Source or Header  |  1992-03-14  |  7KB  |  238 lines

  1. /*
  2.  * jccolor.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 input colorspace conversion routines.
  9.  * These routines are invoked via the methods get_sample_rows
  10.  * and colorin_init/term.
  11.  */
  12.  
  13. #include "jinclude.h"
  14.  
  15.  
  16. static JSAMPARRAY pixel_row;    /* Workspace for a pixel row in input format */
  17.  
  18.  
  19. /*
  20.  * Initialize for colorspace conversion.
  21.  */
  22.  
  23. METHODDEF void
  24. colorin_init (compress_info_ptr cinfo)
  25. {
  26.   /* Allocate a workspace for the result of get_input_row. */
  27.   pixel_row = (*cinfo->emethods->alloc_small_sarray)
  28.         (cinfo->image_width, (long) cinfo->input_components);
  29. }
  30.  
  31.  
  32. /*
  33.  * Fetch some rows of pixels from get_input_row and convert to the
  34.  * JPEG colorspace.
  35.  */
  36.  
  37.  
  38. /*
  39.  * This version handles RGB -> YCbCr conversion.
  40.  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
  41.  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
  42.  * The conversion equations to be implemented are therefore
  43.  *    Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
  44.  *    Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B
  45.  *    Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B
  46.  * where Cb and Cr must be incremented by MAXJSAMPLE/2 to create a
  47.  * nonnegative output value.
  48.  * (These numbers are derived from TIFF Appendix O, draft of 4/10/91.)
  49.  *
  50.  * To avoid floating-point arithmetic, we represent the fractional constants
  51.  * as integers scaled up by 2^14 (about 4 digits precision); we have to divide
  52.  * the products by 2^14, with appropriate rounding, to get the correct answer.
  53.  *
  54.  * For even more speed, we could avoid any multiplications in the inner loop
  55.  * by precalculating the constants times R,G,B for all possible values.
  56.  * This is not currently implemented.
  57.  */
  58.  
  59. #define SCALEBITS    14
  60. #define ONE_HALF    ((INT32) 1 << (SCALEBITS-1))
  61. #define FIX(x)        ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
  62.  
  63.  
  64. METHODDEF void
  65. get_rgb_ycc_rows (compress_info_ptr cinfo,
  66.           int rows_to_read, JSAMPIMAGE image_data)
  67. {
  68.   register INT32 r, g, b;
  69.   register JSAMPROW inptr0, inptr1, inptr2;
  70.   register JSAMPROW outptr0, outptr1, outptr2;
  71.   register long col;
  72.   long width = cinfo->image_width;
  73.   int row;
  74.  
  75.   for (row = 0; row < rows_to_read; row++) {
  76.     /* Read one row from the source file */
  77.     (*cinfo->methods->get_input_row) (cinfo, pixel_row);
  78.     /* Convert colorspace */
  79.     inptr0 = pixel_row[0];
  80.     inptr1 = pixel_row[1];
  81.     inptr2 = pixel_row[2];
  82.     outptr0 = image_data[0][row];
  83.     outptr1 = image_data[1][row];
  84.     outptr2 = image_data[2][row];
  85.     for (col = width; col > 0; col--) {
  86.       r = GETJSAMPLE(*inptr0++);
  87.       g = GETJSAMPLE(*inptr1++);
  88.       b = GETJSAMPLE(*inptr2++);
  89.       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
  90.        * must be too; we do not need an explicit range-limiting operation.
  91.        * Hence the value being shifted is never negative, and we don't
  92.        * need the general RIGHT_SHIFT macro.
  93.        */
  94.       /* Y */
  95.       *outptr0++ = (JSAMPLE)
  96.     ((  FIX(0.29900)*r  + FIX(0.58700)*g + FIX(0.11400)*b
  97.       + ONE_HALF) >> SCALEBITS);
  98.       /* Cb */
  99.       *outptr1++ = (JSAMPLE)
  100.     (((-FIX(0.16874))*r - FIX(0.33126)*g + FIX(0.50000)*b
  101.       + ONE_HALF*(MAXJSAMPLE+1)) >> SCALEBITS);
  102.       /* Cr */
  103.       *outptr2++ = (JSAMPLE)
  104.     ((  FIX(0.50000)*r  - FIX(0.41869)*g - FIX(0.08131)*b
  105.       + ONE_HALF*(MAXJSAMPLE+1)) >> SCALEBITS);
  106.     }
  107.   }
  108. }
  109.  
  110.  
  111. /*
  112.  * Fetch some rows of pixels from get_input_row and convert to the
  113.  * JPEG colorspace.
  114.  * This version handles grayscale (no conversion).
  115.  */
  116.  
  117. METHODDEF void
  118. get_grayscale_rows (compress_info_ptr cinfo,
  119.             int rows_to_read, JSAMPIMAGE image_data)
  120. {
  121.   int row;
  122.  
  123.   for (row = 0; row < rows_to_read; row++) {
  124.     /* Read one row from the source file */
  125.     (*cinfo->methods->get_input_row) (cinfo, pixel_row);
  126.     /* Convert colorspace (gamma mapping needed here) */
  127.     jcopy_sample_rows(pixel_row, 0, image_data[0], row,
  128.               1, cinfo->image_width);
  129.   }
  130. }
  131.  
  132.  
  133. /*
  134.  * Fetch some rows of pixels from get_input_row and convert to the
  135.  * JPEG colorspace.
  136.  * This version handles multi-component colorspaces without conversion.
  137.  */
  138.  
  139. METHODDEF void
  140. get_noconvert_rows (compress_info_ptr cinfo,
  141.             int rows_to_read, JSAMPIMAGE image_data)
  142. {
  143.   int row, ci;
  144.  
  145.   for (row = 0; row < rows_to_read; row++) {
  146.     /* Read one row from the source file */
  147.     (*cinfo->methods->get_input_row) (cinfo, pixel_row);
  148.     /* Convert colorspace (gamma mapping needed here) */
  149.     for (ci = 0; ci < cinfo->input_components; ci++) {
  150.       jcopy_sample_rows(pixel_row, ci, image_data[ci], row,
  151.             1, cinfo->image_width);
  152.     }
  153.   }
  154. }
  155.  
  156.  
  157. /*
  158.  * Finish up at the end of the file.
  159.  */
  160.  
  161. METHODDEF void
  162. colorin_term (compress_info_ptr cinfo)
  163. {
  164.   /* no work (we let free_all release the workspace) */
  165. }
  166.  
  167.  
  168. /*
  169.  * The method selection routine for input colorspace conversion.
  170.  */
  171.  
  172. GLOBAL void
  173. jselccolor (compress_info_ptr cinfo)
  174. {
  175.   /* Make sure input_components agrees with in_color_space */
  176.   switch (cinfo->in_color_space) {
  177.   case CS_GRAYSCALE:
  178.     if (cinfo->input_components != 1)
  179.       ERREXIT(cinfo->emethods, "Bogus input colorspace");
  180.     break;
  181.  
  182.   case CS_RGB:
  183.   case CS_YCbCr:
  184.   case CS_YIQ:
  185.     if (cinfo->input_components != 3)
  186.       ERREXIT(cinfo->emethods, "Bogus input colorspace");
  187.     break;
  188.  
  189.   case CS_CMYK:
  190.     if (cinfo->input_components != 4)
  191.       ERREXIT(cinfo->emethods, "Bogus input colorspace");
  192.     break;
  193.  
  194.   default:
  195.     ERREXIT(cinfo->emethods, "Unsupported input colorspace");
  196.     break;
  197.   }
  198.  
  199.   /* Check num_components, set conversion method based on requested space */
  200.   switch (cinfo->jpeg_color_space) {
  201.   case CS_GRAYSCALE:
  202.     if (cinfo->num_components != 1)
  203.       ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
  204.     if (cinfo->in_color_space == CS_GRAYSCALE)
  205.       cinfo->methods->get_sample_rows = get_grayscale_rows;
  206.     else
  207.       ERREXIT(cinfo->emethods, "Unsupported color conversion request");
  208.     break;
  209.  
  210.   case CS_YCbCr:
  211.     if (cinfo->num_components != 3)
  212.       ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
  213.     if (cinfo->in_color_space == CS_RGB)
  214.       cinfo->methods->get_sample_rows = get_rgb_ycc_rows;
  215.     else if (cinfo->in_color_space == CS_YCbCr)
  216.       cinfo->methods->get_sample_rows = get_noconvert_rows;
  217.     else
  218.       ERREXIT(cinfo->emethods, "Unsupported color conversion request");
  219.     break;
  220.  
  221.   case CS_CMYK:
  222.     if (cinfo->num_components != 4)
  223.       ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
  224.     if (cinfo->in_color_space == CS_CMYK)
  225.       cinfo->methods->get_sample_rows = get_noconvert_rows;
  226.     else
  227.       ERREXIT(cinfo->emethods, "Unsupported color conversion request");
  228.     break;
  229.  
  230.   default:
  231.     ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
  232.     break;
  233.   }
  234.  
  235.   cinfo->methods->colorin_init = colorin_init;
  236.   cinfo->methods->colorin_term = colorin_term;
  237. }
  238.