home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 9 / CD_ASCQ_09_1193.iso / news / 4441 / mpegcode / src / rgbtoycc.c < prev    next >
C/C++ Source or Header  |  1993-09-27  |  10KB  |  337 lines

  1. /*===========================================================================*
  2.  * rgbtoycc.c                                     *
  3.  *                                         *
  4.  *    Procedures to convert from RGB space to YUV space             *
  5.  *                                         *
  6.  * EXPORTED PROCEDURES:                                 *
  7.  *    PNMtoYUV                                 *
  8.  *    PPMtoYUV                                 *
  9.  *                                         *
  10.  *===========================================================================*/
  11.  
  12. /*
  13.  * Copyright (c) 1993 The Regents of the University of California.
  14.  * All rights reserved.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software and its
  17.  * documentation for any purpose, without fee, and without written agreement is
  18.  * hereby granted, provided that the above copyright notice and the following
  19.  * two paragraphs appear in all copies of this software.
  20.  *
  21.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  22.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  23.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  24.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  *
  26.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  27.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  28.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  29.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  30.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  31.  */
  32.  
  33. /*  
  34.  *  $Header: /n/picasso/users/keving/encode/src/RCS/rgbtoycc.c,v 1.1 1993/07/22 22:23:43 keving Exp keving $
  35.  *  $Log: rgbtoycc.c,v $
  36.  * Revision 1.1  1993/07/22  22:23:43  keving
  37.  * nothing
  38.  *
  39.  */
  40.  
  41.  
  42. /*==============*
  43.  * HEADER FILES *
  44.  *==============*/
  45.  
  46. #include "all.h"
  47. #include "frame.h"
  48. #include "fsize.h"
  49. #include "rgbtoycc.h"
  50.  
  51.  
  52. /*=====================*
  53.  * EXPORTED PROCEDURES *
  54.  *=====================*/
  55.  
  56.  
  57. /*===========================================================================*
  58.  *
  59.  * PNMtoYUV
  60.  *
  61.  *    convert PNM data into YUV data
  62.  *
  63.  * RETURNS:    nothing
  64.  *
  65.  * SIDE EFFECTS:    none
  66.  *
  67.  *===========================================================================*/
  68. void
  69. PNMtoYUV(frame)
  70.     MpegFrame *frame;
  71. {
  72.     register int x, y;
  73.     register uint8 *dy0, *dy1;
  74.     register uint8 *dcr, *dcb;
  75.     register xel *src0, *src1;
  76.     register int ydivisor, cdivisor;
  77.     static boolean  first = TRUE;
  78.     static float  mult299[1024], mult587[1024], mult114[1024];
  79.     static float  mult16874[1024], mult33126[1024], mult5[1024];
  80.     static float mult41869[1024], mult08131[1024];
  81.  
  82.     if ( first ) {
  83.         register int index;
  84.     register int maxValue;
  85.  
  86.     maxValue = frame->rgb_maxval;
  87.  
  88.         for ( index = 0; index <= maxValue; index++ ) {
  89.         mult299[index] = index*0.29900;
  90.         mult587[index] = index*0.58700;
  91.         mult114[index] = index*0.11400;
  92.         mult16874[index] = -0.16874*index;
  93.         mult33126[index] = -0.33126*index;
  94.         mult5[index] = index*0.50000;
  95.         mult41869[index] = -0.41869*index;
  96.         mult08131[index] = -0.08131*index;
  97.     }
  98.     
  99.     first = FALSE;
  100.     }
  101.  
  102.     Frame_AllocYCC(frame);
  103.  
  104.     /*
  105.      * okay.  Now, convert everything into YCrCb space. (the specific
  106.      * numbers come from the JPEG source, jccolor.c) The conversion
  107.      * equations to be implemented are therefore
  108.      *
  109.      * Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
  110.      * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B
  111.      * Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B
  112.      */
  113.  
  114. /* ydivisor should be a FLOAT, shouldn't it?!?! */
  115.  
  116.     ydivisor = (frame->rgb_maxval + 1) / 256;    /* for normalizing values
  117.                          * 0-255 */
  118.     cdivisor = ydivisor * 4;    /* because we're averaging 4 pixels */
  119.  
  120.     for (y = 0; y < Fsize_y; y += 2) {
  121.     for (x = 0, src0 = frame->rgb_data[y], src1 = frame->rgb_data[y + 1],
  122.          dy0 = frame->orig_y[y], dy1 = frame->orig_y[y + 1],
  123.          dcr = frame->orig_cr[y / 2], dcb = frame->orig_cb[y / 2];
  124.          x < Fsize_x;
  125.          x += 2, dy0 += 2, dy1 += 2, dcr++,
  126.          dcb++, src0 += 2, src1 += 2) {
  127.  
  128.         *dy0 = (mult299[PPM_GETR(*src0)] +
  129.             mult587[PPM_GETG(*src0)] +
  130.             mult114[PPM_GETB(*src0)]) / ydivisor;
  131.  
  132.         *dy1 = (mult299[PPM_GETR(*src1)] +
  133.             mult587[PPM_GETG(*src1)] +
  134.             mult114[PPM_GETB(*src1)]) / ydivisor;
  135.  
  136.         dy0[1] = (mult299[PPM_GETR(src0[1])] +
  137.               mult587[PPM_GETG(src0[1])] +
  138.               mult114[PPM_GETB(src0[1])]) / ydivisor;
  139.  
  140.         dy1[1] = (mult299[PPM_GETR(src1[1])] +
  141.               mult587[PPM_GETG(src1[1])] +
  142.               mult114[PPM_GETB(src1[1])]) / ydivisor;
  143.  
  144.         *dcb = ((mult16874[PPM_GETR(*src0)] +
  145.              mult33126[PPM_GETG(*src0)] +
  146.              mult5[PPM_GETB(*src0)] +
  147.              mult16874[PPM_GETR(*src1)] +
  148.              mult33126[PPM_GETG(*src1)] +
  149.              mult5[PPM_GETB(*src1)] +
  150.              mult16874[PPM_GETR(src0[1])] +
  151.              mult33126[PPM_GETG(src0[1])] +
  152.              mult5[PPM_GETB(src0[1])] +
  153.              mult16874[PPM_GETR(src1[1])] +
  154.              mult33126[PPM_GETG(src1[1])] +
  155.              mult5[PPM_GETB(src1[1])]) / cdivisor) + 128;
  156.  
  157.         *dcr = ((mult5[PPM_GETR(*src0)] +
  158.              mult41869[PPM_GETG(*src0)] +
  159.              mult08131[PPM_GETB(*src0)] +
  160.              mult5[PPM_GETR(*src1)] +
  161.              mult41869[PPM_GETG(*src1)] +
  162.              mult08131[PPM_GETB(*src1)] +
  163.              mult5[PPM_GETR(src0[1])] +
  164.              mult41869[PPM_GETG(src0[1])] +
  165.              mult08131[PPM_GETB(src0[1])] +
  166.              mult5[PPM_GETR(src1[1])] +
  167.              mult41869[PPM_GETG(src1[1])] +
  168.              mult08131[PPM_GETB(src1[1])]) / cdivisor) + 128;
  169.  
  170.         /* if your floating point is faster than your loads, you
  171.          * might consider this:
  172.          */
  173. #ifdef BLEAH
  174.         *dy0 = (PPM_GETR(*src0) * 0.29900 +
  175.             PPM_GETG(*src0) * 0.58700 +
  176.             PPM_GETB(*src0) * 0.11400) / ydivisor;
  177.         *dy1 = (PPM_GETR(*src1) * 0.29900 +
  178.             PPM_GETG(*src1) * 0.58700 +
  179.             PPM_GETB(*src1) * 0.11400) / ydivisor;
  180.  
  181.         dy0[1] = (PPM_GETR(src0[1]) * 0.29900 +
  182.               PPM_GETG(src0[1]) * 0.58700 +
  183.               PPM_GETB(src0[1]) * 0.11400) / ydivisor;
  184.  
  185.         dy1[1] = (PPM_GETR(src1[1]) * 0.29900 +
  186.               PPM_GETG(src1[1]) * 0.58700 +
  187.               PPM_GETB(src1[1]) * 0.11400) / ydivisor;
  188.  
  189.         *dcb = ((PPM_GETR(*src0) * -0.16874 +
  190.              PPM_GETG(*src0) * -0.33126 +
  191.              PPM_GETB(*src0) * 0.50000 +
  192.              PPM_GETR(*src1) * -0.16874 +
  193.              PPM_GETG(*src1) * -0. +
  194.              PPM_GETB(*src1) * 0.50000 +
  195.              PPM_GETR(src0[1]) * -0.16874 +
  196.              PPM_GETG(src0[1]) * -0.33126 +
  197.              PPM_GETB(src0[1]) * 0.50000 +
  198.              PPM_GETR(src1[1]) * -0.16874 +
  199.              PPM_GETG(src1[1]) * -0.33126 +
  200.              PPM_GETB(src1[1]) * 0.50000) / cdivisor) + 128;
  201.  
  202.         *dcr = ((PPM_GETR(*src0) * 0.50000 +
  203.              PPM_GETG(*src0) * -0.41869 +
  204.              PPM_GETB(*src0) * -0.08131 +
  205.              PPM_GETR(*src1) * 0.50000 +
  206.              PPM_GETG(*src1) * -0.41869 +
  207.              PPM_GETB(*src1) * -0.08131 +
  208.              PPM_GETR(src0[1]) * 0.50000 +
  209.              PPM_GETG(src0[1]) * -0.41869 +
  210.              PPM_GETB(src0[1]) * -0.08131 +
  211.              PPM_GETR(src1[1]) * 0.50000 +
  212.              PPM_GETG(src1[1]) * -0.41869 +
  213.              PPM_GETB(src1[1]) * -0.08131) / cdivisor) + 128;
  214. #endif
  215.  
  216.         DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", x, y, PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), *dy0, *dcb, *dcr));
  217.     }
  218.     }
  219. }
  220.  
  221.  
  222.  
  223. /*===========================================================================*
  224.  *
  225.  * PPMtoYUV
  226.  *
  227.  *    convert PPM data into YUV data
  228.  *    same as PNMtoYUV, except extracts data from ppm_data, and
  229.  *    assumes that ydivisor = 1
  230.  *
  231.  * RETURNS:    nothing
  232.  *
  233.  * SIDE EFFECTS:    none
  234.  *
  235.  *===========================================================================*/
  236. void
  237. PPMtoYUV(frame)
  238.     MpegFrame *frame;
  239. {
  240.     register int x, y;
  241.     register uint8 *dy0, *dy1;
  242.     register uint8 *dcr, *dcb;
  243.     register uint8 *src0, *src1;
  244.     register int cdivisor;
  245.     static boolean  first = TRUE;
  246.     static float  mult299[1024], mult587[1024], mult114[1024];
  247.     static float  mult16874[1024], mult33126[1024], mult5[1024];
  248.     static float mult41869[1024], mult08131[1024];
  249.  
  250.     if ( first ) {
  251.         register int index;
  252.     register int maxValue;
  253.  
  254.     maxValue = frame->rgb_maxval;
  255.  
  256.         for ( index = 0; index <= maxValue; index++ ) {
  257.         mult299[index] = index*0.29900;
  258.         mult587[index] = index*0.58700;
  259.         mult114[index] = index*0.11400;
  260.         mult16874[index] = -0.16874*index;
  261.         mult33126[index] = -0.33126*index;
  262.         mult5[index] = index*0.50000;
  263.         mult41869[index] = -0.41869*index;
  264.         mult08131[index] = -0.08131*index;
  265.     }
  266.     
  267.     first = FALSE;
  268.     }
  269.  
  270.     Frame_AllocYCC(frame);
  271.  
  272.     /* assume ydivisor = 1, so cdivisor = 4 */
  273.     if ( frame->rgb_maxval != 255 ) {
  274.     fprintf(stderr, "PPM max gray value != 255.  Exiting.\n");
  275.     exit(1);
  276.     }
  277.  
  278.     cdivisor = 4;
  279.  
  280.     for (y = 0; y < Fsize_y; y += 2) {
  281.     src0 = frame->ppm_data[y];
  282.     src1 = frame->ppm_data[y + 1];
  283.     dy0 = frame->orig_y[y];
  284.     dy1 = frame->orig_y[y + 1];
  285.     dcr = frame->orig_cr[y / 2];
  286.     dcb = frame->orig_cb[y / 2];
  287.  
  288.     for ( x = 0; x < Fsize_x; x += 2, dy0 += 2, dy1 += 2, dcr++,
  289.                    dcb++, src0 += 6, src1 += 6) {
  290.         *dy0 = (mult299[*src0] +
  291.             mult587[src0[1]] +
  292.             mult114[src0[2]]);
  293.  
  294.         *dy1 = (mult299[*src1] +
  295.             mult587[src1[1]] +
  296.             mult114[src1[2]]);
  297.  
  298.         dy0[1] = (mult299[src0[3]] +
  299.               mult587[src0[4]] +
  300.               mult114[src0[5]]);
  301.  
  302.         dy1[1] = (mult299[src1[3]] +
  303.               mult587[src1[4]] +
  304.               mult114[src1[5]]);
  305.  
  306.         *dcb = ((mult16874[*src0] +
  307.              mult33126[src0[1]] +
  308.              mult5[src0[2]] +
  309.              mult16874[*src1] +
  310.              mult33126[src1[1]] +
  311.              mult5[src1[2]] +
  312.              mult16874[src0[3]] +
  313.              mult33126[src0[4]] +
  314.              mult5[src0[5]] +
  315.              mult16874[src1[3]] +
  316.              mult33126[src1[4]] +
  317.              mult5[src1[5]]) / cdivisor) + 128;
  318.  
  319.         *dcr = ((mult5[*src0] +
  320.              mult41869[src0[1]] +
  321.              mult08131[src0[2]] +
  322.              mult5[*src1] +
  323.              mult41869[src1[1]] +
  324.              mult08131[src1[2]] +
  325.              mult5[src0[3]] +
  326.              mult41869[src0[4]] +
  327.              mult08131[src0[5]] +
  328.              mult5[src1[3]] +
  329.              mult41869[src1[4]] +
  330.              mult08131[src1[5]]) / cdivisor) + 128;
  331.  
  332.         DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", x, y, PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), *dy0, *dcb, *dcr));
  333.     }
  334.     }
  335. }
  336.  
  337.