diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 25af2eaadf284829c9b6e9b99ce8b999791e847c..7a876381a08d407e26531d0946de2163152c69e4 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -532,6 +532,24 @@ uint32_t ImageSource::GetImageInfo(uint32_t index, ImageInfo &imageInfo) return SUCCESS; } +uint32_t ImageSource::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const std::string &path) +{ + 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 modify image property, ret:%{public}u.", ret); + return ret; + } + ret = mainDecoder_->ModifyImageProperty(index, key, value, path); + if (ret != SUCCESS) { + IMAGE_LOGE("[ImageSource] GetImagePropertyInt fail, ret:%{public}u", ret); + return ret; + } + return SUCCESS; +} + uint32_t ImageSource::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value) { std::unique_lock guard(decodingMutex_); diff --git a/frameworks/kits/js/common/image_source_napi.cpp b/frameworks/kits/js/common/image_source_napi.cpp index 1f0b3aca833897b46d3683bd3a421763be66a62c..35c8f13ed29f3f4dd2d5a11b87a44b3a569b1765 100644 --- a/frameworks/kits/js/common/image_source_napi.cpp +++ b/frameworks/kits/js/common/image_source_napi.cpp @@ -34,6 +34,7 @@ namespace OHOS { namespace Media { napi_ref ImageSourceNapi::sConstructor_ = nullptr; std::shared_ptr ImageSourceNapi::sImgSrc_ = nullptr; +std::shared_ptr ImageSourceNapi::sIncPixelMap_ = nullptr; static const std::string CLASS_NAME = "ImageSource"; struct ImageSourceAsyncContext { @@ -143,6 +144,7 @@ napi_value ImageSourceNapi::Init(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo), + DECLARE_NAPI_FUNCTION("modifyImageProperty", ModifyImageProperty), DECLARE_NAPI_FUNCTION("getImageProperty", GetImageProperty), DECLARE_NAPI_FUNCTION("createPixelMap", CreatePixelMap), DECLARE_NAPI_FUNCTION("updateData", UpdateData), @@ -200,6 +202,8 @@ napi_value ImageSourceNapi::Constructor(napi_env env, napi_callback_info info) if (pImgSrcNapi != nullptr) { pImgSrcNapi->env_ = env; pImgSrcNapi->nativeImgSrc = sImgSrc_; + pImgSrcNapi->navIncPixelMap_ = sIncPixelMap_; + sIncPixelMap_ = nullptr; status = napi_wrap(env, thisVar, reinterpret_cast(pImgSrcNapi.get()), ImageSourceNapi::Destructor, nullptr, &(pImgSrcNapi->wrapper_)); @@ -493,6 +497,8 @@ napi_value ImageSourceNapi::CreateIncrementalSource(napi_env env, napi_callback_ IncrementalSourceOptions incOpts; incOpts.incrementalMode = IncrementalMode::INCREMENTAL_DATA; std::unique_ptr imageSource = ImageSource::CreateIncrementalImageSource(incOpts, errorCode); + DecodeOptions decodeOpts; + std::unique_ptr incPixelMap = imageSource->CreateIncrementalPixelMap(0, decodeOpts, errorCode); HiLog::Debug(LABEL, "CreateIncrementalImageSource end"); if (errorCode != SUCCESS || imageSource == nullptr) { HiLog::Error(LABEL, "CreateIncrementalImageSource error"); @@ -503,6 +509,7 @@ napi_value ImageSourceNapi::CreateIncrementalSource(napi_env env, napi_callback_ status = napi_get_reference_value(env, sConstructor_, &constructor); if (IMG_IS_OK(status)) { sImgSrc_ = std::move(imageSource); + sIncPixelMap_ = std::move(incPixelMap); status = napi_new_instance(env, constructor, NUM_0, nullptr, &result); } if (!IMG_IS_OK(status)) { @@ -585,8 +592,18 @@ static void CreatePixelMapExecute(napi_env env, void *data) HiLog::Error(LABEL, "empty context rImageSource"); } - context->rPixelMap = context->rImageSource->CreatePixelMap(context->decodeOpts, errorCode); - + if (context->constructor_ != nullptr) { + auto incPixelMap = context->constructor_->GetIncrementalPixelMap(); + if (incPixelMap != nullptr) { + HiLog::Info(LABEL, "Get Incremental PixelMap!!!"); + context->rPixelMap = incPixelMap; + } + } else { + HiLog::Info(LABEL, "Get Incremental PixelMap!!!"); + } + if (context->rPixelMap == nullptr) { + context->rPixelMap = context->rImageSource->CreatePixelMap(context->decodeOpts, errorCode); + } if (context->rPixelMap == nullptr) { HiLog::Error(LABEL, "empty context rPixelMap"); } @@ -634,7 +651,7 @@ napi_value ImageSourceNapi::CreatePixelMap(napi_env env, napi_callback_info info nullptr, HiLog::Error(LABEL, "fail to unwrap context")); IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, imageSourceNapi->nativeImgSrc), nullptr, HiLog::Error(LABEL, "fail to unwrap nativeImgSrc")); - + asyncContext->constructor_ = imageSourceNapi.get(); asyncContext->rImageSource = imageSourceNapi->nativeImgSrc; IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource), nullptr, HiLog::Error(LABEL, "empty native rImageSource")); @@ -687,6 +704,21 @@ static bool ParsePropertyOptions(napi_env env, napi_value root, ImageSourceAsync return true; } +static void ModifyImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context) +{ + HiLog::Debug(LABEL, "ModifyPropertyComplete IN"); + + if (context == nullptr) { + HiLog::Error(LABEL, "context is nullptr"); + return; + } + napi_value result = nullptr; + napi_get_undefined(env, &result); + + HiLog::Debug(LABEL, "ModifyPropertyComplete OUT"); + ImageSourceCallbackRoutine(env, context, result); +} + static void GetImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context) { HiLog::Debug(LABEL, "GetImagePropertyComplete IN"); @@ -754,6 +786,92 @@ static std::unique_ptr UnwrapContext(napi_env env, napi return context; } +static std::unique_ptr UnwrapContextForModify(napi_env env, + napi_callback_info info) +{ + int32_t refCount = 1; + napi_status status; + napi_value thisVar = nullptr; + napi_value argValue[NUM_4] = {0}; + size_t argCount = NUM_4; + IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar); + HiLog::Debug(LABEL, "UnwrapContextForModify argCount is [%{public}zu]", argCount); + + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info")); + + std::unique_ptr context = std::make_unique(); + status = napi_unwrap(env, thisVar, reinterpret_cast(&context->constructor_)); + + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_), + nullptr, HiLog::Error(LABEL, "fail to unwrap context")); + + context->rImageSource = context->constructor_->nativeImgSrc; + + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource), + nullptr, HiLog::Error(LABEL, "empty native rImageSource")); + if (argCount < NUM_1 || argCount > NUM_4) { + HiLog::Error(LABEL, "argCount missmatch"); + return nullptr; + } + if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) { + context->keyStr = GetStringArgument(env, argValue[NUM_0]); + } else { + HiLog::Error(LABEL, "arg 0 type missmatch"); + return nullptr; + } + if (ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_string) { + context->valueStr = GetStringArgument(env, argValue[NUM_1]); + } else { + HiLog::Error(LABEL, "arg 1 type missmatch"); + return nullptr; + } + if (argCount == NUM_3 || argCount == NUM_4) { + if (ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_object) { + IMG_NAPI_CHECK_RET_D(ParsePropertyOptions(env, argValue[NUM_2], context.get()), + nullptr, HiLog::Error(LABEL, "PropertyOptions mismatch")); + } + if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) { + napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef); + } + } + return context; +} + +napi_value ImageSourceNapi::ModifyImageProperty(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + + napi_status status; + HiLog::Debug(LABEL, "ModifyImageProperty IN"); + std::unique_ptr asyncContext = UnwrapContextForModify(env, info); + if (asyncContext == nullptr) { + HiLog::Error(LABEL, "async context unwrap failed"); + return result; + } + + if (asyncContext->callbackRef == nullptr) { + napi_create_promise(env, &(asyncContext->deferred), &result); + } else { + napi_get_undefined(env, &result); + } + + IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ModifyImageProperty", + [](napi_env env, void *data) + { + auto context = static_cast(data); + context->status = context->rImageSource->ModifyImageProperty(context->index, + context->keyStr, context->valueStr, context->pathName); + }, + reinterpret_cast(ModifyImagePropertyComplete), + asyncContext, + asyncContext->work); + + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), + nullptr, HiLog::Error(LABEL, "fail to create async work")); + return result; +} + napi_value ImageSourceNapi::GetImageProperty(napi_env env, napi_callback_info info) { napi_value result = nullptr; @@ -793,8 +911,31 @@ napi_value ImageSourceNapi::GetImageProperty(napi_env env, napi_callback_info in static void UpdateDataExecute(napi_env env, void *data) { auto context = static_cast(data); - context->isSuccess = context->rImageSource->UpdateData(static_cast(context->updataBuffer), - context->updataBufferSize, context->isCompleted); + uint8_t *buffer = static_cast(context->updataBuffer); + if (context->updataBufferOffset < context->updataBufferSize) { + buffer = buffer + context->updataBufferOffset; + } + + uint32_t lastSize = context->updataBufferSize - context->updataBufferOffset; + uint32_t size = context->updataLength < lastSize ? context->updataLength : lastSize; + + uint32_t res = context->rImageSource->UpdateData(buffer, size, + context->isCompleted); + context->isSuccess = res == 0; + if (context->isSuccess && context->constructor_ != nullptr) { + auto incPixelMap = context->constructor_->GetIncrementalPixelMap(); + if (incPixelMap != nullptr) { + uint8_t decodeProgress = 0; + uint32_t err = incPixelMap->PromoteDecoding(decodeProgress); + if (!(err == SUCCESS || (err == ERR_IMAGE_SOURCE_DATA_INCOMPLETE && !context->isCompleted))) { + HiLog::Error(LABEL, "UpdateData PromoteDecoding error"); + context->isSuccess = false; + } + if (context->isCompleted) { + incPixelMap->DetachFromDecoding(); + } + } + } } static void UpdateDataComplete(napi_env env, napi_status status, void *data) @@ -810,6 +951,14 @@ static void UpdateDataComplete(napi_env env, napi_status status, void *data) ImageSourceCallbackRoutine(env, context, result); } +static bool isNapiTypedArray(napi_env env, napi_value val) +{ + bool res = false; + napi_is_typedarray(env, val, &res); + HiLog::Debug(LABEL, "isNapiTypedArray %{public}d", res); + return res; +} + napi_value ImageSourceNapi::UpdateData(napi_env env, napi_callback_info info) { napi_value result = nullptr; @@ -836,11 +985,15 @@ napi_value ImageSourceNapi::UpdateData(napi_env env, napi_callback_info info) IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource), nullptr, HiLog::Error(LABEL, "empty native rImageSource")); - - if (argCount > NUM_0 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) { - size_t bufferSize = static_cast(asyncContext->updataBufferSize); - status = napi_get_arraybuffer_info(env, argValue[NUM_0], - &(asyncContext->updataBuffer), &bufferSize); + HiLog::Error(LABEL, "UpdateData argCount %{public}d ", argCount); + if (argCount > NUM_0 && isNapiTypedArray(env, argValue[NUM_0])) { + HiLog::Error(LABEL, "UpdateData napi_get_arraybuffer_info "); + napi_typedarray_type type; + napi_value arraybuffer; + size_t offset; + status = napi_get_typedarray_info(env, argValue[NUM_0], &type, + &(asyncContext->updataBufferSize), &(asyncContext->updataBuffer), + &arraybuffer, &offset); } if (argCount >= NUM_2 && ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_boolean) { @@ -848,11 +1001,13 @@ napi_value ImageSourceNapi::UpdateData(napi_env env, napi_callback_info info) } if (argCount >= NUM_3 && ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_number) { + asyncContext->updataBufferOffset = 0; status = napi_get_value_uint32(env, argValue[NUM_2], &(asyncContext->updataBufferOffset)); HiLog::Debug(LABEL, "asyncContext->updataBufferOffset is [%{public}u]", asyncContext->updataBufferOffset); } if (argCount >= NUM_4 && ImageNapiUtils::getType(env, argValue[NUM_3]) == napi_number) { + asyncContext->updataLength = 0; status = napi_get_value_uint32(env, argValue[NUM_3], &(asyncContext->updataLength)); HiLog::Debug(LABEL, "asyncContext->updataLength is [%{public}u]", asyncContext->updataLength); } diff --git a/interfaces/innerkits/include/image_source.h b/interfaces/innerkits/include/image_source.h index 04021861a14604ec2cccdeb30cd8259323c2d0c7..1c33bbe017fd4588019093bd2a2186afc6bf77ac 100644 --- a/interfaces/innerkits/include/image_source.h +++ b/interfaces/innerkits/include/image_source.h @@ -162,6 +162,8 @@ public: 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 uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + const std::string &path); NATIVEEXPORT const NinePatchInfo &GetNinePatchInfo() const; NATIVEEXPORT void SetMemoryUsagePreference(const MemoryUsagePreference preference); NATIVEEXPORT MemoryUsagePreference GetMemoryUsagePreference(); diff --git a/interfaces/kits/js/common/include/image_source_napi.h b/interfaces/kits/js/common/include/image_source_napi.h index e63fdb21756a54ac7b6682a0ac73778f55ce229e..fe3248f322be0eccf4958150e25887f55e34bae1 100644 --- a/interfaces/kits/js/common/include/image_source_napi.h +++ b/interfaces/kits/js/common/include/image_source_napi.h @@ -22,6 +22,7 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" #include "pixel_map_napi.h" +#include "incremental_pixel_map.h" namespace OHOS { namespace Media { @@ -32,6 +33,10 @@ public: static napi_value Init(napi_env env, napi_value exports); std::shared_ptr nativeImgSrc = nullptr; + std::shared_ptr GetIncrementalPixelMap() + { + return navIncPixelMap_; + } private: static napi_value Constructor(napi_env env, napi_callback_info info); static void Destructor(napi_env env, void *nativeObject, void *finalize); @@ -47,12 +52,15 @@ private: // methods static napi_value GetImageInfo(napi_env env, napi_callback_info info); static napi_value CreatePixelMap(napi_env env, napi_callback_info info); + static napi_value ModifyImageProperty(napi_env env, napi_callback_info info); static napi_value GetImageProperty(napi_env env, napi_callback_info info); static napi_value UpdateData(napi_env env, napi_callback_info info); static napi_value Release(napi_env env, napi_callback_info info); static napi_ref sConstructor_; static std::shared_ptr sImgSrc_; + static std::shared_ptr sIncPixelMap_; + std::shared_ptr navIncPixelMap_ = nullptr; napi_env env_ = nullptr; napi_ref wrapper_ = nullptr; diff --git a/plugins/common/libs/image/libjpegplugin/BUILD.gn b/plugins/common/libs/image/libjpegplugin/BUILD.gn index 7403c06dec8c7282201fed64de34aa6f0922d040..3b7ad305724e9d51e276c847f896dbdd24a10445 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_info.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", diff --git a/plugins/common/libs/image/libjpegplugin/include/exif_info.h b/plugins/common/libs/image/libjpegplugin/include/exif_info.h new file mode 100644 index 0000000000000000000000000000000000000000..7b33539bddd0ae8cd7068254f97b232000f021ff --- /dev/null +++ b/plugins/common/libs/image/libjpegplugin/include/exif_info.h @@ -0,0 +1,65 @@ +/* + * 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_INFO_H +#define EXIF_INFO_H +#include +#include "hilog/log.h" +#include "log_tags.h" +namespace OHOS { +namespace ImagePlugin { +/* + * Class responsible for storing and parsing EXIF information from a JPEG blob + */ +class EXIFInfo { +public: + EXIFInfo(); + ~EXIFInfo(); + /* + * 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 ParseExifData(const unsigned char *buf, unsigned len); + int ParseExifData(const std::string &data); + bool ModifyExifData(const std::string &tag, const std::string &value, const std::string &path); + +public: + std::string bitsPerSample_; // Number of bits in each pixel of an image. + std::string orientation_; + std::string imageLength_; // Image length. + std::string imageWidth_; // mage width. + std::string gpsLatitude_; + std::string gpsLongitude_; + std::string gpsLatitudeRef_; + std::string gpsLongitudeRef_; + std::string dateTimeOriginal_; // Original date and time. + +private: + void SetExifTagValues(const std::string &tag, const std::string &value); + int GetImageFileDirectory(const std::string &tag); + void* InitExifTag(std::string *exif, int ifd, std::string tag); + void* CreateExifTag(std::string *exif, int ifd, std::string tag, size_t len, std::string format); + long GetFileSize(FILE *fp); + void ReleaseSource(unsigned char *buf, FILE *file); + +private: + int imageFileDirectory_; + std::string* exifData_; +}; +} // namespace ImagePlugin +} // namespace OHOS +#endif // EXIF_INFO_H diff --git a/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h b/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h index 588f4ecafd01874f8c0b114e6358846141e43938..902f86cdf96d48e2a83fcb5622867db50cc4e8f4 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_info.h" namespace OHOS { namespace ImagePlugin { @@ -52,6 +53,8 @@ public: 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; + uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + const std::string &path) override; private: DISALLOW_COPY_AND_MOVE(JpegDecoder); int ExifPrintMethod(); @@ -65,6 +68,7 @@ private: void CreateDecoder(); bool IsMarker(uint8_t rawPrefix, uint8_t rawMarkderCode, uint8_t markerCode); bool FindMarker(InputDataStream &stream, uint8_t marker); + int getExifTagFromKey(const std::string &key, const std::string &value); static MultimediaPlugin::PluginServer &pluginServer_; jpeg_decompress_struct decodeInfo_; @@ -75,6 +79,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/src/exif_info.cpp b/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28e067a391c2430accb15f6642f3add7e41fe116 --- /dev/null +++ b/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp @@ -0,0 +1,108 @@ +/* + * 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 "exif_info.h" +#include +#include +#include "string_ex.h" + +namespace OHOS { +namespace ImagePlugin { +namespace { + using namespace OHOS::HiviewDFX; + constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "Exif" }; + static const int PARSE_EXIF_SUCCESS = 0; +} + +EXIFInfo::EXIFInfo() : imageFileDirectory_(0), exifData_(nullptr) +{ +} + +EXIFInfo::~EXIFInfo() +{ + if (exifData_ != nullptr) { + exifData_ = nullptr; + } +} + +int EXIFInfo::ParseExifData(const unsigned char *buf, unsigned len) +{ + return PARSE_EXIF_SUCCESS; +} + +int EXIFInfo::ParseExifData(const std::string &data) +{ + return ParseExifData((const unsigned char *)data.data(), data.length()); +} + +void EXIFInfo::SetExifTagValues(const std::string &tag, const std::string &value) +{ + HiLog::Error(LABEL, "No match tag name!"); +} + +bool EXIFInfo::ModifyExifData(const std::string &tag, const std::string &value, const std::string &path) +{ + if (imageFileDirectory_ == 0) { + return false; + } + return true; +} + +int EXIFInfo::GetImageFileDirectory(const std::string &tag) +{ + return 0; +} + +void* EXIFInfo::InitExifTag(std::string *exif, int ifd, std::string tag) +{ + return nullptr; +} + +void* EXIFInfo::CreateExifTag(std::string *exif, int ifd, std::string tag, + size_t len, std::string format) +{ + return nullptr; +} + +long EXIFInfo::GetFileSize(FILE *fp) +{ + long int position; + long size; + + /* Save the current position. */ + position = ftell(fp); + + /* Jump to the end of the file. */ + fseek(fp, 0L, SEEK_END); + + /* Get the end position. */ + size = ftell(fp); + + /* Jump back to the original position. */ + fseek(fp, position, SEEK_SET); + + return size; +} + +void EXIFInfo::ReleaseSource(unsigned char *buf, FILE *file) +{ + if (buf) { + free(buf); + } + buf = nullptr; + fclose(file); + file = nullptr; +} +} // namespace ImagePlugin +} // namespace OHOS diff --git a/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp b/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp index 977f8d20b2bff5f93fc270354ed5c1c9954b4d07..f74dbd5ec723b5b830962a8a6272b7e3cc1ce33d 100644 --- a/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp @@ -16,6 +16,7 @@ #include "jerror.h" #include "media_errors.h" +#include "string_ex.h" #ifndef _WIN32 #include "securec.h" #else @@ -49,12 +50,13 @@ 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_LENGTH = "ImageLength"; 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"; +const std::string DATE_TIME_ORIGINAL = "DateTimeOriginal"; } // namespace PluginServer &JpegDecoder::pluginServer_ = DelayedRefSingleton::GetInstance(); @@ -104,6 +106,30 @@ 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"); + 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); + + int code = exifInfo_.ParseExifData(buf, fsize); + delete[] buf; + if (code) { + HiLog::Error(LABEL, "Error parsing EXIF: code %{public}d", code); + return ERR_MEDIA_VALUE_INVALID; + } + + return Media::SUCCESS; } uint32_t JpegDecoder::GetImageSize(uint32_t index, PlSize &size) @@ -548,6 +574,45 @@ uint32_t JpegDecoder::GetImagePropertyInt(uint32_t index, const std::string &key uint32_t JpegDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value) { HiLog::Error(LABEL, "[GetImagePropertyString] enter jped plugin, key:%{public}s", key.c_str()); + if (IsSameTextStr(key, BITS_PER_SAMPLE)) { + value = exifInfo_.bitsPerSample_; + } else if (IsSameTextStr(key, ORIENTATION)) { + value = exifInfo_.orientation_; + } else if (IsSameTextStr(key, IMAGE_LENGTH)) { + value = exifInfo_.imageLength_; + } else if (IsSameTextStr(key, IMAGE_WIDTH)) { + value = exifInfo_.imageWidth_; + } else if (IsSameTextStr(key, GPS_LATITUDE)) { + value = exifInfo_.gpsLatitude_; + } else if (IsSameTextStr(key, GPS_LONGITUDE)) { + value = exifInfo_.gpsLongitude_; + } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) { + value = exifInfo_.gpsLatitudeRef_; + } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) { + value = exifInfo_.gpsLongitudeRef_; + } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) { + value = exifInfo_.dateTimeOriginal_; + } else { + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + HiLog::Error(LABEL, "[GetImagePropertyString] enter jped plugin, value:%{public}s", value.c_str()); + return Media::SUCCESS; +} + +int JpegDecoder::getExifTagFromKey(const std::string &key, const std::string &value) +{ + return 0; +} + +uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const std::string &path) +{ + HiLog::Error(LABEL, "[ModifyImageProperty] enter jped plugin, key:%{public}s, value:%{public}s", + key.c_str(), value.c_str()); + int tag = getExifTagFromKey(key, value); + if (tag == 0) { + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } return Media::SUCCESS; } diff --git a/plugins/manager/include/image/abs_image_decoder.h b/plugins/manager/include/image/abs_image_decoder.h index 801719b8b13b841bb362d566f7fc8aa983d86f98..7dffb2e5606cdb8a4e29e5dd98a3e23fed2b1db4 100644 --- a/plugins/manager/include/image/abs_image_decoder.h +++ b/plugins/manager/include/image/abs_image_decoder.h @@ -147,6 +147,13 @@ public: return Media::ERR_MEDIA_INVALID_OPERATION; } + // modify image property. + virtual uint32_t ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const std::string &path) + { + return Media::ERR_MEDIA_INVALID_OPERATION; + } + // define multiple subservices for this interface static constexpr uint16_t SERVICE_DEFAULT = 0; };