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