/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2019, Google Inc. * * format_convert.cpp - qcam - Convert buffer to RGB */ #include "format_converter.h" #include #include #include #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(const libcamera::PixelFormat &format, const QSize &size) { switch (format) { case libcamera::formats::NV12: formatFamily_ = NV; horzSubSample_ = 2; vertSubSample_ = 2; nvSwap_ = false; break; case libcamera::formats::NV21: formatFamily_ = NV; horzSubSample_ = 2; vertSubSample_ = 2; nvSwap_ = true; break; case libcamera::formats::NV16: formatFamily_ = NV; horzSubSample_ = 2; vertSubSample_ = 1; nvSwap_ = false; break; case libcamera::formats::NV61: formatFamily_ = NV; horzSubSample_ = 2; vertSubSample_ = 1; nvSwap_ = true; break; case libcamera::formats::NV24: formatFamily_ = NV; horzSubSample_ = 1; vertSubSample_ = 1; nvSwap_ = false; break; case libcamera::formats::NV42: formatFamily_ = NV; horzSubSample_ = 1; vertSubSample_ = 1; nvSwap_ = true; break; case libcamera::formats::RGB888: formatFamily_ = RGB; r_pos_ = 2; g_pos_ = 1; b_pos_ = 0; bpp_ = 3; break; case libcamera::formats::BGR888: formatFamily_ = RGB; r_pos_ = 0; g_pos_ = 1; b_pos_ = 2; bpp_ = 3; break; case libcamera::formats::ARGB8888: formatFamily_ = RGB; r_pos_ = 2; g_pos_ = 1; b_pos_ = 0; bpp_ = 4; break; case libcamera::formats::RGBA8888: formatFamily_ = RGB; r_pos_ = 3; g_pos_ = 2; b_pos_ = 1; bpp_ = 4; break; case libcamera::formats::ABGR8888: formatFamily_ = RGB; r_pos_ = 0; g_pos_ = 1; b_pos_ = 2; bpp_ = 4; break; case libcamera::formats::BGRA8888: formatFamily_ = RGB; r_pos_ = 1; g_pos_ = 2; b_pos_ = 3; bpp_ = 4; break; case libcamera::formats::VYUY: formatFamily_ = YUV; y_pos_ = 1; cb_pos_ = 2; break; case libcamera::formats::YVYU: formatFamily_ = YUV; y_pos_ = 0; cb_pos_ = 3; break; case libcamera::formats::UYVY: formatFamily_ = YUV; y_pos_ = 1; cb_pos_ = 0; break; case libcamera::formats::YUYV: formatFamily_ = YUV; y_pos_ = 0; cb_pos_ = 1; break; case libcamera::formats::MJPEG: formatFamily_ = MJPEG; break; default: return -EINVAL; }; format_ = format; width_ = size.width(); height_ = size.height(); return 0; } void FormatConverter::convert(const unsigned char *src, size_t size, QImage *dst) { switch (formatFamily_) { case MJPEG: dst->loadFromData(src, size, "JPEG"); break; case YUV: convertYUV(src, dst->bits()); break; case RGB: convertRGB(src, dst->bits()); break; case NV: convertNV(src, dst->bits()); break; }; } 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::convertNV(const unsigned char *src, unsigned char *dst) { unsigned int c_stride = width_ * (2 / horzSubSample_); unsigned int c_inc = horzSubSample_ == 1 ? 2 : 0; unsigned int cb_pos = nvSwap_ ? 1 : 0; unsigned int cr_pos = nvSwap_ ? 0 : 1; const unsigned char *src_c = src + width_ * height_; int r, g, b; for (unsigned int y = 0; y < height_; y++) { const unsigned char *src_y = src + y * width_; const unsigned char *src_cb = src_c + (y / vertSubSample_) * c_stride + cb_pos; const unsigned char *src_cr = src_c + (y / vertSubSample_) * c_stride + cr_pos; for (unsigned int x = 0; x < width_; x += 2) { yuv_to_rgb(*src_y, *src_cb, *src_c<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link-2"><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line></svg> ; dst[dst_y * dst_stride + 4 * dst_x + 2] = r; dst[dst_y * dst_stride + 4 * dst_x + 3] = 0xff; dst_x++; src_x++; } } }