Faster RGB to YUV conversion
authorWim Taymans <wim.taymans@gmail.com>
Sat, 2 Feb 2002 16:21:41 +0000 (16:21 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Sat, 2 Feb 2002 16:21:41 +0000 (16:21 +0000)
Original commit message from CVS:
Faster RGB to YUV conversion

ext/hermes/rgb2yuv.c

index 7495c71..6aa1e80 100644 (file)
 
 #include <gst/gst.h>
 
-#define RGB2YUV_SHIFT 8
-#define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
-#define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
-#define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
-#define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
-#define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
-#define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
-#define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
-#define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
-#define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
-
-/**
- *
- * height should be a multiple of 2 and width should be a multiple of 2 (if this is a
- * problem for anyone then tell me, and ill fix it)
- * chrominance data is only taken from every secound line others are ignored FIXME write HQ version
- */
-void
-gst_colorspace_rgb32_to_i420 (unsigned char *src, unsigned char *dest, guint width, guint height)
+#define Y_FROM_RGB(r,g,b)      ((9798 * (r) + 19235 * (g) + 3736 * (b)) >> 15)
+#define U_FROM_BY(b,y)                 ((16122 * ((b) - (y))) >> 15) + 128;
+#define V_FROM_RY(r,y)                 ((25203 * ((r) - (y))) >> 15) + 128;
+
+static void
+gst_colorspace_rgb32_to_yuv (unsigned char *src, 
+                            unsigned char *ydst,
+                            unsigned char *udst,
+                            unsigned char *vdst,
+                            guint width, guint height)
 {
   int y;
   const int chrom_width = width >> 1;
-  const int chrom_size = (width * height) >> 2;
+  int Y;
+  int b, g, r;
 
-  unsigned char *ydst = dest;
-  unsigned char *udst = ydst + (width * height);
-  unsigned char *vdst = udst + chrom_size;
-
-  for (y = 0; y < height; y += 2) {
+  for (y = height; y; y -= 2) {
     int i;
 
-    for (i = 0; i < chrom_width; i++) {
-      unsigned int b = src[8 * i + 0];
-      unsigned int g = src[8 * i + 1];
-      unsigned int r = src[8 * i + 2];
+    for (i = chrom_width; i; i--) {
+      b = *src++;
+      g = *src++;
+      r = *src++;
+      src++;
 
-      unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      unsigned int V = ((RV * r + GV * g + BV * b) >> RGB2YUV_SHIFT) + 128;
-      unsigned int U = ((RU * r + GU * g + BU * b) >> RGB2YUV_SHIFT) + 128;
+      Y = Y_FROM_RGB (r,g,b);
 
-      udst[i] = U;
-      vdst[i] = V;
-      ydst[2 * i] = Y;
+      *ydst++ = Y;
+      *udst++ = U_FROM_BY (b,Y);
+      *vdst++ = V_FROM_RY (r,Y);
 
-      b = src[8 * i + 4];
-      g = src[8 * i + 5];
-      r = src[8 * i + 6];
+      b = *src++;
+      g = *src++;
+      r = *src++; src++;
 
-      Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      ydst[2 * i + 1] = Y;
+      *ydst++ = Y_FROM_RGB (r,g,b);
     }
-    ydst += width;
-    src += (width * 4);
-
-    for (i = 0; i < chrom_width; i++) {
-      unsigned int b = src[8 * i + 0];
-      unsigned int g = src[8 * i + 1];
-      unsigned int r = src[8 * i + 2];
-
-      unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
 
-      ydst[2 * i] = Y;
-
-      b = src[8 * i + 4];
-      g = src[8 * i + 5];
-      r = src[8 * i + 6];
-
-      Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      ydst[2 * i + 1] = Y;
+    for (i = width; i; i--) {
+      b = *src++;
+      g = *src++;
+      r = *src++; src++;
+      *ydst++ = Y_FROM_RGB (r,g,b);
     }
-    udst += chrom_width;
-    vdst += chrom_width;
-    ydst += width;
-    src += (width * 4);
   }
 }
 
 void
-gst_colorspace_rgb32_to_yv12 (unsigned char *src, unsigned char *dest, guint width, guint height)
+gst_colorspace_rgb32_to_i420 (unsigned char *src, unsigned char *dest, guint width, guint height)
 {
-  int y;
-  const int chrom_width = width >> 1;
-  const int chrom_size = (width * height) >> 2;
-
   unsigned char *ydst = dest;
-  unsigned char *vdst = ydst + (width * height);
-  unsigned char *udst = vdst + chrom_size;
-
-  for (y = 0; y < height; y += 2) {
-    int i;
-
-    for (i = 0; i < chrom_width; i++) {
-      unsigned int b = src[8 * i + 0];
-      unsigned int g = src[8 * i + 1];
-      unsigned int r = src[8 * i + 2];
-
-      unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      unsigned int V = ((RV * r + GV * g + BV * b) >> RGB2YUV_SHIFT) + 128;
-      unsigned int U = ((RU * r + GU * g + BU * b) >> RGB2YUV_SHIFT) + 128;
-
-      udst[i] = U;
-      vdst[i] = V;
-      ydst[2 * i] = Y;
-
-      b = src[8 * i + 4];
-      g = src[8 * i + 5];
-      r = src[8 * i + 6];
-
-      Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      ydst[2 * i + 1] = Y;
-    }
-    ydst += width;
-    src += (width * 4);
-
-    for (i = 0; i < chrom_width; i++) {
-      unsigned int b = src[8 * i + 0];
-      unsigned int g = src[8 * i + 1];
-      unsigned int r = src[8 * i + 2];
-
-      unsigned int Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
+  unsigned char *udst = ydst + (width * height);
+  unsigned char *vdst = udst + ((width * height) >> 2);
 
-      ydst[2 * i] = Y;
+  gst_colorspace_rgb32_to_yuv (src, ydst, udst, vdst, width, height);
+}
 
-      b = src[8 * i + 4];
-      g = src[8 * i + 5];
-      r = src[8 * i + 6];
+void
+gst_colorspace_rgb32_to_yv12 (unsigned char *src, unsigned char *dest, guint width, guint height)
+{
+  unsigned char *ydst = dest;
+  unsigned char *vdst = ydst + (width * height);
+  unsigned char *udst = vdst + ((width * height) >> 2);
 
-      Y = ((RY * r + GY * g + BY * b) >> RGB2YUV_SHIFT) + 16;
-      ydst[2 * i + 1] = Y;
-    }
-    udst += chrom_width;
-    vdst += chrom_width;
-    ydst += width;
-    src += (width * 4);
-  }
+  gst_colorspace_rgb32_to_yuv (src, ydst, udst, vdst, width, height);
 }