From patchwork Tue Aug 23 11:45:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17185 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id C07D9C3272 for ; Tue, 23 Aug 2022 11:45:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B728261FBD; Tue, 23 Aug 2022 13:45:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1661255158; bh=QC/RUcj4gZHfW7/8C9EtiiPbbCt2nGWW8vsDMsLJhgI=; h=To:Date:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=gPxrBCIkaqmSLDYdXDSyeW/GP+vzsYiwHzDAYxrgfa4AruQP+J2frNNi8gJR6DNIv BtlN2wpztLfQK4n3KsOXBY+66SUXhyKG9QIHJOJZLoKjoHqMXMhb8tzHkC0s7rn6iu gu30mzwciYoL9ri2wPv40SbgVKykoZwCgmQ2IpmZf7u/OKV8aPiZl8cg664RDG009X 5V8wKyE6FAZly/xGsgb0KR7kM73sc0+9L9X/nG3BA0jBI7ncDQ99/DdMXXDuwnTtwX vCVqcSas2dWwCC2Y9ghIlMAiFMzXrVnEUAZRCE3BTv9hRDpwQ38vqVbAY0RGN92R7V +sAtRt2duIe+Q== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 09383603E3 for ; Tue, 23 Aug 2022 13:45:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dkO6yBao"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3E6C82B3 for ; Tue, 23 Aug 2022 13:45:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1661255156; bh=QC/RUcj4gZHfW7/8C9EtiiPbbCt2nGWW8vsDMsLJhgI=; h=From:To:Subject:Date:From; b=dkO6yBaoWMlbFTw7upq2hWscuG6UjNnWkBW//3A2uoieP/ouLL+UqL1AsOUMBRVWt wFpnqwHtce4B+U4Aa7HaC2K/YIPzxDdU+cVW9QIMogvan7v0p5jjTrHMqjvIjWm8oJ Cdao4Zl0naTmHQVW9RiYCagGMIoXTo2gUQk1Oi5U= To: libcamera-devel@lists.libcamera.org Date: Tue, 23 Aug 2022 14:45:51 +0300 Message-Id: <20220823114551.27796-1-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2] libcamera: color_space: Rename Jpeg to Sycc X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The JPEG color space is badly name, as the JPEG specification (ITU-T T.81) doesn't define any particular color space: The interchange format does not specify a complete coded image representation. Application-dependent information, e.g. colour space, is outside the scope of this Specification. The JFIF specification (ITU-T T.871) is clearer as it requires ITU-R BT.601 YCbCr encoding and a full quantization range: The interpretations of Y, CB, and CR are derived from the E'Y, E'Cb, and E'Cr signals defined in the 625-line specification of Rec. ITU-R BT.601, but these signals are normalized so as to permit the usage of the full range of 256 levels of the 8-bit binary encoding of the Y component. It however doesn't specify color primaries or a transfer function explicitly. It only mentions the latter when describing the conversion from YCbCr to RGB: The inverse relationship for computing full scale 8-bit per colour channel gamma pre-corrected RGB values (following Rec. ITU-R BT.601 gamma pre-correction and colour primary specifications) from YCbCr colours (with 256 levels per component) can be computed as follows: [...] Given that ITU-R BT.601-5 (1995) didn't specify color primaries or a transfer function, and that the later ITU-R BT.601-7 (2011) version specifies color primaries for the 625-line variant that do not match sRGB, the JPEG color space in libcamera is badly named. This is confirmed by ITU-T T.871: As this Recommendation | International Standard is based on the prior informally-circulated JFIF version 1.02 specification that was produced in 1992, which referenced Rec. ITU-R BT.601 (formerly CCIR 601), it references that specification for definition of the E'Y, E'Cb, and E'Cr signals that correspond to the YCBCR values specified herein. However, since the development of the prior JFIF version 1.02 specification, additional industry specifications have been developed, Rec. ITU-R BT.601 has been updated, and common industry practice has emerged which often follows the sYCC specification in IEC 61966-2-1/Amd.1. The difference between the use of the colour interpretation specification in this Recommendation | International Standard and that of the sYCC specification may be considered negligible in practice. Rename the color space to sYCC, as its definition matches the sYCC standard, and indicate that it is typically used to encode JPEG images. Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain Reviewed-by: Paul Elder --- Changes since v1: - Rename more instances of JPEG to sYCC - Reword the references to the V4L2 documentation --- include/libcamera/color_space.h | 2 +- src/libcamera/color_space.cpp | 43 +++++++++++-------- .../pipeline/raspberrypi/raspberrypi.cpp | 10 ++--- src/libcamera/v4l2_device.cpp | 4 +- src/py/libcamera/py_main.cpp | 2 +- 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/include/libcamera/color_space.h b/include/libcamera/color_space.h index 0d39fbc02220..8030a264c66f 100644 --- a/include/libcamera/color_space.h +++ b/include/libcamera/color_space.h @@ -46,8 +46,8 @@ public: } static const ColorSpace Raw; - static const ColorSpace Jpeg; static const ColorSpace Srgb; + static const ColorSpace Sycc; static const ColorSpace Smpte170m; static const ColorSpace Rec709; static const ColorSpace Rec2020; diff --git a/src/libcamera/color_space.cpp b/src/libcamera/color_space.cpp index caf397607b10..f0d6109ac4fb 100644 --- a/src/libcamera/color_space.cpp +++ b/src/libcamera/color_space.cpp @@ -29,21 +29,28 @@ namespace libcamera { * (sometimes also referred to as the quantisation) of the color space. * * Certain combinations of these fields form well-known standard color - * spaces such as "JPEG" or "REC709". + * spaces such as "sRGB" or "Rec709". * * In the strictest sense a "color space" formally only refers to the * color primaries and white point. Here, however, the ColorSpace class * adopts the common broader usage that includes the transfer function, * Y'CbCr encoding method and quantisation. * - * For more information on the specific color spaces described here, please - * see: + * More information on color spaces is available in the V4L2 documentation, see + * in particular * * - sRGB * - JPEG * - SMPTE 170M * - Rec.709 * - Rec.2020 + * + * Note that there is no guarantee of a 1:1 mapping between color space names + * and definitions in libcamera and V4L2. A notable difference is that the sYCC + * libcamera color space is called JPEG in V4L2 due to historical reasons. + * + * \todo Define the color space fully in the libcamera API to avoid referencing + * V4L2 */ /** @@ -121,8 +128,8 @@ namespace libcamera { * \brief Assemble and return a readable string representation of the * ColorSpace * - * If the color space matches a standard ColorSpace (such as ColorSpace::Jpeg) - * then the short name of the color space ("JPEG") is returned. Otherwise + * If the color space matches a standard ColorSpace (such as ColorSpace::Sycc) + * then the short name of the color space ("sYCC") is returned. Otherwise * the four constituent parts of the ColorSpace are assembled into a longer * string. * @@ -134,8 +141,8 @@ std::string ColorSpace::toString() const static const std::array, 6> colorSpaceNames = { { { ColorSpace::Raw, "RAW" }, - { ColorSpace::Jpeg, "JPEG" }, { ColorSpace::Srgb, "sRGB" }, + { ColorSpace::Sycc, "sYCC" }, { ColorSpace::Smpte170m, "SMPTE170M" }, { ColorSpace::Rec709, "Rec709" }, { ColorSpace::Rec2020, "Rec2020" }, @@ -242,21 +249,10 @@ const ColorSpace ColorSpace::Raw = { Range::Full }; -/** - * \brief A constant representing the JPEG color space used for - * encoding JPEG images - */ -const ColorSpace ColorSpace::Jpeg = { - Primaries::Rec709, - TransferFunction::Srgb, - YcbcrEncoding::Rec601, - Range::Full -}; - /** * \brief A constant representing the sRGB color space * - * This is identical to the JPEG color space except that the Y'CbCr + * This is identical to the sYCC color space except that the Y'CbCr * range is limited rather than full. */ const ColorSpace ColorSpace::Srgb = { @@ -266,6 +262,17 @@ const ColorSpace ColorSpace::Srgb = { Range::Limited }; +/** + * \brief A constant representing the sYCC color space, typically used for + * encoding JPEG images + */ +const ColorSpace ColorSpace::Sycc = { + Primaries::Rec709, + TransferFunction::Srgb, + YcbcrEncoding::Rec601, + Range::Full +}; + /** * \brief A constant representing the SMPTE170M color space */ diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index e895584d4fbc..b4094898ca6c 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -593,11 +593,11 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, fmts = data->isp_[Isp::Output0].dev()->formats(); pixelFormat = formats::NV12; /* - * Still image codecs usually expect the JPEG color space. + * Still image codecs usually expect the sYCC color space. * Even RGB codecs will be fine as the RGB we get with the - * JPEG color space is the same as sRGB. + * sYCC color space is the same as sRGB. */ - colorSpace = ColorSpace::Jpeg; + colorSpace = ColorSpace::Sycc; /* Return the largest sensor resolution. */ size = sensorSize; bufferCount = 1; @@ -628,7 +628,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, case StreamRole::Viewfinder: fmts = data->isp_[Isp::Output0].dev()->formats(); pixelFormat = formats::ARGB8888; - colorSpace = ColorSpace::Jpeg; + colorSpace = ColorSpace::Sycc; size = { 800, 600 }; bufferCount = 4; outCount++; @@ -835,7 +835,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) format.size = maxSize; format.fourcc = dev->toV4L2PixelFormat(formats::YUV420); /* No one asked for output, so the color space doesn't matter. */ - format.colorSpace = ColorSpace::Jpeg; + format.colorSpace = ColorSpace::Sycc; ret = dev->setFormat(&format); if (ret) { LOG(RPI, Error) diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 3fc8438f6579..b22a981ff1a6 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -745,8 +745,8 @@ void V4L2Device::eventAvailable() static const std::map v4l2ToColorSpace = { { V4L2_COLORSPACE_RAW, ColorSpace::Raw }, - { V4L2_COLORSPACE_JPEG, ColorSpace::Jpeg }, { V4L2_COLORSPACE_SRGB, ColorSpace::Srgb }, + { V4L2_COLORSPACE_JPEG, ColorSpace::Sycc }, { V4L2_COLORSPACE_SMPTE170M, ColorSpace::Smpte170m }, { V4L2_COLORSPACE_REC709, ColorSpace::Rec709 }, { V4L2_COLORSPACE_BT2020, ColorSpace::Rec2020 }, @@ -771,8 +771,8 @@ static const std::map v4l2ToRange = { static const std::vector> colorSpaceToV4l2 = { { ColorSpace::Raw, V4L2_COLORSPACE_RAW }, - { ColorSpace::Jpeg, V4L2_COLORSPACE_JPEG }, { ColorSpace::Srgb, V4L2_COLORSPACE_SRGB }, + { ColorSpace::Sycc, V4L2_COLORSPACE_JPEG }, { ColorSpace::Smpte170m, V4L2_COLORSPACE_SMPTE170M }, { ColorSpace::Rec709, V4L2_COLORSPACE_REC709 }, { ColorSpace::Rec2020, V4L2_COLORSPACE_BT2020 }, diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index 7e613a3f2a5a..75947889f7b1 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -463,8 +463,8 @@ PYBIND11_MODULE(_libcamera, m) .def_readwrite("ycbcrEncoding", &ColorSpace::ycbcrEncoding) .def_readwrite("range", &ColorSpace::range) .def_static("Raw", []() { return ColorSpace::Raw; }) - .def_static("Jpeg", []() { return ColorSpace::Jpeg; }) .def_static("Srgb", []() { return ColorSpace::Srgb; }) + .def_static("Sycc", []() { return ColorSpace::Sycc; }) .def_static("Smpte170m", []() { return ColorSpace::Smpte170m; }) .def_static("Rec709", []() { return ColorSpace::Rec709; }) .def_static("Rec2020", []() { return ColorSpace::Rec2020; });