summaryrefslogtreecommitdiff
path: root/v4l2-apps
diff options
context:
space:
mode:
authorhans@localhost.localdomain <hans@localhost.localdomain>2008-08-03 12:43:49 +0200
committerhans@localhost.localdomain <hans@localhost.localdomain>2008-08-03 12:43:49 +0200
commitd0280d4d77c5f7dd211cc827284347828e260ab9 (patch)
treefe85554044bd410d9a7ec3159d1adbaba11afe59 /v4l2-apps
parentf07be0b40ae3cbb2ae809d5f4151782f68eabb42 (diff)
downloadmediapointer-dvb-s2-d0280d4d77c5f7dd211cc827284347828e260ab9.tar.gz
mediapointer-dvb-s2-d0280d4d77c5f7dd211cc827284347828e260ab9.tar.bz2
libv4l: add support for converting to rgb24
From: Jean-Francois Moine <moinejf@free.fr> Add support for conversion to RGB24 (before we only support BGR24) based on a patch by Jean-Francois Moine Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Diffstat (limited to 'v4l2-apps')
-rw-r--r--v4l2-apps/lib/libv4l/ChangeLog2
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/bayer.c30
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h6
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c69
-rw-r--r--v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c47
5 files changed, 132 insertions, 22 deletions
diff --git a/v4l2-apps/lib/libv4l/ChangeLog b/v4l2-apps/lib/libv4l/ChangeLog
index 37620001a..efa501f56 100644
--- a/v4l2-apps/lib/libv4l/ChangeLog
+++ b/v4l2-apps/lib/libv4l/ChangeLog
@@ -3,6 +3,8 @@ libv4l-0.4.0
* Be more relaxed in our checks for mixing read and mmap access, we were
being more strict in this then certain kernel drivers (bttv) making xawtv
unhappy
+* Add support for conversion to RGB24 (before we only support BGR24) based
+ on a patch by Jean-Francois Moine
libv4l-0.3.9
------------
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c b/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
index 166c13011..ca7bb486f 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c
@@ -163,14 +163,10 @@ static void v4lconvert_border_bayer_line_to_bgr24(
}
/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
-void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
- unsigned char *bgr, int width, int height, unsigned int pixfmt)
+static void bayer_to_rgbbgr24(const unsigned char *bayer,
+ unsigned char *bgr, int width, int height, unsigned int pixfmt,
+ int start_with_green, int blue_line)
{
- int blue_line = pixfmt == V4L2_PIX_FMT_SBGGR8
- || pixfmt == V4L2_PIX_FMT_SGBRG8;
- int start_with_green = pixfmt == V4L2_PIX_FMT_SGBRG8
- || pixfmt == V4L2_PIX_FMT_SGRBG8;
-
/* render the first line */
v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width,
start_with_green, blue_line);
@@ -317,6 +313,26 @@ void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
!start_with_green, !blue_line);
}
+void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
+ unsigned char *bgr, int width, int height, unsigned int pixfmt)
+{
+ bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
+ pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
+ || pixfmt == V4L2_PIX_FMT_SGRBG8,
+ pixfmt != V4L2_PIX_FMT_SBGGR8 /* blue line */
+ && pixfmt != V4L2_PIX_FMT_SGBRG8);
+}
+
+void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
+ unsigned char *bgr, int width, int height, unsigned int pixfmt)
+{
+ bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
+ pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */
+ || pixfmt == V4L2_PIX_FMT_SGRBG8,
+ pixfmt == V4L2_PIX_FMT_SBGGR8 /* blue line */
+ || pixfmt == V4L2_PIX_FMT_SGBRG8);
+}
+
static void v4lconvert_border_bayer_line_to_y(
const unsigned char* bayer, const unsigned char* adjacent_bayer,
unsigned char *y, int width, int start_with_green, int blue_line)
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
index 90d8f2bdb..a85121cad 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h
@@ -71,6 +71,9 @@ struct v4lconvert_data {
};
+void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst,
+ int width, int height);
+
void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst,
int width, int height);
@@ -92,6 +95,9 @@ void v4lconvert_decode_sn9c10x(const unsigned char *src, unsigned char *dst,
void v4lconvert_decode_pac207(const unsigned char *src, unsigned char *dst,
int width, int height);
+void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
+ unsigned char *rgb, int width, int height, unsigned int pixfmt);
+
void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
unsigned char *rgb, int width, int height, unsigned int pixfmt);
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
index 2bbc44bd6..ffde7e1e8 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c
@@ -30,6 +30,7 @@
/* Note for proper functioning of v4lconvert_enum_fmt the first entries in
supported_src_pixfmts must match with the entries in supported_dst_pixfmts */
#define SUPPORTED_DST_PIXFMTS \
+ V4L2_PIX_FMT_RGB24, \
V4L2_PIX_FMT_BGR24, \
V4L2_PIX_FMT_YUV420
@@ -191,6 +192,7 @@ int v4lconvert_try_format(struct v4lconvert_data *data,
if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt) {
dest_fmt->fmt.pix.pixelformat = desired_pixfmt;
switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width * 3;
dest_fmt->fmt.pix.sizeimage = dest_fmt->fmt.pix.width *
@@ -228,6 +230,7 @@ int v4lconvert_convert(struct v4lconvert_data *data,
/* sanity check, is the dest buffer large enough? */
switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
needed = dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3;
break;
@@ -283,12 +286,19 @@ int v4lconvert_convert(struct v4lconvert_data *data,
components[2] = components[1] + (dest_fmt->fmt.pix.width *
dest_fmt->fmt.pix.height) / 4;
- if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24) {
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ tinyjpeg_set_components(data->jdec, components, 1);
+ result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24);
+ break;
+ case V4L2_PIX_FMT_BGR24:
tinyjpeg_set_components(data->jdec, components, 1);
result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24);
- } else {
+ break;
+ default:
tinyjpeg_set_components(data->jdec, components, 3);
result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P);
+ break;
}
/* If the JPEG header checked out ok and we get an error during actual
@@ -304,12 +314,20 @@ int v4lconvert_convert(struct v4lconvert_data *data,
case V4L2_PIX_FMT_SGBRG8:
case V4L2_PIX_FMT_SGRBG8:
case V4L2_PIX_FMT_SRGGB8:
- if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_bayer_to_rgb24(src, dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat);
+ break;
+ case V4L2_PIX_FMT_BGR24:
v4lconvert_bayer_to_bgr24(src, dest, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat);
- else
+ break;
+ default:
v4lconvert_bayer_to_yuv420(src, dest, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat);
+ break;
+ }
break;
/* YUYV line by line formats */
@@ -319,8 +337,8 @@ int v4lconvert_convert(struct v4lconvert_data *data,
{
unsigned char tmpbuf[dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height *
3 / 2];
- unsigned char *my_dst = (dest_fmt->fmt.pix.pixelformat ==
- V4L2_PIX_FMT_BGR24) ? tmpbuf : dest;
+ unsigned char *my_dst = (dest_fmt->fmt.pix.pixelformat !=
+ V4L2_PIX_FMT_YUV420) ? tmpbuf : dest;
switch (src_fmt->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_SPCA501:
@@ -337,10 +355,16 @@ int v4lconvert_convert(struct v4lconvert_data *data,
break;
}
- if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_yuv420_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height);
-
+ break;
+ }
break;
}
@@ -370,24 +394,39 @@ int v4lconvert_convert(struct v4lconvert_data *data,
break;
}
- if (dest_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_BGR24)
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_bayer_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height, bayer_fmt);
+ break;
+ case V4L2_PIX_FMT_BGR24:
v4lconvert_bayer_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height, bayer_fmt);
- else
+ break;
+ default:
v4lconvert_bayer_to_yuv420(tmpbuf, dest, dest_fmt->fmt.pix.width,
dest_fmt->fmt.pix.height, bayer_fmt);
+ break;
+ }
break;
}
+ case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
- /* dest must be V4L2_PIX_FMT_YUV420 then */
- printf("FIXME add bgr24 -> yuv420 conversion\n");
+ printf("FIXME add rgb24/bgr24 -> yuv420 conversion\n");
break;
case V4L2_PIX_FMT_YUV420:
- /* dest must be V4L2_PIX_FMT_BGR24 then */
- v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width,
- dest_fmt->fmt.pix.height);
+ switch (dest_fmt->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_yuv420_to_rgb24(src, dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width,
+ dest_fmt->fmt.pix.height);
+ break;
+ }
break;
default:
diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
index 388e64111..bda4cc342 100644
--- a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
+++ b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c
@@ -80,3 +80,50 @@ 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 i,j;
+
+ const unsigned char *ysrc = src;
+ const unsigned char *usrc = src + width * height;
+ const unsigned char *vsrc = usrc + (width * height) / 4;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j += 2) {
+#if 1 /* fast slightly less accurate multiplication free code */
+ int u1 = (((*usrc - 128) << 7) + (*usrc - 128)) >> 6;
+ int rg = (((*usrc - 128) << 1) + (*usrc - 128) +
+ ((*vsrc - 128) << 2) + ((*vsrc - 128) << 1)) >> 3;
+ int v1 = (((*vsrc - 128) << 1) + (*vsrc - 128)) >> 1;
+
+ *dest++ = CLIP(*ysrc + v1);
+ *dest++ = CLIP(*ysrc - rg);
+ *dest++ = CLIP(*ysrc + u1);
+ ysrc++;
+
+ *dest++ = CLIP(*ysrc + v1);
+ *dest++ = CLIP(*ysrc - rg);
+ *dest++ = CLIP(*ysrc + u1);
+#else
+ *dest++ = YUV2R(*ysrc, *usrc, *vsrc);
+ *dest++ = YUV2G(*ysrc, *usrc, *vsrc);
+ *dest++ = YUV2B(*ysrc, *usrc, *vsrc);
+ ysrc++;
+
+ *dest++ = YUV2R(*ysrc, *usrc, *vsrc);
+ *dest++ = YUV2G(*ysrc, *usrc, *vsrc);
+ *dest++ = YUV2B(*ysrc, *usrc, *vsrc);
+#endif
+ ysrc++;
+ usrc++;
+ vsrc++;
+ }
+ /* Rewind u and v for next line */
+ if (i&1) {
+ usrc -= width / 2;
+ vsrc -= width / 2;
+ }
+ }
+}