• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "jpeg_decoder.h"
17 #include <map>
18 #include "hitrace_meter.h"
19 #include "image_trace.h"
20 #include "image_utils.h"
21 #include "jerror.h"
22 #include "media_errors.h"
23 #include "string_ex.h"
24 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
25 #include "surface_buffer.h"
26 #endif
27 
28 #ifndef _WIN32
29 #include "securec.h"
30 #else
31 #include "memory.h"
32 #endif
33 
34 namespace OHOS {
35 namespace ImagePlugin {
36 using namespace OHOS::HiviewDFX;
37 using namespace MultimediaPlugin;
38 using namespace Media;
39 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "JpegDecoder" };
40 static constexpr uint32_t PL_ICC_MARKER = JPEG_APP0 + 2;
41 static constexpr uint32_t PL_MARKER_LENGTH_LIMIT = 0xFFFF;
42 namespace {
43 constexpr uint32_t NUM_100 = 100;
44 constexpr uint32_t PIXEL_BYTES_RGB_565 = 2;
45 constexpr uint32_t MARKER_SIZE = 2;
46 constexpr uint32_t MARKER_LENGTH = 2;
47 constexpr uint8_t MARKER_LENGTH_0_OFFSET = 0;
48 constexpr uint8_t MARKER_LENGTH_1_OFFSET = 1;
49 constexpr uint32_t MARKER_LENGTH_SHIFT = 8;
50 constexpr uint8_t JPG_MARKER_PREFIX_OFFSET = 0;
51 constexpr uint8_t JPG_MARKER_CODE_OFFSET = 1;
52 constexpr uint8_t JPG_MARKER_PREFIX = 0XFF;
53 constexpr uint8_t JPG_MARKER_SOI = 0XD8;
54 constexpr uint8_t JPG_MARKER_SOS = 0XDA;
55 constexpr uint8_t JPG_MARKER_RST = 0XD0;
56 constexpr uint8_t JPG_MARKER_RST0 = 0XD0;
57 constexpr uint8_t JPG_MARKER_RSTN = 0XD7;
58 constexpr uint8_t JPG_MARKER_APP = 0XE0;
59 constexpr uint8_t JPG_MARKER_APP0 = 0XE0;
60 constexpr uint8_t JPG_MARKER_APPN = 0XEF;
61 constexpr size_t TIMES_LEN = 19;
62 constexpr size_t DATE_LEN = 10;
63 constexpr float SCALES[] = { 0.1875f, 0.3125f, 0.4375f, 0.5625f, 0.6875f, 0.8125f, 0.9375f, 1.0f };
64 constexpr int SCALE_NUMS[] = { 2, 3, 4, 5, 6, 7, 8, 8 };
65 constexpr int SCALE_NUMS_LENGTH = 7;
66 const std::string BITS_PER_SAMPLE = "BitsPerSample";
67 const std::string ORIENTATION = "Orientation";
68 const std::string IMAGE_LENGTH = "ImageLength";
69 const std::string IMAGE_WIDTH = "ImageWidth";
70 const std::string GPS_LATITUDE = "GPSLatitude";
71 const std::string GPS_LONGITUDE = "GPSLongitude";
72 const std::string GPS_LATITUDE_REF = "GPSLatitudeRef";
73 const std::string GPS_LONGITUDE_REF = "GPSLongitudeRef";
74 const std::string DATE_TIME_ORIGINAL = "DateTimeOriginal";
75 const std::string DATE_TIME_ORIGINAL_MEDIA = "DateTimeOriginalForMedia";
76 const std::string EXPOSURE_TIME = "ExposureTime";
77 const std::string F_NUMBER = "FNumber";
78 const std::string ISO_SPEED_RATINGS = "ISOSpeedRatings";
79 const std::string SCENE_TYPE = "SceneType";
80 const std::string COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
81 const std::string DATE_TIME = "DateTime";
82 const std::string GPS_TIME_STAMP = "GPSTimeStamp";
83 const std::string GPS_DATE_STAMP = "GPSDateStamp";
84 const std::string IMAGE_DESCRIPTION = "ImageDescription";
85 const std::string MAKE = "Make";
86 const std::string MODEL = "Model";
87 const std::string PHOTO_MODE = "PhotoMode";
88 const std::string SENSITIVITY_TYPE = "SensitivityType";
89 const std::string STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
90 const std::string RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
91 const std::string ISO_SPEED = "ISOSpeedRatings";
92 const std::string APERTURE_VALUE = "ApertureValue";
93 const std::string EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
94 const std::string METERING_MODE = "MeteringMode";
95 const std::string LIGHT_SOURCE = "LightSource";
96 const std::string FLASH = "Flash";
97 const std::string FOCAL_LENGTH = "FocalLength";
98 const std::string USER_COMMENT = "UserComment";
99 const std::string PIXEL_X_DIMENSION = "PixelXDimension";
100 const std::string PIXEL_Y_DIMENSION = "PixelYDimension";
101 const std::string WHITE_BALANCE = "WhiteBalance";
102 const std::string FOCAL_LENGTH_IN_35_MM_FILM = "FocalLengthIn35mmFilm";
103 const std::string HW_MNOTE_CAPTURE_MODE = "HwMnoteCaptureMode";
104 const std::string HW_MNOTE_PHYSICAL_APERTURE = "HwMnotePhysicalAperture";
105 static const std::map<std::string, uint32_t> PROPERTY_INT = {
106     {"Top-left", 0},
107     {"Bottom-right", 180},
108     {"Right-top", 90},
109     {"Left-bottom", 270},
110 };
111 constexpr uint32_t JPEG_APP1_SIZE = 2;
112 constexpr uint32_t ADDRESS_4 = 4;
113 constexpr int OFFSET_8 = 8;
114 } // namespace
115 
116 PluginServer &JpegDecoder::pluginServer_ = DelayedRefSingleton<PluginServer>::GetInstance();
117 
JpegSrcMgr(InputDataStream * stream)118 JpegSrcMgr::JpegSrcMgr(InputDataStream *stream) : inputStream(stream)
119 {
120     init_source = InitSrcStream;
121     fill_input_buffer = FillInputBuffer;
122     skip_input_data = SkipInputData;
123     resync_to_restart = jpeg_resync_to_restart;
124     term_source = TermSrcStream;
125 }
126 
JpegDecoder()127 JpegDecoder::JpegDecoder() : srcMgr_(nullptr)
128 {
129     CreateDecoder();
130 #if !defined(_WIN32) && !defined(_APPLE) && !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
131     CreateHwDecompressor();
132 #endif
133 }
134 
CreateDecoder()135 void JpegDecoder::CreateDecoder()
136 {
137     // create decompress struct
138     jpeg_create_decompress(&decodeInfo_);
139 
140     // set error output
141     decodeInfo_.err = jpeg_std_error(&jerr_);
142     jerr_.error_exit = ErrorExit;
143     if (decodeInfo_.err == nullptr) {
144         HiLog::Error(LABEL, "create jpeg decoder failed.");
145         return;
146     }
147     decodeInfo_.err->output_message = &OutputErrorMessage;
148 }
149 
~JpegDecoder()150 JpegDecoder::~JpegDecoder()
151 {
152     jpeg_destroy_decompress(&decodeInfo_);
153     if (hwJpegDecompress_ != nullptr) {
154         delete hwJpegDecompress_;
155         hwJpegDecompress_ = nullptr;
156     }
157 }
158 
SetSource(InputDataStream & sourceStream)159 void JpegDecoder::SetSource(InputDataStream &sourceStream)
160 {
161     srcMgr_.inputStream = &sourceStream;
162     state_ = JpegDecodingState::SOURCE_INITED;
163 }
164 
GetImageSize(uint32_t index,PlSize & size)165 uint32_t JpegDecoder::GetImageSize(uint32_t index, PlSize &size)
166 {
167     if (index >= JPEG_IMAGE_NUM) {
168         HiLog::Error(LABEL, "decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
169         return ERR_IMAGE_INVALID_PARAMETER;
170     }
171     if (state_ < JpegDecodingState::SOURCE_INITED) {
172         HiLog::Error(LABEL, "get image size failed for state %{public}d.", state_);
173         return ERR_MEDIA_INVALID_OPERATION;
174     }
175     if (state_ >= JpegDecodingState::BASE_INFO_PARSED) {
176         size.width = decodeInfo_.image_width;
177         size.height = decodeInfo_.image_height;
178         return Media::SUCCESS;
179     }
180     // only state JpegDecodingState::SOURCE_INITED and JpegDecodingState::BASE_INFO_PARSING can go here.
181     uint32_t ret = DecodeHeader();
182     if (ret != Media::SUCCESS) {
183         HiLog::Error(LABEL, "decode header error on get image size, ret:%{public}u.", ret);
184         state_ = JpegDecodingState::BASE_INFO_PARSING;
185         return ret;
186     }
187     size.width = decodeInfo_.image_width;
188     size.height = decodeInfo_.image_height;
189     state_ = JpegDecodingState::BASE_INFO_PARSED;
190     return Media::SUCCESS;
191 }
192 
GetDecodeFormat(PlPixelFormat format,PlPixelFormat & outputFormat)193 J_COLOR_SPACE JpegDecoder::GetDecodeFormat(PlPixelFormat format, PlPixelFormat &outputFormat)
194 {
195     outputFormat = format;
196     J_COLOR_SPACE colorSpace = JCS_UNKNOWN;
197     switch (format) {
198         case PlPixelFormat::UNKNOWN:
199         case PlPixelFormat::RGBA_8888: {
200             colorSpace = JCS_EXT_RGBA;
201             outputFormat = PlPixelFormat::RGBA_8888;
202             break;
203         }
204         case PlPixelFormat::BGRA_8888: {
205             colorSpace = JCS_EXT_BGRA;
206             outputFormat = PlPixelFormat::BGRA_8888;
207             break;
208         }
209         case PlPixelFormat::ARGB_8888: {
210             colorSpace = JCS_EXT_ARGB;
211             break;
212         }
213         case PlPixelFormat::ALPHA_8: {
214             colorSpace = JCS_GRAYSCALE;
215             break;
216         }
217         case PlPixelFormat::RGB_565: {
218             colorSpace = JCS_RGB;
219             outputFormat = PlPixelFormat::RGB_888;
220             break;
221         }
222         case PlPixelFormat::RGB_888: {
223             // NOTICE: libjpeg make BE as default when we are LE
224             colorSpace = JCS_EXT_BGR;
225             break;
226         }
227         default: {
228             colorSpace = JCS_EXT_RGBA;
229             outputFormat = PlPixelFormat::RGBA_8888;
230             break;
231         }
232     }
233     return colorSpace;
234 }
235 
CalculateInSampleSize(const jpeg_decompress_struct & dInfo,const PixelDecodeOptions & opts)236 static int CalculateInSampleSize(const jpeg_decompress_struct &dInfo, const PixelDecodeOptions &opts)
237 {
238     int inSampleSize = 1;
239     // Input height and width of image
240     int width = dInfo.image_width;
241     int height = dInfo.image_height;
242 
243     if (opts.desiredSize.height > 0 && opts.desiredSize.width > 0) {
244         int reqHeight = opts.desiredSize.height;
245         int reqWidth = opts.desiredSize.width;
246 
247         if (height > reqHeight || width > reqWidth) {
248             const int halfHeight = height >> 1;
249             const int halfWidth = width >> 1;
250 
251             // Calculate the largest inSampleSize value that is a power of 2 and keeps both
252             // height and width larger than the requested height and width.
253             while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
254                 inSampleSize <<= 1;
255             }
256         }
257     }
258     return inSampleSize;
259 }
260 
261 /*
262  * Calculate a valid scale fraction for this decoder, given an input sampleSize
263  */
GetScaledFraction(const int & inSampleSize,jpeg_decompress_struct & dInfo)264 static void GetScaledFraction(const int& inSampleSize, jpeg_decompress_struct& dInfo)
265 {
266     // libjpeg-turbo supports scaling only by 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, and 1/1
267     // Using binary search to find the appropriate scaling ratio based on SCALES and SCALE-NUM arrays
268     unsigned int num = 1;
269     unsigned int denom = 8;
270     float desiredScale = 1.0f / static_cast<float>(inSampleSize);
271 
272     int left = 0, right = SCALE_NUMS_LENGTH;
273     while (left <= right) {
274         int mid = left + (right - left) / 2;
275         if (desiredScale >= SCALES[mid]) {
276             num = SCALE_NUMS[mid];
277             left = mid + 1;
278         } else {
279             right = mid - 1;
280         }
281     }
282     dInfo.scale_num = num;
283     dInfo.scale_denom = denom;
284 }
285 
SetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)286 uint32_t JpegDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
287 {
288     if (index >= JPEG_IMAGE_NUM) {
289         HiLog::Error(LABEL, "decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
290         return ERR_IMAGE_INVALID_PARAMETER;
291     }
292     if (state_ < JpegDecodingState::SOURCE_INITED) {
293         HiLog::Error(LABEL, "set decode options failed for state %{public}d.", state_);
294         return ERR_MEDIA_INVALID_OPERATION;
295     }
296     if (state_ >= JpegDecodingState::IMAGE_DECODING) {
297         FinishOldDecompress();
298         state_ = JpegDecodingState::SOURCE_INITED;
299     }
300     if (state_ < JpegDecodingState::BASE_INFO_PARSED) {
301         uint32_t ret = DecodeHeader();
302         if (ret != Media::SUCCESS) {
303             state_ = JpegDecodingState::BASE_INFO_PARSING;
304             HiLog::Error(LABEL, "decode header error on set decode options:%{public}u.", ret);
305             return ret;
306         }
307         state_ = JpegDecodingState::BASE_INFO_PARSED;
308     }
309     // only state JpegDecodingState::BASE_INFO_PARSED can go here.
310     int inSampleSize = CalculateInSampleSize(decodeInfo_, opts);
311     GetScaledFraction(inSampleSize, decodeInfo_);
312     uint32_t ret = StartDecompress(opts);
313     if (ret != Media::SUCCESS) {
314         HiLog::Error(LABEL, "start decompress failed on set decode options:%{public}u.", ret);
315         return ret;
316     }
317     info.pixelFormat = outputFormat_;
318     info.size.width = decodeInfo_.output_width;
319     info.size.height = decodeInfo_.output_height;
320     info.alphaType = PlAlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
321     opts_ = opts;
322     state_ = JpegDecodingState::IMAGE_DECODING;
323     return Media::SUCCESS;
324 }
325 
GetRowBytes()326 uint32_t JpegDecoder::GetRowBytes()
327 {
328     uint32_t pixelBytes =
329         (decodeInfo_.out_color_space == JCS_RGB565) ? PIXEL_BYTES_RGB_565 : decodeInfo_.out_color_components;
330     return decodeInfo_.output_width * pixelBytes;
331 }
332 
DoSwDecode(DecodeContext & context)333 uint32_t JpegDecoder::DoSwDecode(DecodeContext &context) __attribute__((no_sanitize("cfi")))
334 {
335     StartTrace(HITRACE_TAG_ZIMAGE, "DoSwDecode");
336     if (setjmp(jerr_.setjmp_buffer)) {
337         HiLog::Error(LABEL, "decode image failed.");
338         return ERR_IMAGE_DECODE_ABNORMAL;
339     }
340     uint32_t rowStride = GetRowBytes();
341     if (context.pixelsBuffer.buffer == nullptr) {
342         uint64_t byteCount = static_cast<uint64_t>(rowStride) * decodeInfo_.output_height;
343 #if !defined(_WIN32) && !defined(_APPLE) && !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
344         if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
345             uint32_t id = context.pixelmapUniqueId_;
346             std::string name = "JPEG RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(id);
347             int fd = AshmemCreate(name.c_str(), byteCount);
348             if (fd < 0) {
349                 return ERR_SHAMEM_DATA_ABNORMAL;
350             }
351             int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
352             if (result < 0) {
353                 ::close(fd);
354                 return ERR_SHAMEM_DATA_ABNORMAL;
355             }
356             void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
357             if (ptr == MAP_FAILED) {
358                 ::close(fd);
359                 return ERR_SHAMEM_DATA_ABNORMAL;
360             }
361             context.pixelsBuffer.buffer = ptr;
362             void *fdBuffer = new int32_t();
363             if (fdBuffer == nullptr) {
364                 HiLog::Error(LABEL, "new fdBuffer fail");
365                 ::munmap(ptr, byteCount);
366                 ::close(fd);
367                 context.pixelsBuffer.buffer = nullptr;
368                 return ERR_SHAMEM_DATA_ABNORMAL;
369             }
370             *static_cast<int32_t *>(fdBuffer) = fd;
371             context.pixelsBuffer.context = fdBuffer;
372             context.pixelsBuffer.bufferSize = byteCount;
373             context.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
374             context.freeFunc = nullptr;
375         } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
376             sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
377             BufferRequestConfig requestConfig = {
378                 .width = decodeInfo_.output_width,
379                 .height = decodeInfo_.output_height,
380                 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
381                 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
382                 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
383                 .timeout = 0,
384                 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
385                 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
386             };
387             GSError ret = sb->Alloc(requestConfig);
388             if (ret != GSERROR_OK) {
389                 HiLog::Error(LABEL, "SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
390                 return ERR_DMA_NOT_EXIST;
391             }
392             void* nativeBuffer = sb.GetRefPtr();
393             int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
394             if (err != OHOS::GSERROR_OK) {
395                 HiLog::Error(LABEL, "NativeBufferReference failed");
396                 return ERR_DMA_DATA_ABNORMAL;
397             }
398 
399             context.pixelsBuffer.buffer = sb->GetVirAddr();
400             context.pixelsBuffer.context = nativeBuffer;
401             context.pixelsBuffer.bufferSize = byteCount;
402             context.allocatorType = AllocatorType::DMA_ALLOC;
403             context.freeFunc = nullptr;
404         } else {
405             void *outputBuffer = malloc(byteCount);
406             if (outputBuffer == nullptr) {
407                 HiLog::Error(LABEL, "alloc output buffer size:[%{public}llu] error.",
408                              static_cast<unsigned long long>(byteCount));
409                 return ERR_IMAGE_MALLOC_ABNORMAL;
410             }
411             context.pixelsBuffer.buffer = outputBuffer;
412             context.pixelsBuffer.context = nullptr;
413             context.pixelsBuffer.bufferSize = byteCount;
414             context.allocatorType = AllocatorType::HEAP_ALLOC;
415             context.freeFunc = nullptr;
416         }
417 #else
418         void *outputBuffer = malloc(byteCount);
419         if (outputBuffer == nullptr) {
420             HiLog::Error(LABEL, "alloc output buffer size:[%{public}llu] error.",
421                          static_cast<unsigned long long>(byteCount));
422             return ERR_IMAGE_MALLOC_ABNORMAL;
423         }
424         context.pixelsBuffer.buffer = outputBuffer;
425         context.pixelsBuffer.context = nullptr;
426         context.pixelsBuffer.bufferSize = byteCount;
427         context.allocatorType = AllocatorType::HEAP_ALLOC;
428         context.freeFunc = nullptr;
429 #endif
430     }
431     uint8_t *base = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
432     if (base == nullptr) {
433         HiLog::Error(LABEL, "decode image buffer is null.");
434         return ERR_IMAGE_INVALID_PARAMETER;
435     }
436     srcMgr_.inputStream->Seek(streamPosition_);
437     uint8_t *buffer = nullptr;
438 #if !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
439     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
440         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
441         rowStride = sbBuffer->GetStride();
442     }
443 #endif
444     while (decodeInfo_.output_scanline < decodeInfo_.output_height) {
445         buffer = base + rowStride * decodeInfo_.output_scanline;
446         uint32_t readLineNum = jpeg_read_scanlines(&decodeInfo_, &buffer, RW_LINE_NUM);
447         if (readLineNum < RW_LINE_NUM) {
448             streamPosition_ = srcMgr_.inputStream->Tell();
449             HiLog::Error(LABEL, "read line fail, read num:%{public}u, total read num:%{public}u.", readLineNum,
450                          decodeInfo_.output_scanline);
451             return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
452         }
453     }
454     streamPosition_ = srcMgr_.inputStream->Tell();
455 
456 #ifdef IMAGE_COLORSPACE_FLAG
457     // parser icc profile info
458     uint32_t iccPaseredResult = iccProfileInfo_.ParsingICCProfile(&decodeInfo_);
459     if (iccPaseredResult == OHOS::Media::ERR_IMAGE_DENCODE_ICC_FAILED) {
460         HiLog::Error(LABEL, "dencode image icc error.");
461         return iccPaseredResult;
462     }
463 #endif
464     FinishTrace(HITRACE_TAG_ZIMAGE);
465     return Media::SUCCESS;
466 }
467 
Decode(uint32_t index,DecodeContext & context)468 uint32_t JpegDecoder::Decode(uint32_t index, DecodeContext &context)
469 {
470     if (index >= JPEG_IMAGE_NUM) {
471         HiLog::Error(LABEL, "decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
472         return ERR_IMAGE_INVALID_PARAMETER;
473     }
474     if (state_ < JpegDecodingState::IMAGE_DECODING) {
475         HiLog::Error(LABEL, "decode failed for state %{public}d.", state_);
476         return ERR_MEDIA_INVALID_OPERATION;
477     }
478     if (state_ > JpegDecodingState::IMAGE_DECODING) {
479         FinishOldDecompress();
480         state_ = JpegDecodingState::SOURCE_INITED;
481         uint32_t ret = DecodeHeader();
482         if (ret != Media::SUCCESS) {
483             state_ = JpegDecodingState::BASE_INFO_PARSING;
484             HiLog::Error(LABEL, "decode header error on decode:%{public}u.", ret);
485             return ret;
486         }
487         state_ = JpegDecodingState::BASE_INFO_PARSED;
488         ret = StartDecompress(opts_);
489         if (ret != Media::SUCCESS) {
490             HiLog::Error(LABEL, "start decompress failed on decode:%{public}u.", ret);
491             return ret;
492         }
493         state_ = JpegDecodingState::IMAGE_DECODING;
494     }
495     // only state JpegDecodingState::IMAGE_DECODING can go here.
496     if (hwJpegDecompress_ != nullptr) {
497         srcMgr_.inputStream->Seek(streamPosition_);
498         uint32_t ret = hwJpegDecompress_->Decompress(&decodeInfo_, srcMgr_.inputStream, context);
499         if (ret == Media::SUCCESS) {
500             state_ = JpegDecodingState::IMAGE_DECODED;
501             HiLog::Debug(LABEL, "jpeg hardware decode success.");
502             return ret;
503         }
504     }
505     uint32_t ret = DoSwDecode(context);
506     if (ret == Media::SUCCESS) {
507         state_ = JpegDecodingState::IMAGE_DECODED;
508         HiLog::Debug(LABEL, "jpeg software decode success.");
509         return Media::SUCCESS;
510     }
511     if (ret == ERR_IMAGE_SOURCE_DATA_INCOMPLETE && opts_.allowPartialImage) {
512         state_ = JpegDecodingState::IMAGE_PARTIAL;
513         context.ifPartialOutput = true;
514         return Media::SUCCESS;
515     }
516     state_ = JpegDecodingState::IMAGE_ERROR;
517     return ret;
518 }
519 
Reset()520 void JpegDecoder::Reset()
521 {
522     srcMgr_.inputStream = nullptr;
523 }
524 
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & progContext)525 uint32_t JpegDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &progContext)
526 {
527     progContext.totalProcessProgress = 0;
528     if (index >= JPEG_IMAGE_NUM) {
529         HiLog::Error(LABEL, "decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
530         return ERR_IMAGE_INVALID_PARAMETER;
531     }
532     if (state_ != JpegDecodingState::IMAGE_DECODING) {
533         HiLog::Error(LABEL, "incremental decode failed for state %{public}d.", state_);
534         return ERR_MEDIA_INVALID_OPERATION;
535     }
536 
537     uint32_t ret = DoSwDecode(progContext.decodeContext);
538     if (ret == Media::SUCCESS) {
539         state_ = JpegDecodingState::IMAGE_DECODED;
540     }
541     // get promote decode progress, in percentage: 0~100.
542     progContext.totalProcessProgress =
543         decodeInfo_.output_height == 0 ? 0 : (decodeInfo_.output_scanline * NUM_100) / decodeInfo_.output_height;
544     HiLog::Debug(LABEL, "incremental decode progress %{public}u.", progContext.totalProcessProgress);
545     return ret;
546 }
547 
CreateHwDecompressor()548 void JpegDecoder::CreateHwDecompressor()
549 {
550     std::map<std::string, AttrData> capabilities;
551     const std::string format = "image/jpeg";
552     capabilities.insert(std::map<std::string, AttrData>::value_type("encodeFormat", AttrData(format)));
553     hwJpegDecompress_ = pluginServer_.CreateObject<AbsImageDecompressComponent>(
554         AbsImageDecompressComponent::SERVICE_DEFAULT, capabilities);
555     if (hwJpegDecompress_ == nullptr) {
556         HiLog::Error(LABEL, "get hardware jpeg decompress component failed.");
557         return;
558     }
559 }
560 
FinishOldDecompress()561 void JpegDecoder::FinishOldDecompress()
562 {
563     if (state_ < JpegDecodingState::IMAGE_DECODING) {
564         return;
565     }
566     jpeg_destroy_decompress(&decodeInfo_);
567     CreateDecoder();
568 }
569 
IsMarker(uint8_t rawMarkerPrefix,uint8_t rawMarkderCode,uint8_t markerCode)570 bool JpegDecoder::IsMarker(uint8_t rawMarkerPrefix, uint8_t rawMarkderCode, uint8_t markerCode)
571 {
572     if (rawMarkerPrefix != JPG_MARKER_PREFIX) {
573         return false;
574     }
575 
576     // RSTn, n from 0 to 7
577     if (rawMarkderCode >= JPG_MARKER_RST0 && rawMarkderCode <= JPG_MARKER_RSTN && markerCode == JPG_MARKER_RST) {
578         return true;
579     }
580 
581     // APPn, n from 0 to 15
582     if (rawMarkderCode >= JPG_MARKER_APP0 && rawMarkderCode <= JPG_MARKER_APPN && markerCode == JPG_MARKER_APP) {
583         return true;
584     }
585 
586     if (rawMarkderCode == markerCode) {
587         return true;
588     }
589     return false;
590 }
591 
FindMarker(InputDataStream & stream,uint8_t marker)592 bool JpegDecoder::FindMarker(InputDataStream &stream, uint8_t marker)
593 {
594     uint8_t buffer[MARKER_SIZE] = { 0 };
595     uint32_t readSize = 0;
596     stream.Seek(0);
597     while (true) {
598         uint32_t cur = stream.Tell();
599         if (!stream.Seek(cur + MARKER_SIZE)) {
600             return false;
601         }
602         stream.Seek(cur);
603 
604         // read marker code
605         stream.Read(MARKER_SIZE, buffer, sizeof(buffer), readSize);
606         if (readSize != MARKER_SIZE) {
607             return false;
608         }
609 
610         uint8_t markerPrefix = buffer[JPG_MARKER_PREFIX_OFFSET];
611         uint8_t markerCode = buffer[JPG_MARKER_CODE_OFFSET];
612         if (IsMarker(markerPrefix, markerCode, JPG_MARKER_SOS)) {
613             return true;
614         }
615 
616         if (IsMarker(markerPrefix, markerCode, JPG_MARKER_SOI) || IsMarker(markerPrefix, markerCode, JPG_MARKER_RST)) {
617             continue;
618         }
619 
620         cur = stream.Tell();
621         if (!stream.Seek(cur + MARKER_LENGTH)) {
622             return false;
623         }
624         stream.Seek(cur);
625         // read marker length
626         stream.Read(MARKER_LENGTH, buffer, sizeof(buffer), readSize);
627         if (readSize != MARKER_LENGTH) {
628             return false;
629         }
630         // skip data, length = sizeof(length) + sizeof(data)
631         uint32_t length = (buffer[MARKER_LENGTH_0_OFFSET] << MARKER_LENGTH_SHIFT) + buffer[MARKER_LENGTH_1_OFFSET];
632         if (!stream.Seek(cur + length)) {
633             return false;
634         }
635     }
636 }
637 
DecodeHeader()638 uint32_t JpegDecoder::DecodeHeader()
639 {
640     if (setjmp(jerr_.setjmp_buffer)) {
641         HiLog::Error(LABEL, "get image size failed.");
642         return ERR_IMAGE_DECODE_ABNORMAL;
643     }
644     if (state_ == JpegDecodingState::SOURCE_INITED) {
645         srcMgr_.inputStream->Seek(0);
646     } else {
647         srcMgr_.inputStream->Seek(streamPosition_);
648     }
649     decodeInfo_.src = &srcMgr_;
650 
651     /**
652      * The function jpeg_read_header() shall read the JPEG datastream until the first SOS marker is encountered
653      * incremental decoding should have enough data(contains SOS marker) before calling jpeg_read_header.
654      */
655     if (!srcMgr_.inputStream->IsStreamCompleted()) {
656         uint32_t curPos = srcMgr_.inputStream->Tell();
657         while (true) {
658             if (!FindMarker(*srcMgr_.inputStream, JPG_MARKER_SOS)) {
659                 srcMgr_.inputStream->Seek(curPos);
660                 return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
661             }
662             srcMgr_.inputStream->Seek(curPos);
663             break;
664         }
665     }
666 
667     // call jpeg_save_markers, use to get ICC profile.
668     jpeg_save_markers(&decodeInfo_, PL_ICC_MARKER, PL_MARKER_LENGTH_LIMIT);
669     int32_t ret = jpeg_read_header(&decodeInfo_, true);
670     streamPosition_ = srcMgr_.inputStream->Tell();
671     if (ret == JPEG_SUSPENDED) {
672         HiLog::Debug(LABEL, "image input data incomplete, decode header error:%{public}u.", ret);
673         return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
674     } else if (ret != JPEG_HEADER_OK) {
675         HiLog::Error(LABEL, "image type is not jpeg, decode header error:%{public}u.", ret);
676         return ERR_IMAGE_GET_DATA_ABNORMAL;
677     }
678     return Media::SUCCESS;
679 }
680 
StartDecompress(const PixelDecodeOptions & opts)681 uint32_t JpegDecoder::StartDecompress(const PixelDecodeOptions &opts)
682 {
683     if (setjmp(jerr_.setjmp_buffer)) {
684         HiLog::Error(LABEL, "set output image info failed.");
685         return ERR_IMAGE_DECODE_ABNORMAL;
686     }
687     // set decode options
688     if (decodeInfo_.jpeg_color_space == JCS_CMYK || decodeInfo_.jpeg_color_space == JCS_YCCK) {
689         // can't support CMYK to alpha8 convert
690         if (opts.desiredPixelFormat == PlPixelFormat::ALPHA_8) {
691             HiLog::Error(LABEL, "can't support colorspace CMYK to alpha convert.");
692             return ERR_IMAGE_UNKNOWN_FORMAT;
693         }
694         HiLog::Debug(LABEL, "jpeg colorspace is CMYK.");
695         decodeInfo_.out_color_space = JCS_CMYK;
696         outputFormat_ = PlPixelFormat::CMYK;
697     } else {
698         decodeInfo_.out_color_space = GetDecodeFormat(opts.desiredPixelFormat, outputFormat_);
699         if (decodeInfo_.out_color_space == JCS_UNKNOWN) {
700             HiLog::Error(LABEL, "set jpeg output color space invalid.");
701             return ERR_IMAGE_UNKNOWN_FORMAT;
702         }
703     }
704     srcMgr_.inputStream->Seek(streamPosition_);
705     if (jpeg_start_decompress(&decodeInfo_) != TRUE) {
706         streamPosition_ = srcMgr_.inputStream->Tell();
707         HiLog::Error(LABEL, "jpeg start decompress failed, invalid input.");
708         return ERR_IMAGE_INVALID_PARAMETER;
709     }
710     streamPosition_ = srcMgr_.inputStream->Tell();
711     return Media::SUCCESS;
712 }
713 
ParseExifData()714 bool JpegDecoder::ParseExifData()
715 {
716     HiLog::Debug(LABEL, "ParseExifData enter");
717     uint32_t curPos = srcMgr_.inputStream->Tell();
718     srcMgr_.inputStream->Seek(0);
719     unsigned long fsize = static_cast<unsigned long>(srcMgr_.inputStream->GetStreamSize());
720     if (fsize <= 0) {
721         HiLog::Error(LABEL, "Get stream size failed");
722         return false;
723     }
724     unsigned char *buf = new unsigned char[fsize];
725     uint32_t readSize = 0;
726     srcMgr_.inputStream->Read(fsize, buf, fsize, readSize);
727     HiLog::Debug(LABEL, "parsing EXIF: fsize %{public}lu", fsize);
728 
729     int code = exifInfo_.ParseExifData(buf, fsize);
730     delete[] buf;
731     srcMgr_.inputStream->Seek(curPos);
732     if (code) {
733         HiLog::Error(LABEL, "Error parsing EXIF: code %{public}d", code);
734         return false;
735     }
736     return true;
737 }
738 
GetImagePropertyInt(uint32_t index,const std::string & key,int32_t & value)739 uint32_t JpegDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
740 {
741     HiLog::Debug(LABEL, "[GetImagePropertyInt] enter jpeg plugin, key:%{public}s", key.c_str());
742     if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
743         HiLog::Error(LABEL, "[GetImagePropertyInt] this key is used to check the original format of raw image!");
744         return Media::ERR_MEDIA_VALUE_INVALID;
745     }
746 
747     if (!exifInfo_.IsExifDataParsed()) {
748         if (!ParseExifData()) {
749             HiLog::Error(LABEL, "[GetImagePropertyInt] Parse exif data failed!");
750             return Media::ERROR;
751         }
752     }
753     if (IsSameTextStr(key, ORIENTATION)) {
754         if (PROPERTY_INT.find(exifInfo_.orientation_) != PROPERTY_INT.end()) {
755             value = PROPERTY_INT.at(exifInfo_.orientation_);
756         } else {
757             HiLog::Error(LABEL, "[GetImagePropertyInt] The exifinfo:%{public}s is not found",
758                 exifInfo_.orientation_.c_str());
759             return Media::ERR_MEDIA_VALUE_INVALID;
760         }
761     } else {
762         HiLog::Error(LABEL, "[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
763         return Media::ERR_MEDIA_VALUE_INVALID;
764     }
765     return Media::SUCCESS;
766 }
767 
GetImagePropertyString(uint32_t index,const std::string & key,std::string & value)768 uint32_t JpegDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
769 {
770     HiLog::Debug(LABEL, "[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
771     if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
772         HiLog::Error(LABEL,
773             "[GetImagePropertyString] this key is used to check the original format of raw image!");
774         return Media::ERR_MEDIA_VALUE_INVALID;
775     }
776 
777     if (!exifInfo_.IsExifDataParsed()) {
778         if (!ParseExifData()) {
779             HiLog::Error(LABEL, "[GetImagePropertyString] Parse exif data failed!");
780             return Media::ERROR;
781         }
782     }
783 
784     if (IsSameTextStr(key, BITS_PER_SAMPLE)) {
785         value = exifInfo_.bitsPerSample_;
786     } else if (IsSameTextStr(key, ORIENTATION)) {
787         value = exifInfo_.orientation_;
788     } else if (IsSameTextStr(key, IMAGE_LENGTH)) {
789         value = exifInfo_.imageLength_;
790     } else if (IsSameTextStr(key, IMAGE_WIDTH)) {
791         value = exifInfo_.imageWidth_;
792     } else if (IsSameTextStr(key, GPS_LATITUDE)) {
793         value = exifInfo_.gpsLatitude_;
794     } else if (IsSameTextStr(key, GPS_LONGITUDE)) {
795         value = exifInfo_.gpsLongitude_;
796     } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) {
797         value = exifInfo_.gpsLatitudeRef_;
798     } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) {
799         value = exifInfo_.gpsLongitudeRef_;
800     } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) {
801         value = exifInfo_.dateTimeOriginal_;
802     } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL_MEDIA)) {
803         FormatTimeStamp(value, exifInfo_.dateTimeOriginal_);
804     } else if (GetImagePropertyString(key, value) != Media::SUCCESS) {
805         return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
806     }
807 
808     if (IsSameTextStr(value, EXIFInfo::DEFAULT_EXIF_VALUE)) {
809         HiLog::Error(LABEL, "[GetImagePropertyString] enter jpeg plugin, ifd and entry are not matched!");
810         return Media::ERR_MEDIA_VALUE_INVALID;
811     }
812     HiLog::Debug(LABEL, "[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
813     return Media::SUCCESS;
814 }
815 
GetImagePropertyString(const std::string & key,std::string & value)816 uint32_t JpegDecoder::GetImagePropertyString(const std::string &key, std::string &value)
817 {
818     if (IsSameTextStr(key, EXPOSURE_TIME)) {
819         value = exifInfo_.exposureTime_;
820     } else if (IsSameTextStr(key, F_NUMBER)) {
821         value = exifInfo_.fNumber_;
822     } else if (IsSameTextStr(key, ISO_SPEED_RATINGS)) {
823         value = exifInfo_.isoSpeedRatings_;
824     } else if (IsSameTextStr(key, SCENE_TYPE)) {
825         value = exifInfo_.sceneType_;
826     } else if (IsSameTextStr(key, COMPRESSED_BITS_PER_PIXEL)) {
827         value = exifInfo_.compressedBitsPerPixel_;
828     } else if (IsSameTextStr(key, DATE_TIME)) {
829         value = exifInfo_.dateTime_;
830     } else if (IsSameTextStr(key, GPS_TIME_STAMP)) {
831         value = exifInfo_.gpsTimeStamp_;
832     } else if (IsSameTextStr(key, GPS_DATE_STAMP)) {
833         value = exifInfo_.gpsDateStamp_;
834     } else if (IsSameTextStr(key, IMAGE_DESCRIPTION)) {
835         value = exifInfo_.imageDescription_;
836     } else if (IsSameTextStr(key, MAKE)) {
837         value = exifInfo_.make_;
838     } else if (IsSameTextStr(key, MODEL)) {
839         value = exifInfo_.model_;
840     } else if (IsSameTextStr(key, PHOTO_MODE)) {
841         value = exifInfo_.photoMode_;
842     } else if (IsSameTextStr(key, SENSITIVITY_TYPE)) {
843         value = exifInfo_.sensitivityType_;
844     } else if (IsSameTextStr(key, STANDARD_OUTPUT_SENSITIVITY)) {
845         value = exifInfo_.standardOutputSensitivity_;
846     } else if (IsSameTextStr(key, RECOMMENDED_EXPOSURE_INDEX)) {
847         value = exifInfo_.recommendedExposureIndex_;
848     } else if (IsSameTextStr(key, ISO_SPEED)) {
849         value = exifInfo_.isoSpeedRatings_;
850     } else if (IsSameTextStr(key, APERTURE_VALUE)) {
851         value = exifInfo_.apertureValue_;
852     } else if (IsSameTextStr(key, EXPOSURE_BIAS_VALUE)) {
853         value = exifInfo_.exposureBiasValue_;
854     } else if (IsSameTextStr(key, METERING_MODE)) {
855         value = exifInfo_.meteringMode_;
856     } else if (IsSameTextStr(key, LIGHT_SOURCE)) {
857         value = exifInfo_.lightSource_;
858     } else if (IsSameTextStr(key, FLASH)) {
859         value = exifInfo_.flash_;
860     } else if (IsSameTextStr(key, FOCAL_LENGTH)) {
861         value = exifInfo_.focalLength_;
862     } else {
863         return GetImagePropertyStringEx(key, value);
864     }
865 
866     return Media::SUCCESS;
867 }
868 
GetImagePropertyStringEx(const std::string & key,std::string & value)869 uint32_t JpegDecoder::GetImagePropertyStringEx(const std::string &key, std::string &value)
870 {
871     if (IsSameTextStr(key, USER_COMMENT)) {
872         value = exifInfo_.userComment_;
873     } else if (IsSameTextStr(key, PIXEL_X_DIMENSION)) {
874         value = exifInfo_.pixelXDimension_;
875     } else if (IsSameTextStr(key, PIXEL_Y_DIMENSION)) {
876         value = exifInfo_.pixelYDimension_;
877     } else if (IsSameTextStr(key, WHITE_BALANCE)) {
878         value = exifInfo_.whiteBalance_;
879     } else if (IsSameTextStr(key, FOCAL_LENGTH_IN_35_MM_FILM)) {
880         value = exifInfo_.focalLengthIn35mmFilm_;
881     } else if (IsSameTextStr(key, HW_MNOTE_CAPTURE_MODE)) {
882         value = exifInfo_.hwMnoteCaptureMode_;
883     } else if (IsSameTextStr(key, HW_MNOTE_PHYSICAL_APERTURE)) {
884         value = exifInfo_.hwMnotePhysicalAperture_;
885     } else {
886         return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
887     }
888     return Media::SUCCESS;
889 }
890 
InitOriginalTimes(std::string & dataTime)891 void InitOriginalTimes(std::string &dataTime)
892 {
893     for (size_t i = 0; i < dataTime.size() && i < TIMES_LEN; i++) {
894         if ((dataTime[i] < '0' || dataTime[i] > '9') && dataTime[i] != ' ') {
895             if (i < DATE_LEN) {
896                 dataTime[i] = '-';
897             } else {
898                 dataTime[i] = ':';
899             }
900         }
901     }
902 }
903 
SetOriginalTimes(std::string & dataTime)904 std::string SetOriginalTimes(std::string &dataTime)
905 {
906     InitOriginalTimes(dataTime);
907     std::string data = "";
908     std::string time = "";
909     std::string::size_type position = dataTime.find(" ");
910     if (position == dataTime.npos) {
911         data = dataTime;
912         if (data.find("-") == data.npos) {
913             data += "-01-01";
914         } else if (data.find_first_of("-") == data.find_last_of("-")) {
915             data += "-01";
916         }
917         time += " 00:00:00";
918     } else {
919         data = dataTime.substr(0, position);
920         time = dataTime.substr(position);
921         if (data.find("-") == data.npos) {
922             data += "-01-01";
923         } else if (data.find_first_of("-") == data.find_last_of("-")) {
924             data += "-01";
925         }
926         if (time.find(":") == data.npos) {
927             time += ":00:00";
928         } else if (time.find_first_of(":") == time.find_last_of(":")) {
929             time += ":00";
930         } else {
931             std::string timeTmp = time;
932             time = timeTmp.substr(0, time.find("."));
933         }
934     }
935     return data + time;
936 }
937 
FormatTimeStamp(std::string & value,std::string & src)938 void JpegDecoder::FormatTimeStamp(std::string &value, std::string &src)
939 {
940     value = "";
941     if (!IsSameTextStr(src, "")) {
942         value = SetOriginalTimes(src);
943     }
944 }
945 
getExifTagFromKey(const std::string & key)946 ExifTag JpegDecoder::getExifTagFromKey(const std::string &key)
947 {
948     if (IsSameTextStr(key, BITS_PER_SAMPLE)) {
949         return EXIF_TAG_BITS_PER_SAMPLE;
950     } else if (IsSameTextStr(key, ORIENTATION)) {
951         return EXIF_TAG_ORIENTATION;
952     } else if (IsSameTextStr(key, IMAGE_LENGTH)) {
953         return EXIF_TAG_IMAGE_LENGTH;
954     } else if (IsSameTextStr(key, IMAGE_WIDTH)) {
955         return EXIF_TAG_IMAGE_WIDTH;
956     } else if (IsSameTextStr(key, GPS_LATITUDE)) {
957         return EXIF_TAG_GPS_LATITUDE;
958     } else if (IsSameTextStr(key, GPS_LONGITUDE)) {
959         return EXIF_TAG_GPS_LONGITUDE;
960     } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) {
961         return EXIF_TAG_GPS_LATITUDE_REF;
962     } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) {
963         return EXIF_TAG_GPS_LONGITUDE_REF;
964     } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) {
965         return EXIF_TAG_DATE_TIME_ORIGINAL;
966     } else if (IsSameTextStr(key, EXPOSURE_TIME)) {
967         return EXIF_TAG_EXPOSURE_TIME;
968     } else if (IsSameTextStr(key, F_NUMBER)) {
969         return EXIF_TAG_FNUMBER;
970     } else if (IsSameTextStr(key, ISO_SPEED_RATINGS)) {
971         return EXIF_TAG_ISO_SPEED_RATINGS;
972     } else if (IsSameTextStr(key, SCENE_TYPE)) {
973         return EXIF_TAG_SCENE_TYPE;
974     } else if (IsSameTextStr(key, COMPRESSED_BITS_PER_PIXEL)) {
975         return EXIF_TAG_COMPRESSED_BITS_PER_PIXEL;
976     } else {
977         return EXIF_TAG_PRINT_IMAGE_MATCHING;
978     }
979 }
980 
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,const std::string & path)981 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
982     const std::string &value, const std::string &path)
983 {
984     HiLog::Debug(LABEL, "[ModifyImageProperty] with path:%{public}s, key:%{public}s, value:%{public}s",
985         path.c_str(), key.c_str(), value.c_str());
986     ExifTag tag = getExifTagFromKey(key);
987     if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
988         return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
989     }
990 
991     uint32_t ret = exifInfo_.ModifyExifData(tag, value, path);
992     if (ret != Media::SUCCESS) {
993         return ret;
994     }
995     return Media::SUCCESS;
996 }
997 
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,const int fd)998 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
999     const std::string &value, const int fd)
1000 {
1001     HiLog::Debug(LABEL, "[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
1002         fd, key.c_str(), value.c_str());
1003     ExifTag tag = getExifTagFromKey(key);
1004     if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
1005         return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1006     }
1007 
1008     uint32_t ret = exifInfo_.ModifyExifData(tag, value, fd);
1009     if (ret != Media::SUCCESS) {
1010         return ret;
1011     }
1012     return Media::SUCCESS;
1013 }
1014 
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,uint8_t * data,uint32_t size)1015 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1016     const std::string &value, uint8_t *data, uint32_t size)
1017 {
1018     HiLog::Debug(LABEL, "[ModifyImageProperty] with key:%{public}s, value:%{public}s",
1019         key.c_str(), value.c_str());
1020     ExifTag tag = getExifTagFromKey(key);
1021     if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
1022         return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1023     }
1024 
1025     uint32_t ret = exifInfo_.ModifyExifData(tag, value, data, size);
1026     if (ret != Media::SUCCESS) {
1027         return ret;
1028     }
1029     return Media::SUCCESS;
1030 }
1031 
GetFilterArea(const int & privacyType,std::vector<std::pair<uint32_t,uint32_t>> & ranges)1032 uint32_t JpegDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1033 {
1034     HiLog::Debug(LABEL, "[GetFilterArea] with privacyType:%{public}d ", privacyType);
1035     if (srcMgr_.inputStream == nullptr) {
1036         HiLog::Error(LABEL, "[GetFilterArea] srcMgr_.inputStream is nullptr.");
1037         return Media::ERR_MEDIA_INVALID_OPERATION;
1038     }
1039     uint32_t curPos = srcMgr_.inputStream->Tell();
1040     srcMgr_.inputStream->Seek(ADDRESS_4);
1041     // app1SizeBuf is used to get value of EXIF data size
1042     uint8_t *app1SizeBuf = new uint8_t[JPEG_APP1_SIZE];
1043     uint32_t readSize = 0;
1044     if (!srcMgr_.inputStream->Read(JPEG_APP1_SIZE, app1SizeBuf, JPEG_APP1_SIZE, readSize)) {
1045         HiLog::Error(LABEL, "[GetFilterArea] get app1 size failed.");
1046         return Media::ERR_MEDIA_INVALID_OPERATION;
1047     }
1048     uint32_t app1Size =
1049         static_cast<unsigned int>(app1SizeBuf[1]) | static_cast<unsigned int>(app1SizeBuf[0] << OFFSET_8);
1050     delete[] app1SizeBuf;
1051     uint32_t fsize = static_cast<uint32_t>(srcMgr_.inputStream->GetStreamSize());
1052     if (app1Size > fsize) {
1053         HiLog::Error(LABEL, "[GetFilterArea] file format is illegal.");
1054         return Media::ERR_MEDIA_INVALID_OPERATION;
1055     }
1056 
1057     srcMgr_.inputStream->Seek(0);
1058     uint32_t bufSize = app1Size + ADDRESS_4;
1059     // buf is from image file head to exif data end
1060     uint8_t *buf = new uint8_t[bufSize];
1061     srcMgr_.inputStream->Read(bufSize, buf, bufSize, readSize);
1062     uint32_t ret = exifInfo_.GetFilterArea(buf, bufSize, privacyType, ranges);
1063     delete[] buf;
1064     srcMgr_.inputStream->Seek(curPos);
1065     if (ret != Media::SUCCESS) {
1066         HiLog::Error(LABEL, "[GetFilterArea]: failed to get area, errno %{public}d", ret);
1067         return ret;
1068     }
1069     return Media::SUCCESS;
1070 }
1071 
1072 #ifdef IMAGE_COLORSPACE_FLAG
getGrColorSpace()1073 OHOS::ColorManager::ColorSpace JpegDecoder::getGrColorSpace()
1074 {
1075     OHOS::ColorManager::ColorSpace grColorSpace = iccProfileInfo_.getGrColorSpace();
1076     return grColorSpace;
1077 }
1078 
IsSupportICCProfile()1079 bool JpegDecoder::IsSupportICCProfile()
1080 {
1081     bool isSupportICCProfile = iccProfileInfo_.IsSupportICCProfile();
1082     return isSupportICCProfile;
1083 }
1084 #endif
1085 } // namespace ImagePlugin
1086 } // namespace OHOS
1087