HSV32 and HSV24 are single plane interleaved Hue Saturation Value
formats.

Signed-off-by: Ricardo Ribalda Delgado <ricardo.riba...@gmail.com>
---
 lib/libv4lconvert/libv4lconvert-priv.h |  3 ++
 lib/libv4lconvert/libv4lconvert.c      | 62 +++++++++++++++++++++++++++
 lib/libv4lconvert/rgbyuv.c             | 77 ++++++++++++++++++++++++++++++++++
 3 files changed, 142 insertions(+)

diff --git a/lib/libv4lconvert/libv4lconvert-priv.h 
b/lib/libv4lconvert/libv4lconvert-priv.h
index 1740efc94456..e23893475a6e 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -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);
 
diff --git a/lib/libv4lconvert/libv4lconvert.c 
b/lib/libv4lconvert/libv4lconvert.c
index d3d89362d3ca..da718918b030 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -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");
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index a0f8256bf7ab..2c91b71ff715 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -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;
+               }
+}
+
-- 
2.10.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to