From patchwork Sat Jun 6 15:50:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 3974 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B7A3A61167 for ; Sat, 6 Jun 2020 17:50:47 +0200 (CEST) X-Halon-ID: 7b3444b2-a80d-11ea-933e-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p4fca2eca.dip0.t-ipconnect.de [79.202.46.202]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 7b3444b2-a80d-11ea-933e-005056917a89; Sat, 06 Jun 2020 17:50:44 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 6 Jun 2020 17:50:38 +0200 Message-Id: <20200606155039.1874519-2-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200606155039.1874519-1-niklas.soderlund@ragnatech.se> References: <20200606155039.1874519-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/2] qcam: dng_writer: Make thumbnail downscaling format dependent 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-List-Received-Date: Sat, 06 Jun 2020 15:50:48 -0000 Some RAW formats are easier to generate thumbnails for if the downscaling factor for the thumbnail is configurable. Prepare for addition of such formats by allowing the downscale to differ between formats. Signed-off-by: Niklas Söderlund --- src/qcam/dng_writer.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp index cbd8bed3e6d02269..9435eeec5438f158 100644 --- a/src/qcam/dng_writer.cpp +++ b/src/qcam/dng_writer.cpp @@ -28,6 +28,7 @@ struct FormatInfo { CFAPatternColour pattern[4]; void (*packScanline)(void *output, const void *input, unsigned int width); + unsigned int thumbDownscaleFactor; void (*thumbScanline)(const FormatInfo &info, void *output, const void *input, unsigned int width, unsigned int stride); @@ -87,48 +88,56 @@ static const std::map formatInfo = { .bitsPerSample = 10, .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, .packScanline = packScanlineSBGGR10P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SGBRG10, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 10, .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, .packScanline = packScanlineSBGGR10P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SGRBG10, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 10, .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, .packScanline = packScanlineSBGGR10P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SRGGB10, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 10, .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, .packScanline = packScanlineSBGGR10P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SBGGR12, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 12, .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, .packScanline = packScanlineSBGGR12P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SGBRG12, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 12, .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, .packScanline = packScanlineSBGGR12P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SGRBG12, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 12, .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, .packScanline = packScanlineSBGGR12P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, { PixelFormat(DRM_FORMAT_SRGGB12, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 12, .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, .packScanline = packScanlineSBGGR12P, + .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, }; @@ -178,13 +187,14 @@ int DNGWriter::write(const char *filename, const Camera *camera, TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); /* - * Thumbnail-specific tags. The thumbnail is stored as an RGB image - * with 1/16 of the raw image resolution. Greyscale would save space, - * but doesn't seem well supported by RawTherapee. + * Thumbnail-specific tags. The thumbnail is stored as an RGB image with + * format dependet downscaling of the raw image resolution. Greyscale + * would save space, but doesn't seem well supported by RawTherapee. */ + const unsigned int thumbScale = info->thumbDownscaleFactor; TIFFSetField(tif, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE); - TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, config.size.width / 16); - TIFFSetField(tif, TIFFTAG_IMAGELENGTH, config.size.height / 16); + TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, config.size.width / thumbScale); + TIFFSetField(tif, TIFFTAG_IMAGELENGTH, config.size.height / thumbScale); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); @@ -202,9 +212,10 @@ int DNGWriter::write(const char *filename, const Camera *camera, /* Write the thumbnail. */ const uint8_t *row = static_cast(data); - for (unsigned int y = 0; y < config.size.height / 16; y++) { + for (unsigned int y = 0; y < config.size.height / thumbScale; y++) { info->thumbScanline(*info, &scanline, row, - config.size.width / 16, config.stride); + config.size.width / thumbScale, + config.stride); if (TIFFWriteScanline(tif, &scanline, y, 0) != 1) { std::cerr << "Failed to write thumbnail scanline" @@ -213,7 +224,7 @@ int DNGWriter::write(const char *filename, const Camera *camera, return -EINVAL; } - row += config.stride * 16; + row += config.stride * thumbScale; } TIFFWriteDirectory(tif); From patchwork Sat Jun 6 15:50:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 3975 Return-Path: Received: from vsp-unauthed02.binero.net (vsp-unauthed02.binero.net [195.74.38.227]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 53A4861167 for ; Sat, 6 Jun 2020 17:50:48 +0200 (CEST) X-Halon-ID: 7bb77386-a80d-11ea-933e-005056917a89 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p4fca2eca.dip0.t-ipconnect.de [79.202.46.202]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA id 7bb77386-a80d-11ea-933e-005056917a89; Sat, 06 Jun 2020 17:50:45 +0200 (CEST) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Sat, 6 Jun 2020 17:50:39 +0200 Message-Id: <20200606155039.1874519-3-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200606155039.1874519-1-niklas.soderlund@ragnatech.se> References: <20200606155039.1874519-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 2/2] qcam: dng_writer: Add support for IPU3 Bayer formats 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-List-Received-Date: Sat, 06 Jun 2020 15:50:49 -0000 Add support for the Bayer formats produced on the IPU3. The format uses a memory layout that is hard to repack and keep the 10-bit sample size, therefore scale the samples to 16-bit when creating the scanlines. Signed-off-by: Niklas Söderlund --- src/qcam/dng_writer.cpp | 77 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/qcam/dng_writer.cpp b/src/qcam/dng_writer.cpp index 9435eeec5438f158..8c128041c37f26fe 100644 --- a/src/qcam/dng_writer.cpp +++ b/src/qcam/dng_writer.cpp @@ -83,6 +83,55 @@ void thumbScanlineSBGGRxxP(const FormatInfo &info, void *output, } } +void packScanlineIPU3(void *output, const void *input, unsigned int width) +{ + const uint8_t *in = static_cast(input); + uint16_t *out = static_cast(output); + + /* + * Upsacle the 10-bit format to 16-bit as it's none trivial to pack it + * it as 10-bits without gaps. + * + * \todo Improve packig to keep the 10-bit sample size. + */ + for (unsigned int x = 0; x < width; x += 25) { + for (unsigned int i = 0; i < 6; i++) { + *out++ = ((in[1] & 0x02) << 8 | in[0]) << 6; + *out++ = ((in[2] & 0x0f) << 6 | in[1] >> 2) << 6; + *out++ = ((in[3] & 0x3f) << 4 | in[2] >> 4) << 6; + *out++ = ((in[4] & 0xff) << 2 | in[3] >> 6) << 6; + in += 5; + } + + *out++ = ((in[1] & 0x02) << 8 | in[0]) << 6; + in += 2; + } +} + +void thumbScanlineIPU3(const FormatInfo &info, void *output, + const void *input, unsigned int width, + unsigned int stride) +{ + const uint8_t *in = static_cast(input); + uint8_t *out = static_cast(output); + + /* Number of bytes corresponding to 25 pixels. */ + unsigned int skip = 32; + + for (unsigned int x = 0; x < width; x++) { + uint8_t val1 = ((in[1] & 0x02) << 8 | in[0]) << 6; + uint8_t val2 = ((in[2] & 0x0f) << 6 | in[1] >> 2) << 6; + uint8_t val3 = ((in[stride + 1] & 0x02) << 8 | in[stride + 0]) << 6; + uint8_t val4 = ((in[stride + 2] & 0x0f) << 6 | in[stride + 1] >> 2) << 6; + uint8_t value = (val1 + val2 + val3 + val4) >> 2; + + *out++ = value; + *out++ = value; + *out++ = value; + in += skip; + } +} + static const std::map formatInfo = { { PixelFormat(DRM_FORMAT_SBGGR10, MIPI_FORMAT_MOD_CSI2_PACKED), { .bitsPerSample = 10, @@ -140,6 +189,34 @@ static const std::map formatInfo = { .thumbDownscaleFactor = 16, .thumbScanline = thumbScanlineSBGGRxxP, } }, + { PixelFormat(DRM_FORMAT_SBGGR10, IPU3_FORMAT_MOD_PACKED), { + .bitsPerSample = 16, + .pattern = { CFAPatternBlue, CFAPatternGreen, CFAPatternGreen, CFAPatternRed }, + .packScanline = packScanlineIPU3, + .thumbDownscaleFactor = 25, + .thumbScanline = thumbScanlineIPU3, + } }, + { PixelFormat(DRM_FORMAT_SGBRG10, IPU3_FORMAT_MOD_PACKED), { + .bitsPerSample = 16, + .pattern = { CFAPatternGreen, CFAPatternBlue, CFAPatternRed, CFAPatternGreen }, + .packScanline = packScanlineIPU3, + .thumbDownscaleFactor = 25, + .thumbScanline = thumbScanlineIPU3, + } }, + { PixelFormat(DRM_FORMAT_SGRBG10, IPU3_FORMAT_MOD_PACKED), { + .bitsPerSample = 16, + .pattern = { CFAPatternGreen, CFAPatternRed, CFAPatternBlue, CFAPatternGreen }, + .packScanline = packScanlineIPU3, + .thumbDownscaleFactor = 25, + .thumbScanline = thumbScanlineIPU3, + } }, + { PixelFormat(DRM_FORMAT_SRGGB10, IPU3_FORMAT_MOD_PACKED), { + .bitsPerSample = 16, + .pattern = { CFAPatternRed, CFAPatternGreen, CFAPatternGreen, CFAPatternBlue }, + .packScanline = packScanlineIPU3, + .thumbDownscaleFactor = 25, + .thumbScanline = thumbScanlineIPU3, + } }, }; int DNGWriter::write(const char *filename, const Camera *camera,