mirror of
https://gitee.com/openharmony/multimedia_image_framework
synced 2024-11-27 09:10:54 +00:00
!1192 Add color space name on decoding options
Merge pull request !1192 from caochuan/feature/image_source_color_space_name
This commit is contained in:
commit
f9e3ab1c6d
@ -1554,19 +1554,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;
|
||||
@ -1592,10 +1579,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)
|
||||
|
@ -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"
|
||||
|
@ -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") {
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -70,6 +70,7 @@ ohos_shared_library("imageformatagent") {
|
||||
# external_deps = [ "hilog:libhilog" ]
|
||||
external_deps = [
|
||||
"c_utils:utils",
|
||||
"graphic_2d:color_manager",
|
||||
"hilog:libhilog",
|
||||
]
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
]
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user