aboutsummaryrefslogtreecommitdiff
path: root/yuv.c
diff options
context:
space:
mode:
Diffstat (limited to 'yuv.c')
-rw-r--r--yuv.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/yuv.c b/yuv.c
new file mode 100644
index 0000000..4e6cd69
--- /dev/null
+++ b/yuv.c
@@ -0,0 +1,201 @@
+/*
+ * EffecTV - Realtime Digital Video Effector
+ * Copyright (C) 2001-2002 FUKUCHI Kentaro
+ *
+ * yuv.c: YUV(YCbCr) color system utilities
+ *
+ */
+
+#include <math.h>
+#include "m_pd.h"
+
+/*
+ * conversion from YUV to RGB
+ * r = 1.164*(y-16) + 1.596*(v-128);
+ * g = 1.164*(y-16) - 0.813*(v-128) - 0.391*(u-128);
+ * b = 1.164*(y-16) + 2.018*(u-128);
+ * conversion from RGB to YUV
+ * y = 0.257*r + 0.504*g + 0.098*b + 16
+ * u = -0.148*r - 0.291*g + 0.439*b + 128
+ * v = 0.439*r - 0.368*g - 0.071*b + 128
+ */
+
+float YtoRGB[256];
+float VtoR[256], VtoG[256];
+float UtoG[256], UtoB[256];
+float RtoY[256], RtoU[256], RtoV[256];
+float GtoY[256], GtoU[256], GtoV[256];
+float BtoY[256], BtoV[256];
+
+static int yuvinit=-1;
+
+int yuv_init(void)
+{
+ int i;
+
+ if(yuvinit==-1) {
+ for(i=0; i<256; i++) {
+ YtoRGB[i] = 1.164*(i-16);
+ VtoR[i] = 1.596*(i-128);
+ VtoG[i] = -0.813*(i-128);
+ UtoG[i] = -0.391*(i-128);
+ UtoB[i] = 2.018*(i-128);
+ RtoY[i] = 0.257*i;
+ RtoU[i] = -0.148*i;
+ RtoV[i] = 0.439*i;
+ GtoY[i] = 0.504*i;
+ GtoU[i] = -0.291*i;
+ GtoV[i] = -0.368*i;
+ BtoY[i] = 0.098*i;
+ BtoV[i] = -0.071*i;
+ }
+ yuvinit=1;
+ }
+
+ return 0;
+}
+
+unsigned char yuv_RGBtoY(int rgb)
+{
+ int i;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ i = RtoY[(rgb>>16)&0xff];
+ i += GtoY[(rgb>>8)&0xff];
+ i += BtoY[rgb&0xff];
+ i += 16;
+
+ return i;
+}
+
+unsigned char yuv_RGBtoU(int rgb)
+{
+ int i;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ i = RtoU[(rgb>>16)&0xff];
+ i += GtoU[(rgb>>8)&0xff];
+ i += RtoV[rgb&0xff];/* BtoU == RtoV */
+ i += 128;
+
+ return i;
+}
+
+unsigned char yuv_RGBtoV(int rgb)
+{
+ int i;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ i = RtoV[(rgb>>16)&0xff];
+ i += GtoV[(rgb>>8)&0xff];
+ i += BtoV[rgb&0xff];
+ i += 128;
+
+ return i;
+}
+
+unsigned char yuv_YUVtoR(unsigned char y, unsigned char u, unsigned char v)
+{
+ int r;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ r = YtoRGB[(int)y] + VtoR[(int)v];
+ if ( r>255 ) r=255;
+ if ( r<0 ) r=0;
+ return r;
+}
+
+unsigned char yuv_YUVtoG(unsigned char y, unsigned char u, unsigned char v)
+{
+ int g;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ g = YtoRGB[(int)y] + UtoG[(int)u] + VtoG[(int)v];
+ if ( g>255 ) g=255;
+ if ( g<0 ) g=0;
+ return g;
+}
+
+unsigned char yuv_YUVtoB(unsigned char y, unsigned char u, unsigned char v)
+{
+ int b;
+
+ if ( yuvinit == -1 ) { yuv_init(); }
+ b = YtoRGB[(int)y] + UtoB[(int)u];
+ if ( b>255 ) b=255;
+ if ( b<0 ) b=0;
+ return b;
+}
+
+int yuv_YUVtoRGB(unsigned char y, unsigned char u, unsigned char v)
+{
+ if ( yuvinit == -1 ) { yuv_init(); }
+ return ( (yuv_YUVtoR(y,u,v)<<16) + (yuv_YUVtoG(y,u,v)<<8) + (yuv_YUVtoB(y,u,v)) );
+}
+
+void yuv_Y122RGB( short int* packet, unsigned int *rgb, int width, int height )
+{
+ unsigned char y=0,u=0,v=0;
+ int X,Y;
+ int uoffset = width*height;
+ int maxoffset = width*height+((width*height)>>1);
+ int voffset = width*height+((width*height)>>2);
+
+ if ( !packet || !rgb )
+ {
+ post( "yuv_Y122RGB : pointers are NULL !!!" );
+ return;
+ }
+ if ( yuvinit == -1 ) { yuv_init(); }
+ for(Y=0; Y < height; Y++){
+ for(X=0; X < width; X++){
+ // post( "yuv_Y122RGB : X=%d Y=%d", X, Y );
+ if ( (Y*width+X) < maxoffset )
+ y=(packet[Y*width+X]>>7);
+ if( (uoffset+((Y>>1)*width+(X>>1))) < maxoffset )
+ u=(packet[uoffset+((Y>>1)*width+(X>>1))]>>8)+128;
+ if( (voffset+((Y>>1)*width+(X>>1))) < maxoffset )
+ v=(packet[voffset+((Y>>1)*width+(X>>1))]>>8)+128;
+
+ rgb[Y*width+X] = yuv_YUVtoRGB( y, u, v );
+ }
+ }
+
+}
+
+void yuv_RGB2Y12( unsigned int *rgb, short int* packet, int width, int height )
+{
+ short int y,u,v,iu=0,iv=0;
+ int X,Y;
+ int uoffset = width*height;
+ int maxoffset = width*height+((width*height)>>1);
+ int voffset = width*height+((width*height)>>2);
+
+ if ( !packet || !rgb )
+ {
+ post( "yuv_RGB2Y12 : pointers are NULL !!!" );
+ return;
+ }
+ if ( yuvinit == -1 ) { yuv_init(); };
+ for(Y=0; Y < height; Y++)
+ for(X=0; X < width; X++){
+ {
+ // post( "yuv_RGB2Y12 : X=%d Y=%d", X, Y );
+ y=yuv_RGBtoY( rgb[Y*width+X] );
+ u=yuv_RGBtoU( rgb[Y*width+X] );
+ v=yuv_RGBtoV( rgb[Y*width+X] );
+
+ if ( (Y*width+X) < maxoffset )
+ packet[Y*width+X]=(y<<7);
+ if( (uoffset+iu) < maxoffset )
+ packet[uoffset+iu]=(u-128<<8);
+ if( (voffset+iv) < maxoffset )
+ packet[voffset+iv]=(v-128<<8);
+ if ( ( X%2 == 0) && ( Y%2 == 0) )
+ {
+ iu++; iv++;
+ }
+ }
+ }
+
+}