@@ -271,6 +271,9 @@ void v4lconvert_hm12_to_bgr24(const unsigned char *src,
void v4lconvert_hm12_to_yuv420(const unsigned char *src,
unsigned char *dst, int width, int height, int yvu);
+void v4lconvert_hsv_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height, int bgr, int Xin, unsigned char hsv_enc);
+
void v4lconvert_rotate90(unsigned char *src, unsigned char *dest,
struct v4l2_format *fmt);
@@ -142,6 +142,9 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
{ V4L2_PIX_FMT_Y10BPACK, 10, 20, 20, 0 },
{ V4L2_PIX_FMT_Y16, 16, 20, 20, 0 },
{ V4L2_PIX_FMT_Y16_BE, 16, 20, 20, 0 },
+ /* hsv formats */
+ { V4L2_PIX_FMT_HSV32, 32, 5, 4, 0 },
+ { V4L2_PIX_FMT_HSV24, 24, 5, 4, 0 },
};
static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = {
@@ -1327,6 +1330,65 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
break;
}
break;
+ case V4L2_PIX_FMT_HSV24:
+ if (src_size < (width * height * 3)) {
+ V4LCONVERT_ERR("short hsv24 data frame\n");
+ errno = EPIPE;
+ result = -1;
+ }
+ switch (dest_pix_fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 24, fmt->fmt.pix.hsv_enc);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 1,
+ 24, fmt->fmt.pix.hsv_enc);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 24, fmt->fmt.pix.hsv_enc);
+ v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 3);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 24, fmt->fmt.pix.hsv_enc);
+ v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 3);
+ break;
+ }
+
+ break;
+
+ case V4L2_PIX_FMT_HSV32:
+ if (src_size < (width * height * 4)) {
+ V4LCONVERT_ERR("short hsv32 data frame\n");
+ errno = EPIPE;
+ result = -1;
+ }
+ switch (dest_pix_fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 32, fmt->fmt.pix.hsv_enc);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 1,
+ 32, fmt->fmt.pix.hsv_enc);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 32, fmt->fmt.pix.hsv_enc);
+ v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 0, 3);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_hsv_to_rgb24(src, dest, width, height, 0,
+ 32, fmt->fmt.pix.hsv_enc);
+ v4lconvert_rgb24_to_yuv420(src, dest, fmt, 0, 1, 3);
+ break;
+ }
+
+ break;
+
+
default:
V4LCONVERT_ERR("Unknown src format in conversion\n");
@@ -770,3 +770,80 @@ void v4lconvert_rgb32_to_rgb24(const unsigned char *src, unsigned char *dest,
}
}
}
+
+static void hsvtorgb(const unsigned char *hsv, unsigned char *rgb,
+ unsigned char hsv_enc)
+{
+ /* From http://stackoverflow.com/questions/3018313/ */
+ uint8_t region;
+ uint8_t remain;
+ uint8_t p, q, t;
+
+ if (!hsv[1]) {
+ rgb[0] = rgb[1] = rgb[2] = hsv[2];
+ return;
+ }
+
+ if (hsv_enc == V4L2_HSV_ENC_256) {
+
+ region = hsv[0] / 43;
+ remain = (hsv[0] - (region * 43)) * 6;
+
+ } else {
+ int aux;
+
+ region = hsv[0] / (180/6);
+
+ /* Remain must be scaled to 0..255 */
+ aux = (hsv[0] % (180/6)) * 6 * 256;
+ aux /= 180;
+ remain = aux;
+ }
+
+ p = (hsv[2] * (255 - hsv[1])) >> 8;
+ q = (hsv[2] * (255 - ((hsv[1] * remain) >> 8))) >> 8;
+ t = (hsv[2] * (255 - ((hsv[1] * (255 - remain)) >> 8))) >> 8;
+
+ switch (region) {
+ case 0:
+ rgb[0] = hsv[2]; rgb[1] = t; rgb[2] = p;
+ break;
+ case 1:
+ rgb[0] = q; rgb[1] = hsv[2]; rgb[2] = p;
+ break;
+ case 2:
+ rgb[0] = p; rgb[1] = hsv[2]; rgb[2] = t;
+ break;
+ case 3:
+ rgb[0] = p; rgb[1] = q; rgb[2] = hsv[2];
+ break;
+ case 4:
+ rgb[0] = t; rgb[1] = p; rgb[2] = hsv[2];
+ break;
+ default:
+ rgb[0] = hsv[2]; rgb[1] = p; rgb[2] = q;
+ break;
+ }
+
+}
+
+void v4lconvert_hsv_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height, int bgr, int Xin, unsigned char hsv_enc){
+ int j, k;
+ int bppIN = Xin / 8;
+ unsigned char rgb[3];
+
+ src += bppIN - 3;
+
+ while (--height >= 0)
+ for (j = 0; j < width; j++) {
+ hsvtorgb(src, rgb, hsv_enc);
+ for (k = 0; k < 3; k++)
+ if (bgr && k < 3)
+ *dest++ = rgb[2-k];
+ else
+ *dest++ = rgb[k];
+ src += bppIN;
+ }
+}
+
HSV32 and HSV24 are single plane interleaved Hue Saturation Value formats. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> --- lib/libv4lconvert/libv4lconvert-priv.h | 3 ++ lib/libv4lconvert/libv4lconvert.c | 62 +++++++++++++++++++++++++++ lib/libv4lconvert/rgbyuv.c | 77 ++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+)