summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
diff options
context:
space:
mode:
Diffstat (limited to 'v4l2-apps/libv4l/libv4lconvert/rgbyuv.c')
-rw-r--r--v4l2-apps/libv4l/libv4lconvert/rgbyuv.c197
1 files changed, 178 insertions, 19 deletions
diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
index 0f26b227a..00706be9d 100644
--- a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
+++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c
@@ -20,13 +20,65 @@
*/
+#include <string.h>
#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;
@@ -267,19 +339,71 @@ void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest,
}
}
-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 *vdest;
+ 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];
+ *dest++ = src1[1];
+ *dest++ = src1[3];
src1 += 4;
}
}
@@ -287,11 +411,17 @@ 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 */
- *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */
+ *udest++ = ((int) src[0] + src1[0]) / 2; /* U */
+ *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */
src += 4;
src1 += 4;
}
@@ -314,3 +444,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;
+ }
+}