summaryrefslogtreecommitdiffstats
path: root/ext/hermes/rgb2yuv.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/hermes/rgb2yuv.c')
-rw-r--r--ext/hermes/rgb2yuv.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/ext/hermes/rgb2yuv.c b/ext/hermes/rgb2yuv.c
new file mode 100644
index 00000000..7495c71b
--- /dev/null
+++ b/ext/hermes/rgb2yuv.c
@@ -0,0 +1,150 @@
+/*
+ *
+ * rgb2rgb.c, Software RGB to YUV convertor
+ * Written by Nick Kurshev.
+ * palette & yuv & runtime cpu stuff by Michael (michaelni@gmx.at) (under GPL)
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+#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)
+{
+ int y;
+ const int chrom_width = width >> 1;
+ const int chrom_size = (width * height) >> 2;
+
+ unsigned char *ydst = dest;
+ unsigned char *udst = ydst + (width * height);
+ unsigned char *vdst = udst + 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;
+
+ 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;
+ }
+ 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)
+{
+ 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;
+
+ 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;
+ }
+ udst += chrom_width;
+ vdst += chrom_width;
+ ydst += width;
+ src += (width * 4);
+ }
+}