1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "exif_utils.h"
17094332d3Sopenharmony_ci#include <cassert>
18094332d3Sopenharmony_ci#include <cstdio>
19094332d3Sopenharmony_ci#include <cstdint>
20094332d3Sopenharmony_ci#include <cmath>
21094332d3Sopenharmony_ci#include <cstring>
22094332d3Sopenharmony_ci#include <iostream>
23094332d3Sopenharmony_ci#include <camera.h>
24094332d3Sopenharmony_ci#include "securec.h"
25094332d3Sopenharmony_ci
26094332d3Sopenharmony_cinamespace OHOS::Camera {
27094332d3Sopenharmony_cistatic const unsigned int IMAGE_DATA_OFFSET = 20;
28094332d3Sopenharmony_ci
29094332d3Sopenharmony_ci// Raw exif header data
30094332d3Sopenharmony_cistatic const unsigned char EXIF_HEADER[] = {0xff, 0xd8, 0xff, 0xe1};
31094332d3Sopenharmony_ci
32094332d3Sopenharmony_cistatic const unsigned int EXIF_HEADER_LENGTH = sizeof(EXIF_HEADER);
33094332d3Sopenharmony_ci
34094332d3Sopenharmony_ci#define FILE_BYTE_ORDER EXIF_BYTE_ORDER_INTEL
35094332d3Sopenharmony_ci
36094332d3Sopenharmony_cistatic ExifEntry *CreateTag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len, ExifFormat format)
37094332d3Sopenharmony_ci{
38094332d3Sopenharmony_ci    void *buf = nullptr;
39094332d3Sopenharmony_ci    ExifEntry *entry = nullptr;
40094332d3Sopenharmony_ci
41094332d3Sopenharmony_ci    ExifMem *mem = exif_mem_new_default();
42094332d3Sopenharmony_ci    assert(mem != NULL);
43094332d3Sopenharmony_ci
44094332d3Sopenharmony_ci    entry = exif_entry_new_mem(mem);
45094332d3Sopenharmony_ci    assert(entry != nullptr);
46094332d3Sopenharmony_ci
47094332d3Sopenharmony_ci    buf = exif_mem_alloc(mem, len);
48094332d3Sopenharmony_ci    assert(buf != nullptr);
49094332d3Sopenharmony_ci
50094332d3Sopenharmony_ci    entry->data = static_cast<unsigned char*>(buf);
51094332d3Sopenharmony_ci    entry->size = len;
52094332d3Sopenharmony_ci    entry->tag = tag;
53094332d3Sopenharmony_ci    entry->components = len;
54094332d3Sopenharmony_ci    entry->format = format;
55094332d3Sopenharmony_ci
56094332d3Sopenharmony_ci    exif_content_add_entry(exif->ifd[ifd], entry);
57094332d3Sopenharmony_ci
58094332d3Sopenharmony_ci    exif_mem_unref(mem);
59094332d3Sopenharmony_ci    exif_entry_unref(entry);
60094332d3Sopenharmony_ci
61094332d3Sopenharmony_ci    return entry;
62094332d3Sopenharmony_ci}
63094332d3Sopenharmony_ci
64094332d3Sopenharmony_ciuint32_t ExifUtils::GetGpsRef(LatOrLong latOrLongType, double number, char *gpsRef, int length)
65094332d3Sopenharmony_ci{
66094332d3Sopenharmony_ci    char north[2] = "N";
67094332d3Sopenharmony_ci    char south[2] = "S";
68094332d3Sopenharmony_ci    char east[2] = "E";
69094332d3Sopenharmony_ci    char west[2] = "W";
70094332d3Sopenharmony_ci
71094332d3Sopenharmony_ci    if (gpsRef == nullptr) {
72094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s gpsRef is null.", __FUNCTION__);
73094332d3Sopenharmony_ci        return RC_ERROR;
74094332d3Sopenharmony_ci    }
75094332d3Sopenharmony_ci
76094332d3Sopenharmony_ci    if (latOrLongType == LATITUDE_TYPE) {
77094332d3Sopenharmony_ci        if (number > 0) {
78094332d3Sopenharmony_ci            if (strncpy_s(gpsRef, length, north, strlen(north)) != 0) {
79094332d3Sopenharmony_ci                CAMERA_LOGE("%{public}s exif strncpy_s failed.", __FUNCTION__);
80094332d3Sopenharmony_ci                return RC_ERROR;
81094332d3Sopenharmony_ci            }
82094332d3Sopenharmony_ci        } else {
83094332d3Sopenharmony_ci            if (strncpy_s(gpsRef, length, south, strlen(south)) != 0) {
84094332d3Sopenharmony_ci                CAMERA_LOGE("%{public}s exif strncpy_s failed.", __FUNCTION__);
85094332d3Sopenharmony_ci                return RC_ERROR;
86094332d3Sopenharmony_ci            }
87094332d3Sopenharmony_ci        }
88094332d3Sopenharmony_ci    } else {
89094332d3Sopenharmony_ci        if (number > 0) {
90094332d3Sopenharmony_ci            if (strncpy_s(gpsRef, length, east, strlen(east)) != 0) {
91094332d3Sopenharmony_ci                CAMERA_LOGE("%{public}s exif strncpy_s failed.", __FUNCTION__);
92094332d3Sopenharmony_ci                return RC_ERROR;
93094332d3Sopenharmony_ci            }
94094332d3Sopenharmony_ci        } else {
95094332d3Sopenharmony_ci            if (strncpy_s(gpsRef, length, west, strlen(west)) != 0) {
96094332d3Sopenharmony_ci                CAMERA_LOGE("%{public}s exif strncpy_s failed.", __FUNCTION__);
97094332d3Sopenharmony_ci                return RC_ERROR;
98094332d3Sopenharmony_ci            }
99094332d3Sopenharmony_ci        }
100094332d3Sopenharmony_ci    }
101094332d3Sopenharmony_ci
102094332d3Sopenharmony_ci    return RC_OK;
103094332d3Sopenharmony_ci}
104094332d3Sopenharmony_ci
105094332d3Sopenharmony_ciuint32_t ExifUtils::AddLatOrLongInfo(ExifData *exif,
106094332d3Sopenharmony_ci    double number, LatOrLong latOrLongType)
107094332d3Sopenharmony_ci{
108094332d3Sopenharmony_ci    ExifEntry *entry = nullptr;
109094332d3Sopenharmony_ci    char gpsRef[2] = {0}; // Index
110094332d3Sopenharmony_ci    ExifRational gpsRational[3]; // Index
111094332d3Sopenharmony_ci    int32_t degree = 0;
112094332d3Sopenharmony_ci    int32_t minute = 0;
113094332d3Sopenharmony_ci    int32_t second = 0;
114094332d3Sopenharmony_ci
115094332d3Sopenharmony_ci    if (GetGpsRef(latOrLongType, number, gpsRef, sizeof(gpsRef)) != RC_OK) {
116094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif GetGpsRef failed.", __FUNCTION__);
117094332d3Sopenharmony_ci        return RC_ERROR;
118094332d3Sopenharmony_ci    }
119094332d3Sopenharmony_ci
120094332d3Sopenharmony_ci    ConvertGpsDataToDms(number, &degree, &minute, &second);
121094332d3Sopenharmony_ci    gpsRational[0].numerator = degree; // Index
122094332d3Sopenharmony_ci    gpsRational[0].denominator = 1;
123094332d3Sopenharmony_ci    gpsRational[1].numerator = minute; // Index
124094332d3Sopenharmony_ci    gpsRational[1].denominator = 1;
125094332d3Sopenharmony_ci    gpsRational[2].numerator = second; // Index
126094332d3Sopenharmony_ci    gpsRational[2].denominator = 1;
127094332d3Sopenharmony_ci
128094332d3Sopenharmony_ci    // LATITUDE_TYPE/LONGITUDE_TYPE reference
129094332d3Sopenharmony_ci    if (latOrLongType == LATITUDE_TYPE) {
130094332d3Sopenharmony_ci        entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF, sizeof(gpsRef), EXIF_FORMAT_ASCII);
131094332d3Sopenharmony_ci    } else {
132094332d3Sopenharmony_ci        entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF, sizeof(gpsRef), EXIF_FORMAT_ASCII);
133094332d3Sopenharmony_ci    }
134094332d3Sopenharmony_ci    if (memcpy_s(entry->data, entry->size, gpsRef, sizeof(gpsRef)) != 0) {
135094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
136094332d3Sopenharmony_ci        return RC_ERROR;
137094332d3Sopenharmony_ci    }
138094332d3Sopenharmony_ci    // LATITUDE_TYPE/LONGITUDE_TYPE value
139094332d3Sopenharmony_ci    constexpr uint32_t gpsDmsCount = 3;
140094332d3Sopenharmony_ci    if (latOrLongType == LATITUDE_TYPE) {
141094332d3Sopenharmony_ci        entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,
142094332d3Sopenharmony_ci            gpsDmsCount * exif_format_get_size(EXIF_FORMAT_RATIONAL),
143094332d3Sopenharmony_ci            EXIF_FORMAT_RATIONAL);
144094332d3Sopenharmony_ci    } else {
145094332d3Sopenharmony_ci        entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,
146094332d3Sopenharmony_ci            gpsDmsCount * exif_format_get_size(EXIF_FORMAT_RATIONAL),
147094332d3Sopenharmony_ci            EXIF_FORMAT_RATIONAL);
148094332d3Sopenharmony_ci    }
149094332d3Sopenharmony_ci    exif_set_rational(entry->data, FILE_BYTE_ORDER, gpsRational[0]);
150094332d3Sopenharmony_ci    exif_set_rational(entry->data + 8, FILE_BYTE_ORDER, gpsRational[1]); // 8bit
151094332d3Sopenharmony_ci    exif_set_rational(entry->data + 16, FILE_BYTE_ORDER, gpsRational[2]); // 16bit
152094332d3Sopenharmony_ci    return RC_OK;
153094332d3Sopenharmony_ci}
154094332d3Sopenharmony_ci
155094332d3Sopenharmony_ciuint32_t ExifUtils::AddAltitudeInfo(ExifData *exif, double altitude)
156094332d3Sopenharmony_ci{
157094332d3Sopenharmony_ci    unsigned char seaLevelFlag = 0;
158094332d3Sopenharmony_ci    ExifEntry *entry = nullptr;
159094332d3Sopenharmony_ci    ExifRational gpsAltitudeRational;
160094332d3Sopenharmony_ci    exif_rational altitudeRational;
161094332d3Sopenharmony_ci
162094332d3Sopenharmony_ci    if (altitude > 0) {
163094332d3Sopenharmony_ci        seaLevelFlag = 0;
164094332d3Sopenharmony_ci    } else {
165094332d3Sopenharmony_ci        altitude = abs(altitude);
166094332d3Sopenharmony_ci        seaLevelFlag = 1;
167094332d3Sopenharmony_ci    }
168094332d3Sopenharmony_ci    ConvertAltitudeToRational(altitude, altitudeRational);
169094332d3Sopenharmony_ci    gpsAltitudeRational.numerator = altitudeRational.numerator;
170094332d3Sopenharmony_ci    gpsAltitudeRational.denominator = altitudeRational.denominator;
171094332d3Sopenharmony_ci    // Altitude reference
172094332d3Sopenharmony_ci    entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF, sizeof(seaLevelFlag), EXIF_FORMAT_BYTE);
173094332d3Sopenharmony_ci    exif_set_short(entry->data, FILE_BYTE_ORDER, seaLevelFlag);
174094332d3Sopenharmony_ci
175094332d3Sopenharmony_ci    // Altitude value
176094332d3Sopenharmony_ci    entry = CreateTag(exif, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE, exif_format_get_size(EXIF_FORMAT_RATIONAL),
177094332d3Sopenharmony_ci        EXIF_FORMAT_RATIONAL);
178094332d3Sopenharmony_ci    exif_set_rational(entry->data, FILE_BYTE_ORDER, gpsAltitudeRational);
179094332d3Sopenharmony_ci    return RC_OK;
180094332d3Sopenharmony_ci}
181094332d3Sopenharmony_ci
182094332d3Sopenharmony_ciuint32_t ExifUtils::IsJpegPicture(unsigned char *dataBuffer, int32_t dataBufferSize, void *address)
183094332d3Sopenharmony_ci{
184094332d3Sopenharmony_ci    if (memcpy_s(dataBuffer, dataBufferSize, address, dataBufferSize) != 0) {
185094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
186094332d3Sopenharmony_ci        return RC_ERROR;
187094332d3Sopenharmony_ci    }
188094332d3Sopenharmony_ci
189094332d3Sopenharmony_ci    if (!(dataBuffer[0] == 0xFF && dataBuffer[1] == 0xD8)) {
190094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s not jpeg file,won't add exif for it.", __FUNCTION__);
191094332d3Sopenharmony_ci        return RC_ERROR;
192094332d3Sopenharmony_ci    }
193094332d3Sopenharmony_ci
194094332d3Sopenharmony_ci    if ((dataBuffer[6] == 'E' && dataBuffer[7] == 'x' && dataBuffer[8] == 'i' && dataBuffer[9] == 'f')) { // Index
195094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s already add exif, won't overwrite exif info.", __FUNCTION__);
196094332d3Sopenharmony_ci        return RC_ERROR;
197094332d3Sopenharmony_ci    }
198094332d3Sopenharmony_ci    return RC_OK;
199094332d3Sopenharmony_ci}
200094332d3Sopenharmony_ci
201094332d3Sopenharmony_ciuint32_t ExifUtils::PackageJpeg(unsigned char *tempBuffer, int32_t totalTempBufferSize, unsigned char *exifData,
202094332d3Sopenharmony_ci    unsigned int exifDataLength, data_info sourceData)
203094332d3Sopenharmony_ci{
204094332d3Sopenharmony_ci    unsigned char orderValue = 0;
205094332d3Sopenharmony_ci    unsigned char value = 0;
206094332d3Sopenharmony_ci    constexpr uint32_t exifBlockLength = 2;
207094332d3Sopenharmony_ci    orderValue = (exifDataLength + exifBlockLength) >> 8; // 8bit
208094332d3Sopenharmony_ci    value = (exifDataLength + exifBlockLength) & 0xff;
209094332d3Sopenharmony_ci    if (memcpy_s(tempBuffer, totalTempBufferSize, EXIF_HEADER, EXIF_HEADER_LENGTH) != 0) {
210094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
211094332d3Sopenharmony_ci        return RC_ERROR;
212094332d3Sopenharmony_ci    }
213094332d3Sopenharmony_ci    if (memcpy_s(tempBuffer + EXIF_HEADER_LENGTH, totalTempBufferSize, &orderValue,
214094332d3Sopenharmony_ci        sizeof(orderValue)) != 0) {
215094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
216094332d3Sopenharmony_ci        return RC_ERROR;
217094332d3Sopenharmony_ci    }
218094332d3Sopenharmony_ci    if (memcpy_s(tempBuffer + EXIF_HEADER_LENGTH + sizeof(orderValue), totalTempBufferSize, &value,
219094332d3Sopenharmony_ci        sizeof(value)) != 0) {
220094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
221094332d3Sopenharmony_ci        return RC_ERROR;
222094332d3Sopenharmony_ci    }
223094332d3Sopenharmony_ci    if (memcpy_s(tempBuffer + EXIF_HEADER_LENGTH + sizeof(orderValue) + sizeof(value), totalTempBufferSize,
224094332d3Sopenharmony_ci        exifData, exifDataLength) != 0) {
225094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
226094332d3Sopenharmony_ci        return RC_ERROR;
227094332d3Sopenharmony_ci    }
228094332d3Sopenharmony_ci    if (memcpy_s(tempBuffer + EXIF_HEADER_LENGTH + sizeof(orderValue) + sizeof(value) + exifDataLength,
229094332d3Sopenharmony_ci        totalTempBufferSize,
230094332d3Sopenharmony_ci        sourceData.dataBuffer + IMAGE_DATA_OFFSET,
231094332d3Sopenharmony_ci        sourceData.dataBufferSize - IMAGE_DATA_OFFSET) != 0) {
232094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
233094332d3Sopenharmony_ci        return RC_ERROR;
234094332d3Sopenharmony_ci    }
235094332d3Sopenharmony_ci    return RC_OK;
236094332d3Sopenharmony_ci}
237094332d3Sopenharmony_ci
238094332d3Sopenharmony_ciuint32_t ExifUtils::SetExifData(exif_data info, ExifData *exif,
239094332d3Sopenharmony_ci    unsigned char **exifData, unsigned int *exifDataLength)
240094332d3Sopenharmony_ci{
241094332d3Sopenharmony_ci    CHECK_IF_PTR_NULL_RETURN_VALUE(exif, RC_ERROR);
242094332d3Sopenharmony_ci
243094332d3Sopenharmony_ci    exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
244094332d3Sopenharmony_ci    exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
245094332d3Sopenharmony_ci    exif_data_set_byte_order(exif, FILE_BYTE_ORDER);
246094332d3Sopenharmony_ci    if (AddLatOrLongInfo(exif, info.latitude, LATITUDE_TYPE) != RC_OK) {
247094332d3Sopenharmony_ci        return RC_ERROR;
248094332d3Sopenharmony_ci    }
249094332d3Sopenharmony_ci    if (AddLatOrLongInfo(exif, info.longitude, LONGITUDE_TYPE) != RC_OK) {
250094332d3Sopenharmony_ci        return RC_ERROR;
251094332d3Sopenharmony_ci    }
252094332d3Sopenharmony_ci    if (AddAltitudeInfo(exif, info.altitude) != RC_OK) {
253094332d3Sopenharmony_ci        return RC_ERROR;
254094332d3Sopenharmony_ci    }
255094332d3Sopenharmony_ci    exif_data_save_data(exif, exifData, exifDataLength);
256094332d3Sopenharmony_ci
257094332d3Sopenharmony_ci    return RC_OK;
258094332d3Sopenharmony_ci}
259094332d3Sopenharmony_ci
260094332d3Sopenharmony_civoid ExifUtils::FreeResource(unsigned char *dataBuffer, unsigned char *tempBuffer,
261094332d3Sopenharmony_ci    ExifData *exif, unsigned char *exifData)
262094332d3Sopenharmony_ci{
263094332d3Sopenharmony_ci    if (dataBuffer != nullptr) {
264094332d3Sopenharmony_ci        free(dataBuffer);
265094332d3Sopenharmony_ci    }
266094332d3Sopenharmony_ci    if (tempBuffer != nullptr) {
267094332d3Sopenharmony_ci        free(tempBuffer);
268094332d3Sopenharmony_ci    }
269094332d3Sopenharmony_ci    free(exifData);
270094332d3Sopenharmony_ci    exif_data_unref(exif);
271094332d3Sopenharmony_ci}
272094332d3Sopenharmony_ci
273094332d3Sopenharmony_ciuint32_t ExifUtils::AddCustomExifInfo(exif_data info, void *address, int32_t &outPutSize)
274094332d3Sopenharmony_ci{
275094332d3Sopenharmony_ci    int32_t ret = RC_ERROR;
276094332d3Sopenharmony_ci    unsigned char *exifData = nullptr;
277094332d3Sopenharmony_ci    unsigned int exifDataLength = 0;
278094332d3Sopenharmony_ci    ExifData *exif = nullptr;
279094332d3Sopenharmony_ci    unsigned char *dataBuffer = nullptr;
280094332d3Sopenharmony_ci    unsigned char *tempBuffer = nullptr;
281094332d3Sopenharmony_ci    int32_t totalTempBufferSize = 0;
282094332d3Sopenharmony_ci    int32_t dataBufferSize = info.frame_size;
283094332d3Sopenharmony_ci    constexpr uint32_t exifBlockLength = 2;
284094332d3Sopenharmony_ci
285094332d3Sopenharmony_ci    exif = exif_data_new();
286094332d3Sopenharmony_ci    if (!exif) {
287094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif new failed.", __FUNCTION__);
288094332d3Sopenharmony_ci        return ret;
289094332d3Sopenharmony_ci    }
290094332d3Sopenharmony_ci
291094332d3Sopenharmony_ci    if (SetExifData(info, exif, &exifData, &exifDataLength) != RC_OK) {
292094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif SetExifData failed.", __FUNCTION__);
293094332d3Sopenharmony_ci        return ret;
294094332d3Sopenharmony_ci    }
295094332d3Sopenharmony_ci
296094332d3Sopenharmony_ci    dataBuffer = static_cast<unsigned char *>(malloc(dataBufferSize));
297094332d3Sopenharmony_ci    if (!dataBuffer) {
298094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s Allocate data buf failed.", __FUNCTION__);
299094332d3Sopenharmony_ci        return ret;
300094332d3Sopenharmony_ci    }
301094332d3Sopenharmony_ci    data_info sourceData;
302094332d3Sopenharmony_ci    sourceData.dataBuffer = dataBuffer;
303094332d3Sopenharmony_ci    sourceData.dataBufferSize = dataBufferSize;
304094332d3Sopenharmony_ci
305094332d3Sopenharmony_ci    // Check buffer whether is valid
306094332d3Sopenharmony_ci    if (IsJpegPicture(dataBuffer, dataBufferSize, address) == RC_ERROR) {
307094332d3Sopenharmony_ci        goto error;
308094332d3Sopenharmony_ci    }
309094332d3Sopenharmony_ci    totalTempBufferSize = EXIF_HEADER_LENGTH + exifBlockLength +  exifDataLength +
310094332d3Sopenharmony_ci        (static_cast<uint32_t>(dataBufferSize) - IMAGE_DATA_OFFSET);
311094332d3Sopenharmony_ci    tempBuffer = static_cast<unsigned char *>(malloc(totalTempBufferSize));
312094332d3Sopenharmony_ci    if (!tempBuffer) {
313094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s Allocate temp buf failed.", __FUNCTION__);
314094332d3Sopenharmony_ci        return ret;
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    ret = PackageJpeg(tempBuffer, totalTempBufferSize, exifData, exifDataLength, sourceData);
317094332d3Sopenharmony_ci    outPutSize = totalTempBufferSize;
318094332d3Sopenharmony_ci    if (memcpy_s(address, totalTempBufferSize, tempBuffer, totalTempBufferSize) != 0) {
319094332d3Sopenharmony_ci        CAMERA_LOGE("%{public}s exif memcpy_s failed.", __FUNCTION__);
320094332d3Sopenharmony_ci        return RC_ERROR;
321094332d3Sopenharmony_ci    }
322094332d3Sopenharmony_ci
323094332d3Sopenharmony_cierror:
324094332d3Sopenharmony_ci    FreeResource(dataBuffer, tempBuffer, exif, exifData);
325094332d3Sopenharmony_ci
326094332d3Sopenharmony_ci    return ret;
327094332d3Sopenharmony_ci}
328094332d3Sopenharmony_ci
329094332d3Sopenharmony_civoid ExifUtils::ConvertGpsDataToDms(double number, int32_t *degrees, int32_t *minutes, int32_t *seconds)
330094332d3Sopenharmony_ci{
331094332d3Sopenharmony_ci    number = abs(number);
332094332d3Sopenharmony_ci    double  approximateNumber = 0.0;
333094332d3Sopenharmony_ci    constexpr uint32_t timePeriod = 60;
334094332d3Sopenharmony_ci    constexpr uint32_t roundingValue = 5;
335094332d3Sopenharmony_ci    constexpr uint32_t precision = 10;
336094332d3Sopenharmony_ci    int32_t hour = static_cast<int32_t>(number);
337094332d3Sopenharmony_ci    int32_t minute = static_cast<int32_t>((number - hour) * timePeriod);
338094332d3Sopenharmony_ci    int32_t second = static_cast<int32_t>(((number - hour) * timePeriod - minute) * timePeriod);
339094332d3Sopenharmony_ci
340094332d3Sopenharmony_ci    approximateNumber = ((number - hour) * timePeriod - minute) * timePeriod - second;
341094332d3Sopenharmony_ci    if (static_cast<int32_t>(approximateNumber * precision) >= roundingValue) {
342094332d3Sopenharmony_ci        second = second + 1;
343094332d3Sopenharmony_ci    }
344094332d3Sopenharmony_ci    if (second == timePeriod) {
345094332d3Sopenharmony_ci        second = 0;
346094332d3Sopenharmony_ci        minute = minute + 1;
347094332d3Sopenharmony_ci    }
348094332d3Sopenharmony_ci    if (minute == timePeriod) {
349094332d3Sopenharmony_ci        minute = 0;
350094332d3Sopenharmony_ci        hour = hour + 1;
351094332d3Sopenharmony_ci    }
352094332d3Sopenharmony_ci    *degrees = hour;
353094332d3Sopenharmony_ci    *minutes = minute;
354094332d3Sopenharmony_ci    *seconds = second;
355094332d3Sopenharmony_ci
356094332d3Sopenharmony_ci    return;
357094332d3Sopenharmony_ci}
358094332d3Sopenharmony_ci
359094332d3Sopenharmony_civoid ExifUtils::ConvertAltitudeToRational(double altitude, exif_rational &outPutAltitude)
360094332d3Sopenharmony_ci{
361094332d3Sopenharmony_ci    long long numerator = 0;
362094332d3Sopenharmony_ci    long long denominator = 1;
363094332d3Sopenharmony_ci    bool isSeparator = false;
364094332d3Sopenharmony_ci    int count = 0;
365094332d3Sopenharmony_ci    std::string strData = "";
366094332d3Sopenharmony_ci    strData = std::to_string(altitude);
367094332d3Sopenharmony_ci    CAMERA_LOGI("%{public}s strData = %{public}s", __FUNCTION__, strData.c_str());
368094332d3Sopenharmony_ci
369094332d3Sopenharmony_ci    count = strData.length();
370094332d3Sopenharmony_ci    CAMERA_LOGI("%{public}s count = %{public}d", __FUNCTION__, count);
371094332d3Sopenharmony_ci    constexpr uint32_t digitPosition = 10;
372094332d3Sopenharmony_ci    for (int i = 0; i < count; i++) {
373094332d3Sopenharmony_ci        char character = strData[i];
374094332d3Sopenharmony_ci        if (character == '.') {
375094332d3Sopenharmony_ci            isSeparator = true;
376094332d3Sopenharmony_ci        } else {
377094332d3Sopenharmony_ci            numerator = numerator * digitPosition + (character  - '0');
378094332d3Sopenharmony_ci            CAMERA_LOGI("%{public}s numerator =  %{public}lld", __FUNCTION__, numerator);
379094332d3Sopenharmony_ci            if (isSeparator) {
380094332d3Sopenharmony_ci                denominator *= digitPosition;
381094332d3Sopenharmony_ci                CAMERA_LOGI("%{public}s denominator =  %{public}lld", __FUNCTION__, denominator);
382094332d3Sopenharmony_ci            }
383094332d3Sopenharmony_ci        }
384094332d3Sopenharmony_ci    }
385094332d3Sopenharmony_ci    constexpr uint32_t commonDivisor = 2;
386094332d3Sopenharmony_ci    constexpr uint32_t resetValue = 1;
387094332d3Sopenharmony_ci    for (int i = commonDivisor; static_cast<long long>(i) < numerator; i++) {
388094332d3Sopenharmony_ci        if ((numerator % i == 0) && (denominator % i == 0)) {
389094332d3Sopenharmony_ci            numerator /= i;
390094332d3Sopenharmony_ci            denominator /= i;
391094332d3Sopenharmony_ci            i = resetValue;
392094332d3Sopenharmony_ci        }
393094332d3Sopenharmony_ci    }
394094332d3Sopenharmony_ci
395094332d3Sopenharmony_ci    outPutAltitude.numerator = numerator;
396094332d3Sopenharmony_ci    outPutAltitude.denominator = denominator;
397094332d3Sopenharmony_ci    CAMERA_LOGI("%{public}s outPutAltitude.numerator =  %{public}d and outPutAltitude.denominator =  %{public}d",
398094332d3Sopenharmony_ci        __FUNCTION__, outPutAltitude.numerator, outPutAltitude.denominator);
399094332d3Sopenharmony_ci}
400094332d3Sopenharmony_ci}  // namespace OHOS::Camera
401