From f07b70543ad38dab1b243138c4c5b52b5628bf45 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Thu, 2 Feb 2023 06:07:42 +0900 Subject: [PATCH] [Tizen] Support CMYK jpg image load Previously, we only load CMYK image store as Pixel::RGBA8888 and do nothing. So, We need to convert this 4byte data as 3byte Pixel::RGB888 format. Change-Id: If3b2a1dc14f59b68bebe7c024164f5f7565aa26b Signed-off-by: Eunki, Hong --- dali/internal/imaging/common/loader-jpeg-turbo.cpp | 85 +++++++++++++++++----- 1 file changed, 65 insertions(+), 20 deletions(-) diff --git a/dali/internal/imaging/common/loader-jpeg-turbo.cpp b/dali/internal/imaging/common/loader-jpeg-turbo.cpp index f448d97..e95b312 100755 --- a/dali/internal/imaging/common/loader-jpeg-turbo.cpp +++ b/dali/internal/imaging/common/loader-jpeg-turbo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -472,6 +472,32 @@ void Rotate270(PixelArray buffer, int width, int height) } } +/** + * @brief Helper function to convert from Turbo Jpeg Pixel Format as TJPF_CMYK to RGB888 by naive method. + * + * @param[in] cmykBuffer buffer of cmyk. + * @param[in] rgbBuffer buffer of Pixel::RGB888 + * @param[in] width width of image. + * @param[in] height height of image. + */ +void ConvertTjpfCMYKToRGB888(PixelArray __restrict__ cmykBuffer, PixelArray __restrict__ rgbBuffer, int32_t width, int32_t height) +{ + const int32_t pixelCount = width * height; + const uint8_t cmykBpp = 4u; + const uint8_t bpp = 3u; + + const PixelArray cmykBufferEnd = cmykBuffer + pixelCount * cmykBpp; + // Convert every pixel + while(cmykBuffer != cmykBufferEnd) + { + const uint16_t channelK = static_cast(*(cmykBuffer + 3u)); + *(rgbBuffer + 0u) = static_cast(static_cast(*(cmykBuffer + 0u)) * channelK / 255); + *(rgbBuffer + 1u) = static_cast(static_cast(*(cmykBuffer + 1u)) * channelK / 255); + *(rgbBuffer + 2u) = static_cast(static_cast(*(cmykBuffer + 2u)) * channelK / 255); + cmykBuffer += cmykBpp; + rgbBuffer += bpp; + } +} } // namespace namespace Dali @@ -620,22 +646,12 @@ bool LoadBitmapFromJpeg( const Dali::ImageLoader::Input& input, Dali::Devel::Pix int chrominanceSubsampling = -1; int preXformImageWidth = 0, preXformImageHeight = 0; - // In Ubuntu, the turbojpeg version is not correct. so build error occurs. - // Temporarily separate Ubuntu and other profiles. -#ifndef DALI_PROFILE_UBUNTU int jpegColorspace = -1; if( tjDecompressHeader3( jpeg.get(), jpegBufferPtr, jpegBufferSize, &preXformImageWidth, &preXformImageHeight, &chrominanceSubsampling, &jpegColorspace ) == -1 ) { DALI_LOG_ERROR("%s\n", tjGetErrorStr()); // Do not set width and height to 0 or return early as this sometimes fails only on determining subsampling type. } -#else - if( tjDecompressHeader2( jpeg.get(), jpegBufferPtr, jpegBufferSize, &preXformImageWidth, &preXformImageHeight, &chrominanceSubsampling ) == -1 ) - { - DALI_LOG_ERROR("%s\n", tjGetErrorStr()); - // Do not set width and height to 0 or return early as this sometimes fails only on determining subsampling type. - } -#endif if(preXformImageWidth == 0 || preXformImageHeight == 0) { @@ -669,7 +685,6 @@ bool LoadBitmapFromJpeg( const Dali::ImageLoader::Input& input, Dali::Devel::Pix // Colorspace conversion options TJPF pixelLibJpegType = TJPF_RGB; Pixel::Format pixelFormat = Pixel::RGB888; -#ifndef DALI_PROFILE_UBUNTU switch (jpegColorspace) { case TJCS_RGB: @@ -691,7 +706,7 @@ bool LoadBitmapFromJpeg( const Dali::ImageLoader::Input& input, Dali::Devel::Pix case TJCS_YCCK: { pixelLibJpegType = TJPF_CMYK; - pixelFormat = Pixel::RGBA8888; + pixelFormat = Pixel::RGB888; break; } default: @@ -701,7 +716,6 @@ bool LoadBitmapFromJpeg( const Dali::ImageLoader::Input& input, Dali::Devel::Pix break; } } -#endif // Allocate a bitmap and decompress the jpeg buffer into its pixel buffer: bitmap = Dali::Devel::PixelBuffer::New(scaledPostXformWidth, scaledPostXformHeight, pixelFormat); @@ -710,18 +724,49 @@ bool LoadBitmapFromJpeg( const Dali::ImageLoader::Input& input, Dali::Devel::Pix auto bitmapPixelBuffer = bitmap.GetBuffer(); - if( tjDecompress2( jpeg.get(), jpegBufferPtr, jpegBufferSize, reinterpret_cast( bitmapPixelBuffer ), scaledPreXformWidth, 0, scaledPreXformHeight, pixelLibJpegType, flags ) == -1 ) + if(pixelLibJpegType == TJPF_CMYK) { - std::string errorString = tjGetErrorStr(); + // Currently we support only for 4 bytes per each CMYK pixel. + const uint8_t cmykBytesPerPixel = 4u; + + uint8_t* cmykBuffer = static_cast(malloc(sizeof(uint8_t) * scaledPostXformWidth * scaledPostXformHeight * cmykBytesPerPixel)); - if( IsJpegErrorFatal( errorString ) ) + int decodeResult = tjDecompress2(jpeg.get(), jpegBufferPtr, jpegBufferSize, reinterpret_cast(cmykBuffer), scaledPreXformWidth, 0, scaledPreXformHeight, pixelLibJpegType, flags); + if(DALI_UNLIKELY(decodeResult == -1)) { - DALI_LOG_ERROR("%s\n", errorString.c_str() ); + std::string errorString = tjGetErrorStr(); + + if(IsJpegErrorFatal(errorString)) + { + DALI_LOG_ERROR("%s\n", errorString.c_str()); + free(cmykBuffer); return false; + } + else + { + DALI_LOG_WARNING("%s\n", errorString.c_str()); + } } - else + ConvertTjpfCMYKToRGB888(cmykBuffer, bitmapPixelBuffer, scaledPostXformWidth, scaledPostXformHeight); + + free(cmykBuffer); + } + else + { + int decodeResult = tjDecompress2(jpeg.get(), jpegBufferPtr, jpegBufferSize, reinterpret_cast(bitmapPixelBuffer), scaledPreXformWidth, 0, scaledPreXformHeight, pixelLibJpegType, flags); + if(DALI_UNLIKELY(decodeResult == -1)) { - DALI_LOG_WARNING("%s\n", errorString.c_str() ); + std::string errorString = tjGetErrorStr(); + + if(IsJpegErrorFatal(errorString)) + { + DALI_LOG_ERROR("%s\n", errorString.c_str()); + return false; + } + else + { + DALI_LOG_WARNING("%s\n", errorString.c_str()); + } } } -- 2.7.4