home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 9
/
CD_ASCQ_09_1193.iso
/
news
/
4441
/
mpegcode
/
src
/
rgbtoycc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-27
|
10KB
|
337 lines
/*===========================================================================*
* rgbtoycc.c *
* *
* Procedures to convert from RGB space to YUV space *
* *
* EXPORTED PROCEDURES: *
* PNMtoYUV *
* PPMtoYUV *
* *
*===========================================================================*/
/*
* Copyright (c) 1993 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*
* $Header: /n/picasso/users/keving/encode/src/RCS/rgbtoycc.c,v 1.1 1993/07/22 22:23:43 keving Exp keving $
* $Log: rgbtoycc.c,v $
* Revision 1.1 1993/07/22 22:23:43 keving
* nothing
*
*/
/*==============*
* HEADER FILES *
*==============*/
#include "all.h"
#include "frame.h"
#include "fsize.h"
#include "rgbtoycc.h"
/*=====================*
* EXPORTED PROCEDURES *
*=====================*/
/*===========================================================================*
*
* PNMtoYUV
*
* convert PNM data into YUV data
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
PNMtoYUV(frame)
MpegFrame *frame;
{
register int x, y;
register uint8 *dy0, *dy1;
register uint8 *dcr, *dcb;
register xel *src0, *src1;
register int ydivisor, cdivisor;
static boolean first = TRUE;
static float mult299[1024], mult587[1024], mult114[1024];
static float mult16874[1024], mult33126[1024], mult5[1024];
static float mult41869[1024], mult08131[1024];
if ( first ) {
register int index;
register int maxValue;
maxValue = frame->rgb_maxval;
for ( index = 0; index <= maxValue; index++ ) {
mult299[index] = index*0.29900;
mult587[index] = index*0.58700;
mult114[index] = index*0.11400;
mult16874[index] = -0.16874*index;
mult33126[index] = -0.33126*index;
mult5[index] = index*0.50000;
mult41869[index] = -0.41869*index;
mult08131[index] = -0.08131*index;
}
first = FALSE;
}
Frame_AllocYCC(frame);
/*
* okay. Now, convert everything into YCrCb space. (the specific
* numbers come from the JPEG source, jccolor.c) The conversion
* equations to be implemented are therefore
*
* Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
* Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B
* Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B
*/
/* ydivisor should be a FLOAT, shouldn't it?!?! */
ydivisor = (frame->rgb_maxval + 1) / 256; /* for normalizing values
* 0-255 */
cdivisor = ydivisor * 4; /* because we're averaging 4 pixels */
for (y = 0; y < Fsize_y; y += 2) {
for (x = 0, src0 = frame->rgb_data[y], src1 = frame->rgb_data[y + 1],
dy0 = frame->orig_y[y], dy1 = frame->orig_y[y + 1],
dcr = frame->orig_cr[y / 2], dcb = frame->orig_cb[y / 2];
x < Fsize_x;
x += 2, dy0 += 2, dy1 += 2, dcr++,
dcb++, src0 += 2, src1 += 2) {
*dy0 = (mult299[PPM_GETR(*src0)] +
mult587[PPM_GETG(*src0)] +
mult114[PPM_GETB(*src0)]) / ydivisor;
*dy1 = (mult299[PPM_GETR(*src1)] +
mult587[PPM_GETG(*src1)] +
mult114[PPM_GETB(*src1)]) / ydivisor;
dy0[1] = (mult299[PPM_GETR(src0[1])] +
mult587[PPM_GETG(src0[1])] +
mult114[PPM_GETB(src0[1])]) / ydivisor;
dy1[1] = (mult299[PPM_GETR(src1[1])] +
mult587[PPM_GETG(src1[1])] +
mult114[PPM_GETB(src1[1])]) / ydivisor;
*dcb = ((mult16874[PPM_GETR(*src0)] +
mult33126[PPM_GETG(*src0)] +
mult5[PPM_GETB(*src0)] +
mult16874[PPM_GETR(*src1)] +
mult33126[PPM_GETG(*src1)] +
mult5[PPM_GETB(*src1)] +
mult16874[PPM_GETR(src0[1])] +
mult33126[PPM_GETG(src0[1])] +
mult5[PPM_GETB(src0[1])] +
mult16874[PPM_GETR(src1[1])] +
mult33126[PPM_GETG(src1[1])] +
mult5[PPM_GETB(src1[1])]) / cdivisor) + 128;
*dcr = ((mult5[PPM_GETR(*src0)] +
mult41869[PPM_GETG(*src0)] +
mult08131[PPM_GETB(*src0)] +
mult5[PPM_GETR(*src1)] +
mult41869[PPM_GETG(*src1)] +
mult08131[PPM_GETB(*src1)] +
mult5[PPM_GETR(src0[1])] +
mult41869[PPM_GETG(src0[1])] +
mult08131[PPM_GETB(src0[1])] +
mult5[PPM_GETR(src1[1])] +
mult41869[PPM_GETG(src1[1])] +
mult08131[PPM_GETB(src1[1])]) / cdivisor) + 128;
/* if your floating point is faster than your loads, you
* might consider this:
*/
#ifdef BLEAH
*dy0 = (PPM_GETR(*src0) * 0.29900 +
PPM_GETG(*src0) * 0.58700 +
PPM_GETB(*src0) * 0.11400) / ydivisor;
*dy1 = (PPM_GETR(*src1) * 0.29900 +
PPM_GETG(*src1) * 0.58700 +
PPM_GETB(*src1) * 0.11400) / ydivisor;
dy0[1] = (PPM_GETR(src0[1]) * 0.29900 +
PPM_GETG(src0[1]) * 0.58700 +
PPM_GETB(src0[1]) * 0.11400) / ydivisor;
dy1[1] = (PPM_GETR(src1[1]) * 0.29900 +
PPM_GETG(src1[1]) * 0.58700 +
PPM_GETB(src1[1]) * 0.11400) / ydivisor;
*dcb = ((PPM_GETR(*src0) * -0.16874 +
PPM_GETG(*src0) * -0.33126 +
PPM_GETB(*src0) * 0.50000 +
PPM_GETR(*src1) * -0.16874 +
PPM_GETG(*src1) * -0. +
PPM_GETB(*src1) * 0.50000 +
PPM_GETR(src0[1]) * -0.16874 +
PPM_GETG(src0[1]) * -0.33126 +
PPM_GETB(src0[1]) * 0.50000 +
PPM_GETR(src1[1]) * -0.16874 +
PPM_GETG(src1[1]) * -0.33126 +
PPM_GETB(src1[1]) * 0.50000) / cdivisor) + 128;
*dcr = ((PPM_GETR(*src0) * 0.50000 +
PPM_GETG(*src0) * -0.41869 +
PPM_GETB(*src0) * -0.08131 +
PPM_GETR(*src1) * 0.50000 +
PPM_GETG(*src1) * -0.41869 +
PPM_GETB(*src1) * -0.08131 +
PPM_GETR(src0[1]) * 0.50000 +
PPM_GETG(src0[1]) * -0.41869 +
PPM_GETB(src0[1]) * -0.08131 +
PPM_GETR(src1[1]) * 0.50000 +
PPM_GETG(src1[1]) * -0.41869 +
PPM_GETB(src1[1]) * -0.08131) / cdivisor) + 128;
#endif
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));
}
}
}
/*===========================================================================*
*
* PPMtoYUV
*
* convert PPM data into YUV data
* same as PNMtoYUV, except extracts data from ppm_data, and
* assumes that ydivisor = 1
*
* RETURNS: nothing
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
PPMtoYUV(frame)
MpegFrame *frame;
{
register int x, y;
register uint8 *dy0, *dy1;
register uint8 *dcr, *dcb;
register uint8 *src0, *src1;
register int cdivisor;
static boolean first = TRUE;
static float mult299[1024], mult587[1024], mult114[1024];
static float mult16874[1024], mult33126[1024], mult5[1024];
static float mult41869[1024], mult08131[1024];
if ( first ) {
register int index;
register int maxValue;
maxValue = frame->rgb_maxval;
for ( index = 0; index <= maxValue; index++ ) {
mult299[index] = index*0.29900;
mult587[index] = index*0.58700;
mult114[index] = index*0.11400;
mult16874[index] = -0.16874*index;
mult33126[index] = -0.33126*index;
mult5[index] = index*0.50000;
mult41869[index] = -0.41869*index;
mult08131[index] = -0.08131*index;
}
first = FALSE;
}
Frame_AllocYCC(frame);
/* assume ydivisor = 1, so cdivisor = 4 */
if ( frame->rgb_maxval != 255 ) {
fprintf(stderr, "PPM max gray value != 255. Exiting.\n");
exit(1);
}
cdivisor = 4;
for (y = 0; y < Fsize_y; y += 2) {
src0 = frame->ppm_data[y];
src1 = frame->ppm_data[y + 1];
dy0 = frame->orig_y[y];
dy1 = frame->orig_y[y + 1];
dcr = frame->orig_cr[y / 2];
dcb = frame->orig_cb[y / 2];
for ( x = 0; x < Fsize_x; x += 2, dy0 += 2, dy1 += 2, dcr++,
dcb++, src0 += 6, src1 += 6) {
*dy0 = (mult299[*src0] +
mult587[src0[1]] +
mult114[src0[2]]);
*dy1 = (mult299[*src1] +
mult587[src1[1]] +
mult114[src1[2]]);
dy0[1] = (mult299[src0[3]] +
mult587[src0[4]] +
mult114[src0[5]]);
dy1[1] = (mult299[src1[3]] +
mult587[src1[4]] +
mult114[src1[5]]);
*dcb = ((mult16874[*src0] +
mult33126[src0[1]] +
mult5[src0[2]] +
mult16874[*src1] +
mult33126[src1[1]] +
mult5[src1[2]] +
mult16874[src0[3]] +
mult33126[src0[4]] +
mult5[src0[5]] +
mult16874[src1[3]] +
mult33126[src1[4]] +
mult5[src1[5]]) / cdivisor) + 128;
*dcr = ((mult5[*src0] +
mult41869[src0[1]] +
mult08131[src0[2]] +
mult5[*src1] +
mult41869[src1[1]] +
mult08131[src1[2]] +
mult5[src0[3]] +
mult41869[src0[4]] +
mult08131[src0[5]] +
mult5[src1[3]] +
mult41869[src1[4]] +
mult08131[src1[5]]) / cdivisor) + 128;
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));
}
}
}