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 "exif_info.h"
17 #include <algorithm>
18 #include <cstdio>
19 #include <memory>
20 #include <unistd.h>
21 #include "media_errors.h"
22 #include "string_ex.h"
23 #include "securec.h"
24
25 namespace OHOS {
26 namespace ImagePlugin {
27 namespace {
28 using namespace OHOS::HiviewDFX;
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_IMAGE, "Exif" };
30 static constexpr int PARSE_EXIF_SUCCESS = 0;
31 static constexpr int PARSE_EXIF_DATA_ERROR = 10001;
32 static constexpr int PARSE_EXIF_IFD_ERROR = 10002;
33 static constexpr int BUFFER_POSITION_4 = 4;
34 static constexpr int BUFFER_POSITION_5 = 5;
35 static constexpr int BUFFER_POSITION_6 = 6;
36 static constexpr int BUFFER_POSITION_7 = 7;
37 static constexpr int BUFFER_POSITION_8 = 8;
38 static constexpr int BUFFER_POSITION_9 = 9;
39 static constexpr int BUFFER_POSITION_12 = 12;
40 static constexpr int BUFFER_POSITION_13 = 13;
41 static constexpr int LENGTH_OFFSET_2 = 2;
42 static constexpr int BYTE_COUNTS_12 = 12;
43 static constexpr int MOVE_OFFSET_8 = 8;
44 static constexpr int MOVE_OFFSET_16 = 16;
45 static constexpr int MOVE_OFFSET_24 = 24;
46 static constexpr int CONSTANT_2 = 2;
47 static constexpr int CONSTANT_3 = 3;
48 static constexpr int CONSTANT_4 = 4;
49 static constexpr unsigned long MAX_FILE_SIZE = 1000 * 1000 * 1000;
50 static constexpr uint32_t ERROR_PARSE_EXIF_FAILED = 1;
51 static constexpr uint32_t ERROR_NO_EXIF_TAGS = 2;
52
53 /* raw EXIF header data */
54 static const unsigned char exifHeader[] = {
55 0xff, 0xd8, 0xff, 0xe1
56 };
57 /* Offset of tiff begin from jpeg file begin */
58 static constexpr uint32_t TIFF_OFFSET_FROM_FILE_BEGIN = 12;
59 static constexpr int PERMISSION_GPS_TYPE = 1;
60
61 static const struct TagEntry {
62 /*! Tag ID. There may be duplicate tags when the same number is used for
63 * different meanings in different IFDs. */
64 ExifTag tag;
65 const std::string name;
66 const uint16_t number;
67 } ExifTagTable[] = {
68 {EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", 0x0000},
69 {EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex", 0x0001},
70 {EXIF_TAG_GPS_LATITUDE_REF, "GPSLatitudeRef", 0x0001},
71 {EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion", 0x0002},
72 {EXIF_TAG_GPS_LATITUDE, "GPSLatitude", 0x0002},
73 {EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", 0x0003},
74 {EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", 0x0004},
75 {EXIF_TAG_GPS_ALTITUDE_REF, "GPSAltitudeRef", 0x0005},
76 {EXIF_TAG_GPS_ALTITUDE, "GPSAltitude", 0x0006},
77 {EXIF_TAG_GPS_TIME_STAMP, "GPSTimeStamp", 0x0007},
78 {EXIF_TAG_GPS_SATELLITES, "GPSSatellites", 0x0008},
79 {EXIF_TAG_GPS_STATUS, "GPSStatus", 0x0009},
80 {EXIF_TAG_GPS_MEASURE_MODE, "GPSMeasureMode", 0x000a},
81 {EXIF_TAG_GPS_DOP, "GPSDOP", 0x000b},
82 {EXIF_TAG_GPS_SPEED_REF, "GPSSpeedRef", 0x000c},
83 {EXIF_TAG_GPS_SPEED, "GPSSpeed", 0x000d},
84 {EXIF_TAG_GPS_TRACK_REF, "GPSTrackRef", 0x000e},
85 {EXIF_TAG_GPS_TRACK, "GPSTrack", 0x000f},
86 {EXIF_TAG_GPS_IMG_DIRECTION_REF, "GPSImgDirectionRef", 0x0010},
87 {EXIF_TAG_GPS_IMG_DIRECTION, "GPSImgDirection", 0x0011},
88 {EXIF_TAG_GPS_MAP_DATUM, "GPSMapDatum", 0x0012},
89 {EXIF_TAG_GPS_DEST_LATITUDE_REF, "GPSDestLatitudeRef", 0x0013},
90 {EXIF_TAG_GPS_DEST_LATITUDE, "GPSDestLatitude", 0x0014},
91 {EXIF_TAG_GPS_DEST_LONGITUDE_REF, "GPSDestLongitudeRef", 0x0015},
92 {EXIF_TAG_GPS_DEST_LONGITUDE, "GPSDestLongitude", 0x0016},
93 {EXIF_TAG_GPS_DEST_BEARING_REF, "GPSDestBearingRef", 0x0017},
94 {EXIF_TAG_GPS_DEST_BEARING, "GPSDestBearing", 0x0018},
95 {EXIF_TAG_GPS_DEST_DISTANCE_REF, "GPSDestDistanceRef", 0x0019},
96 {EXIF_TAG_GPS_DEST_DISTANCE, "GPSDestDistance", 0x001a},
97 {EXIF_TAG_GPS_PROCESSING_METHOD, "GPSProcessingMethod", 0x001b},
98 {EXIF_TAG_GPS_AREA_INFORMATION, "GPSAreaInformation", 0x001c},
99 {EXIF_TAG_GPS_DATE_STAMP, "GPSDateStamp", 0x001d},
100 {EXIF_TAG_GPS_DIFFERENTIAL, "GPSDifferential", 0x001e},
101 {EXIF_TAG_GPS_H_POSITIONING_ERROR, "GPSHPositioningError", 0x001f},
102 /* Not in EXIF 2.2 */
103 {EXIF_TAG_NEW_SUBFILE_TYPE, "NewSubfileType", 0x00fe},
104 {EXIF_TAG_IMAGE_WIDTH, "ImageWidth", 0x0100},
105 {EXIF_TAG_IMAGE_LENGTH, "ImageLength", 0x0101},
106 {EXIF_TAG_BITS_PER_SAMPLE, "BitsPerSample", 0x0102},
107 {EXIF_TAG_COMPRESSION, "Compression", 0x0103},
108 {EXIF_TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation", 0x0106},
109 /* Not in EXIF 2.2 */
110 {EXIF_TAG_FILL_ORDER, "FillOrder", 0x010a},
111 /* Not in EXIF 2.2 */
112 {EXIF_TAG_DOCUMENT_NAME, "DocumentName", 0x010d},
113 {EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription", 0x010e},
114 {EXIF_TAG_MAKE, "Make", 0x010f},
115 {EXIF_TAG_MODEL, "Model", 0x0110},
116 {EXIF_TAG_STRIP_OFFSETS, "StripOffsets", 0x0111},
117 {EXIF_TAG_ORIENTATION, "Orientation", 0x0112},
118 {EXIF_TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel", 0x0115},
119 {EXIF_TAG_ROWS_PER_STRIP, "RowsPerStrip", 0x0116},
120 {EXIF_TAG_STRIP_BYTE_COUNTS, "StripByteCounts", 0x0117},
121 {EXIF_TAG_X_RESOLUTION, "XResolution", 0x011a},
122 {EXIF_TAG_Y_RESOLUTION, "YResolution", 0x011b},
123 {EXIF_TAG_PLANAR_CONFIGURATION, "PlanarConfiguration", 0x011c},
124 {EXIF_TAG_RESOLUTION_UNIT, "ResolutionUnit", 0x0128},
125 {EXIF_TAG_TRANSFER_FUNCTION, "TransferFunction", 0x012d},
126 {EXIF_TAG_SOFTWARE, "Software", 0x0131},
127 {EXIF_TAG_DATE_TIME, "DateTime", 0x0132},
128 {EXIF_TAG_ARTIST, "Artist", 0x013b},
129 {EXIF_TAG_WHITE_POINT, "WhitePoint", 0x013e},
130 {EXIF_TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities", 0x013f},
131 /* Not in EXIF 2.2 */
132 {EXIF_TAG_SUB_IFDS, "SubIFDs", 0x014a},
133 /* Not in EXIF 2.2 */
134 {EXIF_TAG_TRANSFER_RANGE, "TransferRange", 0x0156},
135 /* Not in EXIF 2.2 */
136 {EXIF_TAG_JPEG_PROC, "JPEGProc", 0x0200},
137 {EXIF_TAG_JPEG_INTERCHANGE_FORMAT, "JPEGInterchangeFormat", 0x0201},
138 {EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, "JPEGInterchangeFormatLength", 0x0202},
139 {EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients", 0x0211},
140 {EXIF_TAG_YCBCR_SUB_SAMPLING, "YCbCrSubSampling", 0x0212},
141 {EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning", 0x0213},
142 {EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite", 0x0214},
143 /* Not in EXIF 2.2 */
144 {EXIF_TAG_XML_PACKET, "XMLPacket", 0x02bc},
145 /* Not in EXIF 2.2 */
146 {EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat", 0x1000},
147 /* Not in EXIF 2.2 */
148 {EXIF_TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth", 0x1001},
149 /* Not in EXIF 2.2 */
150 {EXIF_TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength", 0x1002},
151 /* Not in EXIF 2.2 */
152 {EXIF_TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim", 0x828d},
153 /* Not in EXIF 2.2 */
154 {EXIF_TAG_CFA_PATTERN, "CFAPattern", 0x828e},
155 /* Not in EXIF 2.2 */
156 {EXIF_TAG_BATTERY_LEVEL, "BatteryLevel", 0x828f},
157 {EXIF_TAG_COPYRIGHT, "Copyright", 0x8298},
158 {EXIF_TAG_EXPOSURE_TIME, "ExposureTime", 0x829a},
159 {EXIF_TAG_FNUMBER, "FNumber", 0x829d},
160 /* Not in EXIF 2.2 */
161 {EXIF_TAG_IPTC_NAA, "IPTC/NAA", 0x83bb},
162 /* Not in EXIF 2.2 */
163 {EXIF_TAG_IMAGE_RESOURCES, "ImageResources", 0x8649},
164 {EXIF_TAG_EXIF_IFD_POINTER, "ExifIfdPointer", 0x8769},
165 /* Not in EXIF 2.2 */
166 {EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile", 0x8773},
167 {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", 0x8822},
168 {EXIF_TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity", 0x8824},
169 {EXIF_TAG_GPS_INFO_IFD_POINTER, "GPSInfoIFDPointer", 0x8825},
170 {EXIF_TAG_ISO_SPEED_RATINGS, "ISOSpeedRatings", 0x8827},
171 {EXIF_TAG_OECF, "OECF", 0x8828},
172 /* Not in EXIF 2.2 */
173 {EXIF_TAG_TIME_ZONE_OFFSET, "TimeZoneOffset", 0x882a},
174 {EXIF_TAG_EXIF_VERSION, "ExifVersion", 0x9000},
175 {EXIF_TAG_DATE_TIME_ORIGINAL, "DateTimeOriginal", 0x9003},
176 {EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized", 0x9004},
177 {EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration", 0x9101},
178 {EXIF_TAG_COMPRESSED_BITS_PER_PIXEL, "CompressedBitsPerPixel", 0x9102},
179 {EXIF_TAG_SHUTTER_SPEED_VALUE, "ShutterSpeedValue", 0x9201},
180 {EXIF_TAG_APERTURE_VALUE, "ApertureValue", 0x9202},
181 {EXIF_TAG_BRIGHTNESS_VALUE, "BrightnessValue", 0x9203},
182 {EXIF_TAG_EXPOSURE_BIAS_VALUE, "ExposureBiasValue", 0x9204},
183 {EXIF_TAG_MAX_APERTURE_VALUE, "MaxApertureValue", 0x9205},
184 {EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance", 0x9206},
185 {EXIF_TAG_METERING_MODE, "MeteringMode", 0x9207},
186 {EXIF_TAG_LIGHT_SOURCE, "LightSource", 0x9208},
187 {EXIF_TAG_FLASH, "Flash", 0x9209},
188 {EXIF_TAG_FOCAL_LENGTH, "FocalLength", 0x920a},
189 {EXIF_TAG_SUBJECT_AREA, "SubjectArea", 0x9214},
190 /* Not in EXIF 2.2 */
191 {EXIF_TAG_TIFF_EP_STANDARD_ID, "TIFF/EPStandardID", 0x9216},
192 {EXIF_TAG_MAKER_NOTE, "MakerNote", 0x927c},
193 {EXIF_TAG_USER_COMMENT, "UserComment", 0x9286},
194 {EXIF_TAG_SUB_SEC_TIME, "SubsecTime", 0x9290},
195 {EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal", 0x9291},
196 {EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized", 0x9292},
197 /* Not in EXIF 2.2 (Microsoft extension) */
198 {EXIF_TAG_XP_TITLE, "XPTitle", 0x9c9b},
199 /* Not in EXIF 2.2 (Microsoft extension) */
200 {EXIF_TAG_XP_COMMENT, "XPComment", 0x9c9c},
201 /* Not in EXIF 2.2 (Microsoft extension) */
202 {EXIF_TAG_XP_AUTHOR, "XPAuthor", 0x9c9d},
203 /* Not in EXIF 2.2 (Microsoft extension) */
204 {EXIF_TAG_XP_KEYWORDS, "XPKeywords", 0x9c9e},
205 /* Not in EXIF 2.2 (Microsoft extension) */
206 {EXIF_TAG_XP_SUBJECT, "XPSubject", 0x9c9f},
207 {EXIF_TAG_FLASH_PIX_VERSION, "FlashpixVersion", 0xa000},
208 {EXIF_TAG_COLOR_SPACE, "ColorSpace", 0xa001},
209 {EXIF_TAG_PIXEL_X_DIMENSION, "PixelXDimension", 0xa002},
210 {EXIF_TAG_PIXEL_Y_DIMENSION, "PixelYDimension", 0xa003},
211 {EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile", 0xa004},
212 {EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer", 0xa005},
213 {EXIF_TAG_FLASH_ENERGY, "FlashEnergy", 0xa20b},
214 {EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE, "SpatialFrequencyResponse", 0xa20c},
215 {EXIF_TAG_FOCAL_PLANE_X_RESOLUTION, "FocalPlaneXResolution", 0xa20e},
216 {EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION, "FocalPlaneYResolution", 0xa20f},
217 {EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT, "FocalPlaneResolutionUnit", 0xa210},
218 {EXIF_TAG_SUBJECT_LOCATION, "SubjectLocation", 0xa214},
219 {EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", 0xa215},
220 {EXIF_TAG_SENSING_METHOD, "SensingMethod", 0xa217},
221 {EXIF_TAG_FILE_SOURCE, "FileSource", 0xa300},
222 {EXIF_TAG_SCENE_TYPE, "SceneType", 0xa301},
223 {EXIF_TAG_NEW_CFA_PATTERN, "CFAPattern", 0xa302},
224 {EXIF_TAG_CUSTOM_RENDERED, "CustomRendered", 0xa401},
225 {EXIF_TAG_EXPOSURE_MODE, "ExposureMode", 0xa402},
226 {EXIF_TAG_WHITE_BALANCE, "WhiteBalance", 0xa403},
227 {EXIF_TAG_DIGITAL_ZOOM_RATIO, "DigitalZoomRatio", 0xa404},
228 {EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, "FocalLengthIn35mmFilm", 0xa405},
229 {EXIF_TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType", 0xa406},
230 {EXIF_TAG_GAIN_CONTROL, "GainControl", 0xa407},
231 {EXIF_TAG_CONTRAST, "Contrast", 0xa408},
232 {EXIF_TAG_SATURATION, "Saturation", 0xa409},
233 {EXIF_TAG_SHARPNESS, "Sharpness", 0xa40a},
234 {EXIF_TAG_DEVICE_SETTING_DESCRIPTION, "DeviceSettingDescription", 0xa40b},
235 {EXIF_TAG_SUBJECT_DISTANCE_RANGE, "SubjectDistanceRange", 0xa40c},
236 {EXIF_TAG_IMAGE_UNIQUE_ID, "ImageUniqueID", 0xa420},
237 /* EXIF 2.3 */
238 {EXIF_TAG_CAMERA_OWNER_NAME, "CameraOwnerName", 0xa430},
239 /* EXIF 2.3 */
240 {EXIF_TAG_BODY_SERIAL_NUMBER, "BodySerialNumber", 0xa431},
241 /* EXIF 2.3 */
242 {EXIF_TAG_LENS_SPECIFICATION, "LensSpecification", 0xa432},
243 /* EXIF 2.3 */
244 {EXIF_TAG_LENS_MAKE, "LensMake", 0xa433},
245 /* EXIF 2.3 */
246 {EXIF_TAG_LENS_MODEL, "LensModel", 0xa434},
247 /* EXIF 2.3 */
248 {EXIF_TAG_LENS_SERIAL_NUMBER, "LensSerialNumber", 0xa435},
249 /* EXIF 2.32 */
250 {EXIF_TAG_COMPOSITE_IMAGE, "CompositeImage", 0xa460},
251 /* EXIF 2.32 */
252 {EXIF_TAG_SOURCE_IMAGE_NUMBER_OF_COMPOSITE_IMAGE, "SourceImageNumberOfCompositeImage", 0xa461},
253 /* EXIF 2.32 */
254 {EXIF_TAG_SOURCE_EXPOSURE_TIMES_OF_COMPOSITE_IMAGE, "SourceExposureTimesOfCompositeImage", 0xa462},
255 /* EXIF 2.3 */
256 {EXIF_TAG_GAMMA, "Gamma", 0xa500},
257 /* Not in EXIF 2.2 */
258 {EXIF_TAG_PRINT_IMAGE_MATCHING, "PrintImageMatching", 0xc4a5},
259 /* Not in EXIF 2.2 (from the Microsoft HD Photo specification) */
260 {EXIF_TAG_PADDING, "Padding", 0xea1c},
261 {static_cast<ExifTag>(0xffff), "", 0xffff}};
262 }
263
264 const std::string EXIFInfo::DEFAULT_EXIF_VALUE = "default_exif_value";
265
EXIFInfo()266 EXIFInfo::EXIFInfo()
267 : bitsPerSample_(DEFAULT_EXIF_VALUE),
268 orientation_(DEFAULT_EXIF_VALUE),
269 imageLength_(DEFAULT_EXIF_VALUE),
270 imageWidth_(DEFAULT_EXIF_VALUE),
271 gpsLatitude_(DEFAULT_EXIF_VALUE),
272 gpsLongitude_(DEFAULT_EXIF_VALUE),
273 gpsLatitudeRef_(DEFAULT_EXIF_VALUE),
274 gpsLongitudeRef_(DEFAULT_EXIF_VALUE),
275 dateTimeOriginal_(DEFAULT_EXIF_VALUE),
276 exposureTime_(DEFAULT_EXIF_VALUE),
277 fNumber_(DEFAULT_EXIF_VALUE),
278 isoSpeedRatings_(DEFAULT_EXIF_VALUE),
279 sceneType_(DEFAULT_EXIF_VALUE),
280 compressedBitsPerPixel_(DEFAULT_EXIF_VALUE),
281 imageFileDirectory_(EXIF_IFD_COUNT),
282 exifData_(nullptr),
283 isExifDataParsed_(false)
284 {
285 }
286
~EXIFInfo()287 EXIFInfo::~EXIFInfo()
288 {
289 if (exifData_ != nullptr) {
290 exif_data_unref(exifData_);
291 exifData_ = nullptr;
292 }
293 }
294
ParseExifData(const unsigned char * buf,unsigned len)295 int EXIFInfo::ParseExifData(const unsigned char *buf, unsigned len)
296 {
297 HiLog::Debug(LABEL, "ParseExifData ENTER");
298 exifData_ = exif_data_new_from_data(buf, len);
299 if (!exifData_) {
300 return PARSE_EXIF_DATA_ERROR;
301 }
302 exif_data_foreach_content(exifData_,
303 [](ExifContent *ec, void *userData) {
304 ExifIfd ifd = exif_content_get_ifd(ec);
305 (static_cast<EXIFInfo*>(userData))->imageFileDirectory_ = ifd;
306 if (ifd == EXIF_IFD_COUNT) {
307 HiLog::Debug(LABEL, "GetIfd ERROR");
308 return;
309 }
310 exif_content_foreach_entry(ec,
311 [](ExifEntry *ee, void* userData) {
312 if (ee == nullptr || userData == nullptr) {
313 return;
314 }
315 char tagValueChar[1024];
316 exif_entry_get_value(ee, tagValueChar, sizeof(tagValueChar));
317 std::string tagValueStr(&tagValueChar[0], &tagValueChar[strlen(tagValueChar)]);
318 if ((static_cast<EXIFInfo*>(userData))->CheckExifEntryValid(exif_entry_get_ifd(ee), ee->tag)) {
319 (static_cast<EXIFInfo*>(userData))->SetExifTagValues(ee->tag, tagValueStr);
320 }
321 }, userData);
322 }, this);
323
324 if (imageFileDirectory_ == EXIF_IFD_COUNT) {
325 return PARSE_EXIF_IFD_ERROR;
326 }
327 isExifDataParsed_ = true;
328 return PARSE_EXIF_SUCCESS;
329 }
330
ParseExifData(const std::string & data)331 int EXIFInfo::ParseExifData(const std::string &data)
332 {
333 return ParseExifData((const unsigned char *)data.data(), data.length());
334 }
335
IsExifDataParsed()336 bool EXIFInfo::IsExifDataParsed()
337 {
338 return isExifDataParsed_;
339 }
340
SetExifTagValues(const ExifTag & tag,const std::string & value)341 void EXIFInfo::SetExifTagValues(const ExifTag &tag, const std::string &value)
342 {
343 if (tag == EXIF_TAG_BITS_PER_SAMPLE) {
344 bitsPerSample_ = value;
345 } else if (tag == EXIF_TAG_ORIENTATION) {
346 orientation_ = value;
347 } else if (tag == EXIF_TAG_IMAGE_LENGTH) {
348 imageLength_ = value;
349 } else if (tag == EXIF_TAG_IMAGE_WIDTH) {
350 imageWidth_ = value;
351 } else if (tag == EXIF_TAG_GPS_LATITUDE) {
352 gpsLatitude_ = value;
353 } else if (tag == EXIF_TAG_GPS_LONGITUDE) {
354 gpsLongitude_ = value;
355 } else if (tag == EXIF_TAG_GPS_LATITUDE_REF) {
356 gpsLatitudeRef_ = value;
357 } else if (tag == EXIF_TAG_GPS_LONGITUDE_REF) {
358 gpsLongitudeRef_ = value;
359 } else if (tag == EXIF_TAG_DATE_TIME_ORIGINAL) {
360 dateTimeOriginal_ = value;
361 } else if (tag == EXIF_TAG_EXPOSURE_TIME) {
362 exposureTime_ = value;
363 } else if (tag == EXIF_TAG_FNUMBER) {
364 fNumber_ = value;
365 } else if (tag == EXIF_TAG_ISO_SPEED_RATINGS) {
366 isoSpeedRatings_ = value;
367 } else if (tag == EXIF_TAG_SCENE_TYPE) {
368 sceneType_ = value;
369 } else if (tag == EXIF_TAG_COMPRESSED_BITS_PER_PIXEL) {
370 compressedBitsPerPixel_ = value;
371 } else {
372 HiLog::Error(LABEL, "No match tag name!");
373 }
374 }
375
ModifyExifData(const ExifTag & tag,const std::string & value,const std::string & path)376 uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, const std::string &path)
377 {
378 FILE *file = fopen(path.c_str(), "rb");
379 if (file == nullptr) {
380 HiLog::Error(LABEL, "Error creating file %{public}s", path.c_str());
381 return Media::ERR_MEDIA_IO_ABNORMAL;
382 }
383
384 // read jpeg file to buff
385 unsigned long fileLength = GetFileSize(file);
386 if (fileLength == 0 || fileLength > MAX_FILE_SIZE) {
387 HiLog::Error(LABEL, "Get file size failed.");
388 (void)fclose(file);
389 return Media::ERR_MEDIA_BUFFER_TOO_SMALL;
390 }
391
392 unsigned char *fileBuf = static_cast<unsigned char *>(malloc(fileLength));
393 if (fileBuf == nullptr) {
394 HiLog::Error(LABEL, "Allocate buf for %{public}s failed.", path.c_str());
395 (void)fclose(file);
396 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
397 }
398
399 if (fread(fileBuf, fileLength, 1, file) != 1) {
400 HiLog::Error(LABEL, "Read %{public}s failed.", path.c_str());
401 ReleaseSource(&fileBuf, &file);
402 return Media::ERR_MEDIA_READ_PARCEL_FAIL;
403 }
404
405 if (!(fileBuf[0] == 0xFF && fileBuf[1] == 0xD8)) {
406 HiLog::Error(LABEL, "%{public}s is not jpeg file.", path.c_str());
407 ReleaseSource(&fileBuf, &file);
408 return Media::ERR_IMAGE_MISMATCHED_FORMAT;
409 }
410
411 ExifData *ptrExifData = nullptr;
412 bool isNewExifData = false;
413 if (!CreateExifData(fileBuf, fileLength, &ptrExifData, isNewExifData)) {
414 ReleaseSource(&fileBuf, &file);
415 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
416 }
417 (void)fclose(file);
418 file = nullptr;
419
420 unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, fileBuf);
421 if (!isNewExifData && orginExifDataLength == 0) {
422 HiLog::Error(LABEL, "There is no orginExifDataLength node in %{public}s.", path.c_str());
423 exif_data_unref(ptrExifData);
424 free(fileBuf);
425 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
426 }
427
428 ExifByteOrder order = GetExifByteOrder(isNewExifData, fileBuf);
429 FILE *newFile = fopen(path.c_str(), "wb+");
430 if (newFile == nullptr) {
431 HiLog::Error(LABEL, "Error create new file %{public}s", path.c_str());
432 ReleaseSource(&fileBuf, &newFile);
433 return Media::ERR_MEDIA_IO_ABNORMAL;
434 }
435 ExifEntry *entry = nullptr;
436 if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) {
437 ReleaseSource(&fileBuf, &newFile);
438 exif_data_unref(ptrExifData);
439 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
440 }
441 if (!WriteExifDataToFile(ptrExifData, orginExifDataLength, fileLength, fileBuf, newFile)) {
442 ReleaseSource(&fileBuf, &newFile);
443 exif_data_unref(ptrExifData);
444 return Media::ERR_MEDIA_WRITE_PARCEL_FAIL;
445 }
446 ReleaseSource(&fileBuf, &newFile);
447 exif_data_unref(ptrExifData);
448 return Media::SUCCESS;
449 }
450
ModifyExifData(const ExifTag & tag,const std::string & value,const int fd)451 uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value, const int fd)
452 {
453 const int localFd = dup(fd);
454 FILE *file = fdopen(localFd, "wb+");
455 if (file == nullptr) {
456 HiLog::Error(LABEL, "Error creating file %{public}d", localFd);
457 return Media::ERR_MEDIA_IO_ABNORMAL;
458 }
459
460 // read jpeg file to buff
461 unsigned long fileLength = GetFileSize(file);
462 if (fileLength == 0 || fileLength > MAX_FILE_SIZE) {
463 HiLog::Error(LABEL, "Get file size failed.");
464 (void)fclose(file);
465 return Media::ERR_MEDIA_BUFFER_TOO_SMALL;
466 }
467
468 unsigned char *fileBuf = static_cast<unsigned char *>(malloc(fileLength));
469 if (fileBuf == nullptr) {
470 HiLog::Error(LABEL, "Allocate buf for %{public}d failed.", localFd);
471 (void)fclose(file);
472 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
473 }
474
475 // Set current position to begin of file.
476 (void)fseek(file, 0L, 0);
477 if (fread(fileBuf, fileLength, 1, file) != 1) {
478 HiLog::Error(LABEL, "Read %{public}d failed.", localFd);
479 ReleaseSource(&fileBuf, &file);
480 return Media::ERR_MEDIA_READ_PARCEL_FAIL;
481 }
482
483 if (!(fileBuf[0] == 0xFF && fileBuf[1] == 0xD8)) {
484 HiLog::Error(LABEL, "%{public}d is not jpeg file.", localFd);
485 ReleaseSource(&fileBuf, &file);
486 return Media::ERR_IMAGE_MISMATCHED_FORMAT;
487 }
488
489 ExifData *ptrExifData = nullptr;
490 bool isNewExifData = false;
491 if (!CreateExifData(fileBuf, fileLength, &ptrExifData, isNewExifData)) {
492 ReleaseSource(&fileBuf, &file);
493 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
494 }
495
496 unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, fileBuf);
497 if (!isNewExifData && orginExifDataLength == 0) {
498 HiLog::Error(LABEL, "There is no orginExifDataLength node in %{public}d.", localFd);
499 free(fileBuf);
500 exif_data_unref(ptrExifData);
501 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
502 }
503
504 ExifByteOrder order = GetExifByteOrder(isNewExifData, fileBuf);
505 // Set current position to begin of new file.
506 (void)fseek(file, 0L, 0);
507 ExifEntry *entry = nullptr;
508 if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) {
509 ReleaseSource(&fileBuf, &file);
510 exif_data_unref(ptrExifData);
511 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
512 }
513
514 if (!WriteExifDataToFile(ptrExifData, orginExifDataLength, fileLength, fileBuf, file)) {
515 ReleaseSource(&fileBuf, &file);
516 exif_data_unref(ptrExifData);
517 return Media::ERR_MEDIA_WRITE_PARCEL_FAIL;
518 }
519 ReleaseSource(&fileBuf, &file);
520 exif_data_unref(ptrExifData);
521 return Media::SUCCESS;
522 }
523
ModifyExifData(const ExifTag & tag,const std::string & value,unsigned char * data,uint32_t size)524 uint32_t EXIFInfo::ModifyExifData(const ExifTag &tag, const std::string &value,
525 unsigned char *data, uint32_t size)
526 {
527 if (data == nullptr) {
528 HiLog::Error(LABEL, "buffer is nullptr.");
529 return Media::ERR_IMAGE_SOURCE_DATA;
530 }
531
532 if (size == 0) {
533 HiLog::Error(LABEL, "buffer size is 0.");
534 return Media::ERR_MEDIA_BUFFER_TOO_SMALL;
535 }
536
537 if (!(data[0] == 0xFF && data[1] == 0xD8)) {
538 HiLog::Error(LABEL, "This is not jpeg file.");
539 return Media::ERR_IMAGE_MISMATCHED_FORMAT;
540 }
541
542 ExifData *ptrExifData = nullptr;
543 bool isNewExifData = false;
544 if (!CreateExifData(data, size, &ptrExifData, isNewExifData)) {
545 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
546 }
547
548 unsigned int orginExifDataLength = GetOrginExifDataLength(isNewExifData, data);
549 if (!isNewExifData && orginExifDataLength == 0) {
550 HiLog::Error(LABEL, "There is no orginExifDataLength node in buffer.");
551 exif_data_unref(ptrExifData);
552 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
553 }
554
555 ExifByteOrder order = GetExifByteOrder(isNewExifData, data);
556 ExifEntry *entry = nullptr;
557 if (!CreateExifEntry(tag, ptrExifData, value, order, &entry)) {
558 exif_data_unref(ptrExifData);
559 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
560 }
561
562 unsigned char* exifDataBuf = nullptr;
563 unsigned int exifDataBufLength = 0;
564 exif_data_save_data(ptrExifData, &exifDataBuf, &exifDataBufLength);
565 if (exifDataBuf == nullptr) {
566 HiLog::Error(LABEL, "Get Exif Data Buf failed!");
567 exif_data_unref(ptrExifData);
568 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
569 }
570
571 if (size == 0 || size > MAX_FILE_SIZE) {
572 HiLog::Error(LABEL, "Buffer size is out of range.");
573 exif_data_unref(ptrExifData);
574 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
575 }
576 unsigned char *tempBuf = static_cast<unsigned char *>(malloc(size));
577 if (tempBuf == nullptr) {
578 HiLog::Error(LABEL, "Allocate temp buffer ailed.");
579 exif_data_unref(ptrExifData);
580 return Media::ERR_IMAGE_MALLOC_ABNORMAL;
581 }
582
583 // Write EXIF header to buffer
584 uint32_t index = 0;
585 if (sizeof(exifHeader) >= size) {
586 HiLog::Error(LABEL, "There is not enough space for EXIF header!");
587 free(tempBuf);
588 tempBuf = nullptr;
589 exif_data_unref(ptrExifData);
590 return Media::ERR_MEDIA_OUT_OF_RANGE;
591 }
592
593 for (size_t i = 0; i < sizeof(exifHeader); i++) {
594 tempBuf[index] = exifHeader[i];
595 index += 1;
596 }
597
598 // Write EXIF block length in big-endian order
599 unsigned char highBit = static_cast<unsigned char>((exifDataBufLength + LENGTH_OFFSET_2) >> MOVE_OFFSET_8);
600 if (index >= size) {
601 HiLog::Error(LABEL, "There is not enough space for writing EXIF block length!");
602 free(tempBuf);
603 tempBuf = nullptr;
604 exif_data_unref(ptrExifData);
605 return Media::ERR_MEDIA_OUT_OF_RANGE;
606 }
607 tempBuf[index] = highBit;
608 index += 1;
609
610 unsigned char lowBit = static_cast<unsigned char>((exifDataBufLength + LENGTH_OFFSET_2) & 0xff);
611 if (index >= size) {
612 HiLog::Error(LABEL, "There is not enough space for writing EXIF block length!");
613 free(tempBuf);
614 tempBuf = nullptr;
615 exif_data_unref(ptrExifData);
616 return Media::ERR_MEDIA_OUT_OF_RANGE;
617 }
618 tempBuf[index] = lowBit;
619 index += 1;
620
621 // Write EXIF data block
622 if ((index + exifDataBufLength) >= size) {
623 HiLog::Error(LABEL, "There is not enough space for writing EXIF data block!");
624 free(tempBuf);
625 tempBuf = nullptr;
626 exif_data_unref(ptrExifData);
627 return Media::ERR_MEDIA_OUT_OF_RANGE;
628 }
629 for (unsigned int i = 0; i < exifDataBufLength; i++) {
630 tempBuf[index] = exifDataBuf[i];
631 index += 1;
632 }
633
634 // Write JPEG image data, skipping the non-EXIF header
635 if ((index + size - orginExifDataLength - sizeof(exifHeader)) > size) {
636 HiLog::Error(LABEL, "There is not enough space for writing JPEG image data!");
637 free(tempBuf);
638 tempBuf = nullptr;
639 exif_data_unref(ptrExifData);
640 return Media::ERR_MEDIA_OUT_OF_RANGE;
641 }
642 for (unsigned int i = 0; i < (size - orginExifDataLength - sizeof(exifHeader)); i++) {
643 tempBuf[index] = data[orginExifDataLength + sizeof(exifHeader) + i];
644 index += 1;
645 }
646
647 for (unsigned int i = 0; i < size; i++) {
648 data[i] = tempBuf[i];
649 }
650
651 ParseExifData(data, static_cast<unsigned int>(index));
652 free(tempBuf);
653 tempBuf = nullptr;
654 exif_data_unref(ptrExifData);
655 return Media::SUCCESS;
656 }
657
InitExifTag(ExifData * exif,ExifIfd ifd,ExifTag tag)658 ExifEntry* EXIFInfo::InitExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag)
659 {
660 ExifEntry *entry;
661 /* Return an existing tag if one exists */
662 if (!(entry = exif_content_get_entry(exif->ifd[ifd], tag))) {
663 /* Allocate a new entry */
664 entry = exif_entry_new();
665 if (entry == nullptr) {
666 HiLog::Error(LABEL, "Create new entry failed!");
667 return nullptr;
668 }
669 entry->tag = tag; // tag must be set before calling exif_content_add_entry
670 /* Attach the ExifEntry to an IFD */
671 exif_content_add_entry (exif->ifd[ifd], entry);
672
673 /* Allocate memory for the entry and fill with default data */
674 exif_entry_initialize (entry, tag);
675
676 /* Ownership of the ExifEntry has now been passed to the IFD.
677 * One must be very careful in accessing a structure after
678 * unref'ing it; in this case, we know "entry" won't be freed
679 * because the reference count was bumped when it was added to
680 * the IFD.
681 */
682 exif_entry_unref(entry);
683 }
684 return entry;
685 }
686
CreateExifTag(ExifData * exif,ExifIfd ifd,ExifTag tag,size_t len,ExifFormat format)687 ExifEntry* EXIFInfo::CreateExifTag(ExifData *exif, ExifIfd ifd, ExifTag tag,
688 size_t len, ExifFormat format)
689 {
690 void *buf;
691 ExifEntry *exifEntry;
692
693 if ((exifEntry = exif_content_get_entry(exif->ifd[ifd], tag)) != nullptr) {
694 return exifEntry;
695 }
696
697 /* Create a memory allocator to manage this ExifEntry */
698 ExifMem *exifMem = exif_mem_new_default();
699 if (exifMem == nullptr) {
700 HiLog::Error(LABEL, "Create mem failed!");
701 return nullptr;
702 }
703
704 /* Create a new ExifEntry using our allocator */
705 exifEntry = exif_entry_new_mem (exifMem);
706 if (exifEntry == nullptr) {
707 HiLog::Error(LABEL, "Create entry by mem failed!");
708 return nullptr;
709 }
710
711 /* Allocate memory to use for holding the tag data */
712 buf = exif_mem_alloc(exifMem, len);
713 if (buf == nullptr) {
714 HiLog::Error(LABEL, "Allocate memory failed!");
715 return nullptr;
716 }
717
718 /* Fill in the entry */
719 exifEntry->data = static_cast<unsigned char*>(buf);
720 exifEntry->size = len;
721 exifEntry->tag = tag;
722 exifEntry->components = len;
723 exifEntry->format = format;
724
725 /* Attach the ExifEntry to an IFD */
726 exif_content_add_entry (exif->ifd[ifd], exifEntry);
727
728 /* The ExifMem and ExifEntry are now owned elsewhere */
729 exif_mem_unref(exifMem);
730 exif_entry_unref(exifEntry);
731
732 return exifEntry;
733 }
734
GetFileSize(FILE * fp)735 unsigned long EXIFInfo::GetFileSize(FILE *fp)
736 {
737 long int position;
738 long size;
739
740 /* Save the current position. */
741 position = ftell(fp);
742
743 /* Jump to the end of the file. */
744 (void)fseek(fp, 0L, SEEK_END);
745
746 /* Get the end position. */
747 size = ftell(fp);
748
749 /* Jump back to the original position. */
750 (void)fseek(fp, position, SEEK_SET);
751
752 return static_cast<unsigned long>(size);
753 }
754
CreateExifData(unsigned char * buf,unsigned long length,ExifData ** ptrData,bool & isNewExifData)755 bool EXIFInfo::CreateExifData(unsigned char *buf, unsigned long length, ExifData **ptrData, bool &isNewExifData)
756 {
757 if ((buf[BUFFER_POSITION_6] == 'E' && buf[BUFFER_POSITION_7] == 'x' &&
758 buf[BUFFER_POSITION_8] == 'i' && buf[BUFFER_POSITION_9] == 'f')) {
759 *ptrData = exif_data_new_from_data(buf, static_cast<unsigned int>(length));
760 if (!(*ptrData)) {
761 HiLog::Error(LABEL, "Create exif data from file failed.");
762 return false;
763 }
764 isNewExifData = false;
765 HiLog::Debug(LABEL, "Create exif data from buffer.");
766 } else {
767 *ptrData = exif_data_new();
768 if (!(*ptrData)) {
769 HiLog::Error(LABEL, "Create exif data failed.");
770 return false;
771 }
772 /* Set the image options */
773 exif_data_set_option(*ptrData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
774 exif_data_set_data_type(*ptrData, EXIF_DATA_TYPE_COMPRESSED);
775 exif_data_set_byte_order(*ptrData, EXIF_BYTE_ORDER_INTEL);
776
777 /* Create the mandatory EXIF fields with default data */
778 exif_data_fix(*ptrData);
779 isNewExifData = true;
780 HiLog::Debug(LABEL, "Create new exif data.");
781 }
782 return true;
783 }
784
GetOrginExifDataLength(const bool & isNewExifData,unsigned char * buf)785 unsigned int EXIFInfo::GetOrginExifDataLength(const bool &isNewExifData, unsigned char *buf)
786 {
787 unsigned int orginExifDataLength = 0;
788 if (!isNewExifData) {
789 orginExifDataLength = static_cast<unsigned int>(buf[BUFFER_POSITION_5]) |
790 static_cast<unsigned int>(buf[BUFFER_POSITION_4] << MOVE_OFFSET_8);
791 }
792 return orginExifDataLength;
793 }
794
GetExifByteOrder(const bool & isNewExifData,unsigned char * buf)795 ExifByteOrder EXIFInfo::GetExifByteOrder(const bool &isNewExifData, unsigned char *buf)
796 {
797 if (isNewExifData) {
798 return EXIF_BYTE_ORDER_INTEL;
799 } else {
800 if (buf[BUFFER_POSITION_12] == 'M' && buf[BUFFER_POSITION_13] == 'M') {
801 return EXIF_BYTE_ORDER_MOTOROLA;
802 } else {
803 return EXIF_BYTE_ORDER_INTEL;
804 }
805 }
806 }
807
CreateExifEntry(const ExifTag & tag,ExifData * data,const std::string & value,ExifByteOrder order,ExifEntry ** ptrEntry)808 bool EXIFInfo::CreateExifEntry(const ExifTag &tag, ExifData *data, const std::string &value,
809 ExifByteOrder order, ExifEntry **ptrEntry)
810 {
811 switch (tag) {
812 case EXIF_TAG_BITS_PER_SAMPLE: {
813 *ptrEntry = InitExifTag(data, EXIF_IFD_0, EXIF_TAG_BITS_PER_SAMPLE);
814 if ((*ptrEntry) == nullptr) {
815 HiLog::Error(LABEL, "Get exif entry failed.");
816 return false;
817 }
818 std::vector<std::string> bitsVec;
819 SplitStr(value, ",", bitsVec);
820 if (bitsVec.size() > CONSTANT_2) {
821 HiLog::Error(LABEL, "BITS_PER_SAMPLE Invalid value %{public}s", value.c_str());
822 return false;
823 }
824 if (bitsVec.size() != 0) {
825 for (size_t i = 0; i < bitsVec.size(); i++) {
826 exif_set_short((*ptrEntry)->data + i * CONSTANT_2, order, (ExifShort)atoi(bitsVec[i].c_str()));
827 }
828 }
829 break;
830 }
831 case EXIF_TAG_ORIENTATION: {
832 *ptrEntry = InitExifTag(data, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
833 if ((*ptrEntry) == nullptr) {
834 HiLog::Error(LABEL, "Get exif entry failed.");
835 return false;
836 }
837 exif_set_short((*ptrEntry)->data, order, (ExifShort)atoi(value.c_str()));
838 break;
839 }
840 case EXIF_TAG_IMAGE_LENGTH: {
841 *ptrEntry = InitExifTag(data, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH);
842 if ((*ptrEntry) == nullptr) {
843 HiLog::Error(LABEL, "Get exif entry failed.");
844 return false;
845 }
846 exif_set_long((*ptrEntry)->data, order, (ExifLong)atoi(value.c_str()));
847 break;
848 }
849 case EXIF_TAG_IMAGE_WIDTH: {
850 *ptrEntry = InitExifTag(data, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH);
851 if ((*ptrEntry) == nullptr) {
852 HiLog::Error(LABEL, "Get exif entry failed.");
853 return false;
854 }
855 exif_set_long((*ptrEntry)->data, order, (ExifLong)atoi(value.c_str()));
856 break;
857 }
858 case EXIF_TAG_GPS_LATITUDE: {
859 std::vector<std::string> latVec;
860 SplitStr(value, ",", latVec);
861 if (latVec.size() != CONSTANT_2) {
862 HiLog::Error(LABEL, "GPS_LATITUDE Invalid value %{public}s", value.c_str());
863 return false;
864 }
865
866 ExifRational latRational;
867 latRational.numerator = static_cast<ExifSLong>(atoi(latVec[0].c_str()));
868 latRational.denominator = static_cast<ExifSLong>(atoi(latVec[1].c_str()));
869 *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,
870 sizeof(latRational), EXIF_FORMAT_RATIONAL);
871 if ((*ptrEntry) == nullptr) {
872 HiLog::Error(LABEL, "Get exif entry failed.");
873 return false;
874 }
875 exif_set_rational((*ptrEntry)->data, order, latRational);
876 break;
877 }
878 case EXIF_TAG_GPS_LONGITUDE: {
879 std::vector<std::string> longVec;
880 SplitStr(value, ",", longVec);
881 if (longVec.size() != CONSTANT_2) {
882 HiLog::Error(LABEL, "GPS_LONGITUDE Invalid value %{public}s", value.c_str());
883 return false;
884 }
885
886 ExifRational longRational;
887 longRational.numerator = static_cast<ExifSLong>(atoi(longVec[0].c_str()));
888 longRational.denominator = static_cast<ExifSLong>(atoi(longVec[1].c_str()));
889 *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,
890 sizeof(longRational), EXIF_FORMAT_RATIONAL);
891 if ((*ptrEntry) == nullptr) {
892 HiLog::Error(LABEL, "Get exif entry failed.");
893 return false;
894 }
895 exif_set_rational((*ptrEntry)->data, order, longRational);
896 break;
897 }
898 case EXIF_TAG_GPS_LATITUDE_REF: {
899 *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
900 value.length(), EXIF_FORMAT_ASCII);
901 if ((*ptrEntry) == nullptr) {
902 HiLog::Error(LABEL, "Get exif entry failed.");
903 return false;
904 }
905 if (memcpy_s((*ptrEntry)->data, value.length(), value.c_str(), value.length()) != 0) {
906 HiLog::Error(LABEL, "LATITUDE ref memcpy error");
907 }
908 break;
909 }
910 case EXIF_TAG_GPS_LONGITUDE_REF: {
911 *ptrEntry = CreateExifTag(data, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
912 value.length(), EXIF_FORMAT_ASCII);
913 if ((*ptrEntry) == nullptr) {
914 HiLog::Error(LABEL, "Get exif entry failed.");
915 return false;
916 }
917 if (memcpy_s((*ptrEntry)->data, value.length(), value.c_str(), value.length()) != 0) {
918 HiLog::Error(LABEL, "LONGITUDE ref memcpy error");
919 }
920 break;
921 }
922 default:
923 break;
924 }
925 return true;
926 }
927
WriteExifDataToFile(ExifData * data,unsigned int orginExifDataLength,unsigned long fileLength,unsigned char * buf,FILE * fp)928 bool EXIFInfo::WriteExifDataToFile(ExifData *data, unsigned int orginExifDataLength, unsigned long fileLength,
929 unsigned char *buf, FILE *fp)
930 {
931 unsigned char* exifDataBuf = nullptr;
932 unsigned int exifDataBufLength = 0;
933 exif_data_save_data(data, &exifDataBuf, &exifDataBufLength);
934 if (exifDataBuf == nullptr) {
935 HiLog::Error(LABEL, "Get Exif Data Buf failed!");
936 return false;
937 }
938
939 // Write EXIF header
940 if (fwrite(exifHeader, sizeof(exifHeader), 1, fp) != 1) {
941 HiLog::Error(LABEL, "Error writing EXIF header to file!");
942 return false;
943 }
944
945 // Write EXIF block length in big-endian order
946 if (fputc((exifDataBufLength + LENGTH_OFFSET_2) >> MOVE_OFFSET_8, fp) < 0) {
947 HiLog::Error(LABEL, "Error writing EXIF block length to file!");
948 return false;
949 }
950
951 if (fputc((exifDataBufLength + LENGTH_OFFSET_2) & 0xff, fp) < 0) {
952 HiLog::Error(LABEL, "Error writing EXIF block length to file!");
953 return false;
954 }
955
956 // Write EXIF data block
957 if (fwrite(exifDataBuf, exifDataBufLength, 1, fp) != 1) {
958 HiLog::Error(LABEL, "Error writing EXIF data block to file!");
959 return false;
960 }
961 // Write JPEG image data, skipping the non-EXIF header
962 unsigned int dataOffset = orginExifDataLength + sizeof(exifHeader);
963 if (fwrite(buf + dataOffset, fileLength - dataOffset, 1, fp) != 1) {
964 HiLog::Error(LABEL, "Error writing JPEG image data to file!");
965 return false;
966 }
967
968 UpdateCacheExifData(fp);
969 return true;
970 }
971
ReleaseSource(unsigned char ** ptrBuf,FILE ** ptrFile)972 void EXIFInfo::ReleaseSource(unsigned char **ptrBuf, FILE **ptrFile)
973 {
974 if (*ptrBuf) {
975 free(*ptrBuf);
976 *ptrBuf = nullptr;
977 ptrBuf = nullptr;
978 }
979
980 if (*ptrFile != nullptr) {
981 fclose(*ptrFile);
982 *ptrFile = nullptr;
983 ptrFile = nullptr;
984 }
985 }
986
UpdateCacheExifData(FILE * fp)987 void EXIFInfo::UpdateCacheExifData(FILE *fp)
988 {
989 unsigned long fileLength = GetFileSize(fp);
990 if (fileLength == 0 || fileLength > MAX_FILE_SIZE) {
991 HiLog::Error(LABEL, "Get file size failed.");
992 return;
993 }
994
995 unsigned char *fileBuf = static_cast<unsigned char *>(malloc(fileLength));
996 if (fileBuf == nullptr) {
997 HiLog::Error(LABEL, "Allocate buf failed.");
998 return;
999 }
1000
1001 // Set current position to begin of file.
1002 (void)fseek(fp, 0L, 0);
1003 if (fread(fileBuf, fileLength, 1, fp) != 1) {
1004 HiLog::Error(LABEL, "Read new file failed.");
1005 free(fileBuf);
1006 fileBuf = nullptr;
1007 return;
1008 }
1009
1010 ParseExifData(fileBuf, static_cast<unsigned int>(fileLength));
1011 free(fileBuf);
1012 fileBuf = nullptr;
1013 }
1014
GetFilterArea(const uint8_t * buf,const uint32_t & bufSize,const int & privacyType,std::vector<std::pair<uint32_t,uint32_t>> & ranges)1015 uint32_t EXIFInfo::GetFilterArea(const uint8_t *buf,
1016 const uint32_t &bufSize,
1017 const int &privacyType,
1018 std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1019 {
1020 std::unique_ptr<ByteOrderedBuffer> byteOrderedBuffer = std::make_unique<ByteOrderedBuffer>(buf, bufSize);
1021 byteOrderedBuffer->GenerateDEArray();
1022 if (byteOrderedBuffer->directoryEntryArray_.size() == 0) {
1023 HiLog::Error(LABEL, "Read Exif info range failed.");
1024 return ERROR_PARSE_EXIF_FAILED;
1025 }
1026
1027 GetAreaFromExifEntries(privacyType, byteOrderedBuffer->directoryEntryArray_, ranges);
1028 if (ranges.size() == 0) {
1029 HiLog::Error(LABEL, "There is no exif info need filtered in this image.");
1030 return ERROR_NO_EXIF_TAGS;
1031 }
1032
1033 return Media::SUCCESS;
1034 }
1035
GetAreaFromExifEntries(const int & privacyType,const std::vector<DirectoryEntry> & entryArray,std::vector<std::pair<uint32_t,uint32_t>> & ranges)1036 void EXIFInfo::GetAreaFromExifEntries(const int &privacyType,
1037 const std::vector<DirectoryEntry> &entryArray,
1038 std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1039 {
1040 if (privacyType == PERMISSION_GPS_TYPE) {
1041 for (size_t i = 0; i < entryArray.size(); i++) {
1042 if (entryArray[i].ifd == EXIF_IFD_GPS) {
1043 std::pair<uint32_t, uint32_t> range =
1044 std::make_pair(entryArray[i].valueOffset, entryArray[i].valueLength);
1045 ranges.push_back(range);
1046 }
1047 }
1048 }
1049 }
1050
ByteOrderedBuffer(const uint8_t * fileBuf,uint32_t bufferLength)1051 ByteOrderedBuffer::ByteOrderedBuffer(const uint8_t *fileBuf, uint32_t bufferLength)
1052 : buf_(fileBuf), bufferLength_(bufferLength)
1053 {
1054 if (bufferLength >= BUFFER_POSITION_12 && bufferLength >= BUFFER_POSITION_13) {
1055 if (fileBuf[BUFFER_POSITION_12] == 'M' && fileBuf[BUFFER_POSITION_13] == 'M') {
1056 byteOrder_ = EXIF_BYTE_ORDER_MOTOROLA;
1057 } else {
1058 byteOrder_ = EXIF_BYTE_ORDER_INTEL;
1059 }
1060 }
1061 }
1062
~ByteOrderedBuffer()1063 ByteOrderedBuffer::~ByteOrderedBuffer() {}
1064
GenerateDEArray()1065 void ByteOrderedBuffer::GenerateDEArray()
1066 {
1067 // Move current position to begin of IFD0 offset segment
1068 curPosition_ = TIFF_OFFSET_FROM_FILE_BEGIN + CONSTANT_4;
1069 int32_t ifd0Offset = ReadInt32();
1070 if (ifd0Offset < 0) {
1071 HiLog::Error(LABEL, "Get IFD0 offset failed!");
1072 return;
1073 }
1074 // Transform tiff offset to position of file
1075 ifd0Offset = static_cast<int32_t>(TransformTiffOffsetToFilePos(ifd0Offset));
1076 // Move current position to begin of IFD0 segment
1077 curPosition_ = static_cast<uint32_t>(ifd0Offset);
1078
1079 if (curPosition_ + CONSTANT_2 > bufferLength_) {
1080 HiLog::Error(LABEL, "There is no data from the offset: %{public}d.", curPosition_);
1081 return;
1082 }
1083 GetDataRangeFromIFD(EXIF_IFD_0);
1084 }
1085
GetDataRangeFromIFD(const ExifIfd & ifd)1086 void ByteOrderedBuffer::GetDataRangeFromIFD(const ExifIfd &ifd)
1087 {
1088 handledIfdOffsets_.push_back(curPosition_);
1089 int16_t entryCount = ReadShort();
1090 if (static_cast<uint32_t>(curPosition_ + BYTE_COUNTS_12 * entryCount) > bufferLength_ || entryCount <= 0) {
1091 HiLog::Error(LABEL, " The size of entries is either too big or negative.");
1092 return;
1093 }
1094 GetDataRangeFromDE(ifd, entryCount);
1095
1096 if (Peek() + CONSTANT_4 <= bufferLength_) {
1097 int32_t nextIfdOffset = ReadInt32();
1098 if (nextIfdOffset == 0) {
1099 HiLog::Error(LABEL, "Stop reading file since this IFD is finished");
1100 return;
1101 }
1102 // Transform tiff offset to position of file
1103 if (nextIfdOffset != -1) {
1104 nextIfdOffset = static_cast<int32_t>(TransformTiffOffsetToFilePos(nextIfdOffset));
1105 }
1106 // Check if the next IFD offset
1107 // 1. Exists within the boundaries of the buffer
1108 // 2. Does not point to a previously read IFD.
1109 if (nextIfdOffset > 0L && static_cast<uint32_t>(nextIfdOffset) < bufferLength_) {
1110 if (!IsIFDhandled(nextIfdOffset)) {
1111 curPosition_ = static_cast<uint32_t>(nextIfdOffset);
1112 ExifIfd nextIfd = GetNextIfdFromLinkList(ifd);
1113 GetDataRangeFromIFD(nextIfd);
1114 } else {
1115 HiLog::Error(LABEL, "Stop reading buffer since re-reading an IFD at %{public}d.", nextIfdOffset);
1116 }
1117 } else {
1118 HiLog::Error(LABEL, "Stop reading file since a wrong offset at %{public}d.", nextIfdOffset);
1119 }
1120 }
1121 }
1122
GetDataRangeFromDE(const ExifIfd & ifd,const int16_t & count)1123 void ByteOrderedBuffer::GetDataRangeFromDE(const ExifIfd &ifd, const int16_t &count)
1124 {
1125 for (int16_t i = 0; i < count; i++) {
1126 uint16_t tagNumber = ReadUnsignedShort();
1127 uint16_t dataFormat = ReadUnsignedShort();
1128 int32_t numberOfComponents = ReadInt32();
1129 uint32_t nextEntryOffset = Peek() + CONSTANT_4;
1130
1131 uint32_t byteCount = 0;
1132 bool valid = SetDEDataByteCount(tagNumber, dataFormat, numberOfComponents, byteCount);
1133 if (!valid) {
1134 curPosition_ = static_cast<uint32_t>(nextEntryOffset);
1135 continue;
1136 }
1137
1138 // Read a value from data field or seek to the value offset which is stored in data
1139 // field if the size of the entry value is bigger than 4.
1140 // If the size of the entry value is less than 4, value is stored in value offset area.
1141 if (byteCount > CONSTANT_4) {
1142 int32_t offset = ReadInt32();
1143 // Transform tiff offset to position of file
1144 if (offset != -1) {
1145 offset = static_cast<int32_t>(TransformTiffOffsetToFilePos(offset));
1146 }
1147 if ((static_cast<uint32_t>(offset) + byteCount) <= bufferLength_) {
1148 curPosition_ = static_cast<uint32_t>(offset);
1149 } else {
1150 // Skip if invalid data offset.
1151 HiLog::Error(LABEL, "Skip the tag entry since data offset is invalid: %{public}d.", offset);
1152 curPosition_ = nextEntryOffset;
1153 continue;
1154 }
1155 }
1156
1157 // Recursively parse IFD when a IFD pointer tag appears
1158 if (IsIFDPointerTag(tagNumber)) {
1159 ExifIfd ifdOfIFDPointerTag = GetIFDOfIFDPointerTag(tagNumber);
1160 ParseIFDPointerTag(ifdOfIFDPointerTag, dataFormat);
1161 curPosition_ = nextEntryOffset;
1162 continue;
1163 }
1164
1165 uint32_t bytesOffset = Peek();
1166 uint32_t bytesLength = byteCount;
1167 DirectoryEntry directoryEntry = {static_cast<ExifTag>(tagNumber), static_cast<ExifFormat>(dataFormat),
1168 numberOfComponents, bytesOffset, bytesLength, ifd};
1169 directoryEntryArray_.push_back(directoryEntry);
1170
1171 // Seek to next tag offset
1172 if (Peek() != nextEntryOffset) {
1173 curPosition_ = nextEntryOffset;
1174 }
1175 }
1176 }
1177
TransformTiffOffsetToFilePos(const uint32_t & offset)1178 uint32_t ByteOrderedBuffer::TransformTiffOffsetToFilePos(const uint32_t &offset)
1179 {
1180 return offset + TIFF_OFFSET_FROM_FILE_BEGIN;
1181 }
1182
SetDEDataByteCount(const uint16_t & tagNumber,const uint16_t & dataFormat,const int32_t & numberOfComponents,uint32_t & count)1183 bool ByteOrderedBuffer::SetDEDataByteCount(const uint16_t &tagNumber,
1184 const uint16_t &dataFormat,
1185 const int32_t &numberOfComponents,
1186 uint32_t &count)
1187 {
1188 if (IsValidTagNumber(tagNumber)) {
1189 HiLog::Error(LABEL, "Skip the tag entry since tag number is not defined: %{public}d.", tagNumber);
1190 } else if (dataFormat <= 0 || exif_format_get_size(static_cast<ExifFormat>(dataFormat)) == 0) {
1191 HiLog::Error(LABEL, "Skip the tag entry since data format is invalid: %{public}d.", dataFormat);
1192 } else {
1193 count = static_cast<uint32_t>(numberOfComponents) *
1194 static_cast<uint32_t>(exif_format_get_size(static_cast<ExifFormat>(dataFormat)));
1195 if (count < 0) {
1196 HiLog::Error(LABEL, "Skip the tag entry since the number of components is invalid: %{public}d.",
1197 numberOfComponents);
1198 } else {
1199 return true;
1200 }
1201 }
1202 return false;
1203 }
1204
ParseIFDPointerTag(const ExifIfd & ifd,const uint16_t & dataFormat)1205 void ByteOrderedBuffer::ParseIFDPointerTag(const ExifIfd &ifd, const uint16_t &dataFormat)
1206 {
1207 uint32_t offset = 0U;
1208 // Get offset from data field
1209 switch (static_cast<ExifFormat>(dataFormat)) {
1210 case EXIF_FORMAT_SHORT: {
1211 offset = static_cast<uint32_t>(ReadUnsignedShort());
1212 break;
1213 }
1214 case EXIF_FORMAT_SSHORT: {
1215 offset = ReadShort();
1216 break;
1217 }
1218 case EXIF_FORMAT_LONG: {
1219 offset = ReadUnsignedInt32();
1220 break;
1221 }
1222 case EXIF_FORMAT_SLONG: {
1223 offset = static_cast<uint32_t>(ReadInt32());
1224 break;
1225 }
1226 default: {
1227 // Nothing to do
1228 break;
1229 }
1230 }
1231 // Transform tiff offset to position of file
1232 offset = TransformTiffOffsetToFilePos(offset);
1233 // Check if the next IFD offset
1234 // 1. Exists within the boundaries of the buffer
1235 // 2. Does not point to a previously read IFD.
1236 if (offset > 0L && offset < bufferLength_) {
1237 if (!IsIFDhandled(offset)) {
1238 curPosition_ = offset;
1239 GetDataRangeFromIFD(ifd);
1240 } else {
1241 HiLog::Error(LABEL, "Skip jump into the IFD since it has already been read at %{public}d.", offset);
1242 }
1243 } else {
1244 HiLog::Error(LABEL, "Skip jump into the IFD since its offset is invalid: %{public}d.", offset);
1245 }
1246 }
1247
IsValidTagNumber(const uint16_t & tagNumber)1248 bool ByteOrderedBuffer::IsValidTagNumber(const uint16_t &tagNumber)
1249 {
1250 for (uint32_t i = 0; (IsSameTextStr(ExifTagTable[i].name, "")); i++) {
1251 if (ExifTagTable[i].number == tagNumber) {
1252 return true;
1253 }
1254 }
1255 return false;
1256 }
1257
IsIFDhandled(const uint32_t & position)1258 bool ByteOrderedBuffer::IsIFDhandled(const uint32_t &position)
1259 {
1260 if (handledIfdOffsets_.size() == 0) {
1261 HiLog::Error(LABEL, "There is no handled IFD!");
1262 return false;
1263 }
1264
1265 for (size_t i = 0; i < handledIfdOffsets_.size(); i++) {
1266 if (handledIfdOffsets_[i] == position) {
1267 return true;
1268 }
1269 }
1270 return false;
1271 }
1272
IsIFDPointerTag(const uint16_t & tagNumber)1273 bool ByteOrderedBuffer::IsIFDPointerTag(const uint16_t &tagNumber)
1274 {
1275 bool ret = false;
1276 switch (static_cast<ExifTag>(tagNumber)) {
1277 case EXIF_TAG_SUB_IFDS:
1278 case EXIF_TAG_EXIF_IFD_POINTER:
1279 case EXIF_TAG_GPS_INFO_IFD_POINTER:
1280 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
1281 ret = true;
1282 break;
1283 default:
1284 break;
1285 }
1286 return ret;
1287 }
1288
GetIFDOfIFDPointerTag(const uint16_t & tagNumber)1289 ExifIfd ByteOrderedBuffer::GetIFDOfIFDPointerTag(const uint16_t &tagNumber)
1290 {
1291 ExifIfd ifd = EXIF_IFD_COUNT;
1292 switch (static_cast<ExifTag>(tagNumber)) {
1293 case EXIF_TAG_EXIF_IFD_POINTER: {
1294 ifd = EXIF_IFD_EXIF;
1295 break;
1296 }
1297 case EXIF_TAG_GPS_INFO_IFD_POINTER: {
1298 ifd = EXIF_IFD_GPS;
1299 break;
1300 }
1301 case EXIF_TAG_INTEROPERABILITY_IFD_POINTER: {
1302 ifd = EXIF_IFD_INTEROPERABILITY;
1303 break;
1304 }
1305 default: {
1306 break;
1307 }
1308 }
1309 return ifd;
1310 }
1311
GetNextIfdFromLinkList(const ExifIfd & ifd)1312 ExifIfd ByteOrderedBuffer::GetNextIfdFromLinkList(const ExifIfd &ifd)
1313 {
1314 ExifIfd nextIfd = EXIF_IFD_COUNT;
1315 /**
1316 * In jpeg file, the next IFD of IFD_0 in IFD link list is IFD_1,
1317 * other IFD is pointed by tag.
1318 */
1319 if (ifd == EXIF_IFD_0) {
1320 nextIfd = EXIF_IFD_1;
1321 }
1322 return nextIfd;
1323 }
1324
ReadInt32()1325 int32_t ByteOrderedBuffer::ReadInt32()
1326 {
1327 // Move current position to begin of next segment
1328 curPosition_ += CONSTANT_4;
1329 if (curPosition_ > bufferLength_) {
1330 HiLog::Error(LABEL, "Current Position %{public}u out of range.", curPosition_);
1331 return -1;
1332 }
1333
1334 if (byteOrder_ == EXIF_BYTE_ORDER_MOTOROLA) {
1335 return ((static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_4]) << MOVE_OFFSET_24) |
1336 (static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_3]) << MOVE_OFFSET_16) |
1337 (static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_2]) << MOVE_OFFSET_8) |
1338 static_cast<unsigned int>(buf_[curPosition_ - 1]));
1339 } else {
1340 return ((static_cast<unsigned int>(buf_[curPosition_ - 1]) << MOVE_OFFSET_24) |
1341 (static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_2]) << MOVE_OFFSET_16) |
1342 (static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_3]) << MOVE_OFFSET_8) |
1343 static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_4]));
1344 }
1345 }
1346
ReadUnsignedInt32()1347 uint32_t ByteOrderedBuffer::ReadUnsignedInt32()
1348 {
1349 return (static_cast<uint32_t>(ReadInt32()) & 0xffffffff);
1350 }
1351
ReadShort()1352 int16_t ByteOrderedBuffer::ReadShort()
1353 {
1354 // Move current position to begin of next segment
1355 curPosition_ += CONSTANT_2;
1356 if (curPosition_ > bufferLength_) {
1357 HiLog::Error(LABEL, "Current Position %{public}u out of range.", curPosition_);
1358 return -1;
1359 }
1360
1361 if (byteOrder_ == EXIF_BYTE_ORDER_MOTOROLA) {
1362 return ((static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_2]) << MOVE_OFFSET_8) |
1363 static_cast<unsigned int>(buf_[curPosition_ - 1]));
1364 } else {
1365 return ((static_cast<unsigned int>(buf_[curPosition_ - 1]) << MOVE_OFFSET_8) |
1366 static_cast<unsigned int>(buf_[curPosition_ - CONSTANT_2]));
1367 }
1368 }
1369
ReadUnsignedShort()1370 uint16_t ByteOrderedBuffer::ReadUnsignedShort()
1371 {
1372 return (static_cast<uint32_t>(ReadShort()) & 0xffff);
1373 }
1374
Peek()1375 uint32_t ByteOrderedBuffer::Peek()
1376 {
1377 return curPosition_;
1378 }
1379
CheckExifEntryValid(const ExifIfd & ifd,const ExifTag & tag)1380 bool EXIFInfo::CheckExifEntryValid(const ExifIfd &ifd, const ExifTag &tag)
1381 {
1382 bool ret = false;
1383 switch (ifd) {
1384 case EXIF_IFD_0: {
1385 if (tag == EXIF_TAG_ORIENTATION ||
1386 tag == EXIF_TAG_BITS_PER_SAMPLE ||
1387 tag == EXIF_TAG_IMAGE_LENGTH ||
1388 tag == EXIF_TAG_IMAGE_WIDTH) {
1389 ret = true;
1390 }
1391 break;
1392 }
1393 case EXIF_IFD_EXIF: {
1394 if (tag == EXIF_TAG_DATE_TIME_ORIGINAL ||
1395 tag == EXIF_TAG_EXPOSURE_TIME ||
1396 tag == EXIF_TAG_FNUMBER ||
1397 tag == EXIF_TAG_ISO_SPEED_RATINGS ||
1398 tag == EXIF_TAG_SCENE_TYPE ||
1399 tag == EXIF_TAG_COMPRESSED_BITS_PER_PIXEL) {
1400 ret = true;
1401 }
1402 break;
1403 }
1404 case EXIF_IFD_GPS: {
1405 if (tag == EXIF_TAG_GPS_LATITUDE ||
1406 tag == EXIF_TAG_GPS_LONGITUDE ||
1407 tag == EXIF_TAG_GPS_LATITUDE_REF ||
1408 tag == EXIF_TAG_GPS_LONGITUDE_REF) {
1409 ret = true;
1410 }
1411 break;
1412 }
1413 default:
1414 break;
1415 }
1416 return ret;
1417 }
1418 } // namespace ImagePlugin
1419 } // namespace OHOS
1420