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