128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan/* 228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * Copyright 2017 The Chromium OS Authors. All rights reserved. 328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * Use of this source code is governed by a BSD-style license that can be 428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan * found in the LICENSE file. 528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan */ 628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#ifndef INCLUDE_ARC_EXIF_UTILS_H_ 828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#define INCLUDE_ARC_EXIF_UTILS_H_ 928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 1028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <cstddef> 1128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <memory> 1228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <string> 1328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <utility> 1428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <vector> 1528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 1628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanextern "C" { 1728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include <libexif/exif-data.h> 1828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan} 1928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 2028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#include "arc/jpeg_compressor.h" 2128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 2228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathannamespace arc { 2328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 2428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// ExifUtils can generate APP1 segment with tags which caller set. ExifUtils can 2528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// also add a thumbnail in the APP1 segment if thumbnail size is specified. 2628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// ExifUtils can be reused with different images by calling initialize(). 2728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// 2828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// Example of using this class : 2928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// ExifUtils utils; 3028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// utils.initialize(inputYU12Buffer, inputWidth, inputHeight, 3128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// outputJpegQuality); 3228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// ... 3328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// // Call ExifUtils functions to set Exif tags. 3428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// ... 3528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// utils.generateApp1(); 3628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// unsigned int app1Length = utils.getApp1Length(); 3728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// uint8_t* app1Buffer = new uint8_t[app1Length]; 3828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan// memcpy(app1Buffer, utils.getApp1Buffer(), app1Length); 3928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathanclass ExifUtils { 4028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan public: 4128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan ExifUtils(); 4228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan ~ExifUtils(); 4328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 4428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets input YU12 image |buffer| with |width| x |height|. |quality| is the 4528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // compressed JPEG image quality. The caller should not release |buffer| until 4628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // generateApp1() or the destructor is called. initialize() can be called 4728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // multiple times. The setting of Exif tags will be cleared. 4828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool Initialize(const uint8_t* buffer, uint16_t width, uint16_t height, 4928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan int quality); 5028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 5128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the manufacturer of camera. 5228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 5328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetMaker(const std::string& maker); 5428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 5528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the model number of camera. 5628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 5728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetModel(const std::string& model); 5828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 5928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the date and time of image last modified. It takes local time. The 6028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // name of the tag is DateTime in IFD0. 6128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 6228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetDateTime(const struct tm& t); 6328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 6428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the focal length of lens used to take the image in millimeters. 6528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 6628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetFocalLength(uint32_t numerator, uint32_t denominator); 6728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 6828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the latitude with degrees minutes seconds format. 6928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 7028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetGpsLatitude(double latitude); 7128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 7228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the longitude with degrees minutes seconds format. 7328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 7428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetGpsLongitude(double longitude); 7528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 7628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the altitude in meters. 7728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 7828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetGpsAltitude(double altitude); 7928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 8028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets GPS date stamp and time stamp (atomic clock). It takes UTC time. 8128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 8228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetGpsTimestamp(const struct tm& t); 8328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 8428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets GPS processing method. 8528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 8628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetGpsProcessingMethod(const std::string& method); 8728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 8828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Since the size of APP1 segment is limited, it is recommended the 8928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // resolution of thumbnail is equal to or smaller than 640x480. If the 9028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // thumbnail is too big, generateApp1() will return false. 9128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if |width| or |height| is not even. 9228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetThumbnailSize(uint16_t width, uint16_t height); 9328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 9428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets image orientation. 9528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 9628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetOrientation(uint16_t orientation); 9728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 9828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Generates APP1 segment. 9928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if generating APP1 segment fails. 10028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool GenerateApp1(); 10128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 10228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Gets buffer of APP1 segment. This method must be called only after calling 10328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // generateAPP1(). 10428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan const uint8_t* GetApp1Buffer(); 10528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 10628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Gets length of APP1 segment. This method must be called only after calling 10728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // generateAPP1(). 10828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan unsigned int GetApp1Length(); 10928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 11028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan private: 11128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Resets the pointers and memories. 11228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan void Reset(); 11328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 11428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Adds a variable length tag to |exif_data_|. It will remove the original one 11528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // if the tag exists. 11628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns the entry of the tag. The reference count of returned ExifEntry is 11728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // two. 11828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::unique_ptr<ExifEntry> AddVariableLengthEntry(ExifIfd ifd, ExifTag tag, 11928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan ExifFormat format, 12028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint64_t components, 12128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan unsigned int size); 12228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 12328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Adds a entry of |tag| in |exif_data_|. It won't remove the original one if 12428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // the tag exists. 12528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns the entry of the tag. It adds one reference count to returned 12628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // ExifEntry. 12728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan std::unique_ptr<ExifEntry> AddEntry(ExifIfd ifd, ExifTag tag); 12828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 12928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the width (number of columes) of main image. 13028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 13128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetImageWidth(uint16_t width); 13228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 13328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Sets the length (number of rows) of main image. 13428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if memory allocation fails. 13528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool SetImageLength(uint16_t length); 13628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 13728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Generates a thumbnail. Calls compressor_.getCompressedImagePtr() to get the 13828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // result image. 13928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if failed. 14028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool GenerateThumbnail(); 14128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 14228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Resizes the thumbnail yuv image to |thumbnail_width_| x |thumbnail_height_| 14328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // and stores in |scaled_buffer|. 14428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Returns false if scale image failed. 14528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan bool GenerateYuvThumbnail(std::vector<uint8_t>* scaled_buffer); 14628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 14728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // Destroys the buffer of APP1 segment if exists. 14828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan void DestroyApp1(); 14928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 15028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The buffer pointer of yuv image (YU12). Not owned by this class. 15128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan const uint8_t* yu12_buffer_; 15228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The size of yuv image. 15328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint16_t yu12_width_; 15428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint16_t yu12_height_; 15528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 15628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The size of thumbnail. 15728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint16_t thumbnail_width_; 15828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint16_t thumbnail_height_; 15928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 16028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The Exif data (APP1). Owned by this class. 16128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan ExifData* exif_data_; 16228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The raw data of APP1 segment. It's allocated by ExifMem in |exif_data_| but 16328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // owned by this class. 16428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan uint8_t* app1_buffer_; 16528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The length of |app1_buffer_|. 16628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan unsigned int app1_length_; 16728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The quality of compressed thumbnail image. The size of EXIF thumbnail has 16828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // to be smaller than 64KB. If quality is 100, the size may be bigger than 16928e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // 64KB. 17028e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan int thumbnail_jpeg_quality_; 17128e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 17228e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan // The YU12 to Jpeg compressor. 17328e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan JpegCompressor compressor_; 17428e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan}; 17528e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 17628e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan} // namespace arc 17728e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan 17828e0f76353e06b24b7dae54e636dbb5ddc64d1a5Prashanth Swaminathan#endif // INCLUDE_ARC_EXIF_UTILS_H_ 179