diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 80004752c7329f9a8241b35e82fccd7b76ce5681..57e34954cdef63109f8b62a0481374f1a32413e5 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -527,6 +527,25 @@ uint32_t ImageSource::GetImagePropertyInt(uint32_t index, const std::string &key return SUCCESS; } +uint32_t ImageSource::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value) +{ + std::unique_lock guard(decodingMutex_); + uint32_t ret; + auto iter = GetValidImageStatus(0, ret); + if (iter == imageStatusMap_.end()) { + IMAGE_LOGE("[ImageSource]get valid image status fail on get image property, ret:%{public}u.", ret); + return ret; + } + + ret = mainDecoder_->GetImagePropertyString(index, key, value); + if (ret != SUCCESS) { + IMAGE_LOGE("[ImageSource] GetImagePropertyInt fail, ret:%{public}u", ret); + return ret; + } + + return SUCCESS; +} + const SourceInfo &ImageSource::GetSourceInfo(uint32_t &errorCode) { std::lock_guard guard(decodingMutex_); @@ -853,6 +872,7 @@ uint32_t ImageSource::DecodeImageInfo(uint32_t index, ImageStatusMap::iterator & IMAGE_LOGE("[ImageSource]get image size, image decode plugin is null."); return ERR_IMAGE_PLUGIN_CREATE_FAILED; } + ImagePlugin::PlSize size; ret = mainDecoder_->GetImageSize(index, size); if (ret == SUCCESS) { diff --git a/frameworks/innerkitsimpl/common/src/pixel_map.cpp b/frameworks/innerkitsimpl/common/src/pixel_map.cpp index a537f99f8db6ee7a73ad3b7dd485db946eec442d..e5d3b905041b854966830e36abbd551331edee82 100644 --- a/frameworks/innerkitsimpl/common/src/pixel_map.cpp +++ b/frameworks/innerkitsimpl/common/src/pixel_map.cpp @@ -22,10 +22,8 @@ #include "media_errors.h" #include "pixel_convert_adapter.h" #include "pixel_map_utils.h" -#include "pixel_map_parcel.h" #include "post_proc.h" #include "parcel.h" -#include "ipc_file_descriptor.h" #ifndef _WIN32 #include "securec.h" #else @@ -35,6 +33,7 @@ #if !defined(_WIN32) && !defined(_APPLE) #include #include "ashmem.h" +#include "ipc_file_descriptor.h" #endif namespace OHOS { @@ -48,6 +47,9 @@ constexpr uint8_t BGRA_ALPHA_INDEX = 3; constexpr uint8_t BGRA_BYTES = 4; constexpr uint8_t PER_PIXEL_LEN = 1; +constexpr uint8_t FILL_NUMBER = 3; +constexpr uint8_t ALIGN_NUMBER = 4; + PixelMap::~PixelMap() { FreePixelMap(); @@ -111,12 +113,14 @@ void PixelMap::SetPixelsAddr(void *addr, void *context, uint32_t size, Allocator unique_ptr PixelMap::Create(const uint32_t *colors, uint32_t colorLength, const InitializationOptions &opts) { + HiLog::Info(LABEL, "PixelMap::Create1 enter"); return Create(colors, colorLength, 0, opts.size.width, opts); } unique_ptr PixelMap::Create(const uint32_t *colors, uint32_t colorLength, int32_t offset, int32_t stride, const InitializationOptions &opts) { + HiLog::Info(LABEL, "PixelMap::Create2 enter"); if (!CheckParams(colors, colorLength, offset, stride, opts)) { return nullptr; } @@ -194,6 +198,7 @@ bool PixelMap::CheckParams(const uint32_t *colors, uint32_t colorLength, int32_t unique_ptr PixelMap::Create(const InitializationOptions &opts) { + HiLog::Info(LABEL, "PixelMap::Create3 enter"); unique_ptr dstPixelMap = make_unique(); if (dstPixelMap == nullptr) { HiLog::Error(LABEL, "create pixelMap pointer fail"); @@ -209,6 +214,10 @@ unique_ptr PixelMap::Create(const InitializationOptions &opts) return nullptr; } uint32_t bufferSize = dstPixelMap->GetByteCount(); + if (bufferSize <= 0) { + HiLog::Error(LABEL, "calloc parameter bufferSize:[%{public}d] error.", bufferSize); + return nullptr; + } uint8_t *dstPixels = static_cast(calloc(bufferSize, 1)); if (dstPixels == nullptr) { HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize); @@ -245,12 +254,14 @@ void PixelMap::UpdatePixelsAlpha(const AlphaType &alphaType, const PixelFormat & unique_ptr PixelMap::Create(PixelMap &source, const InitializationOptions &opts) { + HiLog::Info(LABEL, "PixelMap::Create4 enter"); Rect rect; return Create(source, rect, opts); } unique_ptr PixelMap::Create(PixelMap &source, const Rect &srcRect, const InitializationOptions &opts) { + HiLog::Info(LABEL, "PixelMap::Create5 enter"); ImageInfo srcImageInfo; source.GetImageInfo(srcImageInfo); PostProc postProc; @@ -305,6 +316,10 @@ bool PixelMap::SourceCropAndConvert(PixelMap &source, const ImageInfo &srcImageI const Rect &srcRect, PixelMap &dstPixelMap) { uint32_t bufferSize = dstPixelMap.GetByteCount(); + if (bufferSize <= 0) { + HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize); + return false; + } void *dstPixels = malloc(bufferSize); if (dstPixels == nullptr) { HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize); @@ -365,10 +380,14 @@ void PixelMap::InitDstImageInfo(const InitializationOptions &opts, const ImageIn bool PixelMap::CopyPixelMap(PixelMap &source, PixelMap &dstPixelMap) { uint32_t bufferSize = source.GetByteCount(); - if (bufferSize == 0 || source.GetPixels() == nullptr) { + if (source.GetPixels() == nullptr) { HiLog::Error(LABEL, "source pixelMap data invalid"); return false; } + if (bufferSize <= 0) { + HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize); + return false; + } uint8_t *dstPixels = static_cast(malloc(bufferSize)); if (dstPixels == nullptr) { HiLog::Error(LABEL, "allocate memory size %{public}u fail", bufferSize); @@ -466,7 +485,7 @@ uint32_t PixelMap::SetImageInfo(ImageInfo &info, bool isReused) return ERR_IMAGE_TOO_LARGE; } if (info.pixelFormat == PixelFormat::ALPHA_8) { - rowDataSize_ = pixelBytes_ * ((info.size.width + 3) / 4 * 4); + rowDataSize_ = pixelBytes_ * ((info.size.width + FILL_NUMBER) / ALIGN_NUMBER * ALIGN_NUMBER); HiLog::Info(LABEL, "ALPHA_8 rowDataSize_ %{public}d.", rowDataSize_); } else { rowDataSize_ = pixelBytes_ * info.size.width; @@ -639,6 +658,7 @@ int32_t PixelMap::GetRowBytes() int32_t PixelMap::GetByteCount() { + HiLog::Debug(LABEL, "GetByteCount"); return rowDataSize_ * imageInfo_.size.height; } @@ -705,15 +725,18 @@ uint8_t PixelMap::GetARGB32ColorB(uint32_t color) bool PixelMap::IsSameImage(const PixelMap &other) { if (data_ == nullptr || other.data_ == nullptr) { + HiLog::Error(LABEL, "IsSameImage data_ is nullptr."); return false; } if (imageInfo_.size.width != other.imageInfo_.size.width || imageInfo_.size.height != other.imageInfo_.size.height || imageInfo_.pixelFormat != other.imageInfo_.pixelFormat || imageInfo_.alphaType != other.imageInfo_.alphaType) { + HiLog::Error(LABEL, "IsSameImage imageInfo check not OK."); return false; } uint64_t size = static_cast(rowDataSize_) * imageInfo_.size.height; if (memcmp(data_, other.data_, size) != 0) { + HiLog::Error(LABEL, "IsSameImage mmemcmp check not OK."); return false; } return true; @@ -1011,7 +1034,139 @@ void *PixelMap::GetFd() const return context_; } -bool PixelMap::WriteFileDescriptor(Parcel &data, int fd) const +void PixelMap::ReleaseMemory(AllocatorType allocType, void *addr, void *context, uint32_t size) +{ + if (allocType == AllocatorType::SHARE_MEM_ALLOC) { +#if !defined(_WIN32) && !defined(_APPLE) + int *fd = static_cast(context); + if (addr != nullptr) { + ::munmap(addr, size); + } + if (fd != nullptr) { + ::close(*fd); + delete fd; + } +#endif + } else if (allocType == AllocatorType::HEAP_ALLOC) { + if (addr != nullptr) { + free(addr); + addr = nullptr; + } + } +} + +bool PixelMap::WriteImageData(Parcel &parcel, size_t size) const +{ + const uint8_t *data = data_; + if (data == nullptr) { + HiLog::Error(LABEL, "write to parcel failed, pixel memory is null."); + return false; + } + if (data == nullptr || size > MAX_IMAGEDATA_SIZE) { + return false; + } + + if (!parcel.WriteInt32(size)) { + return false; + } + if (size <= MIN_IMAGEDATA_SIZE) { + return parcel.WriteUnpadBuffer(data, size); + } +#if !defined(_WIN32) && !defined(_APPLE) + int fd = AshmemCreate("Parcel ImageData", size); + HiLog::Info(LABEL, "AshmemCreate:[%{public}d].", fd); + if (fd < 0) { + return false; + } + + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + HiLog::Info(LABEL, "AshmemSetProt:[%{public}d].", result); + if (result < 0) { + return false; + } + void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (ptr == MAP_FAILED) { + return false; + } + HiLog::Info(LABEL, "mmap success"); + + if (memcpy_s(ptr, size, data, size) != EOK) { + ::munmap(ptr, size); + HiLog::Error(LABEL, "WriteImageData memcpy_s error"); + return false; + } + + if (!WriteFileDescriptor(parcel, fd)) { + ::munmap(ptr, size); + HiLog::Error(LABEL, "WriteImageData WriteFileDescriptor error"); + return false; + } + HiLog::Debug(LABEL, "WriteImageData WriteFileDescriptor success"); + HiLog::Debug(LABEL, "WriteImageData End"); +#endif + return true; +} + +uint8_t *PixelMap::ReadImageData(Parcel &parcel, int32_t bufferSize) +{ + uint8_t *base = nullptr; + int fd = -1; + + if (static_cast(bufferSize) <= MIN_IMAGEDATA_SIZE) { + const uint8_t *ptr = parcel.ReadUnpadBuffer(bufferSize); + if (bufferSize <= 0) { + HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize); + return nullptr; + } + base = static_cast(malloc(bufferSize)); + if (base == nullptr) { + HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize); + return nullptr; + } + if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) { + free(base); + base = nullptr; + HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize); + return nullptr; + } + } else { +#if !defined(_WIN32) && !defined(_APPLE) + fd = ReadFileDescriptor(parcel); + if (fd < 0) { + HiLog::Error(LABEL, "read fd :[%{public}d] error", fd); + return nullptr; + } + void *ptr = ::mmap(nullptr, bufferSize, PROT_READ, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + // do not close fd here. fd will be closed in FileDescriptor, ::close(fd) + HiLog::Error(LABEL, "mmap error"); + return nullptr; + } + if (bufferSize <= 0) { + HiLog::Error(LABEL, "malloc parameter bufferSize:[%{public}d] error.", bufferSize); + return nullptr; + } + base = static_cast(malloc(bufferSize)); + if (base == nullptr) { + HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize); + return nullptr; + } + if (memcpy_s(base, bufferSize, ptr, bufferSize) != 0) { + free(base); + base = nullptr; + HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize); + return nullptr; + } + + ReleaseMemory(AllocatorType::SHARE_MEM_ALLOC, ptr, &fd, bufferSize); +#endif + } + + return base; +} + +bool PixelMap::WriteFileDescriptor(Parcel &parcel, int fd) { if (fd < 0) { return false; @@ -1021,12 +1176,12 @@ bool PixelMap::WriteFileDescriptor(Parcel &data, int fd) const return false; } sptr descriptor = new IPCFileDescriptor(dupFd); - return data.WriteObject(descriptor); + return parcel.WriteObject(descriptor); } -int PixelMap::ReadFileDescriptor(Parcel &data) +int PixelMap::ReadFileDescriptor(Parcel &parcel) { - sptr descriptor = data.ReadObject(); + sptr descriptor = parcel.ReadObject(); if (descriptor == nullptr) { return -1; } @@ -1037,66 +1192,70 @@ int PixelMap::ReadFileDescriptor(Parcel &data) return dup(fd); } -bool PixelMap::Marshalling(Parcel &data) const +bool PixelMap::WriteImageInfo(Parcel &parcel) const { - int32_t PIXEL_MAP_INFO_MAX_LENGTH = 128; - int32_t bufferSize = rowDataSize_ * imageInfo_.size.height; - - if (static_cast(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH) > data.GetDataCapacity() && - !data.SetDataCapacity(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH)) { - HiLog::Error(LABEL, "set parcel max capacity:[%{public}d] failed.", bufferSize + PIXEL_MAP_INFO_MAX_LENGTH); + if (!parcel.WriteInt32(imageInfo_.size.width)) { + HiLog::Error(LABEL, "write image info width:[%{public}d] to parcel failed.", imageInfo_.size.width); return false; } - if (!data.WriteInt32(imageInfo_.size.width)) { - HiLog::Error(LABEL, "write pixel map width:[%{public}d] to parcel failed.", imageInfo_.size.width); + if (!parcel.WriteInt32(imageInfo_.size.height)) { + HiLog::Error(LABEL, "write image info height:[%{public}d] to parcel failed.", imageInfo_.size.height); return false; } - if (!data.WriteInt32(imageInfo_.size.height)) { - HiLog::Error(LABEL, "write pixel map height:[%{public}d] to parcel failed.", imageInfo_.size.height); + if (!parcel.WriteInt32(static_cast(imageInfo_.pixelFormat))) { + HiLog::Error(LABEL, "write image info pixel format:[%{public}d] to parcel failed.", imageInfo_.pixelFormat); return false; } - if (!data.WriteInt32(static_cast(imageInfo_.pixelFormat))) { - HiLog::Error(LABEL, "write pixel map pixel format:[%{public}d] to parcel failed.", imageInfo_.pixelFormat); + if (!parcel.WriteInt32(static_cast(imageInfo_.colorSpace))) { + HiLog::Error(LABEL, "write image info color space:[%{public}d] to parcel failed.", imageInfo_.colorSpace); return false; } - if (!data.WriteInt32(static_cast(imageInfo_.colorSpace))) { - HiLog::Error(LABEL, "write pixel map color space:[%{public}d] to parcel failed.", imageInfo_.colorSpace); + if (!parcel.WriteInt32(static_cast(imageInfo_.alphaType))) { + HiLog::Error(LABEL, "write image info alpha type:[%{public}d] to parcel failed.", imageInfo_.alphaType); return false; } - if (!data.WriteInt32(static_cast(imageInfo_.alphaType))) { - HiLog::Error(LABEL, "write pixel map alpha type:[%{public}d] to parcel failed.", imageInfo_.alphaType); + if (!parcel.WriteInt32(imageInfo_.baseDensity)) { + HiLog::Error(LABEL, "write image info base density:[%{public}d] to parcel failed.", imageInfo_.baseDensity); return false; } - if (!data.WriteInt32(imageInfo_.baseDensity)) { - HiLog::Error(LABEL, "write pixel map base density:[%{public}d] to parcel failed.", imageInfo_.baseDensity); + return true; +} + +bool PixelMap::Marshalling(Parcel &parcel) const +{ + int32_t PIXEL_MAP_INFO_MAX_LENGTH = 128; + int32_t bufferSize = rowDataSize_ * imageInfo_.size.height; + if (static_cast(bufferSize) <= MIN_IMAGEDATA_SIZE && + static_cast(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH) > parcel.GetDataCapacity() && + !parcel.SetDataCapacity(bufferSize + PIXEL_MAP_INFO_MAX_LENGTH)) { + HiLog::Error(LABEL, "set parcel max capacity:[%{public}d] failed.", bufferSize + PIXEL_MAP_INFO_MAX_LENGTH); return false; } - if (!data.WriteInt32(bufferSize)) { - HiLog::Error(LABEL, "write pixel map buffer size:[%{public}d] to parcel failed.", bufferSize); + if (!WriteImageInfo(parcel)) { + HiLog::Error(LABEL, "write image info to parcel failed."); return false; } - if (!data.WriteInt32(static_cast(allocatorType_))) { + + if (!parcel.WriteInt32(static_cast(allocatorType_))) { HiLog::Error(LABEL, "write pixel map allocator type:[%{public}d] to parcel failed.", allocatorType_); return false; } if (allocatorType_ == AllocatorType::SHARE_MEM_ALLOC) { +#if !defined(_WIN32) && !defined(_APPLE) int *fd = static_cast(context_); if (*fd < 0) { HiLog::Error(LABEL, "write pixel map failed, fd < 0."); return false; } - if (!WriteFileDescriptor(data, *fd)) { + + if (!WriteFileDescriptor(parcel, *fd)) { HiLog::Error(LABEL, "write pixel map fd:[%{public}d] to parcel failed.", *fd); return false; } +#endif } else { - const uint8_t *addr = data_; - if (addr == nullptr) { - HiLog::Error(LABEL, "write to parcel failed, pixel memory is null."); - return false; - } - if (!data.WriteBuffer(addr, bufferSize)) { + if (!WriteImageData(parcel, bufferSize)) { HiLog::Error(LABEL, "write pixel map buffer to parcel failed."); return false; } @@ -1104,32 +1263,46 @@ bool PixelMap::Marshalling(Parcel &data) const return true; } -PixelMap *PixelMap::Unmarshalling(Parcel &data) +bool PixelMap::ReadImageInfo(Parcel &parcel, ImageInfo &imgInfo) +{ + imgInfo.size.width = parcel.ReadInt32(); + HiLog::Debug(LABEL, "read pixel map width:[%{public}d] to parcel.", imgInfo.size.width); + imgInfo.size.height = parcel.ReadInt32(); + HiLog::Debug(LABEL, "read pixel map height:[%{public}d] to parcel.", imgInfo.size.height); + imgInfo.pixelFormat = static_cast(parcel.ReadInt32()); + HiLog::Debug(LABEL, "read pixel map pixelFormat:[%{public}d] to parcel.", imgInfo.pixelFormat); + imgInfo.colorSpace = static_cast(parcel.ReadInt32()); + HiLog::Debug(LABEL, "read pixel map colorSpace:[%{public}d] to parcel.", imgInfo.colorSpace); + imgInfo.alphaType = static_cast(parcel.ReadInt32()); + HiLog::Debug(LABEL, "read pixel map alphaType:[%{public}d] to parcel.", imgInfo.alphaType); + imgInfo.baseDensity = parcel.ReadInt32(); + return true; +} + +PixelMap *PixelMap::Unmarshalling(Parcel &parcel) { PixelMap *pixelMap = new PixelMap(); if (pixelMap == nullptr) { - HiLog::Error(LABEL, "create pixelmap pointer fail"); return nullptr; } ImageInfo imgInfo; - imgInfo.size.width = data.ReadInt32(); - imgInfo.size.height = data.ReadInt32(); - imgInfo.pixelFormat = static_cast(data.ReadInt32()); - imgInfo.colorSpace = static_cast(data.ReadInt32()); - imgInfo.alphaType = static_cast(data.ReadInt32()); - imgInfo.baseDensity = data.ReadInt32(); - int32_t bufferSize = data.ReadInt32(); - AllocatorType allocType = static_cast(data.ReadInt32()); + if (!pixelMap->ReadImageInfo(parcel, imgInfo)) { + HiLog::Error(LABEL, "read imageInfo fail"); + return nullptr; + } + + AllocatorType allocType = static_cast(parcel.ReadInt32()); + int32_t bufferSize = parcel.ReadInt32(); uint8_t *base = nullptr; void *context = nullptr; if (allocType == AllocatorType::SHARE_MEM_ALLOC) { - int fd = ReadFileDescriptor(data); +#if !defined(_WIN32) && !defined(_APPLE) + int fd = ReadFileDescriptor(parcel); if (fd < 0) { HiLog::Error(LABEL, "fd < 0"); return nullptr; } - HiLog::Debug(LABEL, "ReadFileDescriptor fd %{public}d.", fd); void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { ::close(fd); @@ -1138,49 +1311,24 @@ PixelMap *PixelMap::Unmarshalling(Parcel &data) } context = new int32_t(); if (context == nullptr) { - HiLog::Error(LABEL, "alloc context error."); ::munmap(ptr, bufferSize); ::close(fd); return nullptr; } *static_cast(context) = fd; base = static_cast(ptr); +#endif } else { - const uint8_t *addr = data.ReadBuffer(bufferSize); - if (addr == nullptr) { - HiLog::Error(LABEL, "read buffer from parcel failed, read buffer addr is null"); - return nullptr; - } - base = static_cast(malloc(bufferSize)); + base = ReadImageData(parcel, bufferSize); if (base == nullptr) { - HiLog::Error(LABEL, "alloc output pixel memory size:[%{public}d] error.", bufferSize); - return nullptr; - } - if (memcpy_s(base, bufferSize, addr, bufferSize) != 0) { - free(base); - base = nullptr; - HiLog::Error(LABEL, "memcpy pixel data size:[%{public}d] error.", bufferSize); + HiLog::Error(LABEL, "get pixel memory size:[%{public}d] error.", bufferSize); return nullptr; } } uint32_t ret = pixelMap->SetImageInfo(imgInfo); if (ret != SUCCESS) { - if (allocType == AllocatorType::SHARE_MEM_ALLOC) { - int *fd = static_cast(context); - if (base != nullptr) { - ::munmap(base, bufferSize); - } - if (fd != nullptr) { - ::close(*fd); - delete fd; - } - } else if (allocType == AllocatorType::HEAP_ALLOC) { - if (base != nullptr) { - free(base); - base = nullptr; - } - } + ReleaseMemory(allocType, base, context, bufferSize); HiLog::Error(LABEL, "create pixel map from parcel failed, set image info error."); return nullptr; } diff --git a/frameworks/innerkitsimpl/test/BUILD.gn b/frameworks/innerkitsimpl/test/BUILD.gn old mode 100644 new mode 100755 index 72f3d28a70af59b594f2df1e6b104831d8ae70c6..c04801531189e55d5644f6dff4c4291248e2f528 --- a/frameworks/innerkitsimpl/test/BUILD.gn +++ b/frameworks/innerkitsimpl/test/BUILD.gn @@ -39,36 +39,36 @@ ohos_unittest("imagepixelmaptest") { # external_deps = [ "hiviewdfx_hilog_native:libhilog" ] } -#ohos_unittest("imagepixelmapparceltest") { -# module_out_path = module_output_path - -# include_dirs = [ -# "//foundation/multimedia/image_standard/interfaces/innerkits/include", -# "//foundation/multimedia/utils/include", -# "//third_party/googletest/googletest/include", -# "//utils/native/base/include", -# "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", -# "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", -# "//foundation/multimedia/image_standard/mock/native/include", -# ] -# sources = [ "./unittest/image_pixel_map_parcel_test.cpp" ] - -# deps = [ -# "//third_party/googletest:gmock_main", -# "//third_party/googletest:gtest_main", -# "//utils/native/base:utils", -# "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", -# "//foundation/multimedia/image_standard:image_framework", -# "//foundation/multimedia/image_standard/mock/native:utils_mock_static", -# "//foundation/multimedia/image_standard/mock/native:log_mock_static", -# ] -# external_deps = [ -# "bytrace_standard:bytrace_core", -# "hiviewdfx_hilog_native:libhilog", -# "ipc:ipc_core", -# "multimedia_image:libimage", -# ] -#} +ohos_unittest("imagepixelmapparceltest") { + module_out_path = module_output_path + + include_dirs = [ + "//foundation/multimedia/image_standard/interfaces/innerkits/include", + "//foundation/multimedia/utils/include", + "//third_party/googletest/googletest/include", + "//utils/native/base/include", + "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", + "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "//foundation/multimedia/image_standard/mock/native/include", + ] + sources = [ "./unittest/image_pixel_map_parcel_test.cpp" ] + + deps = [ + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//utils/native/base:utils", + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", + "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", + #"//foundation/multimedia/image_standard/mock/native:utils_mock_static", + #"//foundation/multimedia/image_standard/mock/native:log_mock_static", + ] + external_deps = [ + "bytrace_standard:bytrace_core", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + #"//foundation/multimedia/image_standard/interfaces/innerkits:image_native", + ] +} ohos_unittest("imagesourcetest") { DUAL_ADAPTER = true @@ -165,8 +165,7 @@ group("unittest") { testonly = true deps = [ ":colorconvertertest", - - # ":imagepixelmapparceltest", + ":imagepixelmapparceltest", ":imagepixelmaptest", ":imagesourcetest", ":transformtest", diff --git a/frameworks/innerkitsimpl/test/unittest/image_pixel_map_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_pixel_map_test.cpp index c9906841482da40260ca97717113a36540ed7166..cbd34f6fd14f0c6196eeeda87563b77ea6c9b445 100644 --- a/frameworks/innerkitsimpl/test/unittest/image_pixel_map_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_pixel_map_test.cpp @@ -27,6 +27,8 @@ static constexpr int32_t PIXEL_MAP_TEST_HEIGHT = 3; static constexpr int32_t PIXEL_MAP_RGB565_BYTE = 2; static constexpr int32_t PIXEL_MAP_RGB888_BYTE = 3; static constexpr int32_t PIXEL_MAP_ARGB8888_BYTE = 4; +constexpr int32_t PIXEL_MAP_BIG_TEST_WIDTH = 4 * 1024; +constexpr int32_t PIXEL_MAP_BIG_TEST_HEIGHT = 3 * 100; class ImagePixelMapTest : public testing::Test { public: @@ -48,7 +50,13 @@ public: int32_t rowDataSize = pixelMapWidth; uint32_t bufferSize = rowDataSize * pixelMapHeight; + if (bufferSize <= 0) { + return nullptr; + } void *buffer = malloc(bufferSize); + if (buffer == nullptr) { + return nullptr; + } char *ch = (char *)buffer; for (unsigned int i = 0; i < bufferSize; i++) { *(ch++) = (char)i; @@ -58,6 +66,36 @@ public: return pixelMap; } + + std::unique_ptr ConstructBigPixmap() + { + int32_t pixelMapWidth = PIXEL_MAP_BIG_TEST_WIDTH; + int32_t pixelMapHeight = PIXEL_MAP_BIG_TEST_HEIGHT; + std::unique_ptr pixelMap = std::make_unique(); + ImageInfo info; + info.size.width = pixelMapWidth; + info.size.height = pixelMapHeight; + info.pixelFormat = PixelFormat::RGB_888; + info.colorSpace = ColorSpace::SRGB; + pixelMap->SetImageInfo(info); + + int32_t bufferSize = pixelMap->GetByteCount(); + if (bufferSize <= 0) { + return nullptr; + } + std::unique_ptr buffer = malloc(bufferSize); + if (buffer == nullptr) { + return nullptr; + } + char *ch = (char *)buffer; + for (int32_t i = 0; i < bufferSize; i++) { + *(ch++) = 'a'; + } + + pixelMap->SetPixelsAddr(buffer, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr); + + return pixelMap; + } /** * @tc.name: ImagePixelMap001 * @tc.desc: ALPHA_8 pixel format pixel map operation @@ -469,22 +507,16 @@ HWTEST_F(ImagePixelMapTest, ImagePixelMap011, TestSize.Level3) GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMap011 start"; Parcel data; - std::unique_ptr pixelmap1 = ConstructPixmap(); - bool ret = pixelmap1.get()->Marshalling(data); - EXPECT_EQ(true, ret); PixelMap *pixelmap2 = PixelMap::Unmarshalling(data); - EXPECT_EQ(pixelmap1->GetHeight(), pixelmap2->GetHeight()); EXPECT_EQ(pixelmap1->GetWidth(), pixelmap2->GetWidth()); EXPECT_EQ(pixelmap1->GetPixelFormat(), pixelmap2->GetPixelFormat()); EXPECT_EQ(pixelmap1->GetColorSpace(), pixelmap2->GetColorSpace()); - EXPECT_EQ(true, pixelmap1->IsSameImage(*pixelmap2)); - GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMap011 end"; } /** @@ -513,5 +545,40 @@ HWTEST_F(ImagePixelMapTest, ImagePixelMap012, TestSize.Level3) EXPECT_EQ(newPixelMap, nullptr); GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMap012 end"; } + + +/** +* @tc.name: ImagePixelMap013 +* @tc.desc: test CreateFromParcel +* @tc.type: FUNC +* @tc.require: AR000FTAMO +*/ +HWTEST_F(ImagePixelMapTest, ImagePixelMap013, TestSize.Level3) +{ + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMap013 start"; + + Parcel data; + std::unique_ptr pixelmap1 = ConstructBigPixmap(); + EXPECT_NE(pixelmap1, nullptr); + GTEST_LOG_(INFO) << "ImagePixelMap013 ConstructPixmap success"; + bool ret = pixelmap1.get()->Marshalling(data); + GTEST_LOG_(INFO) << "ImagePixelMap013 Marshalling success"; + EXPECT_EQ(true, ret); + + PixelMap *pixelmap2 = PixelMap::Unmarshalling(data); + GTEST_LOG_(INFO) << "ImagePixelMap013 Unmarshalling success"; + GTEST_LOG_(INFO) << "ImagePixelMap013 pixelmap1 GetHeight :" << pixelmap1->GetHeight(); + GTEST_LOG_(INFO) << "ImagePixelMap013 pixelmap2 GetHeight :" << pixelmap2->GetHeight(); + EXPECT_EQ(pixelmap1->GetHeight(), pixelmap2->GetHeight()); + GTEST_LOG_(INFO) << "ImagePixelMap013 GetHeight success"; + EXPECT_EQ(pixelmap1->GetWidth(), pixelmap2->GetWidth()); + GTEST_LOG_(INFO) << "ImagePixelMap013 GetWidth success"; + EXPECT_EQ(pixelmap1->GetPixelFormat(), pixelmap2->GetPixelFormat()); + GTEST_LOG_(INFO) << "ImagePixelMap013 GetPixelFormat success"; + EXPECT_EQ(pixelmap1->GetColorSpace(), pixelmap2->GetColorSpace()); + GTEST_LOG_(INFO) << "ImagePixelMap013 GetColorSpace success"; + EXPECT_EQ(true, pixelmap1->IsSameImage(*pixelmap2)); + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMap013 end"; +} } // namespace Multimedia } // namespace OHOS \ No newline at end of file diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_bmp_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_bmp_test.cpp old mode 100644 new mode 100755 index 9bfb0724fdc64ecf1f6cb039f09c94d4ae1184fb..d6b4f82585ee87959d310d02c57cafc679b8b517 --- a/frameworks/innerkitsimpl/test/unittest/image_source_bmp_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_bmp_test.cpp @@ -28,7 +28,7 @@ using namespace testing::ext; using namespace OHOS::Media; using namespace OHOS::HiviewDFX; -static const std::string IMAGE_INPUT_BMP_PATH = "/sdcard/multimedia/image/test.bmp"; +static const std::string IMAGE_INPUT_BMP_PATH = "sdcard/multimedia/image/test.bmp"; static const std::string IMAGE_OUTPUT_BMP_FILE_PATH = "/data/test/test_bmp_file.jpg"; int64_t PackImage(const std::string &filePath, std::unique_ptr pixelMap); @@ -397,4 +397,4 @@ HWTEST_F(ImageSourceBmpTest, BmpImageDecode011, TestSize.Level3) std::unique_ptr pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode); ASSERT_NE(errorCode, SUCCESS); ASSERT_EQ(pixelMap.get(), nullptr); -} \ No newline at end of file +} diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_gif_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_gif_test.cpp old mode 100644 new mode 100755 index 5b3c0d45a34be6f621461518370ddc8f7dd888a2..3f2b6cf257646e8389313cef4cc988cbed5a271c --- a/frameworks/innerkitsimpl/test/unittest/image_source_gif_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_gif_test.cpp @@ -59,7 +59,7 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode001, TestSize.Level3) SourceOptions opts; opts.formatHint = "image/gif"; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.gif", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.gif", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); /** @@ -119,7 +119,7 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode002, TestSize.Level3) uint32_t errorCode = 0; SourceOptions opts; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.gif", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.gif", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); /** @@ -146,7 +146,7 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode003, TestSize.Level3) SourceOptions opts; opts.formatHint = "image/gif"; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/gif/test.gif", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/gif/test.gif", opts, errorCode); ASSERT_EQ(errorCode, ERR_IMAGE_SOURCE_DATA); ASSERT_EQ(imageSource.get(), nullptr); } @@ -163,11 +163,11 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode004, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool ret = ImageUtils::GetFileSize("/sdcard/multimedia/image/test.gif", bufferSize); + bool ret = ImageUtils::GetFileSize("sdcard/multimedia/image/test.gif", bufferSize); ASSERT_EQ(ret, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - ret = ReadFileToBuffer("/sdcard/multimedia/image/test.gif", buffer, bufferSize); + ret = ReadFileToBuffer("sdcard/multimedia/image/test.gif", buffer, bufferSize); ASSERT_EQ(ret, true); uint32_t errorCode = 0; SourceOptions opts; @@ -216,7 +216,7 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode005, TestSize.Level3) * @tc.expected: step1. create image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.gif", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.gif", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -266,7 +266,7 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode006, TestSize.Level3) SourceOptions opts; opts.formatHint = "image/gif"; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/moving_test.gif", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/moving_test.gif", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); /** @@ -325,11 +325,11 @@ HWTEST_F(ImageSourceGifTest, GifImageDecode007, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool fileRet = ImageUtils::GetFileSize("/sdcard/multimedia/image/moving_test.gif", bufferSize); + bool fileRet = ImageUtils::GetFileSize("sdcard/multimedia/image/moving_test.gif", bufferSize); ASSERT_EQ(fileRet, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - fileRet = ReadFileToBuffer("/sdcard/multimedia/image/moving_test.gif", buffer, bufferSize); + fileRet = ReadFileToBuffer("sdcard/multimedia/image/moving_test.gif", buffer, bufferSize); ASSERT_EQ(fileRet, true); uint32_t errorCode = 0; IncrementalSourceOptions incOpts; diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_jpeg_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_jpeg_test.cpp old mode 100644 new mode 100755 index 40f9c7b6178cd49e1aa73b723b9bccfdb74ca6ad..055d8cef653364b2867094c35905c763b7290630 --- a/frameworks/innerkitsimpl/test/unittest/image_source_jpeg_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_jpeg_test.cpp @@ -34,9 +34,9 @@ static constexpr OHOS::HiviewDFX::HiLogLabel LABEL_TEST = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "ImageSourceJpegTest" }; static constexpr uint32_t DEFAULT_DELAY_UTIME = 10000; // 10 ms. -static const std::string IMAGE_INPUT_JPEG_PATH = "/sdcard/multimedia/image/test.jpg"; -static const std::string IMAGE_INPUT_HW_JPEG_PATH = "/sdcard/multimedia/image/test_hw.jpg"; -static const std::string IMAGE_INPUT_EXIF_JPEG_PATH = "/sdcard/multimedia/image/test_exif.jpg"; +static const std::string IMAGE_INPUT_JPEG_PATH = "sdcard/multimedia/image/test.jpg"; +static const std::string IMAGE_INPUT_HW_JPEG_PATH = "sdcard/multimedia/image/test_hw.jpg"; +static const std::string IMAGE_INPUT_EXIF_JPEG_PATH = "sdcard/multimedia/image/test_exif.jpg"; static const std::string IMAGE_OUTPUT_JPEG_FILE_PATH = "/data/test/test_file.jpg"; static const std::string IMAGE_OUTPUT_JPEG_BUFFER_PATH = "/data/test/test_buffer.jpg"; static const std::string IMAGE_OUTPUT_JPEG_ISTREAM_PATH = "/data/test/test_istream.jpg"; @@ -49,6 +49,14 @@ static const std::string IMAGE_OUTPUT_JPEG_MULTI_ONETIME1_PATH = "/data/test/tes static const std::string IMAGE_OUTPUT_JPEG_MULTI_INC2_PATH = "/data/test/test_inc2.jpg"; static const std::string IMAGE_OUTPUT_JPEG_MULTI_ONETIME2_PATH = "/data/test/test_onetime2.jpg"; +const std::string ORIENTATION = "Orientation"; +const std::string IMAGE_HEIGHT = "ImageHeight"; +const std::string IMAGE_WIDTH = "ImageWidth"; +const std::string GPS_LATITUDE = "GPSLatitude"; +const std::string GPS_LONGITUDE = "GPSLongitude"; +const std::string GPS_LATITUDE_REF = "GPSLatitudeRef"; +const std::string GPS_LONGITUDE_REF = "GPSLongitudeRef"; + int64_t PackImage(const std::string &filePath, std::unique_ptr pixelMap); bool ReadFileToBuffer(const std::string &filePath, uint8_t *buffer, size_t bufferSize); @@ -509,7 +517,7 @@ HWTEST_F(ImageSourceJpegTest, JpgImageCrop001, TestSize.Level3) * @tc.expected: step1. create jpg image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.jpg", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.jpg", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -570,4 +578,90 @@ HWTEST_F(ImageSourceJpegTest, JpegImageHwDecode001, TestSize.Level3) */ int64_t packSize = PackImage(IMAGE_OUTPUT_HW_JPEG_FILE_PATH, std::move(pixelMap)); ASSERT_NE(packSize, 0); -} \ No newline at end of file +} + +/** + * @tc.name: JpegImageDecode011 + * @tc.desc: Obtains the integer value of a specified property key. + * @tc.type: FUNC + */ +HWTEST_F(ImageSourceJpegTest, JpegImageDecode011, TestSize.Level3) +{ + /** + * @tc.steps: step1. create image source by correct jpeg file path. + * @tc.expected: step1. create image source success. + */ + uint32_t errorCode = 0; + SourceOptions opts; + opts.formatHint = "image/jpeg"; + std::unique_ptr imageSource = ImageSource::CreateImageSource(IMAGE_INPUT_EXIF_JPEG_PATH, opts, errorCode); + ASSERT_EQ(errorCode, SUCCESS); + ASSERT_NE(imageSource.get(), nullptr); + /** + * @tc.steps: step2. Obtains the integer value of a specified property key for an image at the given index in the ImageSource. + * @tc.expected: step2. Obtains property success. + */ + int32_t value = 0;; + errorCode = imageSource->GetImagePropertyInt(0, ORIENTATION, value); + HiLog::Debug(LABEL_TEST, "ORIENTATION is %{public}d.", value); + ASSERT_EQ(errorCode, SUCCESS); + + errorCode = imageSource->GetImagePropertyInt(0, IMAGE_HEIGHT, value); + HiLog::Debug(LABEL_TEST, "IMAGE_HEIGHT is %{public}d.", value); + ASSERT_EQ(errorCode, SUCCESS); + + errorCode = imageSource->GetImagePropertyInt(0, IMAGE_WIDTH, value); + HiLog::Debug(LABEL_TEST, "IMAGE_WIDTH is %{public}d.", value); + ASSERT_EQ(errorCode, SUCCESS); + /** + * @tc.steps: step3. Obtains the integer value of a specified property key for an image at the given index in the ImageSource. + * @tc.expected: step3. Obtains property return ERR_IMAGE_INVALID_PARAMETER error. + */ + errorCode = imageSource->GetImagePropertyInt(0, GPS_LATITUDE, value); + ASSERT_EQ(errorCode, ERR_IMAGE_INVALID_PARAMETER); +} + +/** + * @tc.name: JpegImageDecode012 + * @tc.desc: Obtains the string value of a specified image property key. + * @tc.type: FUNC + */ +HWTEST_F(ImageSourceJpegTest, JpegImageDecode012, TestSize.Level3) +{ + /** + * @tc.steps: step1. create image source by correct jpeg file path. + * @tc.expected: step1. create image source success. + */ + uint32_t errorCode = 0; + SourceOptions opts; + opts.formatHint = "image/jpeg"; + std::unique_ptr imageSource = ImageSource::CreateImageSource(IMAGE_INPUT_EXIF_JPEG_PATH, opts, errorCode); + ASSERT_EQ(errorCode, SUCCESS); + ASSERT_NE(imageSource.get(), nullptr); + /** + * @tc.steps: step2. Obtains the string value of a specified image property key. + * @tc.expected: step2. Obtains property success. + */ + std::string strValue; + errorCode = imageSource->GetImagePropertyString(0, GPS_LATITUDE, strValue); + HiLog::Debug(LABEL_TEST, "GPS_LATITUDE is %{public}s.", strValue.c_str()); + ASSERT_EQ(errorCode, SUCCESS); + + errorCode = imageSource->GetImagePropertyString(0, GPS_LONGITUDE, strValue); + HiLog::Debug(LABEL_TEST, "GPS_LONGITUDE is %{public}s.", strValue.c_str()); + ASSERT_EQ(errorCode, SUCCESS); + + errorCode = imageSource->GetImagePropertyString(0, GPS_LATITUDE_REF, strValue); + HiLog::Debug(LABEL_TEST, "GPS_LATITUDE_REF is %{public}s.", strValue.c_str()); + ASSERT_EQ(errorCode, SUCCESS); + + errorCode = imageSource->GetImagePropertyString(0, GPS_LONGITUDE_REF, strValue); + HiLog::Debug(LABEL_TEST, "GPS_LONGITUDE_REF is %{public}s.", strValue.c_str()); + ASSERT_EQ(errorCode, SUCCESS); + /** + * @tc.steps: step3. Obtains the string value of a specified image property key. + * @tc.expected: step3. Obtains property return ERR_IMAGE_INVALID_PARAMETER error. + */ + errorCode = imageSource->GetImagePropertyString(0, ORIENTATION, strValue); + ASSERT_EQ(errorCode, ERR_IMAGE_INVALID_PARAMETER); +} diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_png_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_png_test.cpp old mode 100644 new mode 100755 index 9ef973f91a4ab992d1014db0bd48e2d805337c4e..7710ab04d0f37cf5d8ee651ee127fe78f7ee3895 --- a/frameworks/innerkitsimpl/test/unittest/image_source_png_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_png_test.cpp @@ -59,7 +59,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode001, TestSize.Level3) SourceOptions opts; opts.formatHint = "image/png"; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.png", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.png", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); /** @@ -75,7 +75,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode001, TestSize.Level3) * @tc.steps: step3. compress the pixel map to png file. * @tc.expected: step3. pack pixel map success and the png compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_file.png", std::move(pixelMap)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_file.png", std::move(pixelMap)); ASSERT_NE(packSize, 0); } @@ -93,7 +93,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode002, TestSize.Level3) uint32_t errorCode = 0; SourceOptions opts; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.png", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.png", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); } @@ -113,7 +113,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode003, TestSize.Level3) SourceOptions opts; opts.formatHint = "image/png"; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.png", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.png", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); } @@ -132,7 +132,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode004, TestSize.Level3) uint32_t errorCode = 0; SourceOptions opts; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/png/test.png", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/png/test.png", opts, errorCode); ASSERT_EQ(errorCode, ERR_IMAGE_SOURCE_DATA); ASSERT_EQ(imageSource.get(), nullptr); } @@ -149,11 +149,11 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode005, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool ret = ImageUtils::GetFileSize("/sdcard/multimedia/image/test.png", bufferSize); + bool ret = ImageUtils::GetFileSize("sdcard/multimedia/image/test.png", bufferSize); ASSERT_EQ(ret, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - ret = ReadFileToBuffer("/sdcard/multimedia/image/test.png", buffer, bufferSize); + ret = ReadFileToBuffer("sdcard/multimedia/image/test.png", buffer, bufferSize); ASSERT_EQ(ret, true); uint32_t errorCode = 0; SourceOptions opts; @@ -173,7 +173,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode005, TestSize.Level3) * @tc.steps: step3. compress the pixel map to jpeg file. * @tc.expected: step3. pack pixel map success and the jpeg compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_file.jpg", std::move(pixelMap)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_file.jpg", std::move(pixelMap)); ASSERT_NE(packSize, 0); free(buffer); } @@ -190,7 +190,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode006, TestSize.Level3) * @tc.expected: step1. create image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -227,11 +227,11 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode007, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool fileRet = ImageUtils::GetFileSize("/sdcard/multimedia/image/test.png", bufferSize); + bool fileRet = ImageUtils::GetFileSize("sdcard/multimedia/image/test.png", bufferSize); ASSERT_EQ(fileRet, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - fileRet = ReadFileToBuffer("/sdcard/multimedia/image/test.png", buffer, bufferSize); + fileRet = ReadFileToBuffer("sdcard/multimedia/image/test.png", buffer, bufferSize); ASSERT_EQ(fileRet, true); uint32_t errorCode = 0; IncrementalSourceOptions incOpts; @@ -272,7 +272,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode007, TestSize.Level3) * @tc.steps: step3. compress the pixel map to jpeg file. * @tc.expected: step3. pack pixel map success and the jpeg compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_file.jpg", std::move(incPixelMap)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_file.jpg", std::move(incPixelMap)); ASSERT_NE(packSize, 0); free(buffer); } @@ -291,7 +291,7 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode008, TestSize.Level3) uint32_t errorCode = 0; SourceOptions opts; std::unique_ptr imageSource = - ImageSource::CreateImageSource("/sdcard/multimedia/image/test.png", opts, errorCode); + ImageSource::CreateImageSource("sdcard/multimedia/image/test.png", opts, errorCode); ASSERT_EQ(errorCode, SUCCESS); ASSERT_NE(imageSource.get(), nullptr); /** @@ -313,9 +313,9 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode008, TestSize.Level3) * @tc.steps: step4. compress the pixlel map to jpeg file. * @tc.expected: step4. pack pixel map success and the jpeg compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_png_file1.jpg", std::move(pixelMap1)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_png_file1.jpg", std::move(pixelMap1)); ASSERT_NE(packSize, 0); - packSize = PackImage("/sdcard/multimedia/image/test_png_file2.jpg", std::move(pixelMap2)); + packSize = PackImage("sdcard/multimedia/image/test_png_file2.jpg", std::move(pixelMap2)); ASSERT_NE(packSize, 0); } @@ -331,11 +331,11 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode009, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool fileRet = ImageUtils::GetFileSize("/sdcard/multimedia/image/test.png", bufferSize); + bool fileRet = ImageUtils::GetFileSize("sdcard/multimedia/image/test.png", bufferSize); ASSERT_EQ(fileRet, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - fileRet = ReadFileToBuffer("/sdcard/multimedia/image/test.png", buffer, bufferSize); + fileRet = ReadFileToBuffer("sdcard/multimedia/image/test.png", buffer, bufferSize); ASSERT_EQ(fileRet, true); uint32_t errorCode = 0; IncrementalSourceOptions incOpts; @@ -380,9 +380,9 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode009, TestSize.Level3) * @tc.steps: step4. compress the pixel map to jpeg file. * @tc.expected: step4. pack bitmap success and the jpeg compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_png_inc1.jpg", std::move(incPixelMap)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_png_inc1.jpg", std::move(incPixelMap)); ASSERT_NE(packSize, 0); - packSize = PackImage("/sdcard/multimedia/image/test_png_onetime1.jpg", std::move(pixelMap1)); + packSize = PackImage("sdcard/multimedia/image/test_png_onetime1.jpg", std::move(pixelMap1)); ASSERT_NE(packSize, 0); free(buffer); } @@ -399,11 +399,11 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode010, TestSize.Level3) * @tc.expected: step1. create image source success. */ size_t bufferSize = 0; - bool fileRet = ImageUtils::GetFileSize("/sdcard/multimedia/image/test.png", bufferSize); + bool fileRet = ImageUtils::GetFileSize("sdcard/multimedia/image/test.png", bufferSize); ASSERT_EQ(fileRet, true); uint8_t *buffer = (uint8_t *)malloc(bufferSize); ASSERT_NE(buffer, nullptr); - fileRet = ReadFileToBuffer("/sdcard/multimedia/image/test.png", buffer, bufferSize); + fileRet = ReadFileToBuffer("sdcard/multimedia/image/test.png", buffer, bufferSize); ASSERT_EQ(fileRet, true); uint32_t errorCode = 0; IncrementalSourceOptions incOpts; @@ -453,9 +453,9 @@ HWTEST_F(ImageSourcePngTest, PngImageDecode010, TestSize.Level3) * @tc.steps: step4. compress the pixel map to jpeg file. * @tc.expected: step4. pack pixel map success and the jpeg compress file size equals to PNG_PACK_SIZE. */ - int64_t packSize = PackImage("/sdcard/multimedia/image/test_png_inc2.jpg", std::move(incPixelMap)); + int64_t packSize = PackImage("sdcard/multimedia/image/test_png_inc2.jpg", std::move(incPixelMap)); ASSERT_NE(packSize, 0); - packSize = PackImage("/sdcard/multimedia/image/test_png_onetime2.jpg", std::move(pixelMap1)); + packSize = PackImage("sdcard/multimedia/image/test_png_onetime2.jpg", std::move(pixelMap1)); ASSERT_NE(packSize, 0); free(buffer); } @@ -472,7 +472,7 @@ HWTEST_F(ImageSourcePngTest, PngImageCrop001, TestSize.Level3) * @tc.expected: step1. create png image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -508,7 +508,7 @@ HWTEST_F(ImageSourcePngTest, PngNinePatch001, TestSize.Level3) * @tc.expected: step1. create png image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.9.png", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.9.png", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -544,7 +544,7 @@ HWTEST_F(ImageSourcePngTest, PngNinePatch002, TestSize.Level3) * @tc.expected: step1. create png image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.png", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -579,7 +579,7 @@ HWTEST_F(ImageSourcePngTest, PngNinePatch003, TestSize.Level3) * @tc.expected: step1. create png image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test.9.png", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test.9.png", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_raw_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_raw_test.cpp old mode 100644 new mode 100755 index b12ddca612699a50d509976b9754225ef5c493ae..f64a303b27b2d2de6840e7a6ccc8071684f1f67a --- a/frameworks/innerkitsimpl/test/unittest/image_source_raw_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_raw_test.cpp @@ -29,7 +29,7 @@ using namespace testing::ext; using namespace OHOS::Media; using namespace OHOS::HiviewDFX; -static const std::string IMAGE_INPUT_DNG_PATH = "/sdcard/multimedia/image/test.dng"; +static const std::string IMAGE_INPUT_DNG_PATH = "sdcard/multimedia/image/test.dng"; static const std::string IMAGE_OUTPUT_DNG_FILE_PATH = "/data/test/test_raw_file.jpg"; class ImageSourceRawTest : public testing::Test { @@ -377,4 +377,4 @@ HWTEST_F(ImageSourceRawTest, RawImageDecode010, TestSize.Level3) std::unique_ptr pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode); ASSERT_NE(errorCode, SUCCESS); ASSERT_EQ(pixelMap.get(), nullptr); -} \ No newline at end of file +} diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_wbmp_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_wbmp_test.cpp old mode 100644 new mode 100755 index 802a17b22e6612c8237233f93460db4c47170e3e..4916e3b15d098aa92b250e57d439a18fe80fd0d1 --- a/frameworks/innerkitsimpl/test/unittest/image_source_wbmp_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_wbmp_test.cpp @@ -30,7 +30,7 @@ using namespace testing::ext; using namespace OHOS::Media; using namespace OHOS::HiviewDFX; -static const std::string IMAGE_INPUT_WBMP_PATH = "/sdcard/multimedia/image/test.wbmp"; +static const std::string IMAGE_INPUT_WBMP_PATH = "sdcard/multimedia/image/test.wbmp"; class ImageSourceWbmpTest : public testing::Test { public: @@ -337,4 +337,4 @@ HWTEST_F(ImageSourceWbmpTest, WbmpImageDecode010, TestSize.Level3) std::unique_ptr pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode); ASSERT_NE(errorCode, SUCCESS); ASSERT_EQ(pixelMap.get(), nullptr); -} \ No newline at end of file +} diff --git a/frameworks/innerkitsimpl/test/unittest/image_source_webp_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_source_webp_test.cpp old mode 100644 new mode 100755 index fa1b8d0d8b9a291fa45db63c373d9bd1be14250b..44927a4a8ac71e73bbfba1817abe5c5bae8a4130 --- a/frameworks/innerkitsimpl/test/unittest/image_source_webp_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_source_webp_test.cpp @@ -34,8 +34,8 @@ static constexpr OHOS::HiviewDFX::HiLogLabel LABEL_TEST = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "ImageSourceWebpTest" }; static constexpr uint32_t DEFAULT_DELAY_UTIME = 10000; // 10 ms. -static const std::string IMAGE_INPUT_WEBP_PATH = "/sdcard/multimedia/image/test_large.webp"; -static const std::string IMAGE_INPUT_HW_JPEG_PATH = "/sdcard/multimedia/image/test_hw.jpg"; +static const std::string IMAGE_INPUT_WEBP_PATH = "sdcard/multimedia/image/test_large.webp"; +static const std::string IMAGE_INPUT_HW_JPEG_PATH = "sdcard/multimedia/image/test_hw.jpg"; static const std::string IMAGE_OUTPUT_JPEG_FILE_PATH = "/data/test/test_webp_file.jpg"; static const std::string IMAGE_OUTPUT_JPEG_BUFFER_PATH = "/data/test/test_webp_buffer.jpg"; static const std::string IMAGE_OUTPUT_JPEG_ISTREAM_PATH = "/data/test/test_webp_istream.jpg"; @@ -508,7 +508,7 @@ HWTEST_F(ImageSourceWebpTest, WebpImageCrop001, TestSize.Level3) * @tc.expected: step1. create webp image source success. */ std::unique_ptr fs = std::make_unique(); - fs->open("/sdcard/multimedia/image/test_large.webp", std::fstream::binary | std::fstream::in); + fs->open("sdcard/multimedia/image/test_large.webp", std::fstream::binary | std::fstream::in); bool isOpen = fs->is_open(); ASSERT_EQ(isOpen, true); uint32_t errorCode = 0; @@ -534,4 +534,4 @@ HWTEST_F(ImageSourceWebpTest, WebpImageCrop001, TestSize.Level3) ASSERT_NE(pixelMap.get(), nullptr); EXPECT_EQ(200, pixelMap->GetWidth()); EXPECT_EQ(300, pixelMap->GetHeight()); -} \ No newline at end of file +} diff --git a/interfaces/innerkits/include/image_source.h b/interfaces/innerkits/include/image_source.h index 74195469120d406dd03dceaccfd76bb00124b39c..7b9dc38d8f5ff49c96456a726ec8a33f3dc52e47 100644 --- a/interfaces/innerkits/include/image_source.h +++ b/interfaces/innerkits/include/image_source.h @@ -159,6 +159,7 @@ public: NATIVEEXPORT void RemoveDecodeListener(DecodeListener *listener); NATIVEEXPORT bool IsIncrementalSource(); NATIVEEXPORT uint32_t GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value); + NATIVEEXPORT uint32_t GetImagePropertyString(uint32_t index, const std::string &key, std::string &value); NATIVEEXPORT const NinePatchInfo &GetNinePatchInfo() const; NATIVEEXPORT void SetMemoryUsagePreference(const MemoryUsagePreference preference); NATIVEEXPORT MemoryUsagePreference GetMemoryUsagePreference(); diff --git a/interfaces/innerkits/include/pixel_map.h b/interfaces/innerkits/include/pixel_map.h index 68a5a44b8b4bdb13abd023aec94a59b48f117717..eccacc2abca823a60e819d5427f49adcd4852b7a 100644 --- a/interfaces/innerkits/include/pixel_map.h +++ b/interfaces/innerkits/include/pixel_map.h @@ -120,6 +120,8 @@ public: NATIVEEXPORT bool Marshalling(Parcel &data) const override; NATIVEEXPORT static PixelMap *Unmarshalling(Parcel &data); private: + static constexpr size_t MAX_IMAGEDATA_SIZE = 128 * 1024 * 1024; // 128M + static constexpr size_t MIN_IMAGEDATA_SIZE = 32 * 1024; // 32k friend class ImageSource; static bool ALPHA8ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount); static bool RGB565ToARGB(const uint8_t *in, uint32_t inCount, uint32_t *out, uint32_t outCount); @@ -162,8 +164,14 @@ private: ? false : true; } - bool WriteFileDescriptor(Parcel &data, int fd) const; - static int ReadFileDescriptor(Parcel &data); + + static void ReleaseMemory(AllocatorType allocType, void *addr, void *context, uint32_t size); + bool WriteImageData(Parcel &parcel, size_t size) const; + static uint8_t *ReadImageData(Parcel &parcel, int32_t size); + static int ReadFileDescriptor(Parcel &parcel); + static bool WriteFileDescriptor(Parcel &parcel, int fd); + bool ReadImageInfo(Parcel &parcel, ImageInfo &imgInfo); + bool WriteImageInfo(Parcel &parcel) const; uint8_t *data_ = nullptr; // this info SHOULD be the final info for decoded pixelmap, not the original image info diff --git a/plugins/common/libs/BUILD.gn b/plugins/common/libs/BUILD.gn index 3e705a6be24c459cafafad3d11bd085f699d0d6c..9f45b2280c50ebe399529eebaef99beeb7253710 100644 --- a/plugins/common/libs/BUILD.gn +++ b/plugins/common/libs/BUILD.gn @@ -40,6 +40,8 @@ group("multimediaplugin") { # "image/libheifplugin:heifplugin", # "image/libheifplugin:heifpluginmetadata", + "image/libbmpplugin:bmpplugin", + "image/libbmpplugin:bmppluginmetadata", "image/libjpegplugin:jpegplugin", "image/libjpegplugin:jpegpluginmetadata", "image/libpngplugin:pngplugin", diff --git a/plugins/common/libs/image/formatagentplugin/src/plugin_export.cpp b/plugins/common/libs/image/formatagentplugin/src/plugin_export.cpp index 9b80719096b3d936164f74d970e6c3da43fbeb9b..ad8b053cea655349eb34638aaed20cbd24572321 100644 --- a/plugins/common/libs/image/formatagentplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/formatagentplugin/src/plugin_export.cpp @@ -27,7 +27,9 @@ #include "wbmp_format_agent.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibImageFormatAgent") +namespace { + const std::string PACKAGE_NAME = ("LibImageFormatAgent"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN @@ -41,14 +43,35 @@ PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::RawFormatAgent) PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::WbmpFormatAgent) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibImageFormatAgent" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} \ No newline at end of file diff --git a/plugins/common/libs/image/libbmpplugin/BUILD.gn b/plugins/common/libs/image/libbmpplugin/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..4bbdceeff66d7389ad81b36ebf047c7cdaa9ceec --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/BUILD.gn @@ -0,0 +1,94 @@ +# Copyright (C) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/multimedia/image_standard/ide/image_decode_config.gni") + +ohos_shared_library("bmpplugin") { + sources = [ + "//foundation/multimedia/image_standard/plugins/common/libs/image/libbmpplugin/src/bmp_decoder.cpp", + "//foundation/multimedia/image_standard/plugins/common/libs/image/libbmpplugin/src/bmp_stream.cpp", + "//foundation/multimedia/image_standard/plugins/common/libs/image/libbmpplugin/src/plugin_export.cpp", + ] + + include_dirs = [ + "//foundation/multimedia/utils/include", + "//foundation/multimedia/image_standard/plugins/manager/include", + "//foundation/multimedia/image_standard/plugins/manager/include/image", + "//foundation/multimedia/image_standard/plugins/manager/include/pluginbase", + "//foundation/multimedia/image_standard/plugins/common/libs/image/libbmpplugin/include", + "//foundation/multimedia/image_standard/interfaces/innerkits/include", + "//foundation/multimedia/image_standard/frameworks/innerkitsimpl/utils/include", + "//third_party/flutter/skia/include/core", + "//third_party/flutter/skia/include/codec", + "//third_party/flutter/skia", + ] + if (use_mingw_win) { + defines = image_decode_windows_defines + include_dirs += [ + "//foundation/multimedia/image_standard/mock/native/include", + "//foundation/multimedia/image_standard/mock/native/include/secure", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/codec", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/core", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/config/win", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/config", + ] + deps = [ + "//foundation/ace/ace_engine/build/third_party/flutter/skia:ace_skia_core", + "//foundation/graphic/ide/libs/skia:skia", + "//foundation/multimedia/image_standard/frameworks/innerkitsimpl/utils:image_utils_static", + "//foundation/multimedia/image_standard/mock/native:log_mock_static", + "//foundation/multimedia/image_standard/plugins/manager:pluginmanager_static", + ] + + #libs = [ "//foundation/multimedia/image/libskia.lib" ] + } else if (use_clang_mac) { + defines = image_decode_mac_defines + include_dirs += [ + "//foundation/multimedia/image_standard/mock/native/include", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/codec", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/core", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/config/mac", + "${asdk_dir}/static_library/${target_os}_${target_cpu}/include/external/skia/include/config", + "//utils/native/base/include", + ] + deps = [ + "//foundation/graphic/ide/libs/skia:skia", + "//foundation/multimedia/image_standard/frameworks/innerkitsimpl/utils:image_utils_static", + "//foundation/multimedia/image_standard/mock/native:log_mock_static", + "//foundation/multimedia/image_standard/plugins/manager:pluginmanager_static", + "//utils/native/base:utilsecurec", + ] + } else { + include_dirs += [ "//utils/native/base/include" ] + deps = [ + "//foundation/ace/ace_engine/build/third_party/flutter/skia:ace_skia_ohos", + "//foundation/multimedia/image_standard/frameworks/innerkitsimpl/utils:image_utils", + "//foundation/multimedia/image_standard/plugins/manager:pluginmanager", + "//utils/native/base:utils", + ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + + #aosp_deps = [ "shared_library:libhwui" ] + } + subsystem_name = "multimedia" + part_name = "multimedia_image_standard" +} + +ohos_prebuilt_etc("bmppluginmetadata") { + source = "bmpplugin.pluginmeta" + relative_install_dir = "multimediaplugin/image" + subsystem_name = "multimedia" + part_name = "multimedia_image_standard" +} diff --git a/plugins/common/libs/image/libbmpplugin/bmpplugin.pluginmeta b/plugins/common/libs/image/libbmpplugin/bmpplugin.pluginmeta new file mode 100755 index 0000000000000000000000000000000000000000..0ffc1cac68e8343cc6bf4f6ad4c875cfb288428b --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/bmpplugin.pluginmeta @@ -0,0 +1,25 @@ +{ + "packageName":"LibBmpPlugin", + "version":"1.0.0.0", + "targetVersion":"1.0.0.0", + "libraryPath":"libbmpplugin.z.so", + "classes": [ + { + "className":"OHOS::ImagePlugin::BmpDecoder", + "services": [ + { + "interfaceID":2, + "serviceType":0 + } + ], + "priority":100, + "capabilities": [ + { + "name":"encodeFormat", + "type":"string", + "value": "image/bmp" + } + ] + } + ] +} diff --git a/plugins/common/libs/image/libbmpplugin/include/bmp_decoder.h b/plugins/common/libs/image/libbmpplugin/include/bmp_decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..af5798c23fb699f757ce89e42863dea68d526ba3 --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/include/bmp_decoder.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BMP_DECODER_H +#define BMP_DECODER_H + +#include +#include +#include "SkCodec.h" +#include "abs_image_decoder.h" +#include "bmp_stream.h" +#include "hilog/log.h" +#include "log_tags.h" +#include "plugin_class_base.h" + +namespace OHOS { +namespace ImagePlugin { +enum class BmpDecodingState : int32_t { + UNDECIDED = 0, + SOURCE_INITED = 1, + BASE_INFO_PARSED = 2, + IMAGE_DECODING = 3, + IMAGE_ERROR = 4, + IMAGE_DECODED = 5 +}; + +class BmpDecoder : public AbsImageDecoder, public OHOS::MultimediaPlugin::PluginClassBase { +public: + BmpDecoder() = default; + virtual ~BmpDecoder() override {}; + void SetSource(InputDataStream &sourceStream) override; + void Reset() override; + uint32_t SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info) override; + uint32_t Decode(uint32_t index, DecodeContext &context) override; + uint32_t GetImageSize(uint32_t index, PlSize &size) override; + uint32_t PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context) override; + +private: + DISALLOW_COPY_AND_MOVE(BmpDecoder); + bool DecodeHeader(); + PlAlphaType ConvertToAlphaType(SkAlphaType alphaType); + SkColorType ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat); + uint32_t SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context); + uint32_t SetShareMemBuffer(uint64_t byteCount, DecodeContext &context); + InputDataStream *stream_ = nullptr; + std::unique_ptr codec_ = nullptr; + SkImageInfo info_; + SkColorType desireColor_ = kUnknown_SkColorType; + BmpDecodingState state_ = BmpDecodingState::UNDECIDED; +}; +} // namespace ImagePlugin +} // namespace OHOS + +#endif // BMP_DECODER_H diff --git a/plugins/common/libs/image/libbmpplugin/include/bmp_stream.h b/plugins/common/libs/image/libbmpplugin/include/bmp_stream.h new file mode 100644 index 0000000000000000000000000000000000000000..7502cabbbb87c4fcfa6587d3929cf45fb89b49cd --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/include/bmp_stream.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BMP_STREAM_H +#define BMP_STREAM_H + +#include +#include +#include "SkStream.h" +#include "hilog/log.h" +#include "input_data_stream.h" +#include "log_tags.h" +#include "nocopyable.h" + +namespace OHOS { +namespace ImagePlugin { +class BmpStream : public SkStream { +public: + BmpStream() = default; + explicit BmpStream(InputDataStream *stream); + virtual ~BmpStream() override {}; + /** + * Reads or skips size number of bytes. + * if buffer is null, skip size bytes, return how many bytes skipped. + * else copy size bytes into buffer, return how many bytes copied. + */ + size_t read(void *buffer, size_t size) override; + /** + * Peeks size number of bytes. + */ + size_t peek(void *buffer, size_t size) const override; + /** + * Returns true when all the bytes in the stream have been read. + */ + bool isAtEnd() const override; + +private: + DISALLOW_COPY_AND_MOVE(BmpStream); + ImagePlugin::InputDataStream *inputStream_ = nullptr; +}; +} // namespace ImagePlugin +} // namespace OHOS + +#endif // BMP_STREAM_H diff --git a/plugins/common/libs/image/libbmpplugin/src/bmp_decoder.cpp b/plugins/common/libs/image/libbmpplugin/src/bmp_decoder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbcc6913a60d0890963da728f3886915e4238cd5 --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/src/bmp_decoder.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bmp_decoder.h" +#include "image_utils.h" +#include "media_errors.h" +#include "securec.h" + +namespace OHOS { +namespace ImagePlugin { +using namespace OHOS::HiviewDFX; +using namespace Media; +using namespace std; +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "BmpDecoder" }; +namespace { +constexpr uint32_t BMP_IMAGE_NUM = 1; +} + +void BmpDecoder::SetSource(InputDataStream &sourceStream) +{ + stream_ = &sourceStream; + state_ = BmpDecodingState::SOURCE_INITED; +} + +void BmpDecoder::Reset() +{ + if (stream_ != nullptr) { + stream_->Seek(0); + } + codec_.release(); + info_.reset(); + desireColor_ = kUnknown_SkColorType; +} + +uint32_t BmpDecoder::GetImageSize(uint32_t index, PlSize &size) +{ + if (index >= BMP_IMAGE_NUM) { + HiLog::Error(LABEL, "GetImageSize failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM); + return ERR_IMAGE_INVALID_PARAMETER; + } + if (state_ < BmpDecodingState::SOURCE_INITED) { + HiLog::Error(LABEL, "GetImageSize failed, invalid state:%{public}d", state_); + return ERR_MEDIA_INVALID_OPERATION; + } + if (state_ >= BmpDecodingState::BASE_INFO_PARSED) { + size.width = info_.width(); + size.height = info_.height(); + return SUCCESS; + } + if (!DecodeHeader()) { + HiLog::Error(LABEL, "GetImageSize failed, decode header failed, state=%{public}d", state_); + return ERR_IMAGE_DECODE_HEAD_ABNORMAL; + } + size.width = info_.width(); + size.height = info_.height(); + state_ = BmpDecodingState::BASE_INFO_PARSED; + return SUCCESS; +} + +uint32_t BmpDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info) +{ + if (index >= BMP_IMAGE_NUM) { + HiLog::Error(LABEL, "SetDecodeOptions failed, invalid index:%{public}u, range:%{public}u", index, + BMP_IMAGE_NUM); + return ERR_IMAGE_INVALID_PARAMETER; + } + if (state_ < BmpDecodingState::SOURCE_INITED) { + HiLog::Error(LABEL, "SetDecodeOptions failed, invalid state %{public}d", state_); + return ERR_MEDIA_INVALID_OPERATION; + } + if (state_ >= BmpDecodingState::IMAGE_DECODING) { + Reset(); + state_ = BmpDecodingState::SOURCE_INITED; + } + if (state_ < BmpDecodingState::BASE_INFO_PARSED) { + if (!DecodeHeader()) { + HiLog::Error(LABEL, "GetImageSize failed, decode header failed, state=%{public}d", state_); + return ERR_IMAGE_DECODE_HEAD_ABNORMAL; + } + state_ = BmpDecodingState::BASE_INFO_PARSED; + } + PlPixelFormat desiredFormat = opts.desiredPixelFormat; + desireColor_ = ConvertToColorType(desiredFormat, info.pixelFormat); + info.size.width = info_.width(); + info.size.height = info_.height(); + info.alphaType = ConvertToAlphaType(info_.alphaType()); + state_ = BmpDecodingState::IMAGE_DECODING; + return SUCCESS; +} + +uint32_t BmpDecoder::SetShareMemBuffer(uint64_t byteCount, DecodeContext &context) +{ + int fd = AshmemCreate("BMP RawData", byteCount); + if (fd < 0) { + return ERR_SHAMEM_DATA_ABNORMAL; + } + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + if (result < 0) { + ::close(fd); + return ERR_SHAMEM_DATA_ABNORMAL; + } + void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + ::close(fd); + return ERR_SHAMEM_DATA_ABNORMAL; + } + context.pixelsBuffer.buffer = ptr; + void *fdBuffer = new int32_t(); + if (fdBuffer == nullptr) { + ::munmap(ptr, byteCount); + ::close(fd); + context.pixelsBuffer.buffer = nullptr; + return ERR_SHAMEM_DATA_ABNORMAL; + } + *static_cast(fdBuffer) = fd; + context.pixelsBuffer.context = fdBuffer; + context.pixelsBuffer.bufferSize = byteCount; + context.allocatorType = AllocatorType::SHARE_MEM_ALLOC; + context.freeFunc = nullptr; + return SUCCESS; +} + +uint32_t BmpDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context) +{ + if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) { +#if !defined(_WIN32) && !defined(_APPLE) + uint32_t res = SetShareMemBuffer(byteCount, context); + if (res != SUCCESS) { + return res; + } +#endif + } else { + if (byteCount <= 0) { + HiLog::Error(LABEL, "Decode failed, byteCount is invalid value"); + return ERR_MEDIA_INVALID_VALUE; + } + void *outputBuffer = malloc(byteCount); + if (outputBuffer == nullptr) { + HiLog::Error(LABEL, "Decode failed, alloc output buffer size:[%{public}llu] error", + static_cast(byteCount)); + return ERR_IMAGE_MALLOC_ABNORMAL; + } +#ifdef _WIN32 + memset(outputBuffer, 0, byteCount); +#else + if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) { + HiLog::Error(LABEL, "Decode failed, memset buffer failed"); + free(outputBuffer); + outputBuffer = nullptr; + return ERR_IMAGE_DECODE_FAILED; + } +#endif + context.pixelsBuffer.buffer = outputBuffer; + context.pixelsBuffer.bufferSize = byteCount; + context.pixelsBuffer.context = nullptr; + context.allocatorType = AllocatorType::HEAP_ALLOC; + context.freeFunc = nullptr; + } + return SUCCESS; +} + +uint32_t BmpDecoder::Decode(uint32_t index, DecodeContext &context) +{ + if (index >= BMP_IMAGE_NUM) { + HiLog::Error(LABEL, "Decode failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM); + return ERR_IMAGE_INVALID_PARAMETER; + } + if (codec_ == nullptr) { + HiLog::Error(LABEL, "Decode failed, codec is null"); + return ERR_IMAGE_DECODE_FAILED; + } + if (state_ != BmpDecodingState::IMAGE_DECODING) { + HiLog::Error(LABEL, "Decode failed, invalid state %{public}d", state_); + return ERR_MEDIA_INVALID_OPERATION; + } + + SkImageInfo dstInfo = info_.makeColorType(desireColor_); + if (ImageUtils::CheckMulOverflow(dstInfo.width(), dstInfo.height(), dstInfo.bytesPerPixel())) { + HiLog::Error(LABEL, "Decode failed, width:%{public}d, height:%{public}d is too large", + dstInfo.width(), dstInfo.height()); + return ERR_IMAGE_DECODE_FAILED; + } + if (context.pixelsBuffer.buffer == nullptr) { + uint64_t byteCount = static_cast(dstInfo.height()) * dstInfo.width() * dstInfo.bytesPerPixel(); + uint32_t res = SetContextPixelsBuffer(byteCount, context); + if (res != SUCCESS) { + return res; + } + } + uint8_t *dstBuffer = static_cast(context.pixelsBuffer.buffer); + size_t rowBytes = dstInfo.width() * dstInfo.bytesPerPixel(); + SkCodec::Result ret = codec_->getPixels(dstInfo, dstBuffer, rowBytes); + if (ret != SkCodec::kSuccess) { + HiLog::Error(LABEL, "Decode failed, get pixels failed, ret=%{public}d", ret); + state_ = BmpDecodingState::IMAGE_ERROR; + return ERR_IMAGE_DECODE_ABNORMAL; + } + state_ = BmpDecodingState::IMAGE_DECODED; + return SUCCESS; +} + +uint32_t BmpDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context) +{ + // currently not support increment decode + return ERR_IMAGE_DATA_UNSUPPORT; +} + +bool BmpDecoder::DecodeHeader() +{ + codec_ = SkCodec::MakeFromStream(make_unique(stream_)); + if (codec_ == nullptr) { + HiLog::Error(LABEL, "create codec from stream failed"); + return false; + } + info_ = codec_->getInfo(); + return true; +} + +PlAlphaType BmpDecoder::ConvertToAlphaType(SkAlphaType alphaType) +{ + switch (alphaType) { + case kOpaque_SkAlphaType: + return PlAlphaType::IMAGE_ALPHA_TYPE_OPAQUE; + case kPremul_SkAlphaType: + return PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL; + case kUnpremul_SkAlphaType: + return PlAlphaType::IMAGE_ALPHA_TYPE_UNPREMUL; + default: + HiLog::Error(LABEL, "known alpha type:%{public}d", alphaType); + break; + } + return PlAlphaType::IMAGE_ALPHA_TYPE_UNKNOWN; +} + +SkColorType BmpDecoder::ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat) +{ + switch (format) { + case PlPixelFormat::UNKNOWN: + case PlPixelFormat::RGBA_8888: { + outputFormat = PlPixelFormat::RGBA_8888; + return kRGBA_8888_SkColorType; + } + case PlPixelFormat::BGRA_8888: { + outputFormat = PlPixelFormat::BGRA_8888; + return kBGRA_8888_SkColorType; + } + case PlPixelFormat::ALPHA_8: { + SkColorType colorType = info_.colorType(); + if (colorType == kAlpha_8_SkColorType || (colorType == kGray_8_SkColorType && info_.isOpaque())) { + outputFormat = PlPixelFormat::ALPHA_8; + return kAlpha_8_SkColorType; + } + break; + } + case PlPixelFormat::RGB_565: { + if (info_.isOpaque()) { + outputFormat = PlPixelFormat::RGB_565; + return kRGB_565_SkColorType; + } + break; + } + default: { + break; + } + } + HiLog::Debug(LABEL, "unsupported convert to format:%{public}d, set default RGBA", format); + outputFormat = PlPixelFormat::RGBA_8888; + return kRGBA_8888_SkColorType; +} +} // namespace ImagePlugin +} // namespace OHOS \ No newline at end of file diff --git a/plugins/common/libs/image/libbmpplugin/src/bmp_stream.cpp b/plugins/common/libs/image/libbmpplugin/src/bmp_stream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6694bce8bed4098442a5bbe0b21624db89f8214e --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/src/bmp_stream.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bmp_stream.h" + +namespace OHOS { +namespace ImagePlugin { +using namespace OHOS::HiviewDFX; +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "BmpStream" }; +BmpStream::BmpStream(InputDataStream *stream) : inputStream_(stream) {} + +size_t BmpStream::read(void *buffer, size_t size) +{ + if (inputStream_ == nullptr) { + HiLog::Error(LABEL, "read failed, inputStream_ is null"); + return 0; + } + if (buffer == nullptr) { + size_t curPosition = static_cast(inputStream_->Tell()); + if (!inputStream_->Seek(curPosition + size)) { + HiLog::Error(LABEL, "read failed, curpositon=%{public}zu, skip size=%{public}zu", curPosition, size); + return 0; + } + return size; + } + uint32_t desireSize = static_cast(size); + uint32_t bufferSize = desireSize; + uint32_t readSize = desireSize; + if (!inputStream_->Read(desireSize, static_cast(buffer), bufferSize, readSize)) { + HiLog::Error(LABEL, "read failed, desire read size=%{public}u", desireSize); + return 0; + } + return readSize; +} + +size_t BmpStream::peek(void *buffer, size_t size) const +{ + if (inputStream_ == nullptr) { + HiLog::Error(LABEL, "peek failed, inputStream_ is null"); + return 0; + } + if (buffer == nullptr) { + HiLog::Error(LABEL, "peek failed, output buffer is null"); + return 0; + } + uint32_t desireSize = static_cast(size); + uint32_t bufferSize = desireSize; + uint32_t readSize = desireSize; + if (!inputStream_->Peek(desireSize, static_cast(buffer), bufferSize, readSize)) { + HiLog::Error(LABEL, "peek failed, desire peek size=%{public}u", desireSize); + return 0; + } + return readSize; +} + +bool BmpStream::isAtEnd() const +{ + if (inputStream_ == nullptr) { + HiLog::Error(LABEL, "get stream status failed, inputStream_ is null."); + return false; + } + size_t size = inputStream_->GetStreamSize(); + return (inputStream_->Tell() == size); +} +} // namespace ImagePlugin +} // namespace OHOS diff --git a/plugins/common/libs/image/libbmpplugin/src/plugin_export.cpp b/plugins/common/libs/image/libbmpplugin/src/plugin_export.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f96396f0675824766ebac4192570ce767b010b7e --- /dev/null +++ b/plugins/common/libs/image/libbmpplugin/src/plugin_export.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "plugin_export.h" +#include "bmp_decoder.h" +#include "hilog/log.h" +#include "log_tags.h" +#include "plugin_utils.h" + +// plugin package name same as metadata. +namespace { + const std::string PACKAGE_NAME = ("LibBmpPlugin"); +} + +// register implement classes of this plugin. +PLUGIN_EXPORT_REGISTER_CLASS_BEGIN +PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::BmpDecoder) +PLUGIN_EXPORT_REGISTER_CLASS_END + +using std::string; +using namespace OHOS::HiviewDFX; + +static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibBmpPlugin" }; + +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) + +// define the external interface of this plugin. +PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() +PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} \ No newline at end of file diff --git a/plugins/common/libs/image/libgifplugin/src/plugin_export.cpp b/plugins/common/libs/image/libgifplugin/src/plugin_export.cpp index 549b117b51dcfaf7e3598595d4965fbc20826cfb..bce66c2cc2d3a5a7f20f72aa6db6be6eb3efa73b 100644 --- a/plugins/common/libs/image/libgifplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/libgifplugin/src/plugin_export.cpp @@ -20,21 +20,44 @@ #include "gif_decoder.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibGifPlugin") +namespace { + const std::string PACKAGE_NAME = ("LibGifPlugin"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::GifDecoder) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibGifPlugin" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/common/libs/image/libheifplugin/src/plugin_export.cpp b/plugins/common/libs/image/libheifplugin/src/plugin_export.cpp index 9e32a21647bb65b5d7dbcd841ceba6e218665f25..b18be40a5c6ef679ccce86e2e1d47b9344c5b172 100644 --- a/plugins/common/libs/image/libheifplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/libheifplugin/src/plugin_export.cpp @@ -20,21 +20,44 @@ #include "plugin_utils.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibHeifPlugin") +namespace { + const std::string PACKAGE_NAME = ("LibHeifPlugin"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::HeifDecoder) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibHeifPlugin" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/common/libs/image/libjpegplugin/BUILD.gn b/plugins/common/libs/image/libjpegplugin/BUILD.gn index 593d55dbec497da7bbcf3601f7b3ce4533c712a3..5fe48517747d59b646cefee2e06023305bd93941 100644 --- a/plugins/common/libs/image/libjpegplugin/BUILD.gn +++ b/plugins/common/libs/image/libjpegplugin/BUILD.gn @@ -16,6 +16,7 @@ import("//foundation/multimedia/image_standard/ide/image_decode_config.gni") ohos_shared_library("jpegplugin") { sources = [ + "//foundation/multimedia/image_standard/plugins/common/libs/image/libjpegplugin/src/exif.cpp", "//foundation/multimedia/image_standard/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp", "//foundation/multimedia/image_standard/plugins/common/libs/image/libjpegplugin/src/jpeg_utils.cpp", "//foundation/multimedia/image_standard/plugins/common/libs/image/libjpegplugin/src/plugin_export.cpp", @@ -41,25 +42,25 @@ ohos_shared_library("jpegplugin") { include_dirs += [ "//foundation/multimedia/image_standard/mock/native/include", - "//third_party/libjpeg", + "//third_party/flutter/skia/third_party/libjpeg-turbo", ] deps = [ + "//foundation/ace/ace_engine/build/third_party/flutter/libjpeg:ace_libjpeg", "//foundation/multimedia/image_standard/interfaces/innerkits:image_static", "//foundation/multimedia/image_standard/mock/native:utils_mock_static", "//foundation/multimedia/image_standard/plugins/manager:pluginmanager_static", - "//third_party/libjpeg:libjpeg_static", ] } else if (use_clang_mac) { defines = image_decode_mac_defines include_dirs += [ "//foundation/multimedia/image_standard/mock/native/include", - "//third_party/libjpeg", + "//third_party/flutter/skia/third_party/libjpeg-turbo", ] deps = [ + "//foundation/ace/ace_engine/build/third_party/flutter/libjpeg:ace_libjpeg", "//foundation/multimedia/image_standard/interfaces/innerkits:image_static", "//foundation/multimedia/image_standard/mock/native:utils_mock_static", "//foundation/multimedia/image_standard/plugins/manager:pluginmanager_static", - "//third_party/libjpeg:libjpeg_static", ] } else { defines = [ "DUAL_ADAPTER" ] @@ -67,16 +68,17 @@ ohos_shared_library("jpegplugin") { include_dirs += [ "//utils/native/base/include" ] sources += [ "//foundation/multimedia/image_standard/plugins/common/libs/image/libjpegplugin/src/jpeg_encoder.cpp" ] deps = [ + #"//third_party/flutter/skia/third_party/libjpeg-turbo:libjpeg", + "//foundation/ace/ace_engine/build/third_party/flutter/libjpeg:ace_libjpeg", "//foundation/multimedia/image_standard/interfaces/innerkits:image_native", "//foundation/multimedia/image_standard/plugins/manager:pluginmanager", - "//third_party/libjpeg:libjpeg_static", "//utils/native/base:utils", ] if (DUAL_ADAPTER) { } else { - deps += [ "//third_party/libjpeg:libjpeg_static" ] - include_dirs += [ "//third_party/libjpeg" ] + deps += [ "//foundation/ace/ace_engine/build/third_party/flutter/libjpeg:ace_libjpeg" ] + include_dirs += [ "//third_party/flutter/skia/third_party/libjpeg-turbo" ] } external_deps = [ "hiviewdfx_hilog_native:libhilog" ] diff --git a/plugins/common/libs/image/libjpegplugin/include/exif.h b/plugins/common/libs/image/libjpegplugin/include/exif.h new file mode 100644 index 0000000000000000000000000000000000000000..4174a998102df4152a68d76c4b53e730e773d899 --- /dev/null +++ b/plugins/common/libs/image/libjpegplugin/include/exif.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __EXIF_H +#define __EXIF_H + +#include +#include "hilog/log.h" +#include "log_tags.h" + +using std::string; +// IF Entry +struct IFEntry { + // Raw fields + unsigned short tag; + unsigned short format; + unsigned data; + unsigned length; + + // Parsed fields + string val_string; + unsigned short val_short; + unsigned val_long; + double val_rational; + unsigned char val_byte; +}; +// +// Class responsible for storing and parsing EXIF information from a JPEG blob +// +class EXIFInfo { +public: + // Parsing function for an entire JPEG image buffer. + // + // PARAM 'data': A pointer to a JPEG image. + // PARAM 'length': The length of the JPEG image. + // RETURN: PARSE_EXIF_SUCCESS (0) on succes with 'result' filled out + // error code otherwise, as defined by the PARSE_EXIF_ERROR_* macros + int ParseFrom(const unsigned char *data, unsigned length); + int ParseFrom(const std::string &data); + void setLatitude(const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, + unsigned data); + void setLongitude(const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, + unsigned data); + void setIFEntryValue(IFEntry result); + void setSubIFEntryValue(IFEntry result); + void setSubIFEntryValueExtend(IFEntry result); + void setGpsEntryValue(unsigned short tag, unsigned short format, unsigned length, unsigned data, + const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, unsigned entry_offs); + int ParseFromEXIFSegment(const unsigned char *buf, unsigned len); + int ParseExifIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned exif_ifd_offset, unsigned &exif_sub_ifd_offset, + unsigned &gps_sub_ifd_offset); + int ParseGpsSubIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned gps_sub_ifd_offset); + int ParseEXIFSubIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned exif_sub_ifd_offset); + // Set all data members to default values. + void Clear(); + + // Data fields filled out by parseFrom() + char ByteAlign; // 0 = Motorola byte alignment, 1 = Intel + std::string ImageDescription; // Image description + std::string Make; // Camera manufacturer's name + std::string Model; // Camera model + unsigned short Orientation; // Image orientation, start of data corresponds to + // 0: unspecified in EXIF data + // 1: upper left of image + // 3: lower right of image + // 6: upper right of image + // 8: lower left of image + // 9: undefined + unsigned short BitsPerSample; // Number of bits per component + std::string Software; // Software used + std::string DateTime; // File change date and time + std::string DateTimeOriginal; // Original file date and time (may not exist) + std::string DateTimeDigitized; // Digitization date and time (may not exist) + std::string SubSecTimeOriginal; // Sub-second time that original picture was taken + std::string Copyright; // File copyright information + double ExposureTime; // Exposure time in seconds + double FNumber; // F/stop + unsigned short ISOSpeedRatings; // ISO speed + double ShutterSpeedValue; // Shutter speed (reciprocal of exposure time) + double ExposureBiasValue; // Exposure bias value in EV + double SubjectDistance; // Distance to focus point in meters + double FocalLength; // Focal length of lens in millimeters + unsigned short FocalLengthIn35mm; // Focal length in 35mm film + char Flash; // 0 = no flash, 1 = flash used + unsigned short MeteringMode; // Metering mode + // 1: average + // 2: center weighted average + // 3: spot + // 4: multi-spot + // 5: multi-segment + unsigned ImageWidth; // Image width reported in EXIF data + unsigned ImageHeight; // Image height reported in EXIF data + struct Geolocation_t { // GPS information embedded in file + double Latitude; // Image latitude expressed as decimal + double Longitude; // Image longitude expressed as decimal + double Altitude; // Altitude in meters, relative to sea level + char AltitudeRef; // 0 = above sea level, -1 = below sea level + struct Coord_t { + double degrees; + double minutes; + double seconds; + char direction; + } LatComponents, LonComponents; // Latitude, Longitude expressed in deg/min/sec + } GeoLocation; + EXIFInfo() { + Clear(); + } +}; + +#define PARSE_EXIF_SUCCESS 0 +#define PARSE_EXIF_ERROR_NO_JPEG 10001 +#define PARSE_EXIF_ERROR_NO_EXIF 10002 +#define PARSE_EXIF_ERROR_UNKNOWN_BYTEALIGN 10003 +#define PARSE_EXIF_ERROR_CORRUPT 10004 + +#define BUFFER_OFFSET_0 0 +#define BUFFER_OFFSET_1 1 +#define BUFFER_OFFSET_2 2 +#define BUFFER_OFFSET_3 3 +#define BUFFER_OFFSET_4 4 +#define BUFFER_OFFSET_8 8 +#define BUFFER_OFFSET_16 16 +#define BUFFER_OFFSET_24 24 + +#endif \ No newline at end of file diff --git a/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h b/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h index 9e5c2dc3ccbb8bff234154b62508a6327d643a6f..76210dfabc2cdc58b4ab86284d6b414e9afd036f 100644 --- a/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h +++ b/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h @@ -26,6 +26,7 @@ #include "log_tags.h" #include "plugin_class_base.h" #include "plugin_server.h" +#include "exif.h" namespace OHOS { namespace ImagePlugin { @@ -50,9 +51,11 @@ public: uint32_t Decode(uint32_t index, DecodeContext &context) override; uint32_t GetImageSize(uint32_t index, PlSize &size) override; uint32_t PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context) override; - + uint32_t GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value) override; + uint32_t GetImagePropertyString(uint32_t index, const std::string &key, std::string &value) override; private: DISALLOW_COPY_AND_MOVE(JpegDecoder); + int ExifPrintMethod(); J_COLOR_SPACE GetDecodeFormat(PlPixelFormat format, PlPixelFormat &outputFormat); void CreateHwDecompressor(); uint32_t DoSwDecode(DecodeContext &context); @@ -73,6 +76,7 @@ private: uint32_t streamPosition_ = 0; // may be changed by other decoders, record it and restore if needed. PlPixelFormat outputFormat_ = PlPixelFormat::UNKNOWN; PixelDecodeOptions opts_; + EXIFInfo exifInfo_; }; } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libjpegplugin/include/jpeg_utils.h b/plugins/common/libs/image/libjpegplugin/include/jpeg_utils.h index 51ac52fe0aabb7ae3eef959e434b9e4f520f33aa..163df9bc4a0bf6573ef92cfdd440556a4f9aeb1c 100644 --- a/plugins/common/libs/image/libjpegplugin/include/jpeg_utils.h +++ b/plugins/common/libs/image/libjpegplugin/include/jpeg_utils.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "hilog/log.h" #include "input_data_stream.h" #include "jerror.h" @@ -74,6 +75,7 @@ void TermSrcStream(j_decompress_ptr dinfo); void InitDstStream(j_compress_ptr cinfo); boolean EmptyOutputBuffer(j_compress_ptr cinfo); void TermDstStream(j_compress_ptr cinfo); +std::string DoubleToString(double num); } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libjpegplugin/src/exif.cpp b/plugins/common/libs/image/libjpegplugin/src/exif.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8518df244dfa3a6fdadd8a066f68c4952679927b --- /dev/null +++ b/plugins/common/libs/image/libjpegplugin/src/exif.cpp @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "exif.h" + +using std::string; + +namespace { + using namespace OHOS::HiviewDFX; + constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "Exif" }; + + //constexpr uint32_t EXIF_MARKER_SIZE = 2; + //constexpr uint32_t EXIF_MARKER_LENGTH = 2; + //constexpr uint8_t EXIF_MARKER_LENGTH_0_OFFSET = 0; + //constexpr uint8_t EXIF_MARKER_LENGTH_1_OFFSET = 1; + //constexpr uint32_t EXIF_MARKER_LENGTH_SHIFT = 8; + constexpr uint8_t EXIF_MARKER_PREFIX_OFFSET = 0; + constexpr uint8_t EXIF_MARKER_CODE_OFFSET = 1; + constexpr uint8_t EXIF_MARKER_PREFIX = 0XFF; + constexpr uint8_t EXIF_MARKER_SOI = 0XD8; + constexpr uint8_t EXIF_MARKER_HEADER = 0XE1; + //constexpr uint8_t EXIF_MARKER_SOS = 0XDA; + //constexpr uint8_t EXIF_MARKER_RST = 0XD0; + //constexpr uint8_t EXIF_MARKER_RST0 = 0XD0; + //constexpr uint8_t EXIF_MARKER_RSTN = 0XD7; + //constexpr uint8_t EXIF_MARKER_APP = 0XE0; + //constexpr uint8_t EXIF_MARKER_APP0 = 0XE0; + //constexpr uint8_t EXIF_MARKER_APPN = 0XEF; + + constexpr uint16_t TAG_BITS_PER_SAMPLE = 0x102; // Bits per sample + constexpr uint16_t TAG_IMAGE_DESCRIPTION = 0x10E; // Image description + constexpr uint16_t TAG_DIGICAM_MAKE = 0x10F; // Digicam make + constexpr uint16_t TAG_DIGICAM_MODEL = 0x110; // Digicam model + constexpr uint16_t TAG_ORIENTATION_OF_IMAGE = 0x112; // Orientation of image + constexpr uint16_t TAG_SOFTWARE = 0x131; // Software used for image + constexpr uint16_t TAG_DATE_TIME = 0x132; // EXIF/TIFF date/time of image modification + constexpr uint16_t TAG_COPYRIGHT_INFO = 0x8298; // Copyright information + constexpr uint16_t TAG_GPS_IFS_OFFSET = 0x8825; // GPS IFS offset + constexpr uint16_t TAG_EXIF_SUB_IFD_OFFSET = 0x8769; // EXIF SubIFD offset + + + constexpr uint16_t TAG_EXPOSURE_TIME = 0x829a; // Exposure time in seconds + constexpr uint16_t TAG_FNUMBER = 0x829d; // FNumber + constexpr uint16_t TAG_ISO_SPEED_RATING = 0x8827; // ISO Speed Rating + constexpr uint16_t TAG_ORIGINAL_DATE_TIME = 0x9003; // Original date and time + constexpr uint16_t TAG_DIGITIZATION_DATE_TIME = 0x9004; // Digitization date and time + constexpr uint16_t TAG_SHUTTER_SPEED_VALUE = 0x9201; // Shutter speed value + constexpr uint16_t TAG_EXPOSURE_BIAS_VALUE = 0x9204; // Exposure bias value + constexpr uint16_t TAG_SUBJECT_DISTANCE = 0x9206; // Subject distance + constexpr uint16_t TAG_FLASH = 0x9209; // Flash used + constexpr uint16_t TAG_FOCAL_LENGTH = 0x920a; // Focal length + constexpr uint16_t TAG_METERING_MODE = 0x9207; // Metering mode + constexpr uint16_t TAG_SUBSECOND_ORIGINAL_TIME = 0x9291; // Subsecond original time + constexpr uint16_t TAG_EXIF_IMAGE_WIDTH = 0xa002; // EXIF Image width + constexpr uint16_t TAG_EXIF_IMAGE_HEIGHT = 0xa003; // EXIF Image height + constexpr uint16_t TAG_FOCAL_LENGTH_IN_35MM = 0xa405; // Focal length in 35mm film + + constexpr uint8_t T_GPS_NOS = 1; // GPS north or south + constexpr uint8_t T_GPS_LAT = 2; // GPS latitude + constexpr uint8_t T_GPS_EOW = 3; // GPS east or west + constexpr uint8_t T_GPS_LON = 4; // GPS longitude + constexpr uint8_t T_GPS_ALT_REF = 5; // GPS altitude reference (below or above sea level) + constexpr uint8_t T_GPS_ALT = 6; // GPS altitude reference + + constexpr uint8_t FORMAT_UNSIGNED_BYTE = 1; + constexpr uint8_t FORMAT_ASCII_STRING = 2; //ascii strings + constexpr uint8_t FORMAT_UNSIGNED_SHORT = 3; //unsigned short + constexpr uint8_t FORMAT_UNSIGNED_LONG = 4; //unsigned long + constexpr uint8_t FORMAT_UNSIGNED_RATIONAL = 5; //unsigned rational + //constexpr uint8_t FORMAT_SIGNED_BYTE = 6; //signed byte + constexpr uint8_t FORMAT_UNDEFINED = 7; //undefined + //constexpr uint8_t FORMAT_SIGNED_SHORT = 8; //signed short + constexpr uint8_t FORMAT_SIGNED_LONG = 9; //signed long + constexpr uint8_t FORMAT_SIGNED_RATIONAL = 10; //signed rational + //constexpr uint8_t FORMAT_SINGLE_FLOAT = 11; //single float + //constexpr uint8_t FORMAT_DOUBLE_FLOAT = 12; //double float + + constexpr uint8_t FORMAT_DEFAULT_VALUE = 0xFF; + // 2 bytes: tag number (data field) + // 2 bytes: data format + // 4 bytes: number of components + // 4 bytes: data value or offset to data value + constexpr uint8_t OFFSET_1 = 1; + constexpr uint8_t OFFSET_2 = 2; + constexpr uint8_t OFFSET_4 = 4; + constexpr uint8_t OFFSET_6 = 6; + constexpr uint8_t OFFSET_8 = 8; + //constexpr uint8_t OFFSET_10 = 10; + constexpr uint8_t OFFSET_12 = 12; + constexpr uint8_t OFFSET_16 = 16; + + constexpr char WEST = 'W'; + constexpr char SOUTH = 'S'; + constexpr char CHAR_I = 'I'; + constexpr char CHAR_M = 'M'; + + // Helper functions + unsigned int parseLong(const unsigned char *buf, bool intel) { + if (intel) + return ((unsigned)buf[BUFFER_OFFSET_3] << BUFFER_OFFSET_24) | + ((unsigned)buf[BUFFER_OFFSET_2] << BUFFER_OFFSET_16) | + ((unsigned)buf[BUFFER_OFFSET_1] << BUFFER_OFFSET_8) | + buf[BUFFER_OFFSET_0]; + + return ((unsigned)buf[BUFFER_OFFSET_0] << BUFFER_OFFSET_24) | + ((unsigned)buf[BUFFER_OFFSET_1] << BUFFER_OFFSET_16) | + ((unsigned)buf[BUFFER_OFFSET_2] << BUFFER_OFFSET_8) | + buf[BUFFER_OFFSET_3]; + } + + unsigned short parseShort(const unsigned char *buf, bool intel) { + if (intel) + return ((unsigned) buf[BUFFER_OFFSET_1]<< BUFFER_OFFSET_8) | buf[BUFFER_OFFSET_0]; + return ((unsigned) buf[BUFFER_OFFSET_0]<< BUFFER_OFFSET_8) | buf[BUFFER_OFFSET_1]; + } + + string parseEXIFString(const unsigned char *buf, + const unsigned num_components, + const unsigned data, + const unsigned base, + const unsigned len) { + string value; + if (num_components <= 4) + value.assign( (const char*)&data, num_components ); + else { + if (base+data+num_components <= len) + value.assign( (const char*)(buf+base+data), num_components ); + } + return value; + } + + double parseEXIFRational(const unsigned char *buf, bool intel) { + double numerator = 0; + double denominator = 1; + + numerator = (double) parseLong(buf, intel); + denominator= (double) parseLong(buf+4, intel); + if(denominator < 1e-20) + return 0; + return numerator/denominator; + } + + IFEntry parseIFEntry(const unsigned char *buf, + const unsigned offs, + const bool alignIntel, + const unsigned base, + const unsigned len) { + IFEntry result; + + // Each directory entry is composed of: + // 2 bytes: tag number (data field) + // 2 bytes: data format + // 4 bytes: number of components + // 4 bytes: data value or offset to data value + result.tag = parseShort(buf + offs, alignIntel); + result.format = parseShort(buf + offs + OFFSET_2, alignIntel); + result.length = parseLong(buf + offs + OFFSET_4, alignIntel); + result.data = parseLong(buf + offs + OFFSET_8, alignIntel); + + // Parse value in specified format + switch (result.format) { + case FORMAT_UNSIGNED_BYTE: + result.val_byte = (unsigned char) *(buf + offs + OFFSET_8); + break; + case FORMAT_ASCII_STRING: + result.val_string = parseEXIFString(buf, result.length, result.data, base, len); + break; + case FORMAT_UNSIGNED_SHORT: + result.val_short = parseShort((const unsigned char *) buf + offs + OFFSET_8, alignIntel); + break; + case FORMAT_UNSIGNED_LONG: + result.val_long = result.data; + break; + case FORMAT_UNSIGNED_RATIONAL: + if (base + result.data + OFFSET_8 <= len) + result.val_rational = parseEXIFRational(buf + base + result.data, alignIntel); + break; + case FORMAT_UNDEFINED: + case FORMAT_SIGNED_LONG: + case FORMAT_SIGNED_RATIONAL: + break; + default: + result.tag = FORMAT_DEFAULT_VALUE; + } + return result; + } +} + +// +// Locates the EXIF segment and parses it using parseFromEXIFSegment +// +int EXIFInfo::ParseFrom(const unsigned char *buf, unsigned len) { + HiLog::Debug(LABEL, "ParseFrom ENTER"); + if (!buf || len < 4) + return PARSE_EXIF_ERROR_NO_EXIF; + if (buf[EXIF_MARKER_PREFIX_OFFSET] != EXIF_MARKER_PREFIX || buf[EXIF_MARKER_CODE_OFFSET] != EXIF_MARKER_SOI) + return PARSE_EXIF_ERROR_NO_JPEG; + + Clear(); + HiLog::Debug(LABEL, "parseFrom clear"); + + unsigned offs = 0; // current offset into buffer + for (offs = 0; offs < len-1; offs++) + if (buf[offs] == EXIF_MARKER_PREFIX && buf[offs+1] == EXIF_MARKER_HEADER) + break; + if (offs + OFFSET_4 > len) + return PARSE_EXIF_ERROR_NO_EXIF; + HiLog::Debug(LABEL, "parseFrom clear1"); + offs += OFFSET_2; + unsigned short section_length = parseShort(buf + offs, false); + if (offs + section_length > len || section_length < 16) + return PARSE_EXIF_ERROR_CORRUPT; + offs += OFFSET_2; + HiLog::Debug(LABEL, "parseFrom exit"); + return ParseFromEXIFSegment(buf + offs, len - offs); +} + +int EXIFInfo::ParseFrom(const string &data) { + return ParseFrom((const unsigned char *)data.data(), data.length()); +} + +// +// Main parsing function for an EXIF segment. +// +// PARAM: 'buf' start of the EXIF TIFF, which must be the bytes "Exif\0\0". +// PARAM: 'len' length of buffer +// +int EXIFInfo::ParseFromEXIFSegment(const unsigned char *buf, unsigned len) { + HiLog::Debug(LABEL, "parseFromEXIFSegment enter"); + bool alignIntel = true; // byte alignment (defined in EXIF header) + unsigned offs = 0; // current offset into buffer + if (!buf || len < OFFSET_6) + return PARSE_EXIF_ERROR_NO_EXIF; + + if (!std::equal(buf, buf + OFFSET_6, "Exif\0\0")) + return PARSE_EXIF_ERROR_NO_EXIF; + offs += OFFSET_6; + + if (offs + OFFSET_8 > len) + return PARSE_EXIF_ERROR_CORRUPT; + unsigned tiff_header_start = offs; + if (buf[offs] == CHAR_I && buf[offs+OFFSET_1] == CHAR_I) + alignIntel = true; + else { + if(buf[offs] == CHAR_M && buf[offs+OFFSET_1] == CHAR_M) + alignIntel = false; + else + return PARSE_EXIF_ERROR_UNKNOWN_BYTEALIGN; + } + this->ByteAlign = alignIntel; + offs += OFFSET_2; + if (0x2a != parseShort(buf+offs, alignIntel)) + return PARSE_EXIF_ERROR_CORRUPT; + offs += OFFSET_2; + unsigned first_ifd_offset = parseLong(buf + offs, alignIntel); + offs += first_ifd_offset - OFFSET_4; + if (offs >= len) + return PARSE_EXIF_ERROR_CORRUPT; + unsigned exif_sub_ifd_offset = len; + unsigned gps_sub_ifd_offset = len; + int resIFD = ParseExifIFD(buf, len, alignIntel, tiff_header_start, offs, exif_sub_ifd_offset, gps_sub_ifd_offset); + if(resIFD != PARSE_EXIF_SUCCESS){ + return resIFD; + } + int resSubIFD = ParseEXIFSubIFD(buf, len, alignIntel, tiff_header_start, exif_sub_ifd_offset); + if(resSubIFD != PARSE_EXIF_SUCCESS){ + return resSubIFD; + } + int resGps = ParseGpsSubIFD(buf, len, alignIntel, tiff_header_start, gps_sub_ifd_offset); + if(resGps != PARSE_EXIF_SUCCESS){ + return resGps; + } + return PARSE_EXIF_SUCCESS; +} + +int EXIFInfo::ParseExifIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned exif_ifd_offset, unsigned &exif_sub_ifd_offset, + unsigned &gps_sub_ifd_offset) +{ + HiLog::Debug(LABEL, "ParseExifIFD enter"); + unsigned offs = exif_ifd_offset;// current offset into buffer + // Now parsing the first Image File Directory (IFD0, for the main image). + // An IFD consists of a variable number of 12-byte directory entries. The + // first two bytes of the IFD section contain the number of directory + // entries in the section. The last 4 bytes of the IFD contain an offset + // to the next IFD, which means this IFD must contain exactly 6 + 12 * num + // bytes of data. + if (offs + OFFSET_2 > len) + return PARSE_EXIF_ERROR_CORRUPT; + int num_entries = parseShort(buf + offs, alignIntel); + if (offs + OFFSET_6 + OFFSET_12 * num_entries > len) + return PARSE_EXIF_ERROR_CORRUPT; + offs += OFFSET_2; + + while (--num_entries >= 0) { + IFEntry result = parseIFEntry(buf, offs, alignIntel, tiff_header_start, len); + offs += OFFSET_12; + setIFEntryValue(result); + switch(result.tag) { + case TAG_GPS_IFS_OFFSET: + gps_sub_ifd_offset = tiff_header_start + result.data; + break; + case TAG_EXIF_SUB_IFD_OFFSET: + exif_sub_ifd_offset = tiff_header_start + result.data; + break; + } + } + HiLog::Debug(LABEL, "ParseEXIFSubIFD EXIT"); + return PARSE_EXIF_SUCCESS; +} + +void EXIFInfo::setIFEntryValue(IFEntry result) { + HiLog::Debug(LABEL, "setIFEntryValue enter"); + switch(result.tag) { + case TAG_BITS_PER_SAMPLE: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->BitsPerSample = result.val_short; + break; + case TAG_IMAGE_DESCRIPTION: + if (result.format == FORMAT_ASCII_STRING) + this->ImageDescription = result.val_string; + break; + case TAG_DIGICAM_MAKE: + if (result.format == FORMAT_ASCII_STRING) + this->Make = result.val_string; + break; + case TAG_DIGICAM_MODEL: + if (result.format == FORMAT_ASCII_STRING) + this->Model = result.val_string; + break; + case TAG_ORIENTATION_OF_IMAGE: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->Orientation = result.val_short; + break; + case TAG_SOFTWARE: + if (result.format == FORMAT_ASCII_STRING) + this->Software = result.val_string; + break; + case TAG_DATE_TIME: + if (result.format == FORMAT_ASCII_STRING) + this->DateTime = result.val_string; + break; + case TAG_COPYRIGHT_INFO: + if (result.format == FORMAT_ASCII_STRING) + this->Copyright = result.val_string; + break; + } + HiLog::Debug(LABEL, "setIFEntryValue exit"); +} + +void EXIFInfo::setSubIFEntryValue(IFEntry result) { + switch(result.tag) { + case TAG_EXPOSURE_TIME: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->ExposureTime = result.val_rational; + break; + case TAG_FNUMBER: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->FNumber = result.val_rational; + break; + case TAG_ISO_SPEED_RATING: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->ISOSpeedRatings = result.val_short; + break; + case TAG_ORIGINAL_DATE_TIME: + if (result.format == FORMAT_ASCII_STRING) + this->DateTimeOriginal = result.val_string; + break; + case TAG_DIGITIZATION_DATE_TIME: + if (result.format == FORMAT_ASCII_STRING) + this->DateTimeDigitized = result.val_string; + break; + case TAG_SHUTTER_SPEED_VALUE: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->ShutterSpeedValue = result.val_rational; + break; + case TAG_EXPOSURE_BIAS_VALUE: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->ExposureBiasValue = result.val_rational; + break; + } +} + +void EXIFInfo::setSubIFEntryValueExtend(IFEntry result) { + switch(result.tag) { + case TAG_SUBJECT_DISTANCE: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->SubjectDistance = result.val_rational; + break; + case TAG_FLASH: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->Flash = result.data ? 1 : 0; + break; + case TAG_FOCAL_LENGTH: + if (result.format == FORMAT_UNSIGNED_RATIONAL) + this->FocalLength = result.val_rational; + break; + case TAG_METERING_MODE: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->MeteringMode = result.val_short; + break; + case TAG_SUBSECOND_ORIGINAL_TIME: + if (result.format == FORMAT_ASCII_STRING) + this->SubSecTimeOriginal = result.val_string; + break; + case TAG_EXIF_IMAGE_WIDTH: + if (result.format == FORMAT_UNSIGNED_LONG) + this->ImageWidth = result.val_long; + if (result.format == FORMAT_UNSIGNED_SHORT) + this->ImageWidth = result.val_short; + break; + case TAG_EXIF_IMAGE_HEIGHT: + if (result.format == FORMAT_UNSIGNED_LONG) + this->ImageHeight = result.val_long; + if (result.format == FORMAT_UNSIGNED_SHORT) + this->ImageHeight = result.val_short; + break; + case TAG_FOCAL_LENGTH_IN_35MM: + if (result.format == FORMAT_UNSIGNED_SHORT) + this->FocalLengthIn35mm = result.val_short; + break; + } +} + +int EXIFInfo::ParseEXIFSubIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned exif_sub_ifd_offset) +{ + HiLog::Debug(LABEL, "ParseEXIFSubIFD enter"); + unsigned offs = exif_sub_ifd_offset;// current offset into buffer + // Jump to the EXIF SubIFD if it exists and parse all the information + // there. Note that it's possible that the EXIF SubIFD doesn't exist. + // The EXIF SubIFD contains most of the interesting information that a + // typical user might want. + if (exif_sub_ifd_offset + OFFSET_4 <= len) { + int num_entries = parseShort(buf + offs, alignIntel); + if (offs + OFFSET_6 + OFFSET_12 * num_entries > len) + return PARSE_EXIF_ERROR_CORRUPT; + offs += OFFSET_2; + while (--num_entries >= 0) { + IFEntry result = parseIFEntry(buf, offs, alignIntel, tiff_header_start, len); + setSubIFEntryValue(result); + setSubIFEntryValueExtend(result); + offs += OFFSET_12; + } + } + HiLog::Debug(LABEL, "ParseEXIFSubIFD EXIT"); + return PARSE_EXIF_SUCCESS; +} + +void EXIFInfo::setLatitude(const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, + unsigned data) { + this->GeoLocation.LatComponents.degrees = + parseEXIFRational(buf + data + tiff_header_start, alignIntel); + this->GeoLocation.LatComponents.minutes = + parseEXIFRational(buf + data + tiff_header_start + OFFSET_8, alignIntel); + this->GeoLocation.LatComponents.seconds = + parseEXIFRational(buf + data + tiff_header_start + OFFSET_16, alignIntel); + this->GeoLocation.Latitude = + this->GeoLocation.LatComponents.degrees + + this->GeoLocation.LatComponents.minutes / 60 + + this->GeoLocation.LatComponents.seconds / 3600; + if (SOUTH == this->GeoLocation.LatComponents.direction) + this->GeoLocation.Latitude = -this->GeoLocation.Latitude; +} + +void EXIFInfo::setLongitude(const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, + unsigned data) { + this->GeoLocation.LonComponents.degrees = + parseEXIFRational(buf + data + tiff_header_start, alignIntel); + this->GeoLocation.LonComponents.minutes = + parseEXIFRational(buf + data + tiff_header_start + OFFSET_8, alignIntel); + this->GeoLocation.LonComponents.seconds = + parseEXIFRational(buf + data + tiff_header_start + OFFSET_16, alignIntel); + this->GeoLocation.Longitude = + this->GeoLocation.LonComponents.degrees + + this->GeoLocation.LonComponents.minutes / 60 + + this->GeoLocation.LonComponents.seconds / 3600; + if (WEST == this->GeoLocation.LonComponents.direction) + this->GeoLocation.Longitude = -this->GeoLocation.Longitude; +} + +void EXIFInfo::setGpsEntryValue(unsigned short tag, unsigned short format, unsigned length, unsigned data, + const unsigned char *buf, bool alignIntel, unsigned tiff_header_start, unsigned entry_offs) { + switch(tag) { + case T_GPS_NOS: + this->GeoLocation.LatComponents.direction = *(buf + entry_offs + OFFSET_8); + if (SOUTH == this->GeoLocation.LatComponents.direction) + this->GeoLocation.Latitude = -this->GeoLocation.Latitude; + break; + case T_GPS_LAT: + if (format == FORMAT_UNSIGNED_RATIONAL && length == 3) { + setLatitude(buf, alignIntel, tiff_header_start, data); + } + break; + case T_GPS_EOW: + this->GeoLocation.LonComponents.direction = *(buf + entry_offs + OFFSET_8); + if (WEST == this->GeoLocation.LonComponents.direction) + this->GeoLocation.Longitude = -this->GeoLocation.Longitude; + break; + case T_GPS_LON: + if (format == FORMAT_UNSIGNED_RATIONAL && length == 3) { + setLongitude(buf, alignIntel, tiff_header_start, data); + } + break; + case T_GPS_ALT_REF: + this->GeoLocation.AltitudeRef = *(buf + entry_offs + OFFSET_8); + if (1 == this->GeoLocation.AltitudeRef) + this->GeoLocation.Altitude = -this->GeoLocation.Altitude; + break; + case T_GPS_ALT: + if (format == FORMAT_UNSIGNED_RATIONAL) { + this->GeoLocation.Altitude = + parseEXIFRational(buf + data + tiff_header_start, alignIntel); + if (1 == this->GeoLocation.AltitudeRef) + this->GeoLocation.Altitude = -this->GeoLocation.Altitude; + } + break; + } +} + +int EXIFInfo::ParseGpsSubIFD(const unsigned char *buf, unsigned len, bool alignIntel, + unsigned tiff_header_start, unsigned gps_sub_ifd_offset) +{ + HiLog::Debug(LABEL, "ParseGpsSubIFD enter"); + // Jump to the GPS SubIFD if it exists and parse all the information + // there. Note that it's possible that the GPS SubIFD doesn't exist. + unsigned offs = gps_sub_ifd_offset;// current offset into buffer + if (offs + OFFSET_4 <= len) { + int num_entries = parseShort(buf + offs, alignIntel); + if (offs + OFFSET_6 + OFFSET_12 * num_entries > len) + return PARSE_EXIF_ERROR_CORRUPT; + offs += OFFSET_2; + while (--num_entries >= 0) { + unsigned short tag = parseShort(buf + offs, alignIntel); + unsigned short format = parseShort(buf + offs + OFFSET_2, alignIntel); + unsigned length = parseLong(buf + offs + OFFSET_4, alignIntel); + unsigned data = parseLong(buf + offs + OFFSET_8, alignIntel); + + setGpsEntryValue(tag, format, length, data, buf, alignIntel, tiff_header_start, offs); + offs += OFFSET_12; + } + } + HiLog::Debug(LABEL, "ParseGpsSubIFD EXIT"); + return PARSE_EXIF_SUCCESS; +} + +void EXIFInfo::Clear() { + // Strings + ImageDescription = ""; + Make = ""; + Model = ""; + Software = ""; + DateTime = ""; + DateTimeOriginal = ""; + DateTimeDigitized = ""; + SubSecTimeOriginal = ""; + Copyright = ""; + + // Shorts / unsigned / double + ByteAlign = 0; + Orientation = 0; + + BitsPerSample = 0; + ExposureTime = 0; + FNumber = 0; + ISOSpeedRatings = 0; + ShutterSpeedValue = 0; + ExposureBiasValue = 0; + SubjectDistance = 0; + FocalLength = 0; + FocalLengthIn35mm = 0; + Flash = 0; + MeteringMode = 0; + ImageWidth = 0; + ImageHeight = 0; + + // Geolocation + GeoLocation.Latitude = 0; + GeoLocation.Longitude = 0; + GeoLocation.Altitude = 0; + GeoLocation.AltitudeRef = 0; + GeoLocation.LatComponents.degrees = 0; + GeoLocation.LatComponents.minutes = 0; + GeoLocation.LatComponents.seconds = 0; + GeoLocation.LatComponents.direction = 0; + GeoLocation.LonComponents.degrees = 0; + GeoLocation.LonComponents.minutes = 0; + GeoLocation.LonComponents.seconds = 0; + GeoLocation.LonComponents.direction = 0; +} \ No newline at end of file diff --git a/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp b/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp index 2989f29a1ed1e3e5723964a109b87cac6ba11422..55e138d17e73665170a5b2f06aef4de5c91d422d 100644 --- a/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp @@ -46,6 +46,14 @@ constexpr uint8_t JPG_MARKER_RSTN = 0XD7; constexpr uint8_t JPG_MARKER_APP = 0XE0; constexpr uint8_t JPG_MARKER_APP0 = 0XE0; constexpr uint8_t JPG_MARKER_APPN = 0XEF; +const std::string BITS_PER_SAMPLE = "BitsPerSample"; +const std::string ORIENTATION = "Orientation"; +const std::string IMAGE_HEIGHT = "ImageHeight"; +const std::string IMAGE_WIDTH = "ImageWidth"; +const std::string GPS_LATITUDE = "GPSLatitude"; +const std::string GPS_LONGITUDE = "GPSLongitude"; +const std::string GPS_LATITUDE_REF = "GPSLatitudeRef"; +const std::string GPS_LONGITUDE_REF = "GPSLongitudeRef"; } // namespace PluginServer &JpegDecoder::pluginServer_ = DelayedRefSingleton::GetInstance(); @@ -95,6 +103,88 @@ void JpegDecoder::SetSource(InputDataStream &sourceStream) { srcMgr_.inputStream = &sourceStream; state_ = JpegDecodingState::SOURCE_INITED; + HiLog::Error(LABEL, "SetSource ExifPrintMethod"); + ExifPrintMethod(); +} + +int JpegDecoder::ExifPrintMethod() +{ + HiLog::Debug(LABEL, "ExifPrintMethod enter"); + // Read the JPEG file into a buffer + //FILE *fp = fopen(argv[1], "rb"); + //if (!fp) { + // HiLog::Error(LABEL, "Can't open file.\n"); + // return -1; + //} + //fseek(fp, 0, SEEK_END); + srcMgr_.inputStream->Seek(0); + unsigned long fsize = 0; + fsize = static_cast(srcMgr_.inputStream->GetStreamSize()); + unsigned char *buf = new unsigned char[fsize]; + uint32_t readSize = 0; + srcMgr_.inputStream->Read(fsize, buf, fsize, readSize); + HiLog::Debug(LABEL, "parsing EXIF: fsize %{public}lu", fsize); + HiLog::Debug(LABEL, "parsing EXIF: readSize %{public}u", readSize); +// if (readSize != MARKER_SIZE) { +// return false; +// } +// unsigned long fsize = ftell(fp); +// rewind(fp); +// unsigned char *buf = new unsigned char[fsize]; +// if (fread(buf, 1, fsize, fp) != fsize) { +// HiLog::Error(LABEL, "Can't read file.\n"); +// delete[] buf; +// return -2; +// } +// fclose(fp); + + // Parse EXIF + // EXIFInfo result; + int code = exifInfo_.ParseFrom(buf, fsize); + delete[] buf; + if (code) { + HiLog::Error(LABEL, "Error parsing EXIF: code %{public}d", code); + return -3; + } + + // Dump EXIF information + HiLog::Error(LABEL, "Camera make : %{public}s\n", exifInfo_.Make.c_str()); + HiLog::Error(LABEL, "Camera model : %{public}s\n", exifInfo_.Model.c_str()); + HiLog::Error(LABEL, "Software : %{public}s\n", exifInfo_.Software.c_str()); + HiLog::Error(LABEL, "Bits per sample : %{public}d\n", exifInfo_.BitsPerSample); + HiLog::Error(LABEL, "Image width : %{public}d\n", exifInfo_.ImageWidth); + HiLog::Error(LABEL, "Image height : %{public}d\n", exifInfo_.ImageHeight); + HiLog::Error(LABEL, "Image description : %{public}s\n", exifInfo_.ImageDescription.c_str()); + HiLog::Error(LABEL, "Image orientation : %{public}d\n", exifInfo_.Orientation); + HiLog::Error(LABEL, "Image copyright : %{public}s\n", exifInfo_.Copyright.c_str()); + HiLog::Error(LABEL, "Image date/time : %{public}s\n", exifInfo_.DateTime.c_str()); + HiLog::Error(LABEL, "Original date/time: %{public}s\n", exifInfo_.DateTimeOriginal.c_str()); + HiLog::Error(LABEL, "Digitize date/time: %{public}s\n", exifInfo_.DateTimeDigitized.c_str()); + HiLog::Error(LABEL, "Subsecond time : %{public}s\n", exifInfo_.SubSecTimeOriginal.c_str()); + HiLog::Error(LABEL, "Exposure time : 1/%{public}d s\n", (unsigned) (1.0/exifInfo_.ExposureTime)); + HiLog::Error(LABEL, "F-stop : f/%.1f\n", exifInfo_.FNumber); + HiLog::Error(LABEL, "ISO speed : %{public}d\n", exifInfo_.ISOSpeedRatings); + HiLog::Error(LABEL, "Subject distance : %{public}f m\n", exifInfo_.SubjectDistance); + HiLog::Error(LABEL, "Exposure bias : %{public}f EV\n", exifInfo_.ExposureBiasValue); + HiLog::Error(LABEL, "Flash used? : %{public}d\n", exifInfo_.Flash); + HiLog::Error(LABEL, "Metering mode : %{public}d\n", exifInfo_.MeteringMode); + HiLog::Error(LABEL, "Lens focal length : %{public}f mm\n", exifInfo_.FocalLength); + HiLog::Error(LABEL, "35mm focal length : %{public}u mm\n", exifInfo_.FocalLengthIn35mm); + HiLog::Error(LABEL, "GPS Latitude : %{public}f deg (%{public}f deg, %{public}f min, %{public}f sec %{public}c)\n", + exifInfo_.GeoLocation.Latitude, + exifInfo_.GeoLocation.LatComponents.degrees, + exifInfo_.GeoLocation.LatComponents.minutes, + exifInfo_.GeoLocation.LatComponents.seconds, + exifInfo_.GeoLocation.LatComponents.direction); + HiLog::Error(LABEL, "GPS Longitude : %{public}f deg (%{public}f deg, %{public}f min, %{public}f sec %{public}c)\n", + exifInfo_.GeoLocation.Longitude, + exifInfo_.GeoLocation.LonComponents.degrees, + exifInfo_.GeoLocation.LonComponents.minutes, + exifInfo_.GeoLocation.LonComponents.seconds, + exifInfo_.GeoLocation.LonComponents.direction); + HiLog::Error(LABEL, "GPS Altitude : %{public}f m\n", exifInfo_.GeoLocation.Altitude); + HiLog::Error(LABEL, "ExifPrintMethod exit"); + return 0; } uint32_t JpegDecoder::GetImageSize(uint32_t index, PlSize &size) @@ -529,5 +619,49 @@ uint32_t JpegDecoder::StartDecompress(const PixelDecodeOptions &opts) streamPosition_ = srcMgr_.inputStream->Tell(); return Media::SUCCESS; } + +uint32_t JpegDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value) +{ + HiLog::Error(LABEL, "[GetImagePropertyInt] enter jped plugin, key:%{public}s", key.c_str()); + + if (key == ORIENTATION) { + value = exifInfo_.Orientation; + } else if (key == IMAGE_HEIGHT) { + value = exifInfo_.ImageHeight; + } else if (key == IMAGE_WIDTH) { + value = exifInfo_.ImageWidth; + } else { + HiLog::Error(LABEL, "[GetImagePropertyInt]key(%{public}s) not supported", key.c_str()); + return ERR_IMAGE_INVALID_PARAMETER; + } + + return Media::SUCCESS; +} + +uint32_t JpegDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value) +{ + HiLog::Error(LABEL, "[GetImagePropertyInt] enter jped plugin, key:%{public}s", key.c_str()); + // uint32_t errorCode = CheckIndex(0); + // if (errorCode != SUCCESS) { + // HiLog::Error(LABEL, "[GetImagePropertyInt]index %{public}u is invalid", index); + // return errorCode; + // } + + if (key == GPS_LATITUDE) { + value = DoubleToString(exifInfo_.GeoLocation.Latitude); + } else if (key == GPS_LONGITUDE) { + value = DoubleToString(exifInfo_.GeoLocation.Longitude); + } else if (key == GPS_LATITUDE_REF) { + value = exifInfo_.GeoLocation.LatComponents.direction; + } else if (key == GPS_LONGITUDE_REF) { + value = exifInfo_.GeoLocation.LonComponents.direction; + } else { + HiLog::Error(LABEL, "[GetImagePropertyInt]key(%{public}s) not supported", key.c_str()); + return ERR_IMAGE_INVALID_PARAMETER; + } + + return Media::SUCCESS; +} + } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libjpegplugin/src/jpeg_utils.cpp b/plugins/common/libs/image/libjpegplugin/src/jpeg_utils.cpp index 36aeff58125d37a97ff104f0266a6e175a985cb4..811ecd10444804c1fe88330bdfc49315952226f8 100644 --- a/plugins/common/libs/image/libjpegplugin/src/jpeg_utils.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/jpeg_utils.cpp @@ -190,5 +190,14 @@ void TermDstStream(j_compress_ptr cinfo) } dest->outputStream->Flush(); } + + +std::string DoubleToString(double num) +{ + char str[256]; + sprintf(str, "%lf", num); + std::string result = str; + return result; +} } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libjpegplugin/src/plugin_export.cpp b/plugins/common/libs/image/libjpegplugin/src/plugin_export.cpp index bac59e55efc0c4cdc6a798d37d3519e95d1bf400..fd9a7c498cddc457284af2e4311494d8e0ae5432 100644 --- a/plugins/common/libs/image/libjpegplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/plugin_export.cpp @@ -21,7 +21,9 @@ #include "log_tags.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibJpegPlugin") +namespace { + const std::string PACKAGE_NAME = ("LibJpegPlugin"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN @@ -31,14 +33,35 @@ PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::JpegEncoder) #endif PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibJpegPlugin" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/common/libs/image/libpngplugin/src/plugin_export.cpp b/plugins/common/libs/image/libpngplugin/src/plugin_export.cpp index d9409b28016c273666949a6ad31ab311b4ee5f81..1be1a31d8f23ac23bc0d53b89cb5d1047075ea9f 100644 --- a/plugins/common/libs/image/libpngplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/libpngplugin/src/plugin_export.cpp @@ -20,21 +20,44 @@ #include "png_decoder.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibPngPlugin") +namespace { + const std::string PACKAGE_NAME = ("LibPngPlugin"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::PngDecoder) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibPngPlugin" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/common/libs/image/libwebpplugin/src/plugin_export.cpp b/plugins/common/libs/image/libwebpplugin/src/plugin_export.cpp index 57159092550d828ecae9a57a24a77465a97aa433..92950d6e2d804b3cb8161b54512e1cfdc117fb26 100644 --- a/plugins/common/libs/image/libwebpplugin/src/plugin_export.cpp +++ b/plugins/common/libs/image/libwebpplugin/src/plugin_export.cpp @@ -20,21 +20,44 @@ #include "webp_decoder.h" // plugin package name same as metadata. -PLUGIN_EXPORT_REGISTER_PACKAGE("LibWebpPlugin") +namespace { + const std::string PACKAGE_NAME = ("LibWebpPlugin"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN PLUGIN_EXPORT_REGISTER_CLASS(OHOS::ImagePlugin::WebpDecoder) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "LibWebpPlugin" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin. PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/manager/include/pluginbase/plugin_utils.h b/plugins/manager/include/pluginbase/plugin_utils.h index 790d3bcb1ed3200146b2c42d51bc7438b987ea7b..d356da374b76f312b434715675bfff327e37458b 100644 --- a/plugins/manager/include/pluginbase/plugin_utils.h +++ b/plugins/manager/include/pluginbase/plugin_utils.h @@ -38,7 +38,9 @@ using PluginObjectCreatorFunc = OHOS::MultimediaPlugin::PluginClassBase *(*)(); // --------- a set of code fragments that helps define a simple plugin_export.cpp file ---------- #define PLUGIN_EXPORT_REGISTER_PACKAGE(packageName) \ -static const std::string PACKAGE_NAME = (packageName); +namespace { \ + const std::string PACKAGE_NAME = (packageName); \ +} #define PLUGIN_EXPORT_REGISTER_CLASS_BEGIN \ using ImplClassMap = std::map; \ diff --git a/plugins/manager/test/unittest/common/plugin_example/plugin_example2/plugin_export.cpp b/plugins/manager/test/unittest/common/plugin_example/plugin_example2/plugin_export.cpp index 761ae7c4d2ef68fc211abd501abd3cb22beff792..9bab70dcfaecac0b34b6e1e7df5cde7508ec3fb6 100644 --- a/plugins/manager/test/unittest/common/plugin_example/plugin_example2/plugin_export.cpp +++ b/plugins/manager/test/unittest/common/plugin_example/plugin_example2/plugin_export.cpp @@ -22,7 +22,9 @@ // this file shows how to easily write the plugin_export.cpp file using the code elements provided by plugin_utils.h. // but sometimes you may need to write this file directly, see plugin_example1. -PLUGIN_EXPORT_REGISTER_PACKAGE("plugin_example2") +namespace { + const std::string PACKAGE_NAME = ("plugin_example2"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN @@ -30,15 +32,36 @@ PLUGIN_EXPORT_REGISTER_CLASS(OHOS::PluginExample::LabelDetector2) PLUGIN_EXPORT_REGISTER_CLASS(OHOS::PluginExample::CloudLabelDetector2) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "plugin_example2" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +} diff --git a/plugins/manager/test/unittest/common/plugin_example/plugin_example3/plugin_export.cpp b/plugins/manager/test/unittest/common/plugin_example/plugin_example3/plugin_export.cpp index 0205a53f35a04c67e0e6abb71db0867f90493e40..9220362649264af63e58ac7e58a773efa0c5cefc 100644 --- a/plugins/manager/test/unittest/common/plugin_example/plugin_example3/plugin_export.cpp +++ b/plugins/manager/test/unittest/common/plugin_example/plugin_example3/plugin_export.cpp @@ -22,7 +22,9 @@ // this file shows how to easily write the plugin_export.cpp file using the code elements provided by plugin_utils.h. // but sometimes you may need to write this file directly, see plugin_example1. -PLUGIN_EXPORT_REGISTER_PACKAGE("plugin_example3") +namespace { + const std::string PACKAGE_NAME = ("plugin_example3"); +} // register implement classes of this plugin. PLUGIN_EXPORT_REGISTER_CLASS_BEGIN @@ -30,15 +32,36 @@ PLUGIN_EXPORT_REGISTER_CLASS(OHOS::PluginExample::LabelDetector3) PLUGIN_EXPORT_REGISTER_CLASS(OHOS::PluginExample::CloudLabelDetector3) PLUGIN_EXPORT_REGISTER_CLASS_END +using std::string; using namespace OHOS::HiviewDFX; static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "plugin_example3" }; -#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__); -#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__); +#define PLUGIN_LOG_D(...) HiLog::Debug(LABEL, __VA_ARGS__) +#define PLUGIN_LOG_E(...) HiLog::Error(LABEL, __VA_ARGS__) // define the external interface of this plugin PLUGIN_EXPORT_DEFAULT_EXTERNAL_START() PLUGIN_EXPORT_DEFAULT_EXTERNAL_STOP() -// PLUGIN_EXPORT_DEFAULT_EXTERNAL_CREATE() +OHOS::MultimediaPlugin::PluginClassBase *PluginExternalCreate(const string &className) +{ + HiLog::Debug(LABEL, "PluginExternalCreate: create object for package: %{public}s, class: %{public}s.", + PACKAGE_NAME.c_str(), className.c_str()); + + auto iter = implClassMap.find(className); + if (iter == implClassMap.end()) { + HiLog::Error(LABEL, "PluginExternalCreate: failed to find class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + auto creator = iter->second; + if (creator == nullptr) { + HiLog::Error(LABEL, "PluginExternalCreate: null creator for class: %{public}s, in package: %{public}s.", + className.c_str(), PACKAGE_NAME.c_str()); + return nullptr; + } + + return creator(); +}