Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

ccvt_c.c

00001 /*
00002    Colour conversion routines (RGB <-> YUV) in plain C
00003    (C) 2000 Nemosoft Unv.    nemosoft@smcc.demon.nl
00004    
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 */
00019 
00020 
00021 #include "ccvt.h"
00022 
00023 #define PUSH_RGB24      1
00024 #define PUSH_BGR24      2
00025 #define PUSH_RGB32      3
00026 #define PUSH_BGR32      4
00027 
00028 /* This is a really simplistic approach. Speedups are welcomed. */
00029 static void ccvt_420i(int width, int height, unsigned char *src, unsigned char *dst, int push)
00030 {
00031         int line, col, linewidth;
00032         int y, u, v, yy, vr, ug, vg, ub;
00033         int r, g, b;
00034         unsigned char *py, *pu, *pv;
00035 
00036         linewidth = width + (width >> 1);
00037         py = src;
00038         pu = py + 4;
00039         pv = pu + linewidth;
00040 
00041         y = *py++;
00042         yy = y << 8;
00043         u = *pu - 128;
00044         ug =   88 * u;
00045         ub =  454 * u;
00046         v = *pv - 128;
00047         vg =  183 * v;
00048         vr =  359 * v;
00049 
00050         /* The biggest problem is the interlaced data, and the fact that odd
00051            add even lines have V and U data, resp. 
00052          */
00053         for (line = 0; line < height; line++) {
00054                 for (col = 0; col < width; col++) {
00055                         r = (yy +      vr) >> 8;
00056                         g = (yy - ug - vg) >> 8;
00057                         b = (yy + ub     ) >> 8;
00058                         
00059                         switch(push) {
00060                         case PUSH_RGB24:
00061                                 *dst++ = r;
00062                                 *dst++ = g;
00063                                 *dst++ = b;
00064                                 break;
00065 
00066                         case PUSH_BGR24:
00067                                 *dst++ = b;
00068                                 *dst++ = g;
00069                                 *dst++ = r;
00070                                 break;
00071                         
00072                         case PUSH_RGB32:
00073                                 *dst++ = r;
00074                                 *dst++ = g;
00075                                 *dst++ = b;
00076                                 *dst++ = 0;
00077                                 break;
00078 
00079                         case PUSH_BGR32:
00080                                 *dst++ = b;
00081                                 *dst++ = g;
00082                                 *dst++ = r;
00083                                 *dst++ = 0;
00084                                 break;
00085                         }
00086                         
00087                         y = *py++;
00088                         yy = y << 8;
00089                         if ((col & 3) == 3)
00090                                 py += 2; // skip u/v
00091                         if (col & 1) {
00092                                 if ((col & 3) == 3) {
00093                                         pu += 4; // skip y
00094                                         pv += 4;
00095                                 }
00096                                 else {
00097                                         pu++;
00098                                         pv++;
00099                                 }
00100                                 u = *pu - 128;
00101                                 ug =   88 * u;
00102                                 ub =  454 * u;
00103                                 v = *pv - 128;
00104                                 vg =  183 * v;
00105                                 vr =  359 * v;
00106                         }
00107                 } /* ..for col */
00108                 if (line & 1) { // odd line: go to next band
00109                         pu += linewidth;
00110                         pv += linewidth;
00111                 }
00112                 else { // rewind u/v pointers
00113                         pu -= linewidth;
00114                         pv -= linewidth;
00115                 }
00116         } /* ..for line */
00117 }
00118 
00119 void ccvt_420i_rgb24(int width, int height, void *src, void *dst)
00120 {
00121         ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB24);
00122 }
00123 
00124 void ccvt_420i_bgr24(int width, int height, void *src, void *dst)
00125 {
00126         ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR24);
00127 }
00128 
00129 void ccvt_420i_rgb32(int width, int height, void *src, void *dst)
00130 {
00131         ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB32);
00132 }
00133 
00134 void ccvt_420i_bgr32(int width, int height, void *src, void *dst)
00135 {
00136         ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR32);
00137 }
00138 
00139 
00140 void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv)
00141 {
00142         short *s, *dy, *du, *dv;
00143         int line, col;
00144 
00145         s = (short *)src;
00146         dy = (short *)dsty;
00147         du = (short *)dstu;
00148         dv = (short *)dstv;
00149         for (line = 0; line < height; line++) {
00150                 for (col = 0; col < width; col += 4) {
00151                         *dy++ = *s++;
00152                         *dy++ = *s++;
00153                         if (line & 1)
00154                                 *dv++ = *s++;
00155                         else
00156                                 *du++ = *s++;
00157                 } /* ..for col */
00158         } /* ..for line */
00159 }
00160 
00161 void ccvt_420i_yuyv(int width, int height, void *src, void *dst)
00162 {
00163         int line, col, linewidth;
00164         unsigned char *py, *pu, *pv, *d;
00165 
00166         linewidth = width + (width >> 1);
00167         py = (unsigned char *)src;
00168         pu = src + 4;
00169         pv = pu + linewidth;
00170         d = (unsigned char *)dst;
00171 
00172         for (line = 0; line < height; line++) {
00173                 for (col = 0; col < width; col += 4) {
00174                         /* four pixels in one go */
00175                         *d++ = *py++;
00176                         *d++ = *pu++;
00177                         *d++ = *py++;
00178                         *d++ = *pv++;
00179                         
00180                         *d++ = *py++;
00181                         *d++ = *pu++;
00182                         *d++ = *py++;
00183                         *d++ = *pv++;
00184 
00185                         py += 2;
00186                         pu += 4;
00187                         pv += 4;
00188                 } /* ..for col */
00189                 if (line & 1) { // odd line: go to next band
00190                         pu += linewidth;
00191                         pv += linewidth;
00192                 }
00193                 else { // rewind u/v pointers
00194                         pu -= linewidth;
00195                         pv -= linewidth;
00196                 }
00197         } /* ..for line */
00198 }
00199 

Generated at Fri Aug 13 17:29:20 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001