Add color space name on decoding options

Signed-off-by: Cao Chuan <caochuan@huawei.com>
This commit is contained in:
Cao Chuan 2023-12-15 15:19:06 +08:00
parent eb7a9a3967
commit 589b911134
12 changed files with 166 additions and 93 deletions

View File

@ -1556,19 +1556,6 @@ uint32_t ImageSource::UpdatePixelMapInfo(const DecodeOptions &opts, ImagePlugin:
return pixelMap.SetImageInfo(info, isReUsed);
}
static void CopyColorSpaceToPlugin(const ColorSpaceInfo &src, PlColorSpaceInfo &dst)
{
dst.isValidColorSpace = src.isValidColorSpace;
for (int i = NUM_0; i < ColorSpaceInfo::XYZ_SIZE; i++) {
for (int j = NUM_0; j < ColorSpaceInfo::XYZ_SIZE; j++) {
dst.xyz[i][j] = src.xyz[i][j];
}
}
for (int k = NUM_0; k < ColorSpaceInfo::XYZ_SIZE; k++) {
dst.transferFn[k] = src.transferFn[k];
}
}
void ImageSource::CopyOptionsToPlugin(const DecodeOptions &opts, PixelDecodeOptions &plOpts)
{
plOpts.CropRect.left = opts.CropRect.left;
@ -1594,10 +1581,7 @@ void ImageSource::CopyOptionsToPlugin(const DecodeOptions &opts, PixelDecodeOpti
plOpts.plSVGResize.isValidPercentage = opts.SVGOpts.SVGResize.isValidPercentage;
plOpts.plSVGResize.resizePercentage = opts.SVGOpts.SVGResize.resizePercentage;
}
if (opts.desiredColorSpaceInfo.isValidColorSpace) {
CopyColorSpaceToPlugin(opts.desiredColorSpaceInfo, plOpts.plDesiredColorSpace);
}
plOpts.plDesiredColorSpace = opts.desiredColorSpaceInfo;
}
void ImageSource::CopyOptionsToProcOpts(const DecodeOptions &opts, DecodeOptions &procOpts, PixelMap &pixelMap)

View File

@ -169,7 +169,10 @@ if (use_clang_ios) {
"//foundation/multimedia/image_framework/mock/native:log_mock_static",
]
deps += skia_platform
external_deps = [ "c_utils:utils" ]
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
]
}
#relative_install_dir = "module/multimedia"

View File

@ -312,6 +312,7 @@ ohos_unittest("imageutilstest") {
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
#"hilog:libhilog",
"hitrace:hitrace_meter",
@ -500,7 +501,10 @@ ohos_unittest("attrdatatest") {
"//third_party/googletest:gtest_main",
]
resource_config_file = "$image_subsystem/test/resource/image/ohos_test.xml"
external_deps = [ "c_utils:utils" ]
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
]
}
ohos_unittest("convertertest") {
@ -620,7 +624,10 @@ ohos_unittest("pluginsmanagersrcframeworktest") {
"//third_party/googletest:gtest_main",
]
resource_config_file = "$image_subsystem/test/resource/image/ohos_test.xml"
external_deps = [ "c_utils:utils" ]
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
]
}
ohos_unittest("pngtest") {

View File

@ -112,6 +112,7 @@ if (use_clang_ios) {
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
"graphic_2d:surface",
"hilog:libhilog",
"hitrace:hitrace_meter",

View File

@ -639,33 +639,6 @@ static PixelFormat ParsePixlForamt(int32_t val)
return PixelFormat::UNKNOWN;
}
static bool ParseColorSpaceInfo(napi_env env, napi_value colorSpace, ColorSpaceInfo &colorSpaceInfo)
{
if (env == nullptr || colorSpace == nullptr) {
HiLog::Error(LABEL, "Invalid args");
return false;
}
auto grColorSpacePtr = OHOS::ColorManager::GetColorSpaceByJSObject(env, colorSpace);
if (grColorSpacePtr == nullptr) {
HiLog::Error(LABEL, "Get colorspace by JS object failed");
return false;
}
auto skColorSpace = grColorSpacePtr->ToSkColorSpace();
if (skColorSpace == nullptr) {
HiLog::Error(LABEL, "To skcolorspace failed");
return false;
}
skcms_Matrix3x3 skMatrix;
skColorSpace->toXYZD50(&skMatrix);
for (int i = 0; i < ColorSpaceInfo::XYZ_SIZE; ++i) {
for (int j = 0; j < ColorSpaceInfo::XYZ_SIZE; ++j) {
colorSpaceInfo.xyz[i][j] = skMatrix.vals[i][j];
}
}
skColorSpace->transferFn(colorSpaceInfo.transferFn);
return true;
}
static bool ParseDecodeOptions2(napi_env env, napi_value root, DecodeOptions* opts, std::string &error)
{
uint32_t tmpNumber = 0;
@ -699,11 +672,11 @@ static bool ParseDecodeOptions2(napi_env env, napi_value root, DecodeOptions* op
HiLog::Debug(LABEL, "no SVGResize percentage");
}
napi_value nDesiredColorSpace = nullptr;
if (napi_get_named_property(env, root, "desiredColorSpace", &nDesiredColorSpace) == napi_ok &&
ParseColorSpaceInfo(env, nDesiredColorSpace, opts->desiredColorSpaceInfo)) {
opts->desiredColorSpaceInfo.isValidColorSpace = true;
if (napi_get_named_property(env, root, "desiredColorSpace", &nDesiredColorSpace) == napi_ok) {
opts->desiredColorSpaceInfo = OHOS::ColorManager::GetColorSpaceByJSObject(env, nDesiredColorSpace);
HiLog::Debug(LABEL, "desiredColorSpace parse finished");
} else {
}
if (opts->desiredColorSpaceInfo == nullptr) {
HiLog::Debug(LABEL, "no desiredColorSpace");
}
return true;

View File

@ -17,6 +17,7 @@
#define INTERFACES_INNERKITS_INCLUDE_IMAGE_TYPE_H_
#include <cinttypes>
#include "color_space.h"
namespace OHOS {
namespace Media {
@ -174,14 +175,6 @@ struct SVGDecodeOptions {
SVGResize SVGResize;
};
struct ColorSpaceInfo {
static constexpr uint8_t XYZ_SIZE = 3;
static constexpr uint8_t TRANSFER_FN_SIZE = 7;
bool isValidColorSpace = false;
float xyz[XYZ_SIZE][XYZ_SIZE] = {{0}};
float transferFn[TRANSFER_FN_SIZE] = {0};
};
struct DecodeOptions {
int32_t fitDensity = 0;
Rect CropRect;
@ -202,7 +195,7 @@ struct DecodeOptions {
bool editable = false;
MemoryUsagePreference preference = MemoryUsagePreference::DEFAULT;
SVGDecodeOptions SVGOpts;
ColorSpaceInfo desiredColorSpaceInfo;
std::shared_ptr<OHOS::ColorManager::ColorSpace> desiredColorSpaceInfo = nullptr;
};
enum class ScaleMode : int32_t {

View File

@ -70,6 +70,7 @@ ohos_shared_library("imageformatagent") {
# external_deps = [ "hilog:libhilog" ]
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
"hilog:libhilog",
]
}

View File

@ -84,6 +84,7 @@ private:
SkColorType ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat);
uint32_t SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context);
uint32_t GetMakerImagePropertyString(const std::string &key, std::string &value);
uint32_t CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts);
void ReportImageType(SkEncodedImageFormat skEncodeFormat);
ImagePlugin::InputDataStream *stream_ = nullptr;
uint32_t streamOff_ = 0;
@ -96,6 +97,9 @@ private:
EXIFInfo exifInfo_;
uint8_t *gifCache_ = nullptr;
uint32_t gifCacheIndex_ = 0;
#ifdef IMAGE_COLORSPACE_FLAG
std::shared_ptr<OHOS::ColorManager::ColorSpace> dstColorSpace_ = nullptr;
#endif
// hardware
OHOS::HDI::Codec::Image::V1_0::CodecImageBuffer outputBuffer_;

View File

@ -16,6 +16,7 @@
#include "ext_decoder.h"
#include <algorithm>
#include <map>
#include "ext_pixel_convert.h"
#include "hilog/log.h"
@ -39,11 +40,23 @@ namespace {
constexpr static size_t SIZE_ZERO = 0;
constexpr static uint32_t DEFAULT_SAMPLE_SIZE = 1;
constexpr static uint32_t NO_EXIF_TAG = 1;
constexpr static uint32_t OFFSET_0 = 0;
constexpr static uint32_t OFFSET_1 = 1;
constexpr static uint32_t OFFSET_2 = 2;
constexpr static uint32_t OFFSET_3 = 3;
constexpr static uint32_t OFFSET_5 = 5;
constexpr static uint32_t SHIFT_BITS_8 = 8;
constexpr static uint32_t SHIFT_BITS_16 = 16;
constexpr static uint32_t SHIFT_BITS_24 = 24;
constexpr static uint32_t DESC_SIGNATURE = 0x64657363;
constexpr static size_t SIZE_1 = 1;
constexpr static size_t SIZE_4 = 4;
constexpr static int HARDWARE_MIN_DIM = 512;
constexpr static int HARDWARE_MAX_DIM = 8192;
constexpr static float HALF = 0.5;
constexpr static float QUARTER = 0.25;
constexpr static float ONE_EIGHTH = 0.125;
constexpr static uint64_t ICC_HEADER_SIZE = 132;
}
namespace OHOS {
@ -397,16 +410,34 @@ static inline bool IsValidCrop(const PlRect &crop, SkImageInfo &info, SkIRect &o
static sk_sp<SkColorSpace> getDesiredColorSpace(SkImageInfo &srcInfo, const PixelDecodeOptions &opts)
{
if (!opts.plDesiredColorSpace.isValidColorSpace) {
if (opts.plDesiredColorSpace == nullptr) {
return srcInfo.refColorSpace();
}
auto xyzSize = PlColorSpaceInfo::XYZ_SIZE * PlColorSpaceInfo::XYZ_SIZE * sizeof(float);
skcms_Matrix3x3 skXYZ;
memcpy_s(&skXYZ, xyzSize, opts.plDesiredColorSpace.xyz, xyzSize);
auto transferFnSize = PlColorSpaceInfo::TRANSFER_FN_SIZE * sizeof(float);
skcms_TransferFunction skTransferFun;
memcpy_s(&skTransferFun, transferFnSize, opts.plDesiredColorSpace.transferFn, transferFnSize);
return SkColorSpace::MakeRGB(skTransferFun, skXYZ);
return opts.plDesiredColorSpace->ToSkColorSpace();
}
uint32_t ExtDecoder::CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts)
{
if (ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel())) {
HiLog::Error(LABEL, "SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
dstInfo_.width(), dstInfo_.height());
return ERR_IMAGE_INVALID_PARAMETER;
}
if (!IsValidCrop(opts.CropRect, info_, dstSubset_)) {
HiLog::Error(LABEL,
"Invalid crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
dstSubset_.left(), dstSubset_.top(), dstSubset_.width(), dstSubset_.height());
return ERR_IMAGE_INVALID_PARAMETER;
}
dstOptions_.fFrameIndex = index;
#ifdef IMAGE_COLORSPACE_FLAG
dstColorSpace_ = opts.plDesiredColorSpace;
#endif
if (IsSupportCropOnDecode(dstSubset_)) {
dstOptions_.fSubset = &dstSubset_;
}
return SUCCESS;
}
uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
@ -444,21 +475,9 @@ uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &
dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
}
if (ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel())) {
HiLog::Error(LABEL, "SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
dstInfo_.width(), dstInfo_.height());
return ERR_IMAGE_INVALID_PARAMETER;
}
dstOptions_.fFrameIndex = index;
if (!IsValidCrop(opts.CropRect, info_, dstSubset_)) {
HiLog::Error(LABEL,
"Invalid crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
dstSubset_.left(), dstSubset_.top(), dstSubset_.width(), dstSubset_.height());
return ERR_IMAGE_INVALID_PARAMETER;
}
if (IsSupportCropOnDecode(dstSubset_)) {
dstOptions_.fSubset = &dstSubset_;
auto resCode = CheckDecodeOptions(index, opts);
if (resCode != SUCCESS) {
return resCode;
}
info.size.width = dstInfo_.width();
@ -902,14 +921,108 @@ SkColorType ExtDecoder::ConvertToColorType(PlPixelFormat format, PlPixelFormat &
}
#ifdef IMAGE_COLORSPACE_FLAG
static uint32_t u8ToU32(const uint8_t* p)
{
return (p[OFFSET_0] << SHIFT_BITS_24) | (p[OFFSET_1] << SHIFT_BITS_16) |
(p[OFFSET_2] << SHIFT_BITS_8) | p[OFFSET_3];
}
struct ICCTag {
uint8_t signature[SIZE_4];
uint8_t offset[SIZE_4];
uint8_t size[SIZE_4];
};
struct ColorSpaceNameEnum {
std::string desc;
OHOS::ColorManager::ColorSpaceName name;
};
static std::vector<ColorSpaceNameEnum> sColorSpaceNamedMap = {
{"Display P3", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
{"sRGB EOTF with DCI-P3 Color Gamut", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
{"DCI-P3 D65 Gamut with sRGB Transfer", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
{"Adobe RGB (1998)", OHOS::ColorManager::ColorSpaceName::ADOBE_RGB},
{"DCI P3", OHOS::ColorManager::ColorSpaceName::DCI_P3},
{"sRGB", OHOS::ColorManager::ColorSpaceName::SRGB}
/*{"BT.2020", OHOS::ColorManager::ColorSpaceName::BT2020}*/
};
static bool MatchColorSpaceName(const uint8_t* buf, uint32_t size, OHOS::ColorManager::ColorSpaceName &name)
{
if (buf == nullptr || size <= OFFSET_5) {
return false;
}
std::vector<char> desc;
// We need skip desc type
for (uint32_t i = OFFSET_5; i < size; i++) {
if (buf[i] != '\0') {
desc.push_back(buf[i]);
}
}
if (desc.size() <= SIZE_1) {
HiLog::Info(LABEL, "empty buffer");
return false;
}
std::string descText(desc.begin() + OFFSET_1, desc.end());
for (auto nameEnum : sColorSpaceNamedMap) {
if (descText.find(nameEnum.desc) == std::string::npos) {
continue;
}
name = nameEnum.name;
return true;
}
HiLog::Error(LABEL, "Failed to match desc [%{public}s]", descText.c_str());
return false;
}
static bool GetColorSpaceName(const skcms_ICCProfile* profile, OHOS::ColorManager::ColorSpaceName &name)
{
if (profile == nullptr || profile->buffer == nullptr) {
HiLog::Info(LABEL, "profile is nullptr");
return false;
}
auto tags = reinterpret_cast<const ICCTag*>(profile->buffer + ICC_HEADER_SIZE);
for (uint32_t i = SIZE_ZERO; i < profile->tag_count; i++) {
auto signature = u8ToU32(tags[i].signature);
if (signature != DESC_SIGNATURE) {
continue;
}
auto size = u8ToU32(tags[i].size);
auto offset = u8ToU32(tags[i].offset);
if (size <= SIZE_ZERO || offset >= profile->size) {
continue;
}
auto buffer = u8ToU32(tags[i].offset) + profile->buffer;
if (MatchColorSpaceName(buffer, size, name)) {
return true;
}
}
return false;
}
OHOS::ColorManager::ColorSpace ExtDecoder::getGrColorSpace()
{
if (dstColorSpace_ != nullptr) {
return *dstColorSpace_;
}
auto skColorSpace = dstInfo_.isEmpty() ? info_.refColorSpace() : dstInfo_.refColorSpace();
return OHOS::ColorManager::ColorSpace(skColorSpace);
OHOS::ColorManager::ColorSpaceName name = OHOS::ColorManager::ColorSpaceName::CUSTOM;
if (codec_ != nullptr) {
auto profile = codec_->getICCProfile();
if (profile != nullptr) {
HiLog::Info(LABEL, "profile got !!!!");
GetColorSpaceName(profile, name);
}
}
return OHOS::ColorManager::ColorSpace(skColorSpace, name);
}
bool ExtDecoder::IsSupportICCProfile()
{
if (dstColorSpace_ != nullptr) {
return true;
}
if (info_.isEmpty()) {
return false;
}

View File

@ -143,6 +143,7 @@ if (use_clang_ios) {
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
"hilog:libhilog",
]
}
@ -225,6 +226,7 @@ ohos_static_library("pluginmanager_static") {
external_deps = [
"c_utils:utils",
"graphic_2d:color_manager",
"hilog:libhilog",
]
}

View File

@ -100,7 +100,7 @@ struct PixelDecodeOptions {
bool editable = false;
PlFillColor plFillColor;
PlSVGResize plSVGResize;
PlColorSpaceInfo plDesiredColorSpace;
std::shared_ptr<OHOS::ColorManager::ColorSpace> plDesiredColorSpace = nullptr;
};
class AbsImageDecoder {

View File

@ -132,14 +132,6 @@ struct PlSVGResize {
uint32_t resizePercentage = 100;
};
struct PlColorSpaceInfo {
static constexpr uint8_t XYZ_SIZE = 3;
static constexpr uint8_t TRANSFER_FN_SIZE = 7;
bool isValidColorSpace = false;
float xyz[XYZ_SIZE][XYZ_SIZE] = {{0}};
float transferFn[TRANSFER_FN_SIZE] = {0};
};
struct PlImageInfo {
PlSize size;
PlPixelFormat pixelFormat = PlPixelFormat::UNKNOWN;