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