diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2019-03-23 03:24:25 +0200 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2019-03-29 17:09:46 +0200 |
commit | 97e8b3a2eb321884fe1e15fb584f41a38cc33d51 (patch) | |
tree | 3ed93b2504e4fcdc3511bcf956f43ad84a558d0f /src/qcam/format_converter.cpp | |
parent | ffef90a1c1f1990581d8fbc22193bfc766d23d3b (diff) |
qcam: Add Qt-based GUI application
qcam is a sample camera GUI application based on Qt. It demonstrates
integration of the Qt event loop with libcamera.
The application lets the user select a camera through the GUI, and then
captures a single stream from the camera and displays it in a window.
Only streams in YUYV formats are supported for now.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src/qcam/format_converter.cpp')
-rw-r--r-- | src/qcam/format_converter.cpp | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp new file mode 100644 index 00000000..6979a054 --- /dev/null +++ b/src/qcam/format_converter.cpp @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * format_convert.cpp - qcam - Convert buffer to RGB + */ + +#include <errno.h> + +#include <linux/videodev2.h> + +#include "format_converter.h" + +#define RGBSHIFT 8 +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#ifndef CLAMP +#define CLAMP(a,low,high) MAX((low),MIN((high),(a))) +#endif +#ifndef CLIP +#define CLIP(x) CLAMP(x,0,255) +#endif + +int FormatConverter::configure(unsigned int format, unsigned int width, + unsigned int height) +{ + switch (format) { + case V4L2_PIX_FMT_VYUY: + y_pos_ = 1; + cb_pos_ = 2; + break; + case V4L2_PIX_FMT_YVYU: + y_pos_ = 0; + cb_pos_ = 3; + break; + case V4L2_PIX_FMT_UYVY: + y_pos_ = 1; + cb_pos_ = 0; + break; + case V4L2_PIX_FMT_YUYV: + y_pos_ = 0; + cb_pos_ = 1; + break; + default: + return -EINVAL; + }; + + width_ = width; + height_ = height; + + return 0; +} + +static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b) +{ + int c = y - 16; + int d = u - 128; + int e = v - 128; + *r = CLIP(( 298 * c + 409 * e + 128) >> RGBSHIFT); + *g = CLIP(( 298 * c - 100 * d - 208 * e + 128) >> RGBSHIFT); + *b = CLIP(( 298 * c + 516 * d + 128) >> RGBSHIFT); +} + +void FormatConverter::convert(const unsigned char *src, unsigned char *dst) +{ + unsigned int src_x, src_y, dst_x, dst_y; + unsigned int src_stride; + unsigned int dst_stride; + unsigned int cr_pos; + int r, g, b, y, cr, cb; + + cr_pos = (cb_pos_ + 2) % 4; + src_stride = width_ * 2; + dst_stride = width_ * 4; + + for (src_y = 0, dst_y = 0; dst_y < height_; src_y++, dst_y++) { + for (src_x = 0, dst_x = 0; dst_x < width_; ) { + cb = src[src_y * src_stride + src_x * 4 + cb_pos_]; + cr = src[src_y * src_stride + src_x * 4 + cr_pos]; + + y = src[src_y * src_stride + src_x * 4 + y_pos_]; + yuv_to_rgb(y, cb, cr, &r, &g, &b); + dst[dst_y * dst_stride + 4 * dst_x + 0] = b; + dst[dst_y * dst_stride + 4 * dst_x + 1] = g; + dst[dst_y * dst_stride + 4 * dst_x + 2] = r; + dst[dst_y * dst_stride + 4 * dst_x + 3] = 0xff; + dst_x++; + + y = src[src_y * src_stride + src_x * 4 + y_pos_ + 2]; + yuv_to_rgb(y, cb, cr, &r, &g, &b); + dst[dst_y * dst_stride + 4 * dst_x + 0] = b; + dst[dst_y * dst_stride + 4 * dst_x + 1] = g; + dst[dst_y * dst_stride + 4 * dst_x + 2] = r; + dst[dst_y * dst_stride + 4 * dst_x + 3] = 0xff; + dst_x++; + + src_x++; + } + } +} |