From 5f90628a20098c6dcde990310eaaabec2cef4694 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 11 Mar 2009 13:10:27 +0100 Subject: libv4l: add support for converting to YV12 planar From: Hans de Goede Add support for converting to YV12 planar (next to the already supported YU12 / I420) and implement RGB/BGR24 -> YU/YV12 conversion Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 139 ++++++++++++++++++++++++++++---- 1 file changed, 123 insertions(+), 16 deletions(-) (limited to 'v4l2-apps/libv4l/libv4lconvert/rgbyuv.c') diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c index 0f26b227a..d5feb457e 100644 --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -20,13 +20,65 @@ */ +#include #include "libv4lconvert-priv.h" -#define RGB2YUV(r,g,b,y,u,v) \ - (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15); \ +#define RGB2Y(r,g,b,y) \ + (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15) + +#define RGB2UV(r,g,b,u,v) \ (u) = (( -4878*(r) - 9578*(g) + 14456*(b) + 4210688) >> 15); \ (v) = (( 14456*(r) - 12105*(g) - 2351*(b) + 4210688) >> 15) +void v4lconvert_rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt, int bgr, int yvu) +{ + int x, y; + unsigned char *udest, *vdest; + + /* Y */ + for (y = 0; y < src_fmt->fmt.pix.height; y++) { + for (x = 0; x < src_fmt->fmt.pix.width; x++) { + if (bgr) { + RGB2Y(src[2], src[1], src[0], *dest++); + } else { + RGB2Y(src[0], src[1], src[2], *dest++); + } + src += 3; + } + src += src_fmt->fmt.pix.bytesperline - 3 * src_fmt->fmt.pix.width; + } + src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline; + + /* U + V */ + if (yvu) { + vdest = dest; + udest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4; + } else { + udest = dest; + vdest = dest + src_fmt->fmt.pix.width * src_fmt->fmt.pix.height / 4; + } + + for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) { + for (x = 0; x < src_fmt->fmt.pix.width / 2; x++) { + int avg_src[3]; + avg_src[0] = (src[0] + src[3] + src[src_fmt->fmt.pix.bytesperline] + + src[src_fmt->fmt.pix.bytesperline + 3]) / 4; + avg_src[1] = (src[1] + src[4] + src[src_fmt->fmt.pix.bytesperline + 1] + + src[src_fmt->fmt.pix.bytesperline + 4]) / 4; + avg_src[2] = (src[2] + src[5] + src[src_fmt->fmt.pix.bytesperline + 2] + + src[src_fmt->fmt.pix.bytesperline + 5]) / 4; + if (bgr) { + RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++); + } else { + RGB2UV(avg_src[0], avg_src[1], avg_src[2], *udest++, *vdest++); + } + src += 6; + } + src += 2 * src_fmt->fmt.pix.bytesperline - 3 * src_fmt->fmt.pix.width; + } +} + #define YUV2R(y, u, v) ({ \ int r = (y) + ((((v)-128)*1436) >> 10); r > 255 ? 255 : r < 0 ? 0 : r; }) #define YUV2G(y, u, v) ({ \ @@ -37,13 +89,20 @@ #define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest, - int width, int height) + int width, int height, int yvu) { int i,j; const unsigned char *ysrc = src; - const unsigned char *usrc = src + width * height; - const unsigned char *vsrc = usrc + (width * height) / 4; + const unsigned char *usrc, *vsrc; + + if (yvu) { + vsrc = src + width * height; + usrc = vsrc + (width * height) / 4; + } else { + usrc = src + width * height; + vsrc = usrc + (width * height) / 4; + } for (i = 0; i < height; i++) { for (j = 0; j < width; j += 2) { @@ -84,13 +143,20 @@ void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest, } void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest, - int width, int height) + int width, int height, int yvu) { int i,j; const unsigned char *ysrc = src; - const unsigned char *usrc = src + width * height; - const unsigned char *vsrc = usrc + (width * height) / 4; + const unsigned char *usrc, *vsrc; + + if (yvu) { + vsrc = src + width * height; + usrc = vsrc + (width * height) / 4; + } else { + usrc = src + width * height; + vsrc = usrc + (width * height) / 4; + } for (i = 0; i < height; i++) { for (j = 0; j < width; j += 2) { @@ -183,11 +249,11 @@ void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dest, } void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, - int width, int height) + int width, int height, int yvu) { int i, j; const unsigned char *src1; - unsigned char *vdest; + unsigned char *udest, *vdest; /* copy the Y values */ src1 = src; @@ -202,10 +268,16 @@ void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, /* copy the U and V values */ src++; /* point to V */ src1 = src + width * 2; /* next line */ - vdest = dest + width * height / 4; + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } for (i = 0; i < height; i += 2) { for (j = 0; j < width; j += 2) { - *dest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *udest++ = ((int) src[0] + src1[0]) / 2; /* U */ *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ src += 4; src1 += 4; @@ -268,11 +340,11 @@ void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest, } void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, - int width, int height) + int width, int height, int yvu) { int i, j; const unsigned char *src1; - unsigned char *vdest; + unsigned char *udest, *vdest; /* copy the Y values */ src1 = src; @@ -287,10 +359,16 @@ void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, /* copy the U and V values */ src++; /* point to V */ src1 = src + width * 2; /* next line */ - vdest = dest + width * height / 4; + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } for (i = 0; i < height; i += 2) { for (j = 0; j < width; j += 2) { - *dest++ = ((int) src[2] + src1[2]) / 2; /* U */ + *udest++ = ((int) src[2] + src1[2]) / 2; /* U */ *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */ src += 4; src1 += 4; @@ -314,3 +392,32 @@ void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, *dst++ = tmp0; } } + +void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dest, + const struct v4l2_format *src_fmt) +{ + int y; + + /* Copy Y */ + for (y = 0; y < src_fmt->fmt.pix.height; y++) { + memcpy(dest, src, src_fmt->fmt.pix.width); + dest += src_fmt->fmt.pix.width; + src += src_fmt->fmt.pix.bytesperline; + } + + /* Copy component 2 */ + src += src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline / 4; + for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) { + memcpy(dest, src, src_fmt->fmt.pix.width / 2); + dest += src_fmt->fmt.pix.width / 2; + src += src_fmt->fmt.pix.bytesperline / 2; + } + + /* Copy component 1 */ + src -= src_fmt->fmt.pix.height * src_fmt->fmt.pix.bytesperline / 2; + for (y = 0; y < src_fmt->fmt.pix.height / 2; y++) { + memcpy(dest, src, src_fmt->fmt.pix.width / 2); + dest += src_fmt->fmt.pix.width / 2; + src += src_fmt->fmt.pix.bytesperline / 2; + } +} -- cgit v1.2.3 From d02d1e3c9f20e691d7d3ff62275d57bfc4766e19 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 11 Mar 2009 13:16:01 +0100 Subject: libv4l: add UYVY support From: Julien BLACHE Attached is a patch to add UYVY support to libv4lconvert. It's obviously a shameless respin of the YVYU conversion routines :P Tested on a USB Apple iSight, which only supports UYVY. Priority: normal Signed-off-by: Julien BLACHE Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 91 +++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'v4l2-apps/libv4l/libv4lconvert/rgbyuv.c') diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c index d5feb457e..ec297b1f7 100644 --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -378,6 +378,97 @@ void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, } } +void v4lconvert_uyvy_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[0]; + int v = src[2]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[1] + u1); + *dest++ = CLIP(src[1] - rg); + *dest++ = CLIP(src[1] + v1); + + *dest++ = CLIP(src[3] + u1); + *dest++ = CLIP(src[3] - rg); + *dest++ = CLIP(src[3] + v1); + src += 4; + } + } +} + +void v4lconvert_uyvy_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[0]; + int v = src[2]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[1] + v1); + *dest++ = CLIP(src[1] - rg); + *dest++ = CLIP(src[1] + u1); + + *dest++ = CLIP(src[3] + v1); + *dest++ = CLIP(src[3] - rg); + *dest++ = CLIP(src[3] + u1); + src += 4; + } + } +} + +void v4lconvert_uyvy_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height, int yvu) +{ + int i, j; + const unsigned char *src1; + unsigned char *udest, *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[1]; + *dest++ = src1[3]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *udest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, int width, int height) { -- cgit v1.2.3 From d58bea2b9caa5512cbd5136719391cc7055fe410 Mon Sep 17 00:00:00 2001 From: "hans@rhel5-devel.localdomain" Date: Wed, 11 Mar 2009 13:16:22 +0100 Subject: libv4l: remove duplicate v4lconvert_yvyu_to_yuv420 function From: Hans de Goede Remove v4lconvert_yvyu_to_yuv420 function as its functionality is duplicate with v4lconvert_yuyv_to_yuv420 Priority: normal Signed-off-by: Hans de Goede --- v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 39 --------------------------------- 1 file changed, 39 deletions(-) (limited to 'v4l2-apps/libv4l/libv4lconvert/rgbyuv.c') diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c index ec297b1f7..00706be9d 100644 --- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -339,45 +339,6 @@ void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest, } } -void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, - int width, int height, int yvu) -{ - int i, j; - const unsigned char *src1; - unsigned char *udest, *vdest; - - /* copy the Y values */ - src1 = src; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { - *dest++ = src1[0]; - *dest++ = src1[2]; - src1 += 4; - } - } - - /* copy the U and V values */ - src++; /* point to V */ - src1 = src + width * 2; /* next line */ - if (yvu) { - vdest = dest; - udest = dest + width * height / 4; - } else { - udest = dest; - vdest = dest + width * height / 4; - } - for (i = 0; i < height; i += 2) { - for (j = 0; j < width; j += 2) { - *udest++ = ((int) src[2] + src1[2]) / 2; /* U */ - *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */ - src += 4; - src1 += 4; - } - src = src1; - src1 += width * 2; - } -} - void v4lconvert_uyvy_to_bgr24(const unsigned char *src, unsigned char *dest, int width, int height) { -- cgit v1.2.3