diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 87d351f8e84ca79dd7ad50d5a612d1a93ac01686..817822a91cb3b91e11050e9b9a79a0c1d80ca4d0 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -545,7 +545,43 @@ uint32_t ImageSource::ModifyImageProperty(uint32_t index, const std::string &key } ret = mainDecoder_->ModifyImageProperty(index, key, value, path); if (ret != SUCCESS) { - IMAGE_LOGE("[ImageSource] GetImagePropertyInt fail, ret:%{public}u", ret); + IMAGE_LOGE("[ImageSource] ModifyImageProperty fail, ret:%{public}u", ret); + return ret; + } + return SUCCESS; +} + +uint32_t ImageSource::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const int fd) +{ + 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, fd); + if (ret != SUCCESS) { + IMAGE_LOGE("[ImageSource] ModifyImageProperty fail, ret:%{public}u", ret); + return ret; + } + return SUCCESS; +} + +uint32_t ImageSource::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, uint8_t *data, uint32_t size) +{ + 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, data, size); + if (ret != SUCCESS) { + IMAGE_LOGE("[ImageSource] ModifyImageProperty fail, ret:%{public}u", ret); return ret; } return SUCCESS; diff --git a/frameworks/kits/js/common/image_source_napi.cpp b/frameworks/kits/js/common/image_source_napi.cpp index fc0b37383098b82a3bd1a669bb6af2c7d670f50a..e990f931e67b9184e11d9c2b094b79f91388ed8b 100644 --- a/frameworks/kits/js/common/image_source_napi.cpp +++ b/frameworks/kits/js/common/image_source_napi.cpp @@ -18,6 +18,7 @@ #include "hilog/log.h" #include "image_napi_utils.h" #include "media_errors.h" +#include "string_ex.h" using OHOS::HiviewDFX::HiLog; namespace { @@ -28,6 +29,7 @@ namespace { constexpr uint32_t NUM_3 = 3; constexpr uint32_t NUM_4 = 4; constexpr uint32_t NUM_5 = 5; + constexpr uint32_t NUM_8 = 8; } namespace OHOS { @@ -38,6 +40,9 @@ std::shared_ptr ImageSourceNapi::sIncPixelMap_ = nullptr; static const std::string CLASS_NAME = "ImageSource"; static const std::string FILE_URL_PREFIX = "file://"; std::string ImageSourceNapi::filePath_ = ""; +int ImageSourceNapi::fileDescriptor_ = -1; +void* ImageSourceNapi::fileBuffer_ = nullptr; +size_t ImageSourceNapi::fileBufferSize_ = 0; struct ImageSourceAsyncContext { napi_env env; @@ -69,6 +74,7 @@ struct ImageSourceAsyncContext { std::shared_ptr rImageSource; std::shared_ptr rPixelMap; napi_value error = nullptr; + std::string errMsg; }; static std::string GetStringArgument(napi_env env, napi_value value) @@ -473,6 +479,11 @@ napi_value ImageSourceNapi::CreateImageSource(napi_env env, napi_callback_info i IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar); IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info")); + filePath_ = ""; + fileDescriptor_ = -1; + fileBuffer_ = nullptr; + fileBufferSize_ = 0; + std::unique_ptr asyncContext = std::make_unique(); uint32_t errorCode = ERR_MEDIA_INVALID_VALUE; SourceOptions opts; @@ -501,10 +512,13 @@ napi_value ImageSourceNapi::CreateImageSource(napi_env env, napi_callback_info i } else if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number) { napi_get_value_int32(env, argValue[NUM_0], &asyncContext->fdIndex); HiLog::Debug(LABEL, "CreateImageSource fdIndex is [%{public}d]", asyncContext->fdIndex); + fileDescriptor_ = asyncContext->fdIndex; imageSource = ImageSource::CreateImageSource(asyncContext->fdIndex, opts, errorCode); } else if (argCount == NUM_1) { status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->sourceBuffer), &(asyncContext->sourceBufferSize)); + fileBuffer_ = asyncContext->sourceBuffer; + fileBufferSize_ = asyncContext->sourceBufferSize; imageSource = ImageSource::CreateImageSource(static_cast(asyncContext->sourceBuffer), asyncContext->sourceBufferSize, opts, errorCode); } @@ -791,11 +805,44 @@ static void ModifyImagePropertyComplete(napi_env env, napi_status status, ImageS HiLog::Error(LABEL, "context is nullptr"); return; } - napi_value result = nullptr; - napi_get_undefined(env, &result); + napi_value result[NUM_2] = {0}; + napi_get_undefined(env, &result[NUM_0]); + napi_get_undefined(env, &result[NUM_1]); + napi_value retVal; + napi_value callback = nullptr; + if (context->status == ERR_MEDIA_WRITE_PARCEL_FAIL) { + if (context->fdIndex != -1) { + napi_create_string_utf8(env, "Create Fd without write permission!", NAPI_AUTO_LENGTH, &result[NUM_0]); + } + } else if (context->status == ERR_MEDIA_OUT_OF_RANGE) { + napi_create_string_utf8(env, "The given buffer size is too small to add new exif data!", + NAPI_AUTO_LENGTH, &result[NUM_0]); + } else if (context->status == ERR_IMAGE_DECODE_EXIF_UNSUPPORT) { + napi_create_string_utf8(env, "The exif data format is not standard, so modify it failed!", + NAPI_AUTO_LENGTH, &result[NUM_0]); + } else if (context->status == ERR_MEDIA_VALUE_INVALID) { + napi_create_string_utf8(env, (context->errMsg).c_str(), NAPI_AUTO_LENGTH, &result[NUM_0]); + } + + if (context->deferred) { + if (context->status == SUCCESS) { + napi_resolve_deferred(env, context->deferred, result[NUM_1]); + } else { + napi_reject_deferred(env, context->deferred, result[NUM_0]); + } + } else { + HiLog::Debug(LABEL, "call callback function"); + napi_get_reference_value(env, context->callbackRef, &callback); + napi_call_function(env, nullptr, callback, NUM_2, result, &retVal); + napi_delete_reference(env, context->callbackRef); + } + + napi_delete_async_work(env, context->work); + + delete context; + context = nullptr; HiLog::Debug(LABEL, "ModifyPropertyComplete OUT"); - ImageSourceCallbackRoutine(env, context, result); } static void GetImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context) @@ -865,6 +912,67 @@ static std::unique_ptr UnwrapContext(napi_env env, napi return context; } +static bool CheckExifDataValue(const std::string &key, const std::string &value, std::string &errorInfo) +{ + if (IsSameTextStr(key, "BitsPerSample")) { + std::vector bitsVec; + SplitStr(value, ",", bitsVec); + if (bitsVec.size() > NUM_2) { + errorInfo = "BitsPerSample has invalid exif value: "; + errorInfo.append(value); + return false; + } + for (size_t i = 0; i < bitsVec.size(); i++) { + if (!IsNumericStr(bitsVec[i])) { + errorInfo = "BitsPerSample has invalid exif value: "; + errorInfo.append(bitsVec[i]); + return false; + } + } + } else if (IsSameTextStr(key, "Orientation")) { + if (!IsNumericStr(value) || atoi(value.c_str()) < 1 || atoi(value.c_str()) > NUM_8) { + errorInfo = "Orientation has invalid exif value: "; + errorInfo.append(value); + return false; + } + } else if (IsSameTextStr(key, "ImageLength") || IsSameTextStr(key, "ImageWidth")) { + if (!IsNumericStr(value)) { + errorInfo = "ImageLength or ImageWidth has invalid exif value: "; + errorInfo.append(value); + return false; + } + } else if (IsSameTextStr(key, "GPSLatitude") || IsSameTextStr(key, "GPSLongitude")) { + std::vector gpsVec; + SplitStr(value, ",", gpsVec); + if (gpsVec.size() != NUM_2) { + errorInfo = "GPSLatitude or GPSLongitude has invalid exif value: "; + errorInfo.append(value); + return false; + } + + for (size_t i = 0; i < gpsVec.size(); i++) { + if (!IsNumericStr(gpsVec[i])) { + errorInfo = "GPSLatitude or GPSLongitude has invalid exif value: "; + errorInfo.append(gpsVec[i]); + return false; + } + } + } else if (IsSameTextStr(key, "GPSLatitudeRef")) { + if (!IsSameTextStr(value, "N") && !IsSameTextStr(value, "S")) { + errorInfo = "GPSLatitudeRef has invalid exif value: "; + errorInfo.append(value); + return false; + } + } else if (IsSameTextStr(key, "GPSLongitudeRef")) { + if (!IsSameTextStr(value, "W") && !IsSameTextStr(value, "E")) { + errorInfo = "GPSLongitudeRef has invalid exif value: "; + errorInfo.append(value); + return false; + } + } + return true; +} + static std::unique_ptr UnwrapContextForModify(napi_env env, napi_callback_info info) { @@ -914,6 +1022,9 @@ static std::unique_ptr UnwrapContextForModify(napi_env } } context->pathName = ImageSourceNapi::filePath_; + context->fdIndex = ImageSourceNapi::fileDescriptor_; + context->sourceBuffer = ImageSourceNapi::fileBuffer_; + context->sourceBufferSize = ImageSourceNapi::fileBufferSize_; return context; } @@ -940,8 +1051,25 @@ napi_value ImageSourceNapi::ModifyImageProperty(napi_env env, napi_callback_info [](napi_env env, void *data) { auto context = static_cast(data); - context->status = context->rImageSource->ModifyImageProperty(context->index, - context->keyStr, context->valueStr, context->pathName); + + if (!CheckExifDataValue(context->keyStr, context->valueStr, context->errMsg)) { + HiLog::Error(LABEL, "There is invalid exif data parameter"); + context->status = ERR_MEDIA_VALUE_INVALID; + return; + } + if (!IsSameTextStr(context->pathName, "")) { + context->status = context->rImageSource->ModifyImageProperty(context->index, + context->keyStr, context->valueStr, context->pathName); + } else if (context->fdIndex != -1) { + context->status = context->rImageSource->ModifyImageProperty(context->index, + context->keyStr, context->valueStr, context->fdIndex); + } else if (context->sourceBuffer != nullptr) { + context->status = context->rImageSource->ModifyImageProperty(context->index, + context->keyStr, context->valueStr, static_cast(context->sourceBuffer), + context->sourceBufferSize); + } else { + HiLog::Error(LABEL, "There is no image source!"); + } }, reinterpret_cast(ModifyImagePropertyComplete), asyncContext, diff --git a/interfaces/innerkits/include/image_source.h b/interfaces/innerkits/include/image_source.h index 1c33bbe017fd4588019093bd2a2186afc6bf77ac..3ec8b00f8d0638a12b6277095ad40936af8a59b1 100644 --- a/interfaces/innerkits/include/image_source.h +++ b/interfaces/innerkits/include/image_source.h @@ -164,6 +164,10 @@ public: 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 uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + const int fd); + NATIVEEXPORT uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + uint8_t *data, uint32_t size); 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 5af361ec566e0e4c443cc82506a0b5fcb1ce4efe..23623f06c8e648341b75b5313854cd9c67efc70a 100644 --- a/interfaces/kits/js/common/include/image_source_napi.h +++ b/interfaces/kits/js/common/include/image_source_napi.h @@ -39,6 +39,9 @@ public: } static std::string filePath_; + static int fileDescriptor_; + static void* fileBuffer_; + static size_t fileBufferSize_; private: static napi_value Constructor(napi_env env, napi_callback_info info); diff --git a/plugins/common/libs/image/libjpegplugin/include/exif_info.h b/plugins/common/libs/image/libjpegplugin/include/exif_info.h index 8ca9cca3567b0b03aa4b21ddf8836ac85d2cac63..803975886f17a6757793d6e3d71e825adaa822e0 100644 --- a/plugins/common/libs/image/libjpegplugin/include/exif_info.h +++ b/plugins/common/libs/image/libjpegplugin/include/exif_info.h @@ -36,7 +36,9 @@ public: */ int ParseExifData(const unsigned char *buf, unsigned len); int ParseExifData(const std::string &data); - bool ModifyExifData(const ExifTag &tag, const std::string &value, const std::string &path); + uint32_t ModifyExifData(const ExifTag &tag, const std::string &value, const std::string &path); + uint32_t ModifyExifData(const ExifTag &tag, const std::string &value, const int fd); + uint32_t ModifyExifData(const ExifTag &tag, const std::string &value, unsigned char *data, uint32_t size); public: std::string bitsPerSample_; // Number of bits in each pixel of an image. @@ -51,11 +53,18 @@ public: private: void SetExifTagValues(const ExifTag &tag, const std::string &value); - ExifIfd GetImageFileDirectory(const ExifTag &tag); ExifEntry* InitExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag); ExifEntry* CreateExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len, ExifFormat format); long GetFileSize(FILE *fp); - void ReleaseSource(unsigned char *buf, FILE *file); + void ReleaseSource(unsigned char **ptrBuf, FILE **ptrFile); + bool CreateExifData(unsigned char *buf, unsigned long length, ExifData **data, bool &isNewExifData); + unsigned int GetOrginExifDataLength(const bool &isNewExifData, unsigned char *buf); + ExifByteOrder GetExifByteOrder(const bool &isNewExifData, unsigned char *buf); + bool CreateExifEntry(const ExifTag &tag, ExifData *data, const std::string &value, + ExifByteOrder order, ExifEntry **ptrEntry); + bool WriteExifDataToFile(ExifData *data, unsigned int orginExifDataLength, unsigned long fileLength, + unsigned char *buf, FILE *fp); + void UpdateCacheExifData(FILE *fp); private: ExifIfd imageFileDirectory_; diff --git a/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h b/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h index 97aacf26ccc8c0d6529a7cf52104d642c537f8df..fa9e20977cb08cf40e19e8697358c2cc16eeec13 100644 --- a/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h +++ b/plugins/common/libs/image/libjpegplugin/include/jpeg_decoder.h @@ -55,7 +55,10 @@ public: 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; - + uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + const int fd) override; + uint32_t ModifyImageProperty(uint32_t index, const std::string &key, const std::string &value, + uint8_t *data, uint32_t size) override; private: DISALLOW_COPY_AND_MOVE(JpegDecoder); int ExifPrintMethod(); @@ -69,7 +72,7 @@ private: void CreateDecoder(); bool IsMarker(uint8_t rawPrefix, uint8_t rawMarkderCode, uint8_t markerCode); bool FindMarker(InputDataStream &stream, uint8_t marker); - ExifTag getExifTagFromKey(const std::string &key, const std::string &value); + ExifTag getExifTagFromKey(const std::string &key); static MultimediaPlugin::PluginServer &pluginServer_; jpeg_decompress_struct decodeInfo_; diff --git a/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp b/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp index b83a24c9ddac227076b54b9dc379eb27d32bac23..dec4d62fc73c33833cf4e82dc0793d8089496883 100644 --- a/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/exif_info.cpp @@ -15,6 +15,8 @@ #include "exif_info.h" #include #include +#include +#include "media_errors.h" #include "string_ex.h" #include "securec.h" @@ -38,6 +40,7 @@ namespace { static const int MOVE_OFFSET_8 = 8; static const int LENGTH_ARRAY_SIZE = 2; static const int CONSTANT_2 = 2; + static const unsigned long MAX_FILE_SIZE = 1000 * 1000 * 1000; /* raw EXIF header data */ static const unsigned char exifHeader[] = { @@ -117,195 +120,188 @@ void EXIFInfo::SetExifTagValues(const ExifTag &tag, const std::string &value) } } -bool EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, const std::string &path) +uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, const std::string &path) { FILE *file = fopen(path.c_str(), "rb"); if (file == nullptr) { HiLog::Error(LABEL, "Error creating file %{public}s", path.c_str()); - return false; + return Media::ERR_MEDIA_IO_ABNORMAL; } // read jpeg file to buff unsigned long fileLength = GetFileSize(file); - if (fileLength == 0) { + if (fileLength == 0 || fileLength > MAX_FILE_SIZE) { HiLog::Error(LABEL, "Get file size failed."); fclose(file); - return false; + return Media::ERR_MEDIA_BUFFER_TOO_SMALL; } - unsigned char *fileBuf = (unsigned char *)malloc(fileLength); + + unsigned char *fileBuf = static_cast(malloc(fileLength)); if (fileBuf == nullptr) { HiLog::Error(LABEL, "Allocate buf for %{public}s failed.", path.c_str()); fclose(file); - return false; + return Media::ERR_IMAGE_MALLOC_ABNORMAL; } if (fread(fileBuf, fileLength, 1, file) != 1) { HiLog::Error(LABEL, "Read %{public}s failed.", path.c_str()); - ReleaseSource(fileBuf, file); - return false; + ReleaseSource(&fileBuf, &file); + return Media::ERR_MEDIA_READ_PARCEL_FAIL; } if (!(fileBuf[0] == 0xFF && fileBuf[1] == 0xD8)) { HiLog::Error(LABEL, "%{public}s is not jpeg file.", path.c_str()); - ReleaseSource(fileBuf, file); - return false; + ReleaseSource(&fileBuf, &file); + return Media::ERR_IMAGE_MISMATCHED_FORMAT; } - unsigned char lenthArray[LENGTH_ARRAY_SIZE] = { - fileBuf[BUFFER_POSITION_5], fileBuf[BUFFER_POSITION_4] - }; - unsigned int orginExifDataLength = *(unsigned int*)lenthArray; - ExifData *ptrExifData = nullptr; - if ((fileBuf[BUFFER_POSITION_6] == 'E' && fileBuf[BUFFER_POSITION_7] == 'x' && - fileBuf[BUFFER_POSITION_8] == 'i' && fileBuf[BUFFER_POSITION_9] == 'f')) { - ptrExifData = exif_data_new_from_file(path.c_str()); - if (!ptrExifData) { - HiLog::Error(LABEL, "Create exif data from file failed."); - ReleaseSource(fileBuf, file); - return false; - } - } else { - ptrExifData = exif_data_new(); - if (!ptrExifData) { - HiLog::Error(LABEL, "Create exif data failed."); - ReleaseSource(fileBuf, file); - return false; - } - /* Set the image options */ - exif_data_set_option(ptrExifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); - exif_data_set_data_type(ptrExifData, EXIF_DATA_TYPE_COMPRESSED); - exif_data_set_byte_order(ptrExifData, EXIF_BYTE_ORDER_INTEL); - - /* Create the mandatory EXIF fields with default data */ - exif_data_fix(ptrExifData); + bool isNewExifData = false; + if (!CreateExifData(fileBuf, fileLength, &ptrExifData, isNewExifData)) { + ReleaseSource(&fileBuf, &file); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; } (void)fclose(file); file = nullptr; - ExifByteOrder order = EXIF_BYTE_ORDER_MOTOROLA; - if (fileBuf[BUFFER_POSITION_12] == 'M' && fileBuf[BUFFER_POSITION_13] == 'M') { - order = EXIF_BYTE_ORDER_MOTOROLA; - } else { - order = EXIF_BYTE_ORDER_INTEL; + unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, fileBuf); + if (!isNewExifData && orginExifDataLength == 0) { + HiLog::Error(LABEL, "There is no orginExifDataLength node in %{public}s.", path.c_str()); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; } - FILE *newFile = fopen(path.c_str(), "wb"); + ExifByteOrder order = GetExifByteOrder(isNewExifData, fileBuf); + FILE *newFile = fopen(path.c_str(), "wb+"); if (newFile == nullptr) { HiLog::Error(LABEL, "Error create new file %{public}s", path.c_str()); - ReleaseSource(fileBuf, newFile); - return false; + ReleaseSource(&fileBuf, &newFile); + return Media::ERR_MEDIA_IO_ABNORMAL; + } + ExifEntry *entry = nullptr; + if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) { + ReleaseSource(&fileBuf, &newFile); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + if (!WriteExifDataToFile(ptrExifData, orginExifDataLength, fileLength, fileBuf, newFile)) { + ReleaseSource(&fileBuf, &newFile); + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_WRITE_PARCEL_FAIL; + } + ReleaseSource(&fileBuf, &newFile); + exif_data_unref(ptrExifData); + return Media::SUCCESS; +} + +uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, const int fd) +{ + const int localFd = dup(fd); + FILE *file = fdopen(localFd, "wb+"); + if (file == nullptr) { + HiLog::Error(LABEL, "Error creating file %{public}d", localFd); + return Media::ERR_MEDIA_IO_ABNORMAL; + } + + // read jpeg file to buff + unsigned long fileLength = GetFileSize(file); + if (fileLength == 0 || fileLength > MAX_FILE_SIZE) { + HiLog::Error(LABEL, "Get file size failed."); + fclose(file); + return Media::ERR_MEDIA_BUFFER_TOO_SMALL; + } + + unsigned char *fileBuf = static_cast(malloc(fileLength)); + if (fileBuf == nullptr) { + HiLog::Error(LABEL, "Allocate buf for %{public}d failed.", localFd); + fclose(file); + return Media::ERR_IMAGE_MALLOC_ABNORMAL; } + // Set current position to begin of file. + (void)fseek(file, 0L, 0); + if (fread(fileBuf, fileLength, 1, file) != 1) { + HiLog::Error(LABEL, "Read %{public}d failed.", localFd); + ReleaseSource(&fileBuf, &file); + return Media::ERR_MEDIA_READ_PARCEL_FAIL; + } + + if (!(fileBuf[0] == 0xFF && fileBuf[1] == 0xD8)) { + HiLog::Error(LABEL, "%{public}d is not jpeg file.", localFd); + ReleaseSource(&fileBuf, &file); + return Media::ERR_IMAGE_MISMATCHED_FORMAT; + } + + ExifData *ptrExifData = nullptr; + bool isNewExifData = false; + if (!CreateExifData(fileBuf, fileLength, &ptrExifData, isNewExifData)) { + ReleaseSource(&fileBuf, &file); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, fileBuf); + if (!isNewExifData && orginExifDataLength == 0) { + HiLog::Error(LABEL, "There is no orginExifDataLength node in %{public}d.", localFd); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + ExifByteOrder order = GetExifByteOrder(isNewExifData, fileBuf); + // Set current position to begin of new file. + (void)fseek(file, 0L, 0); ExifEntry *entry = nullptr; - switch (tag) { - case EXIF_TAG_BITS_PER_SAMPLE: { - entry = InitExifTag(ptrExifData, EXIF_IFD_1, EXIF_TAG_BITS_PER_SAMPLE); - std::vector bitsVec; - SplitStr(value, ",", bitsVec); - if (bitsVec.size() > CONSTANT_2) { - HiLog::Error(LABEL, "BITS_PER_SAMPLE Invalid value %{public}s", value.c_str()); - ReleaseSource(fileBuf, newFile); - return false; - } - if (entry == nullptr) { - return false; - } - if (bitsVec.size() != 0) { - for (size_t i = 0; i < bitsVec.size(); i++) { - exif_set_short(entry->data + i * CONSTANT_2, order, (ExifShort)atoi(bitsVec[i].c_str())); - } - } - break; - } - case EXIF_TAG_ORIENTATION: { - entry = InitExifTag(ptrExifData, EXIF_IFD_0, EXIF_TAG_ORIENTATION); - if (entry == nullptr) { - return false; - } - exif_set_short(entry->data, order, (ExifShort)atoi(value.c_str())); - break; - } - case EXIF_TAG_IMAGE_LENGTH: { - entry = InitExifTag(ptrExifData, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH); - if (entry == nullptr) { - return false; - } - exif_set_short(entry->data, order, (ExifShort)atoi(value.c_str())); - break; - } - case EXIF_TAG_IMAGE_WIDTH: { - entry = InitExifTag(ptrExifData, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH); - if (entry == nullptr) { - return false; - } - exif_set_short(entry->data, order, (ExifShort)atoi(value.c_str())); - break; - } - case EXIF_TAG_GPS_LATITUDE: { - std::vector latVec; - SplitStr(value, ",", latVec); - if (latVec.size() != CONSTANT_2) { - HiLog::Error(LABEL, "GPS_LATITUDE Invalid value %{public}s", value.c_str()); - ReleaseSource(fileBuf, newFile); - return false; - } + if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) { + ReleaseSource(&fileBuf, &file); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } - ExifRational latRational; - latRational.numerator = atoi(latVec[0].c_str()); - latRational.denominator = atoi(latVec[1].c_str()); - entry = CreateExifTag(ptrExifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, - sizeof(latRational), EXIF_FORMAT_RATIONAL); - if (entry == nullptr) { - return false; - } - exif_set_rational(entry->data, order, latRational); - break; - } - case EXIF_TAG_GPS_LONGITUDE: { - std::vector longVec; - SplitStr(value, ",", longVec); - if (longVec.size() != CONSTANT_2) { - HiLog::Error(LABEL, "GPS_LONGITUDE Invalid value %{public}s", value.c_str()); - ReleaseSource(fileBuf, newFile); - return false; - } + if (!WriteExifDataToFile(ptrExifData, orginExifDataLength, fileLength, fileBuf, file)) { + ReleaseSource(&fileBuf, &file); + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_WRITE_PARCEL_FAIL; + } + ReleaseSource(&fileBuf, &file); + exif_data_unref(ptrExifData); + return Media::SUCCESS; +} - ExifRational longRational; - longRational.numerator = atoi(longVec[0].c_str()); - longRational.denominator = atoi(longVec[1].c_str()); - entry = CreateExifTag(ptrExifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, - sizeof(longRational), EXIF_FORMAT_RATIONAL); - if (entry == nullptr) { - return false; - } - exif_set_rational(entry->data, order, longRational); - break; - } - case EXIF_TAG_GPS_LATITUDE_REF: { - entry = CreateExifTag(ptrExifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, - value.length(), EXIF_FORMAT_ASCII); - if (entry == nullptr) { - return false; - } - if (memcpy_s(entry->data, value.length(), value.c_str(), value.length()) != 0) { - HiLog::Error(LABEL, "LATITUDE ref memcpy error"); - } - break; - } - case EXIF_TAG_GPS_LONGITUDE_REF: { - entry = CreateExifTag(ptrExifData, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, - value.length(), EXIF_FORMAT_ASCII); - if (entry == nullptr) { - return false; - } - if (memcpy_s(entry->data, value.length(), value.c_str(), value.length()) != 0) { - HiLog::Error(LABEL, "LONGITUDE ref memcpy error"); - } - break; - } - default: - break; +uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, + unsigned char *data, uint32_t size) +{ + if (data == nullptr) { + HiLog::Error(LABEL, "buffer is nullptr."); + return Media::ERR_IMAGE_SOURCE_DATA; + } + + if (size == 0) { + HiLog::Error(LABEL, "buffer size is 0."); + return Media::ERR_MEDIA_BUFFER_TOO_SMALL; + } + + if (!(data[0] == 0xFF && data[1] == 0xD8)) { + HiLog::Error(LABEL, "This is not jpeg file."); + return Media::ERR_IMAGE_MISMATCHED_FORMAT; + } + + ExifData *ptrExifData = nullptr; + bool isNewExifData = false; + if (!CreateExifData(data, size, &ptrExifData, isNewExifData)) { + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, data); + if (!isNewExifData && orginExifDataLength == 0) { + HiLog::Error(LABEL, "There is no orginExifDataLength node in buffer."); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + ExifByteOrder order = GetExifByteOrder(isNewExifData, data); + ExifEntry *entry = nullptr; + if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) { + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; } unsigned char* exifDataBuf = nullptr; @@ -313,68 +309,95 @@ bool EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, cons exif_data_save_data(ptrExifData, &exifDataBuf, &exifDataBufLength); if (exifDataBuf == nullptr) { HiLog::Error(LABEL, "Get Exif Data Buf failed!"); - return false; + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; } - /* Write EXIF header */ - if (fwrite(exifHeader, sizeof(exifHeader), 1, newFile) != 1) { - HiLog::Error(LABEL, "Error writing EXIF header to file!"); - ReleaseSource(fileBuf, newFile); - return false; + if (size == 0 || size > MAX_FILE_SIZE) { + HiLog::Error(LABEL, "Buffer size is out of range."); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + unsigned char *tempBuf = static_cast(malloc(size)); + if (tempBuf == nullptr) { + HiLog::Error(LABEL, "Allocate temp buffer ailed."); + exif_data_unref(ptrExifData); + return Media::ERR_IMAGE_MALLOC_ABNORMAL; } - /* Write EXIF block length in big-endian order */ - if (fputc((exifDataBufLength + LENGTH_OFFSET_2) >> MOVE_OFFSET_8, newFile) < 0) { - HiLog::Error(LABEL, "Error writing EXIF block length to file!"); - ReleaseSource(fileBuf, newFile); - return false; + // Write EXIF header to buffer + uint32_t index = 0; + if (sizeof(exifHeader) >= size) { + HiLog::Error(LABEL, "There is not enough space for EXIF header!"); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_OUT_OF_RANGE; } - if (fputc((exifDataBufLength + LENGTH_OFFSET_2) & 0xff, newFile) < 0) { - HiLog::Error(LABEL, "Error writing EXIF block length to file!"); - ReleaseSource(fileBuf, newFile); - return false; + + for (size_t i = 0; i < sizeof(exifHeader); i++) { + tempBuf[index] = exifHeader[i]; + index += 1; } - /* Write EXIF data block */ - if (fwrite(exifDataBuf, exifDataBufLength, 1, newFile) != 1) { - HiLog::Error(LABEL, "Error writing EXIF data block to file!"); - ReleaseSource(fileBuf, newFile); - return false; + // Write EXIF block length in big-endian order + unsigned char highBit = static_cast((exifDataBufLength + LENGTH_OFFSET_2) >> MOVE_OFFSET_8); + if (index >= size) { + HiLog::Error(LABEL, "There is not enough space for writing EXIF block length!"); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_OUT_OF_RANGE; } - /* Write JPEG image data, skipping the non-EXIF header */ - unsigned int dataOffset = orginExifDataLength + sizeof(exifHeader); - if (fwrite(fileBuf + dataOffset, fileLength - dataOffset, 1, newFile) != 1) { - HiLog::Error(LABEL, "Error writing JPEG image data to file!"); - ReleaseSource(fileBuf, newFile); - return false; + tempBuf[index] = highBit; + index += 1; + + unsigned char lowBit = static_cast((exifDataBufLength + LENGTH_OFFSET_2) & 0xff); + if (index >= size) { + HiLog::Error(LABEL, "There is not enough space for writing EXIF block length!"); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_OUT_OF_RANGE; + } + tempBuf[index] = lowBit; + index += 1; + + // Write EXIF data block + if ((index + exifDataBufLength) >= size) { + HiLog::Error(LABEL, "There is not enough space for writing EXIF data block!"); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_OUT_OF_RANGE; + } + for (unsigned int i = 0; i < exifDataBufLength; i++) { + tempBuf[index] = exifDataBuf[i]; + index += 1; } - ReleaseSource(fileBuf, newFile); - return true; -} + // Write JPEG image data, skipping the non-EXIF header + if ((index + size - orginExifDataLength - sizeof(exifHeader)) > size) { + HiLog::Error(LABEL, "There is not enough space for writing JPEG image data!"); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::ERR_MEDIA_OUT_OF_RANGE; + } + for (unsigned int i = 0; i < (size - orginExifDataLength - sizeof(exifHeader)); i++) { + tempBuf[index] = data[orginExifDataLength + sizeof(exifHeader) + i]; + index += 1; + } -ExifIfd EXIFInfo::GetImageFileDirectory(const ExifTag &tag) -{ - switch (tag) { - case EXIF_TAG_BITS_PER_SAMPLE: - case EXIF_TAG_ORIENTATION: - case EXIF_TAG_IMAGE_LENGTH: - case EXIF_TAG_IMAGE_WIDTH: { - return EXIF_IFD_0; - } - case EXIF_TAG_DATE_TIME_ORIGINAL: { - return EXIF_IFD_EXIF; - } - case EXIF_TAG_GPS_LATITUDE: - case EXIF_TAG_GPS_LONGITUDE: - case EXIF_TAG_GPS_LATITUDE_REF: - case EXIF_TAG_GPS_LONGITUDE_REF: { - return EXIF_IFD_GPS; - } - default: - break; + for (unsigned int i = 0; i < size; i++) { + data[i] = tempBuf[i]; } - return EXIF_IFD_COUNT; + + ParseExifData(data, static_cast(index)); + free(tempBuf); + tempBuf = nullptr; + exif_data_unref(ptrExifData); + return Media::SUCCESS; } ExifEntry* EXIFInfo::InitExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag) @@ -411,7 +434,7 @@ ExifEntry* EXIFInfo::CreateExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag, { void *buf; ExifEntry *entry; - + if ((entry = exif_content_get_entry(exif->ifd[ifd], tag)) != nullptr) { return entry; } @@ -461,30 +484,247 @@ long EXIFInfo::GetFileSize(FILE *fp) /* Save the current position. */ position = ftell(fp); - + /* Jump to the end of the file. */ - fseek(fp, 0L, SEEK_END); - + (void)fseek(fp, 0L, SEEK_END); + /* Get the end position. */ size = ftell(fp); - + /* Jump back to the original position. */ - fseek(fp, position, SEEK_SET); + (void)fseek(fp, position, SEEK_SET); return size; } -void EXIFInfo::ReleaseSource(unsigned char *buf, FILE *file) +bool EXIFInfo::CreateExifData(unsigned char *buf, unsigned long length, ExifData **ptrData, bool &isNewExifData) { - if (buf) { - free(buf); - buf = nullptr; + if ((buf[BUFFER_POSITION_6] == 'E' && buf[BUFFER_POSITION_7] == 'x' && + buf[BUFFER_POSITION_8] == 'i' && buf[BUFFER_POSITION_9] == 'f')) { + *ptrData = exif_data_new_from_data(buf, static_cast(length)); + if (!(*ptrData)) { + HiLog::Error(LABEL, "Create exif data from file failed."); + return false; + } + isNewExifData = false; + HiLog::Error(LABEL, "Create exif data from buffer."); + } else { + *ptrData = exif_data_new(); + if (!(*ptrData)) { + HiLog::Error(LABEL, "Create exif data failed."); + return false; + } + /* Set the image options */ + exif_data_set_option(*ptrData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); + exif_data_set_data_type(*ptrData, EXIF_DATA_TYPE_COMPRESSED); + exif_data_set_byte_order(*ptrData, EXIF_BYTE_ORDER_INTEL); + + /* Create the mandatory EXIF fields with default data */ + exif_data_fix(*ptrData); + isNewExifData = true; + HiLog::Error(LABEL, "Create new exif data."); } + return true; +} - if (file != nullptr) { - fclose(file); - file = nullptr; +unsigned int EXIFInfo::GetOrginExifDataLength(const bool &isNewExifData, unsigned char *buf) +{ + unsigned int orginExifDataLength = 0; + if (!isNewExifData) { + unsigned char lenthArray[LENGTH_ARRAY_SIZE] = { + buf[BUFFER_POSITION_5], buf[BUFFER_POSITION_4] + }; + orginExifDataLength = *(unsigned int*)lenthArray; + } + return orginExifDataLength; +} + +ExifByteOrder EXIFInfo::GetExifByteOrder(const bool &isNewExifData, unsigned char *buf) +{ + if (isNewExifData) { + return EXIF_BYTE_ORDER_INTEL; + } else { + if (buf[BUFFER_POSITION_12] == 'M' && buf[BUFFER_POSITION_13] == 'M') { + return EXIF_BYTE_ORDER_MOTOROLA; + } else { + return EXIF_BYTE_ORDER_INTEL; + } + } +} + +bool EXIFInfo::CreateExifEntry(const ExifTag &tag, ExifData *data, const std::string &value, + ExifByteOrder order, ExifEntry **ptrEntry) +{ + switch (tag) { + case EXIF_TAG_BITS_PER_SAMPLE: { + *ptrEntry = InitExifTag(data, EXIF_IFD_1, EXIF_TAG_BITS_PER_SAMPLE); + std::vector bitsVec; + SplitStr(value, ",", bitsVec); + if (bitsVec.size() > CONSTANT_2) { + HiLog::Error(LABEL, "BITS_PER_SAMPLE Invalid value %{public}s", value.c_str()); + return false; + } + if (bitsVec.size() != 0) { + for (size_t i = 0; i < bitsVec.size(); i++) { + exif_set_short((*ptrEntry)->data + i * CONSTANT_2, order, (ExifShort)atoi(bitsVec[i].c_str())); + } + } + break; + } + case EXIF_TAG_ORIENTATION: { + *ptrEntry = InitExifTag(data, EXIF_IFD_0, EXIF_TAG_ORIENTATION); + exif_set_short((*ptrEntry)->data, order, (ExifShort)atoi(value.c_str())); + break; + } + case EXIF_TAG_IMAGE_LENGTH: { + *ptrEntry = InitExifTag(data, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH); + exif_set_long((*ptrEntry)->data, order, (ExifLong)atoi(value.c_str())); + break; + } + case EXIF_TAG_IMAGE_WIDTH: { + *ptrEntry = InitExifTag(data, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH); + exif_set_long((*ptrEntry)->data, order, (ExifLong)atoi(value.c_str())); + break; + } + case EXIF_TAG_GPS_LATITUDE: { + std::vector latVec; + SplitStr(value, ",", latVec); + if (latVec.size() != CONSTANT_2) { + HiLog::Error(LABEL, "GPS_LATITUDE Invalid value %{public}s", value.c_str()); + return false; + } + + ExifRational latRational; + latRational.numerator = atoi(latVec[0].c_str()); + latRational.denominator = atoi(latVec[1].c_str()); + *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE, + sizeof(latRational), EXIF_FORMAT_RATIONAL); + exif_set_rational((*ptrEntry)->data, order, latRational); + break; + } + case EXIF_TAG_GPS_LONGITUDE: { + std::vector longVec; + SplitStr(value, ",", longVec); + if (longVec.size() != CONSTANT_2) { + HiLog::Error(LABEL, "GPS_LONGITUDE Invalid value %{public}s", value.c_str()); + return false; + } + + ExifRational longRational; + longRational.numerator = atoi(longVec[0].c_str()); + longRational.denominator = atoi(longVec[1].c_str()); + *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE, + sizeof(longRational), EXIF_FORMAT_RATIONAL); + exif_set_rational((*ptrEntry)->data, order, longRational); + break; + } + case EXIF_TAG_GPS_LATITUDE_REF: { + *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, + value.length(), EXIF_FORMAT_ASCII); + if (memcpy_s((*ptrEntry)->data, value.length(), value.c_str(), value.length()) != 0) { + HiLog::Error(LABEL, "LATITUDE ref memcpy error"); + } + break; + } + case EXIF_TAG_GPS_LONGITUDE_REF: { + *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, + value.length(), EXIF_FORMAT_ASCII); + if (memcpy_s((*ptrEntry)->data, value.length(), value.c_str(), value.length()) != 0) { + HiLog::Error(LABEL, "LONGITUDE ref memcpy error"); + } + break; + } + default: + break; + } + return true; +} + +bool EXIFInfo::WriteExifDataToFile(ExifData *data, unsigned int orginExifDataLength, unsigned long fileLength, + unsigned char *buf, FILE *fp) +{ + unsigned char* exifDataBuf = nullptr; + unsigned int exifDataBufLength = 0; + exif_data_save_data(data, &exifDataBuf, &exifDataBufLength); + if (exifDataBuf == nullptr) { + HiLog::Error(LABEL, "Get Exif Data Buf failed!"); + return false; } + + // Write EXIF header + if (fwrite(exifHeader, sizeof(exifHeader), 1, fp) != 1) { + HiLog::Error(LABEL, "Error writing EXIF header to file!"); + return false; + } + + // Write EXIF block length in big-endian order + if (fputc((exifDataBufLength + LENGTH_OFFSET_2) >> MOVE_OFFSET_8, fp) < 0) { + HiLog::Error(LABEL, "Error writing EXIF block length to file!"); + return false; + } + + if (fputc((exifDataBufLength + LENGTH_OFFSET_2) & 0xff, fp) < 0) { + HiLog::Error(LABEL, "Error writing EXIF block length to file!"); + return false; + } + + // Write EXIF data block + if (fwrite(exifDataBuf, exifDataBufLength, 1, fp) != 1) { + HiLog::Error(LABEL, "Error writing EXIF data block to file!"); + return false; + } + // Write JPEG image data, skipping the non-EXIF header + unsigned int dataOffset = orginExifDataLength + sizeof(exifHeader); + if (fwrite(buf + dataOffset, fileLength - dataOffset, 1, fp) != 1) { + HiLog::Error(LABEL, "Error writing JPEG image data to file!"); + return false; + } + + UpdateCacheExifData(fp); + return true; +} + +void EXIFInfo::ReleaseSource(unsigned char **ptrBuf, FILE **ptrFile) +{ + if (*ptrBuf) { + free(*ptrBuf); + *ptrBuf = nullptr; + ptrBuf = nullptr; + } + + if (*ptrFile != nullptr) { + fclose(*ptrFile); + *ptrFile = nullptr; + ptrFile = nullptr; + } +} + +void EXIFInfo::UpdateCacheExifData(FILE *fp) +{ + unsigned long fileLength = GetFileSize(fp); + if (fileLength == 0 || fileLength > MAX_FILE_SIZE) { + HiLog::Error(LABEL, "Get file size failed."); + return; + } + + unsigned char *fileBuf = static_cast(malloc(fileLength)); + if (fileBuf == nullptr) { + HiLog::Error(LABEL, "Allocate buf failed."); + return; + } + + // Set current position to begin of file. + (void)fseek(fp, 0L, 0); + if (fread(fileBuf, fileLength, 1, fp) != 1) { + HiLog::Error(LABEL, "Read new file failed."); + free(fileBuf); + fileBuf = nullptr; + return; + } + + ParseExifData(fileBuf, static_cast(fileLength)); + free(fileBuf); + fileBuf = 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 cd33b15d447d388af777595aa067616e6b986391..155728a5a100061bc0afe948b3eed2480d0b2a75 100644 --- a/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp +++ b/plugins/common/libs/image/libjpegplugin/src/jpeg_decoder.cpp @@ -600,34 +600,25 @@ uint32_t JpegDecoder::GetImagePropertyString(uint32_t index, const std::string & return Media::SUCCESS; } -ExifTag JpegDecoder::getExifTagFromKey(const std::string &key, const std::string &value) +ExifTag JpegDecoder::getExifTagFromKey(const std::string &key) { if (IsSameTextStr(key, BITS_PER_SAMPLE)) { - exifInfo_.bitsPerSample_ = value; return EXIF_TAG_BITS_PER_SAMPLE; } else if (IsSameTextStr(key, ORIENTATION)) { - exifInfo_.orientation_ = value; return EXIF_TAG_ORIENTATION; } else if (IsSameTextStr(key, IMAGE_LENGTH)) { - exifInfo_.imageLength_ = value; return EXIF_TAG_IMAGE_LENGTH; } else if (IsSameTextStr(key, IMAGE_WIDTH)) { - exifInfo_.imageWidth_ = value; return EXIF_TAG_IMAGE_WIDTH; } else if (IsSameTextStr(key, GPS_LATITUDE)) { - exifInfo_.gpsLatitude_ = value; return EXIF_TAG_GPS_LATITUDE; } else if (IsSameTextStr(key, GPS_LONGITUDE)) { - exifInfo_.gpsLongitude_ = value; return EXIF_TAG_GPS_LONGITUDE; } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) { - exifInfo_.gpsLatitudeRef_ = value; return EXIF_TAG_GPS_LATITUDE_REF; } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) { - exifInfo_.gpsLongitudeRef_ = value; return EXIF_TAG_GPS_LONGITUDE_REF; } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) { - exifInfo_.dateTimeOriginal_ = value; return EXIF_TAG_DATE_TIME_ORIGINAL; } else { return EXIF_TAG_PRINT_IMAGE_MATCHING; @@ -637,15 +628,50 @@ ExifTag JpegDecoder::getExifTagFromKey(const std::string &key, const std::string 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()); - ExifTag tag = getExifTagFromKey(key, value); + HiLog::Error(LABEL, "[ModifyImageProperty] with path:%{public}s, key:%{public}s, value:%{public}s", + path.c_str(), key.c_str(), value.c_str()); + ExifTag tag = getExifTagFromKey(key); if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) { return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; } - if (!exifInfo_.ModifyExifData(tag, value, path)) { - return ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + uint32_t ret = exifInfo_.ModifyExifData(tag, value, path); + if (ret != Media::SUCCESS) { + return ret; + } + return Media::SUCCESS; +} + +uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const int fd) +{ + HiLog::Error(LABEL, "[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s", + fd, key.c_str(), value.c_str()); + ExifTag tag = getExifTagFromKey(key); + if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) { + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + uint32_t ret = exifInfo_.ModifyExifData(tag, value, fd); + if (ret != Media::SUCCESS) { + return ret; + } + return Media::SUCCESS; +} + +uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, uint8_t *data, uint32_t size) +{ + HiLog::Error(LABEL, "[ModifyImageProperty] with buffer:%{public}p, key:%{public}s, value:%{public}s", + data, key.c_str(), value.c_str()); + ExifTag tag = getExifTagFromKey(key); + if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) { + return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT; + } + + uint32_t ret = exifInfo_.ModifyExifData(tag, value, data, size); + if (ret != Media::SUCCESS) { + return ret; } return Media::SUCCESS; } diff --git a/plugins/manager/include/image/abs_image_decoder.h b/plugins/manager/include/image/abs_image_decoder.h index 7dffb2e5606cdb8a4e29e5dd98a3e23fed2b1db4..97e8309c9ff5fc59eca429596380800b9f4bc786 100644 --- a/plugins/manager/include/image/abs_image_decoder.h +++ b/plugins/manager/include/image/abs_image_decoder.h @@ -154,6 +154,18 @@ public: return Media::ERR_MEDIA_INVALID_OPERATION; } + virtual uint32_t ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, const int fd) + { + return Media::ERR_MEDIA_INVALID_OPERATION; + } + + virtual uint32_t ModifyImageProperty(uint32_t index, const std::string &key, + const std::string &value, uint8_t *data, uint32_t size) + { + return Media::ERR_MEDIA_INVALID_OPERATION; + } + // define multiple subservices for this interface static constexpr uint16_t SERVICE_DEFAULT = 0; };