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 = decodeInfo_.image_width;
197 size.height = 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 = decodeInfo_.image_width;
208 size.height = 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 int inSampleSize = CalculateInSampleSize(decodeInfo_, opts);
332 GetScaledFraction(inSampleSize, decodeInfo_);
333 uint32_t ret = StartDecompress(opts);
334 if (ret != Media::SUCCESS) {
335 IMAGE_LOGE("start decompress failed on set decode options:%{public}u.", ret);
336 return ret;
337 }
338 info.pixelFormat = outputFormat_;
339 info.size.width = decodeInfo_.output_width;
340 info.size.height = decodeInfo_.output_height;
341 info.alphaType = AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
342 opts_ = opts;
343 state_ = JpegDecodingState::IMAGE_DECODING;
344 return Media::SUCCESS;
345 }
346
GetRowBytes()347 uint32_t JpegDecoder::GetRowBytes()
348 {
349 uint32_t pixelBytes =
350 (decodeInfo_.out_color_space == JCS_RGB565) ? PIXEL_BYTES_RGB_565 : decodeInfo_.out_color_components;
351 return decodeInfo_.output_width * pixelBytes;
352 }
353
DoSwDecode(DecodeContext & context)354 uint32_t JpegDecoder::DoSwDecode(DecodeContext &context) __attribute__((no_sanitize("cfi")))
355 {
356 ImageTrace imageTrace("JpegDecoder::DoSwDecode");
357 if (setjmp(jerr_.setjmp_buffer)) {
358 IMAGE_LOGE("decode image failed.");
359 return ERR_IMAGE_DECODE_ABNORMAL;
360 }
361 uint32_t rowStride = GetRowBytes();
362 if (context.pixelsBuffer.buffer == nullptr) {
363 if (ImageUtils::CheckMulOverflow(rowStride, decodeInfo_.output_height)) {
364 IMAGE_LOGE("invalid size.");
365 return ERR_IMAGE_DECODE_ABNORMAL;
366 }
367 uint64_t byteCount = static_cast<uint64_t>(rowStride) * static_cast<uint64_t>(decodeInfo_.output_height);
368 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
369 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
370 uint32_t id = context.pixelmapUniqueId_;
371 std::string name = "JPEG RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(id);
372 int fd = AshmemCreate(name.c_str(), byteCount);
373 if (fd < 0) {
374 return ERR_SHAMEM_DATA_ABNORMAL;
375 }
376 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
377 if (result < 0) {
378 ::close(fd);
379 return ERR_SHAMEM_DATA_ABNORMAL;
380 }
381 void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
382 if (ptr == MAP_FAILED) {
383 ::close(fd);
384 return ERR_SHAMEM_DATA_ABNORMAL;
385 }
386 context.pixelsBuffer.buffer = ptr;
387 void *fdBuffer = new int32_t();
388 if (fdBuffer == nullptr) {
389 IMAGE_LOGE("new fdBuffer fail");
390 ::munmap(ptr, byteCount);
391 ::close(fd);
392 context.pixelsBuffer.buffer = nullptr;
393 return ERR_SHAMEM_DATA_ABNORMAL;
394 }
395 *static_cast<int32_t *>(fdBuffer) = fd;
396 context.pixelsBuffer.context = fdBuffer;
397 context.pixelsBuffer.bufferSize = byteCount;
398 context.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
399 context.freeFunc = nullptr;
400 } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
401 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
402 BufferRequestConfig requestConfig = {
403 .width = decodeInfo_.output_width,
404 .height = decodeInfo_.output_height,
405 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
406 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
407 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
408 .timeout = 0,
409 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
410 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
411 };
412 GSError ret = sb->Alloc(requestConfig);
413 if (ret != GSERROR_OK) {
414 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
415 return ERR_DMA_NOT_EXIST;
416 }
417 void* nativeBuffer = sb.GetRefPtr();
418 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
419 if (err != OHOS::GSERROR_OK) {
420 IMAGE_LOGE("NativeBufferReference failed");
421 return ERR_DMA_DATA_ABNORMAL;
422 }
423
424 context.pixelsBuffer.buffer = sb->GetVirAddr();
425 context.pixelsBuffer.context = nativeBuffer;
426 context.pixelsBuffer.bufferSize = byteCount;
427 context.allocatorType = AllocatorType::DMA_ALLOC;
428 context.freeFunc = nullptr;
429 } else {
430 void *outputBuffer = malloc(byteCount);
431 if (outputBuffer == nullptr) {
432 IMAGE_LOGE("alloc output buffer size:[%{public}llu] error.",
433 static_cast<unsigned long long>(byteCount));
434 return ERR_IMAGE_MALLOC_ABNORMAL;
435 }
436 context.pixelsBuffer.buffer = outputBuffer;
437 context.pixelsBuffer.context = nullptr;
438 context.pixelsBuffer.bufferSize = byteCount;
439 context.allocatorType = AllocatorType::HEAP_ALLOC;
440 context.freeFunc = nullptr;
441 }
442 #else
443 void *outputBuffer = malloc(byteCount);
444 if (outputBuffer == nullptr) {
445 IMAGE_LOGE("alloc output buffer size:[%{public}llu] error.", static_cast<unsigned long long>(byteCount));
446 return ERR_IMAGE_MALLOC_ABNORMAL;
447 }
448 context.pixelsBuffer.buffer = outputBuffer;
449 context.pixelsBuffer.context = nullptr;
450 context.pixelsBuffer.bufferSize = byteCount;
451 context.allocatorType = AllocatorType::HEAP_ALLOC;
452 context.freeFunc = nullptr;
453 #endif
454 }
455 uint8_t *base = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
456 if (base == nullptr) {
457 IMAGE_LOGE("decode image buffer is null.");
458 return ERR_IMAGE_INVALID_PARAMETER;
459 }
460
461 if (srcMgr_.inputStream->Seek(streamPosition_ - decodeInfo_.src->bytes_in_buffer)) {
462 auto dataPtr = srcMgr_.inputStream->GetDataPtr();
463 if (dataPtr) {
464 // sourceData_.data() maybe changed after IncrementalSourceStream::UpdateData(), so reset next_input_byte
465 decodeInfo_.src->next_input_byte = dataPtr + streamPosition_ - decodeInfo_.src->bytes_in_buffer;
466 }
467 }
468
469 srcMgr_.inputStream->Seek(streamPosition_);
470 uint8_t *buffer = nullptr;
471 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
472 if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
473 SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
474 rowStride = sbBuffer->GetStride();
475 }
476 #endif
477 while (decodeInfo_.output_scanline < decodeInfo_.output_height) {
478 buffer = base + rowStride * decodeInfo_.output_scanline;
479 uint32_t readLineNum = jpeg_read_scanlines(&decodeInfo_, &buffer, RW_LINE_NUM);
480 if (readLineNum < RW_LINE_NUM) {
481 streamPosition_ = srcMgr_.inputStream->Tell();
482 IMAGE_LOGE("read line fail, read num:%{public}u, total read num:%{public}u.", readLineNum,
483 decodeInfo_.output_scanline);
484 return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
485 }
486 }
487 streamPosition_ = srcMgr_.inputStream->Tell();
488
489 #ifdef IMAGE_COLORSPACE_FLAG
490 // parser icc profile info
491 uint32_t iccPaseredResult = iccProfileInfo_.ParsingICCProfile(&decodeInfo_);
492 if (iccPaseredResult == OHOS::Media::ERR_IMAGE_DENCODE_ICC_FAILED) {
493 IMAGE_LOGE("dencode image icc error.");
494 return iccPaseredResult;
495 }
496 #endif
497 ImageUtils::FlushContextSurfaceBuffer(context);
498 return Media::SUCCESS;
499 }
500
Decode(uint32_t index,DecodeContext & context)501 uint32_t JpegDecoder::Decode(uint32_t index, DecodeContext &context)
502 {
503 ImageTrace imageTrace("JpegDecoder::Decode, index:%u", index);
504 if (index >= JPEG_IMAGE_NUM) {
505 IMAGE_LOGE("decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
506 return ERR_IMAGE_INVALID_PARAMETER;
507 }
508 if (state_ < JpegDecodingState::IMAGE_DECODING) {
509 IMAGE_LOGE("decode failed for state %{public}d.", state_);
510 return ERR_MEDIA_INVALID_OPERATION;
511 }
512 if (state_ > JpegDecodingState::IMAGE_DECODING) {
513 FinishOldDecompress();
514 state_ = JpegDecodingState::SOURCE_INITED;
515 uint32_t ret = DecodeHeader();
516 if (ret != Media::SUCCESS) {
517 state_ = JpegDecodingState::BASE_INFO_PARSING;
518 IMAGE_LOGE("decode header error on decode:%{public}u.", ret);
519 return ret;
520 }
521 state_ = JpegDecodingState::BASE_INFO_PARSED;
522 ret = StartDecompress(opts_);
523 if (ret != Media::SUCCESS) {
524 IMAGE_LOGE("start decompress failed on decode:%{public}u.", ret);
525 return ret;
526 }
527 state_ = JpegDecodingState::IMAGE_DECODING;
528 }
529 // only state JpegDecodingState::IMAGE_DECODING can go here.
530 if (hwJpegDecompress_ != nullptr) {
531 srcMgr_.inputStream->Seek(streamPosition_);
532 uint32_t ret = hwJpegDecompress_->Decompress(&decodeInfo_, srcMgr_.inputStream, context);
533 if (ret == Media::SUCCESS) {
534 state_ = JpegDecodingState::IMAGE_DECODED;
535 IMAGE_LOGD("jpeg hardware decode success.");
536 ImageUtils::InvalidateContextSurfaceBuffer(context);
537 return ret;
538 }
539 }
540 uint32_t ret = DoSwDecode(context);
541 if (ret == Media::SUCCESS) {
542 state_ = JpegDecodingState::IMAGE_DECODED;
543 IMAGE_LOGD("jpeg software decode success.");
544 return Media::SUCCESS;
545 }
546 if (ret == ERR_IMAGE_SOURCE_DATA_INCOMPLETE && opts_.allowPartialImage) {
547 state_ = JpegDecodingState::IMAGE_PARTIAL;
548 context.ifPartialOutput = true;
549 return Media::SUCCESS;
550 }
551 state_ = JpegDecodingState::IMAGE_ERROR;
552 return ret;
553 }
554
Reset()555 void JpegDecoder::Reset()
556 {
557 srcMgr_.inputStream = nullptr;
558 }
559
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & progContext)560 uint32_t JpegDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &progContext)
561 {
562 progContext.totalProcessProgress = 0;
563 if (index >= JPEG_IMAGE_NUM) {
564 IMAGE_LOGE("decode image index:[%{public}u] out of range:[%{public}u].", index, JPEG_IMAGE_NUM);
565 return ERR_IMAGE_INVALID_PARAMETER;
566 }
567 if (state_ != JpegDecodingState::IMAGE_DECODING) {
568 IMAGE_LOGE("incremental decode failed for state %{public}d.", state_);
569 return ERR_MEDIA_INVALID_OPERATION;
570 }
571
572 uint32_t ret = DoSwDecode(progContext.decodeContext);
573 if (ret == Media::SUCCESS) {
574 state_ = JpegDecodingState::IMAGE_DECODED;
575 }
576 // get promote decode progress, in percentage: 0~100.
577 progContext.totalProcessProgress =
578 decodeInfo_.output_height == 0 ? 0 : (decodeInfo_.output_scanline * NUM_100) / decodeInfo_.output_height;
579 IMAGE_LOGD("incremental decode progress %{public}u.", progContext.totalProcessProgress);
580 return ret;
581 }
582
CreateHwDecompressor()583 void JpegDecoder::CreateHwDecompressor()
584 {
585 std::map<std::string, AttrData> capabilities;
586 const std::string format = "image/jpeg";
587 capabilities.insert(std::map<std::string, AttrData>::value_type("encodeFormat", AttrData(format)));
588 hwJpegDecompress_ = pluginServer_.CreateObject<AbsImageDecompressComponent>(
589 AbsImageDecompressComponent::SERVICE_DEFAULT, capabilities);
590 if (hwJpegDecompress_ == nullptr) {
591 IMAGE_LOGE("get hardware jpeg decompress component failed.");
592 return;
593 }
594 }
595
FinishOldDecompress()596 void JpegDecoder::FinishOldDecompress()
597 {
598 if (state_ < JpegDecodingState::IMAGE_DECODING) {
599 return;
600 }
601 jpeg_destroy_decompress(&decodeInfo_);
602 CreateDecoder();
603 }
604
IsMarker(uint8_t rawMarkerPrefix,uint8_t rawMarkderCode,uint8_t markerCode)605 bool JpegDecoder::IsMarker(uint8_t rawMarkerPrefix, uint8_t rawMarkderCode, uint8_t markerCode)
606 {
607 if (rawMarkerPrefix != JPG_MARKER_PREFIX) {
608 return false;
609 }
610
611 // RSTn, n from 0 to 7
612 if (rawMarkderCode >= JPG_MARKER_RST0 && rawMarkderCode <= JPG_MARKER_RSTN && markerCode == JPG_MARKER_RST) {
613 return true;
614 }
615
616 // APPn, n from 0 to 15
617 if (rawMarkderCode >= JPG_MARKER_APP0 && rawMarkderCode <= JPG_MARKER_APPN && markerCode == JPG_MARKER_APP) {
618 return true;
619 }
620
621 if (rawMarkderCode == markerCode) {
622 return true;
623 }
624 return false;
625 }
626
FindMarker(InputDataStream & stream,uint8_t marker)627 bool JpegDecoder::FindMarker(InputDataStream &stream, uint8_t marker)
628 {
629 uint8_t buffer[MARKER_SIZE] = { 0 };
630 uint32_t readSize = 0;
631 stream.Seek(0);
632 while (true) {
633 uint32_t cur = stream.Tell();
634 if (!stream.Seek(cur + MARKER_SIZE)) {
635 return false;
636 }
637 stream.Seek(cur);
638
639 // read marker code
640 stream.Read(MARKER_SIZE, buffer, sizeof(buffer), readSize);
641 if (readSize != MARKER_SIZE) {
642 return false;
643 }
644
645 uint8_t markerPrefix = buffer[JPG_MARKER_PREFIX_OFFSET];
646 uint8_t markerCode = buffer[JPG_MARKER_CODE_OFFSET];
647 if (IsMarker(markerPrefix, markerCode, JPG_MARKER_SOS)) {
648 return true;
649 }
650
651 if (IsMarker(markerPrefix, markerCode, JPG_MARKER_SOI) || IsMarker(markerPrefix, markerCode, JPG_MARKER_RST)) {
652 continue;
653 }
654
655 cur = stream.Tell();
656 if (!stream.Seek(cur + MARKER_LENGTH)) {
657 return false;
658 }
659 stream.Seek(cur);
660 // read marker length
661 stream.Read(MARKER_LENGTH, buffer, sizeof(buffer), readSize);
662 if (readSize != MARKER_LENGTH) {
663 return false;
664 }
665 // skip data, length = sizeof(length) + sizeof(data)
666 uint32_t length = (buffer[MARKER_LENGTH_0_OFFSET] << MARKER_LENGTH_SHIFT) + buffer[MARKER_LENGTH_1_OFFSET];
667 if (!stream.Seek(cur + length)) {
668 return false;
669 }
670 }
671 }
672
DecodeHeader()673 uint32_t JpegDecoder::DecodeHeader()
674 {
675 if (setjmp(jerr_.setjmp_buffer)) {
676 IMAGE_LOGE("get image size failed.");
677 return ERR_IMAGE_DECODE_ABNORMAL;
678 }
679 if (state_ == JpegDecodingState::SOURCE_INITED) {
680 srcMgr_.inputStream->Seek(0);
681 } else {
682 srcMgr_.inputStream->Seek(streamPosition_);
683 }
684 decodeInfo_.src = &srcMgr_;
685
686 /**
687 * The function jpeg_read_header() shall read the JPEG datastream until the first SOS marker is encountered
688 * incremental decoding should have enough data(contains SOS marker) before calling jpeg_read_header.
689 */
690 if (!srcMgr_.inputStream->IsStreamCompleted()) {
691 uint32_t curPos = srcMgr_.inputStream->Tell();
692 while (true) {
693 if (!FindMarker(*srcMgr_.inputStream, JPG_MARKER_SOS)) {
694 srcMgr_.inputStream->Seek(curPos);
695 return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
696 }
697 srcMgr_.inputStream->Seek(curPos);
698 break;
699 }
700 }
701
702 // call jpeg_save_markers, use to get ICC profile.
703 jpeg_save_markers(&decodeInfo_, PL_ICC_MARKER, PL_MARKER_LENGTH_LIMIT);
704 int32_t ret = jpeg_read_header(&decodeInfo_, true);
705 streamPosition_ = srcMgr_.inputStream->Tell();
706 if (ret == JPEG_SUSPENDED) {
707 IMAGE_LOGD("image input data incomplete, decode header error:%{public}u.", ret);
708 return ERR_IMAGE_SOURCE_DATA_INCOMPLETE;
709 } else if (ret != JPEG_HEADER_OK) {
710 IMAGE_LOGE("image type is not jpeg, decode header error:%{public}u.", ret);
711 return ERR_IMAGE_GET_DATA_ABNORMAL;
712 }
713 return Media::SUCCESS;
714 }
715
StartDecompress(const PixelDecodeOptions & opts)716 uint32_t JpegDecoder::StartDecompress(const PixelDecodeOptions &opts)
717 {
718 if (setjmp(jerr_.setjmp_buffer)) {
719 IMAGE_LOGE("set output image info failed.");
720 return ERR_IMAGE_DECODE_ABNORMAL;
721 }
722 // set decode options
723 if (decodeInfo_.jpeg_color_space == JCS_CMYK || decodeInfo_.jpeg_color_space == JCS_YCCK) {
724 // can't support CMYK to alpha8 convert
725 if (opts.desiredPixelFormat == PixelFormat::ALPHA_8) {
726 IMAGE_LOGE("can't support colorspace CMYK to alpha convert.");
727 return ERR_IMAGE_UNKNOWN_FORMAT;
728 }
729 IMAGE_LOGD("jpeg colorspace is CMYK.");
730 decodeInfo_.out_color_space = JCS_CMYK;
731 outputFormat_ = PixelFormat::CMYK;
732 } else {
733 decodeInfo_.out_color_space = GetDecodeFormat(opts.desiredPixelFormat, outputFormat_);
734 if (decodeInfo_.out_color_space == JCS_UNKNOWN) {
735 IMAGE_LOGE("set jpeg output color space invalid.");
736 return ERR_IMAGE_UNKNOWN_FORMAT;
737 }
738 }
739 srcMgr_.inputStream->Seek(streamPosition_);
740 if (jpeg_start_decompress(&decodeInfo_) != TRUE) {
741 streamPosition_ = srcMgr_.inputStream->Tell();
742 IMAGE_LOGE("jpeg start decompress failed, invalid input.");
743 return ERR_IMAGE_INVALID_PARAMETER;
744 }
745 streamPosition_ = srcMgr_.inputStream->Tell();
746 return Media::SUCCESS;
747 }
748
ParseExifData()749 bool JpegDecoder::ParseExifData()
750 {
751 IMAGE_LOGD("ParseExifData enter");
752 uint32_t curPos = srcMgr_.inputStream->Tell();
753 srcMgr_.inputStream->Seek(0);
754 unsigned long fsize = static_cast<unsigned long>(srcMgr_.inputStream->GetStreamSize());
755 if (fsize <= 0) {
756 IMAGE_LOGE("Get stream size failed");
757 return false;
758 }
759 unsigned char *buf = new unsigned char[fsize];
760 uint32_t readSize = 0;
761 srcMgr_.inputStream->Read(fsize, buf, fsize, readSize);
762 IMAGE_LOGD("parsing EXIF: fsize %{public}lu", fsize);
763
764 int code = exifInfo_.ParseExifData(buf, fsize);
765 delete[] buf;
766 srcMgr_.inputStream->Seek(curPos);
767 if (code) {
768 IMAGE_LOGE("Error parsing EXIF: code %{public}d", code);
769 return false;
770 }
771 return true;
772 }
773
GetImagePropertyInt(uint32_t index,const std::string & key,int32_t & value)774 uint32_t JpegDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
775 {
776 IMAGE_LOGD("[GetImagePropertyInt] enter jpeg plugin, key:%{public}s", key.c_str());
777 if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
778 IMAGE_LOGE("[GetImagePropertyInt] this key is used to check the original format of raw image!");
779 return Media::ERR_MEDIA_VALUE_INVALID;
780 }
781
782 if (!exifInfo_.IsExifDataParsed()) {
783 if (!ParseExifData()) {
784 IMAGE_LOGE("[GetImagePropertyInt] Parse exif data failed!");
785 return Media::ERROR;
786 }
787 }
788 if (IsSameTextStr(key, ORIENTATION)) {
789 if (PROPERTY_INT.find(exifInfo_.orientation_) != PROPERTY_INT.end()) {
790 value = PROPERTY_INT.at(exifInfo_.orientation_);
791 } else {
792 IMAGE_LOGE("[GetImagePropertyInt] The exifinfo:%{public}s is not found",
793 exifInfo_.orientation_.c_str());
794 return Media::ERR_MEDIA_VALUE_INVALID;
795 }
796 } else {
797 IMAGE_LOGE("[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
798 return Media::ERR_MEDIA_VALUE_INVALID;
799 }
800 return Media::SUCCESS;
801 }
802
GetImagePropertyString(uint32_t index,const std::string & key,std::string & value)803 uint32_t JpegDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
804 {
805 IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
806 if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
807 IMAGE_LOGE("[GetImagePropertyString] this key is used to check the original format of raw image!");
808 return Media::ERR_MEDIA_VALUE_INVALID;
809 }
810 if (!exifInfo_.IsExifDataParsed()) {
811 if (!ParseExifData()) {
812 IMAGE_LOGE("[GetImagePropertyString] Parse exif data failed!");
813 return Media::ERROR;
814 }
815 }
816 if (IsSameTextStr(key, BITS_PER_SAMPLE)) {
817 value = exifInfo_.bitsPerSample_;
818 } else if (IsSameTextStr(key, ORIENTATION)) {
819 value = exifInfo_.orientation_;
820 } else if (IsSameTextStr(key, IMAGE_LENGTH)) {
821 value = exifInfo_.imageLength_;
822 } else if (IsSameTextStr(key, IMAGE_WIDTH)) {
823 value = exifInfo_.imageWidth_;
824 } else if (IsSameTextStr(key, GPS_LATITUDE)) {
825 value = exifInfo_.gpsLatitude_;
826 } else if (IsSameTextStr(key, GPS_LONGITUDE)) {
827 value = exifInfo_.gpsLongitude_;
828 } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) {
829 value = exifInfo_.gpsLatitudeRef_;
830 } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) {
831 value = exifInfo_.gpsLongitudeRef_;
832 } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) {
833 value = exifInfo_.dateTimeOriginal_;
834 } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL_MEDIA)) {
835 FormatTimeStamp(value, exifInfo_.dateTimeOriginal_);
836 } else if (GetImagePropertyString(key, value) != Media::SUCCESS) {
837 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
838 }
839 if (IsSameTextStr(value, EXIFInfo::DEFAULT_EXIF_VALUE)) {
840 IMAGE_LOGE("[GetImagePropertyString] enter jpeg plugin, ifd and entry are not matched!");
841 return Media::ERR_MEDIA_VALUE_INVALID;
842 }
843 IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
844 return Media::SUCCESS;
845 }
846
GetImagePropertyString(const std::string & key,std::string & value)847 uint32_t JpegDecoder::GetImagePropertyString(const std::string &key, std::string &value)
848 {
849 if (IsSameTextStr(key, EXPOSURE_TIME)) {
850 value = exifInfo_.exposureTime_;
851 } else if (IsSameTextStr(key, F_NUMBER)) {
852 value = exifInfo_.fNumber_;
853 } else if (IsSameTextStr(key, ISO_SPEED_RATINGS)) {
854 value = exifInfo_.isoSpeedRatings_;
855 } else if (IsSameTextStr(key, SCENE_TYPE)) {
856 value = exifInfo_.sceneType_;
857 } else if (IsSameTextStr(key, COMPRESSED_BITS_PER_PIXEL)) {
858 value = exifInfo_.compressedBitsPerPixel_;
859 } else if (IsSameTextStr(key, DATE_TIME)) {
860 value = exifInfo_.dateTime_;
861 } else if (IsSameTextStr(key, GPS_TIME_STAMP)) {
862 value = exifInfo_.gpsTimeStamp_;
863 } else if (IsSameTextStr(key, GPS_DATE_STAMP)) {
864 value = exifInfo_.gpsDateStamp_;
865 } else if (IsSameTextStr(key, IMAGE_DESCRIPTION)) {
866 value = exifInfo_.imageDescription_;
867 } else if (IsSameTextStr(key, MAKE)) {
868 value = exifInfo_.make_;
869 } else if (IsSameTextStr(key, MODEL)) {
870 value = exifInfo_.model_;
871 } else if (IsSameTextStr(key, PHOTO_MODE)) {
872 value = exifInfo_.photoMode_;
873 } else if (IsSameTextStr(key, SENSITIVITY_TYPE)) {
874 value = exifInfo_.sensitivityType_;
875 } else if (IsSameTextStr(key, STANDARD_OUTPUT_SENSITIVITY)) {
876 value = exifInfo_.standardOutputSensitivity_;
877 } else if (IsSameTextStr(key, RECOMMENDED_EXPOSURE_INDEX)) {
878 value = exifInfo_.recommendedExposureIndex_;
879 } else if (IsSameTextStr(key, ISO_SPEED)) {
880 value = exifInfo_.isoSpeedRatings_;
881 } else if (IsSameTextStr(key, APERTURE_VALUE)) {
882 value = exifInfo_.apertureValue_;
883 } else if (IsSameTextStr(key, EXPOSURE_BIAS_VALUE)) {
884 value = exifInfo_.exposureBiasValue_;
885 } else if (IsSameTextStr(key, METERING_MODE)) {
886 value = exifInfo_.meteringMode_;
887 } else if (IsSameTextStr(key, LIGHT_SOURCE)) {
888 value = exifInfo_.lightSource_;
889 } else if (IsSameTextStr(key, FLASH)) {
890 value = exifInfo_.flash_;
891 } else if (IsSameTextStr(key, FOCAL_LENGTH)) {
892 value = exifInfo_.focalLength_;
893 } else {
894 return GetImagePropertyStringEx(key, value);
895 }
896
897 return Media::SUCCESS;
898 }
899
GetImagePropertyStringEx(const std::string & key,std::string & value)900 uint32_t JpegDecoder::GetImagePropertyStringEx(const std::string &key, std::string &value)
901 {
902 if (IsSameTextStr(key, USER_COMMENT)) {
903 value = exifInfo_.userComment_;
904 } else if (IsSameTextStr(key, PIXEL_X_DIMENSION)) {
905 value = exifInfo_.pixelXDimension_;
906 } else if (IsSameTextStr(key, PIXEL_Y_DIMENSION)) {
907 value = exifInfo_.pixelYDimension_;
908 } else if (IsSameTextStr(key, WHITE_BALANCE)) {
909 value = exifInfo_.whiteBalance_;
910 } else if (IsSameTextStr(key, FOCAL_LENGTH_IN_35_MM_FILM)) {
911 value = exifInfo_.focalLengthIn35mmFilm_;
912 } else if (IsSameTextStr(key, HW_MNOTE_CAPTURE_MODE)) {
913 value = exifInfo_.hwMnoteCaptureMode_;
914 } else if (IsSameTextStr(key, HW_MNOTE_PHYSICAL_APERTURE)) {
915 value = exifInfo_.hwMnotePhysicalAperture_;
916 } else {
917 return GetMakerImagePropertyString(key, value);
918 }
919 return Media::SUCCESS;
920 }
921
GetMakerImagePropertyString(const std::string & key,std::string & value)922 uint32_t JpegDecoder::GetMakerImagePropertyString(const std::string &key, std::string &value)
923 {
924 if (exifInfo_.makerInfoTagValueMap.find(key) != exifInfo_.makerInfoTagValueMap.end()) {
925 value = exifInfo_.makerInfoTagValueMap[key];
926 return Media::SUCCESS;
927 }
928 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
929 }
930
InitOriginalTimes(std::string & dataTime)931 void InitOriginalTimes(std::string &dataTime)
932 {
933 for (size_t i = 0; i < dataTime.size() && i < TIMES_LEN; i++) {
934 if ((dataTime[i] < '0' || dataTime[i] > '9') && dataTime[i] != ' ') {
935 if (i < DATE_LEN) {
936 dataTime[i] = '-';
937 } else {
938 dataTime[i] = ':';
939 }
940 }
941 }
942 }
943
SetOriginalTimes(std::string & dataTime)944 std::string SetOriginalTimes(std::string &dataTime)
945 {
946 InitOriginalTimes(dataTime);
947 std::string data = "";
948 std::string time = "";
949 std::string::size_type position = dataTime.find(" ");
950 if (position == dataTime.npos) {
951 data = dataTime;
952 if (data.find("-") == data.npos) {
953 data += "-01-01";
954 } else if (data.find_first_of("-") == data.find_last_of("-")) {
955 data += "-01";
956 }
957 time += " 00:00:00";
958 } else {
959 data = dataTime.substr(0, position);
960 time = dataTime.substr(position);
961 if (data.find("-") == data.npos) {
962 data += "-01-01";
963 } else if (data.find_first_of("-") == data.find_last_of("-")) {
964 data += "-01";
965 }
966 if (time.find(":") == data.npos) {
967 time += ":00:00";
968 } else if (time.find_first_of(":") == time.find_last_of(":")) {
969 time += ":00";
970 } else {
971 std::string timeTmp = time;
972 time = timeTmp.substr(0, time.find("."));
973 }
974 }
975 return data + time;
976 }
977
FormatTimeStamp(std::string & value,std::string & src)978 void JpegDecoder::FormatTimeStamp(std::string &value, std::string &src)
979 {
980 value = "";
981 if (!IsSameTextStr(src, "")) {
982 value = SetOriginalTimes(src);
983 }
984 }
985
getExifTagFromKey(const std::string & key)986 ExifTag JpegDecoder::getExifTagFromKey(const std::string &key)
987 {
988 if (IsSameTextStr(key, BITS_PER_SAMPLE)) {
989 return EXIF_TAG_BITS_PER_SAMPLE;
990 } else if (IsSameTextStr(key, ORIENTATION)) {
991 return EXIF_TAG_ORIENTATION;
992 } else if (IsSameTextStr(key, IMAGE_LENGTH)) {
993 return EXIF_TAG_IMAGE_LENGTH;
994 } else if (IsSameTextStr(key, IMAGE_WIDTH)) {
995 return EXIF_TAG_IMAGE_WIDTH;
996 } else if (IsSameTextStr(key, GPS_LATITUDE)) {
997 return EXIF_TAG_GPS_LATITUDE;
998 } else if (IsSameTextStr(key, GPS_LONGITUDE)) {
999 return EXIF_TAG_GPS_LONGITUDE;
1000 } else if (IsSameTextStr(key, GPS_LATITUDE_REF)) {
1001 return EXIF_TAG_GPS_LATITUDE_REF;
1002 } else if (IsSameTextStr(key, GPS_LONGITUDE_REF)) {
1003 return EXIF_TAG_GPS_LONGITUDE_REF;
1004 } else if (IsSameTextStr(key, DATE_TIME_ORIGINAL)) {
1005 return EXIF_TAG_DATE_TIME_ORIGINAL;
1006 } else if (IsSameTextStr(key, EXPOSURE_TIME)) {
1007 return EXIF_TAG_EXPOSURE_TIME;
1008 } else if (IsSameTextStr(key, F_NUMBER)) {
1009 return EXIF_TAG_FNUMBER;
1010 } else if (IsSameTextStr(key, ISO_SPEED_RATINGS)) {
1011 return EXIF_TAG_ISO_SPEED_RATINGS;
1012 } else if (IsSameTextStr(key, SCENE_TYPE)) {
1013 return EXIF_TAG_SCENE_TYPE;
1014 } else if (IsSameTextStr(key, COMPRESSED_BITS_PER_PIXEL)) {
1015 return EXIF_TAG_COMPRESSED_BITS_PER_PIXEL;
1016 } else {
1017 return EXIF_TAG_PRINT_IMAGE_MATCHING;
1018 }
1019 }
1020
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,const std::string & path)1021 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1022 const std::string &value, const std::string &path)
1023 {
1024 IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s", key.c_str());
1025 ExifTag tag = getExifTagFromKey(key);
1026 if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
1027 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1028 }
1029
1030 uint32_t ret = exifInfo_.ModifyExifData(tag, value, path);
1031 if (ret != Media::SUCCESS) {
1032 return ret;
1033 }
1034 return Media::SUCCESS;
1035 }
1036
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,const int fd)1037 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1038 const std::string &value, const int fd)
1039 {
1040 IMAGE_LOGD("[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
1041 fd, key.c_str(), value.c_str());
1042 ExifTag tag = getExifTagFromKey(key);
1043 if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
1044 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1045 }
1046
1047 uint32_t ret = exifInfo_.ModifyExifData(tag, value, fd);
1048 if (ret != Media::SUCCESS) {
1049 return ret;
1050 }
1051 return Media::SUCCESS;
1052 }
1053
ModifyImageProperty(uint32_t index,const std::string & key,const std::string & value,uint8_t * data,uint32_t size)1054 uint32_t JpegDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1055 const std::string &value, uint8_t *data, uint32_t size)
1056 {
1057 IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s, value:%{public}s",
1058 key.c_str(), value.c_str());
1059 ExifTag tag = getExifTagFromKey(key);
1060 if (tag == EXIF_TAG_PRINT_IMAGE_MATCHING) {
1061 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1062 }
1063
1064 uint32_t ret = exifInfo_.ModifyExifData(tag, value, data, size);
1065 if (ret != Media::SUCCESS) {
1066 return ret;
1067 }
1068 return Media::SUCCESS;
1069 }
1070
GetFilterArea(const int & privacyType,std::vector<std::pair<uint32_t,uint32_t>> & ranges)1071 uint32_t JpegDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1072 {
1073 IMAGE_LOGD("[GetFilterArea] with privacyType:%{public}d ", privacyType);
1074 if (srcMgr_.inputStream == nullptr) {
1075 IMAGE_LOGE("[GetFilterArea] srcMgr_.inputStream is nullptr.");
1076 return Media::ERR_MEDIA_INVALID_OPERATION;
1077 }
1078 uint32_t curPos = srcMgr_.inputStream->Tell();
1079 srcMgr_.inputStream->Seek(ADDRESS_4);
1080 // app1SizeBuf is used to get value of EXIF data size
1081 uint8_t *app1SizeBuf = new uint8_t[JPEG_APP1_SIZE];
1082 uint32_t readSize = 0;
1083 if (!srcMgr_.inputStream->Read(JPEG_APP1_SIZE, app1SizeBuf, JPEG_APP1_SIZE, readSize)) {
1084 IMAGE_LOGE("[GetFilterArea] get app1 size failed.");
1085 return Media::ERR_MEDIA_INVALID_OPERATION;
1086 }
1087 uint32_t app1Size =
1088 static_cast<unsigned int>(app1SizeBuf[1]) | static_cast<unsigned int>(app1SizeBuf[0] << OFFSET_8);
1089 delete[] app1SizeBuf;
1090 uint32_t fsize = static_cast<uint32_t>(srcMgr_.inputStream->GetStreamSize());
1091 if (app1Size > fsize) {
1092 IMAGE_LOGE("[GetFilterArea] file format is illegal.");
1093 return Media::ERR_MEDIA_INVALID_OPERATION;
1094 }
1095
1096 srcMgr_.inputStream->Seek(0);
1097 uint32_t bufSize = app1Size + ADDRESS_4;
1098 // buf is from image file head to exif data end
1099 uint8_t *buf = new uint8_t[bufSize];
1100 srcMgr_.inputStream->Read(bufSize, buf, bufSize, readSize);
1101 uint32_t ret = exifInfo_.GetFilterArea(buf, bufSize, privacyType, ranges);
1102 delete[] buf;
1103 srcMgr_.inputStream->Seek(curPos);
1104 if (ret != Media::SUCCESS) {
1105 IMAGE_LOGE("[GetFilterArea]: failed to get area, errno %{public}d", ret);
1106 return ret;
1107 }
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