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, °ree, &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