Coverage Report

Created: 2026-10-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/include/exiv2/exif.hpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
/*!
4
  @file    exif.hpp
5
  @brief   Encoding and decoding of Exif data
6
  @author  Andreas Huggel (ahu)
7
           <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
8
  @date    09-Jan-04, ahu: created
9
 */
10
#ifndef EXIV2_EXIF_HPP
11
#define EXIV2_EXIF_HPP
12
13
// *****************************************************************************
14
#include "exiv2lib_export.h"
15
16
// included header files
17
#include "config.h"
18
#include "metadatum.hpp"
19
#include "params.hpp"
20
21
// + standard includes
22
#include <list>
23
24
// *****************************************************************************
25
// namespace extensions
26
/*!
27
  @brief Provides classes and functions to encode and decode Exif and Iptc data.
28
         The <b>libexiv2</b> API consists of the objects of this namespace.
29
 */
30
namespace Exiv2 {
31
// *****************************************************************************
32
// class declarations
33
class ExifData;
34
class ExifKey;
35
enum class IfdId : uint32_t;
36
37
// *****************************************************************************
38
// class definitions
39
40
/*!
41
  @brief An Exif metadatum, consisting of an ExifKey and a Value and
42
         methods to manipulate these.
43
 */
44
class EXIV2API Exifdatum : public Metadatum {
45
  template <typename T>
46
  friend Exifdatum& setValue(Exifdatum&, const T&);
47
48
 public:
49
  //! @name Creators
50
  //@{
51
  /*!
52
    @brief Constructor for new tags created by an application. The
53
           %Exifdatum is created from a \em key / value pair. %Exifdatum copies
54
           (clones) the \em key and value if one is provided. Alternatively,
55
           a program can create an 'empty' %Exifdatum with only a key
56
           and set the value using setValue().
57
58
    @param key %ExifKey.
59
    @param pValue Pointer to an %Exifdatum value.
60
    @throw Error if the key cannot be parsed and converted.
61
   */
62
  explicit Exifdatum(const ExifKey& key, const Value* pValue = nullptr);
63
  //! Copy constructor
64
  Exifdatum(const Exifdatum& rhs);
65
  //! Destructor
66
  ~Exifdatum() override;
67
  //@}
68
69
  //! @name Manipulators
70
  //@{
71
  //! Assignment operator
72
  Exifdatum& operator=(const Exifdatum& rhs);
73
  /*!
74
    @brief Assign \em value to the %Exifdatum. The type of the new Value
75
           is set to UShortValue.
76
   */
77
  Exifdatum& operator=(const uint16_t& value);
78
  /*!
79
    @brief Assign \em value to the %Exifdatum. The type of the new Value
80
           is set to ULongValue.
81
   */
82
  Exifdatum& operator=(const uint32_t& value);
83
  /*!
84
    @brief Assign \em value to the %Exifdatum. The type of the new Value
85
           is set to URationalValue.
86
   */
87
  Exifdatum& operator=(const URational& value);
88
  /*!
89
    @brief Assign \em value to the %Exifdatum. The type of the new Value
90
           is set to ShortValue.
91
   */
92
  Exifdatum& operator=(const int16_t& value);
93
  /*!
94
    @brief Assign \em value to the %Exifdatum. The type of the new Value
95
           is set to LongValue.
96
   */
97
  Exifdatum& operator=(const int32_t& value);
98
  /*!
99
    @brief Assign \em value to the %Exifdatum. The type of the new Value
100
           is set to RationalValue.
101
   */
102
  Exifdatum& operator=(const Rational& value);
103
  /*!
104
    @brief Assign \em value to the %Exifdatum.
105
           Calls setValue(const std::string&).
106
   */
107
  Exifdatum& operator=(const std::string& value);
108
  /*!
109
    @brief Assign \em value to the %Exifdatum.
110
           Calls setValue(const Value*).
111
   */
112
  Exifdatum& operator=(const Value& value);
113
  void setValue(const Value* pValue) override;
114
  /*!
115
    @brief Set the value to the string \em value.  Uses Value::read(const
116
           std::string&).  If the %Exifdatum does not have a Value yet,
117
           then a %Value of the correct type for this %Exifdatum is
118
           created. An AsciiValue is created for unknown tags. Return
119
           0 if the value was read successfully.
120
   */
121
  int setValue(const std::string& value) override;
122
  /*!
123
    @brief Set the data area by copying (cloning) the buffer pointed to
124
           by \em buf.
125
126
    Values may have a data area, which can contain additional
127
    information besides the actual value. This method is used to set such
128
    a data area.
129
130
    @param buf Pointer to the source data area
131
    @param len Size of the data area
132
    @return Return -1 if the %Exifdatum does not have a value yet or the
133
            value has no data area, else 0.
134
   */
135
  int setDataArea(const byte* buf, size_t len) const;
136
  //@}
137
138
  //! @name Accessors
139
  //@{
140
  //! Return the key of the %Exifdatum.
141
  [[nodiscard]] std::string key() const override;
142
  [[nodiscard]] const char* familyName() const override;
143
  [[nodiscard]] std::string groupName() const override;
144
  [[nodiscard]] std::string tagName() const override;
145
  [[nodiscard]] std::string tagLabel() const override;
146
  [[nodiscard]] std::string tagDesc() const override;
147
  [[nodiscard]] uint16_t tag() const override;
148
  //! Return the IFD id as an integer. (Do not use, this is meant for library internal use.)
149
  [[nodiscard]] IfdId ifdId() const;
150
  //! Return the name of the IFD
151
  [[nodiscard]] const char* ifdName() const;
152
  //! Return the index (unique id of this key within the original IFD)
153
  [[nodiscard]] int idx() const;
154
  /*!
155
    @brief Write value to a data buffer and return the number
156
           of bytes written.
157
158
    The user must ensure that the buffer has enough memory. Otherwise
159
    the call results in undefined behaviour.
160
161
    @param buf Data buffer to write to.
162
    @param byteOrder Applicable byte order (little or big endian).
163
    @return Number of characters written.
164
  */
165
  size_t copy(byte* buf, ByteOrder byteOrder) const override;
166
  std::ostream& write(std::ostream& os, const ExifData* pMetadata = nullptr) const override;
167
  //! Return the type id of the value
168
  [[nodiscard]] TypeId typeId() const override;
169
  //! Return the name of the type
170
  [[nodiscard]] const char* typeName() const override;
171
  //! Return the size in bytes of one component of this type
172
  [[nodiscard]] size_t typeSize() const override;
173
  //! Return the number of components in the value
174
  [[nodiscard]] size_t count() const override;
175
  //! Return the size of the value in bytes
176
  [[nodiscard]] size_t size() const override;
177
  //! Return the value as a string.
178
  [[nodiscard]] std::string toString() const override;
179
  [[nodiscard]] std::string toString(size_t n) const override;
180
  [[nodiscard]] int64_t toInt64(size_t n = 0) const override;
181
  [[nodiscard]] float toFloat(size_t n = 0) const override;
182
  [[nodiscard]] Rational toRational(size_t n = 0) const override;
183
  [[nodiscard]] std::unique_ptr<Value> getValue() const override;
184
  [[nodiscard]] const Value& value() const override;
185
  //! Return the size of the data area.
186
  [[nodiscard]] size_t sizeDataArea() const;
187
  /*!
188
    @brief Return a copy of the data area of the value. The caller owns
189
           this copy and %DataBuf ensures that it will be deleted.
190
191
    Values may have a data area, which can contain additional
192
    information besides the actual value. This method is used to access
193
    such a data area.
194
195
    @return A %DataBuf containing a copy of the data area or an empty
196
            %DataBuf if the value does not have a data area assigned or the
197
            value is not set.
198
   */
199
  [[nodiscard]] DataBuf dataArea() const;
200
  //@}
201
202
 private:
203
  // DATA
204
  std::unique_ptr<ExifKey> key_;  //!< Key
205
  std::unique_ptr<Value> value_;  //!< Value
206
207
};  // class Exifdatum
208
209
/*!
210
  @brief Access to a Exif %thumbnail image. This class provides higher level
211
         accessors to the thumbnail image that is optionally embedded in IFD1
212
         of the Exif data. These methods do not write to the Exif metadata.
213
         Manipulators are provided in subclass ExifThumb.
214
215
  @note Various other preview and thumbnail images may be contained in an
216
        image, depending on its format and the camera make and model. This
217
        class only provides access to the Exif thumbnail as specified in the
218
        Exif standard.
219
 */
220
class EXIV2API ExifThumbC {
221
 public:
222
  //! @name Creators
223
  //@{
224
  //! Constructor.
225
  explicit ExifThumbC(const ExifData& exifData);
226
  //@}
227
228
  //! @name Accessors
229
  //@{
230
  /*!
231
    @brief Return the thumbnail image in a %DataBuf. The caller owns the
232
           data buffer and %DataBuf ensures that it will be deleted.
233
   */
234
  [[nodiscard]] DataBuf copy() const;
235
#ifdef EXV_ENABLE_FILESYSTEM
236
  /*!
237
    @brief Write the thumbnail image to a file.
238
239
    A filename extension is appended to \em path according to the image
240
    type of the thumbnail, so \em path should not include an extension.
241
    The function will overwrite an existing file of the same name.
242
243
    @param path File name of the thumbnail without extension.
244
    @return The number of bytes written.
245
  */
246
  [[nodiscard]] size_t writeFile(const std::string& path) const;
247
#endif
248
  /*!
249
    @brief Return the MIME type of the thumbnail, either \c "image/tiff"
250
           or \c "image/jpeg".
251
   */
252
  [[nodiscard]] const char* mimeType() const;
253
  /*!
254
    @brief Return the file extension for the format of the thumbnail
255
           (".tif" or ".jpg").
256
   */
257
  [[nodiscard]] const char* extension() const;
258
  //@}
259
260
 private:
261
  // DATA
262
  const ExifData& exifData_;  //!< Const reference to the Exif metadata.
263
264
};  // class ExifThumb
265
266
/*!
267
  @brief Access and modify an Exif %thumbnail image. This class implements
268
         manipulators to set and erase the thumbnail image that is optionally
269
         embedded in IFD1 of the Exif data. Accessors are provided by the
270
         base class, ExifThumbC.
271
272
  @note Various other preview and thumbnail images may be contained in an
273
        image, depending on its format and the camera make and model. This
274
        class only provides access to the Exif thumbnail as specified in the
275
        Exif standard.
276
 */
277
class EXIV2API ExifThumb : public ExifThumbC {
278
 public:
279
  //! @name Creators
280
  //@{
281
  //! Constructor.
282
  explicit ExifThumb(ExifData& exifData);
283
  //@}
284
285
  //! @name Manipulators
286
  //@{
287
#ifdef EXV_ENABLE_FILESYSTEM
288
  /*!
289
    @brief Set the Exif thumbnail to the JPEG image \em path. Set
290
           XResolution, YResolution and ResolutionUnit to \em xres,
291
           \em yres and \em unit, respectively.
292
293
    This results in the minimal thumbnail tags being set for a JPEG
294
    thumbnail, as mandated by the Exif standard.
295
296
    @throw Error if reading the file fails.
297
298
    @note  No checks on the file format or size are performed.
299
    @note  Additional existing Exif thumbnail tags are not modified.
300
    @note  The JPEG image inserted as thumbnail image should not
301
           itself contain Exif data (or other metadata), as existing
302
           applications may have problems with that. (The preview
303
           application that comes with OS X for one.) - David Harvey.
304
   */
305
  void setJpegThumbnail(const std::string& path, URational xres, URational yres, uint16_t unit);
306
#endif
307
  /*!
308
    @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,
309
           and size \em size. Set XResolution, YResolution and
310
           ResolutionUnit to \em xres, \em yres and \em unit, respectively.
311
312
    This results in the minimal thumbnail tags being set for a JPEG
313
    thumbnail, as mandated by the Exif standard.
314
315
    @throw Error if reading the file fails.
316
317
    @note  No checks on the image format or size are performed.
318
    @note  Additional existing Exif thumbnail tags are not modified.
319
    @note  The JPEG image inserted as thumbnail image should not
320
           itself contain Exif data (or other metadata), as existing
321
           applications may have problems with that. (The preview
322
           application that comes with OS X for one.) - David Harvey.
323
   */
324
  void setJpegThumbnail(const byte* buf, size_t size, URational xres, URational yres, uint16_t unit);
325
#ifdef EXV_ENABLE_FILESYSTEM
326
  /*!
327
    @brief Set the Exif thumbnail to the JPEG image \em path.
328
329
    This sets only the Compression, JPEGInterchangeFormat and
330
    JPEGInterchangeFormatLength tags, which is not all the thumbnail
331
    Exif information mandatory according to the Exif standard. (But it's
332
    enough to work with the thumbnail.)
333
334
    @throw Error if reading the file fails.
335
336
    @note  No checks on the file format or size are performed.
337
    @note  Additional existing Exif thumbnail tags are not modified.
338
   */
339
  void setJpegThumbnail(const std::string& path);
340
#endif
341
  /*!
342
    @brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,
343
           and size \em size.
344
345
    This sets only the Compression, JPEGInterchangeFormat and
346
    JPEGInterchangeFormatLength tags, which is not all the thumbnail
347
    Exif information mandatory according to the Exif standard. (But it's
348
    enough to work with the thumbnail.)
349
350
    @note  No checks on the image format or size are performed.
351
    @note  Additional existing Exif thumbnail tags are not modified.
352
   */
353
  void setJpegThumbnail(const byte* buf, size_t size);
354
  /*!
355
    @brief Delete the thumbnail from the Exif data. Removes all
356
           Exif.%Thumbnail.*, i.e., Exif IFD1 tags.
357
   */
358
  void erase();
359
  //@}
360
361
 private:
362
  // DATA
363
  ExifData& exifData_;  //!< Reference to the related Exif metadata.
364
365
};  // class ExifThumb
366
367
//! Container type to hold all metadata
368
using ExifMetadata = std::list<Exifdatum>;
369
370
/*!
371
  @brief A container for Exif data.  This is a top-level class of the %Exiv2
372
         library. The container holds Exifdatum objects.
373
374
  Provide high-level access to the Exif data of an image:
375
  - read Exif information from JPEG files
376
  - access metadata through keys and standard C++ iterators
377
  - add, modify and delete metadata
378
  - write Exif data to JPEG files
379
  - extract Exif metadata to files, insert from these files
380
  - extract and delete Exif thumbnail (JPEG and TIFF thumbnails)
381
*/
382
class EXIV2API ExifData {
383
 public:
384
  //! ExifMetadata iterator type
385
  using iterator = ExifMetadata::iterator;
386
  //! ExifMetadata const iterator type
387
  using const_iterator = ExifMetadata::const_iterator;
388
389
  //! @name Manipulators
390
  //@{
391
  /*!
392
    @brief Returns a reference to the %Exifdatum that is associated with a
393
           particular \em key. If %ExifData does not already contain such
394
           an %Exifdatum, operator[] adds object \em Exifdatum(key).
395
396
    @note  Since operator[] might insert a new element, it can't be a const
397
           member function.
398
   */
399
  Exifdatum& operator[](const std::string& key);
400
  /*!
401
    @brief Add an Exifdatum from the supplied key and value pair.  This
402
           method copies (clones) key and value. No duplicate checks are
403
           performed, i.e., it is possible to add multiple metadata with
404
           the same key.
405
   */
406
  void add(const ExifKey& key, const Value* pValue);
407
  /*!
408
    @brief Add a copy of the \em exifdatum to the Exif metadata.  No
409
           duplicate checks are performed, i.e., it is possible to add
410
           multiple metadata with the same key.
411
412
    @throw Error if the makernote cannot be created
413
   */
414
  void add(const Exifdatum& exifdatum);
415
  /*!
416
    @brief Delete the Exifdatum at iterator position \em pos, return the
417
           position of the next exifdatum. Note that iterators into
418
           the metadata, including \em pos, are potentially invalidated
419
           by this call.
420
   */
421
  iterator erase(iterator pos);
422
  /*!
423
    @brief Remove all elements of the range \em beg, \em end, return the
424
           position of the next element. Note that iterators into
425
           the metadata are potentially invalidated by this call.
426
   */
427
  iterator erase(iterator beg, iterator end);
428
  /*!
429
    @brief Delete all Exifdatum instances resulting in an empty container.
430
           Note that this also removes thumbnails.
431
   */
432
  void clear();
433
  //! Sort metadata by key
434
  void sortByKey();
435
  //! Sort metadata by tag
436
  void sortByTag();
437
  //! Begin of the metadata
438
119k
  iterator begin() {
439
119k
    return exifMetadata_.begin();
440
119k
  }
441
  //! End of the metadata
442
8.27M
  iterator end() {
443
8.27M
    return exifMetadata_.end();
444
8.27M
  }
445
  /*!
446
    @brief Find the first Exifdatum with the given \em key, return an
447
           iterator to it.
448
   */
449
  iterator findKey(const ExifKey& key);
450
  //@}
451
452
  //! @name Accessors
453
  //@{
454
  //! Begin of the metadata
455
3.33k
  [[nodiscard]] const_iterator begin() const {
456
3.33k
    return exifMetadata_.begin();
457
3.33k
  }
458
  //! End of the metadata
459
201k
  [[nodiscard]] const_iterator end() const {
460
201k
    return exifMetadata_.end();
461
201k
  }
462
  /*!
463
    @brief Find the first Exifdatum with the given \em key, return a const
464
           iterator to it.
465
   */
466
  [[nodiscard]] const_iterator findKey(const ExifKey& key) const;
467
  //! Return true if there is no Exif metadata
468
8.67k
  [[nodiscard]] bool empty() const {
469
8.67k
    return exifMetadata_.empty();
470
8.67k
  }
471
  //! Get the number of metadata entries
472
0
  [[nodiscard]] size_t count() const {
473
0
    return exifMetadata_.size();
474
0
  }
475
  //@}
476
477
 private:
478
  // DATA
479
  ExifMetadata exifMetadata_;
480
};  // class ExifData
481
482
/*!
483
  @brief Stateless parser class for Exif data. Images use this class to
484
         decode and encode binary Exif data.
485
486
  @note  Encode is lossy and is not the inverse of decode.
487
 */
488
class EXIV2API ExifParser {
489
 public:
490
  /*!
491
    @brief Decode metadata from a buffer \em pData of length \em size
492
           with binary Exif data to the provided metadata container.
493
494
           The buffer must start with a TIFF header. Return byte order
495
           in which the data is encoded.
496
497
    @param exifData Exif metadata container.
498
    @param pData   Pointer to the data buffer. Must point to data in
499
                   binary Exif format; no checks are performed.
500
    @param size    Length of the data buffer
501
    @param dp      Parameters for all decode() functions
502
    @return Byte order in which the data is encoded.
503
  */
504
  static ByteOrder decode(ExifData& exifData, const byte* pData, size_t size, const DecodeParams& dp);
505
  /*!
506
    @brief Encode Exif metadata from the provided metadata to binary Exif
507
           format.
508
509
    The original binary Exif data in the memory block \em pData, \em size
510
    is parsed and updated in-place if possible ("non-intrusive"
511
    writing). If that is not possible (e.g., if new tags were added), the
512
    entire Exif structure is re-written to the \em blob ("intrusive"
513
    writing). The return value indicates which write method was used. If
514
    it is \c wmNonIntrusive, the original memory \em pData, \em size
515
    contains the result and \em blob is empty. If the return value is
516
    \c wmIntrusive, a new Exif structure was created and returned in
517
    \em blob. The memory block \em pData, \em size may be partly updated in
518
    this case and should not be used anymore.
519
520
    Encode is a lossy operation. It attempts to fit the Exif data into a
521
    binary block suitable as the payload of a JPEG APP1 Exif segment,
522
    which can be at most 65527 bytes large. Encode omits IFD0 tags that
523
    are "not recorded" in compressed images according to the Exif 2.2
524
    specification. It also doesn't write tags in groups which do not occur
525
    in JPEG images. If the resulting binary block is larger than allowed,
526
    it further deletes specific large preview tags, unknown tags larger
527
    than 4kB and known tags larger than 40kB. The operation succeeds even
528
    if the end result is still larger than the allowed size. Application
529
    should therefore always check the size of the \em blob.
530
531
    @param blob      Container for the binary Exif data if "intrusive"
532
                     writing is necessary. Empty otherwise.
533
    @param pData     Pointer to the binary Exif data buffer. Must
534
                     point to data in Exif format; no checks are
535
                     performed. Will be modified if "non-intrusive"
536
                     writing is possible.
537
    @param size      Length of the data buffer.
538
    @param byteOrder Byte order to use.
539
    @param exifData  Exif metadata container.
540
541
    @return Write method used.
542
  */
543
  static WriteMethod encode(Blob& blob, const byte* pData, size_t size, ByteOrder byteOrder, ExifData& exifData);
544
  /*!
545
    @brief Encode metadata from the provided metadata to Exif format.
546
547
    Encode Exif metadata from the \em ExifData container to binary Exif
548
    format in the \em blob, encoded in \em byteOrder.
549
550
    This simpler encode method uses "intrusive" writing, i.e., it builds
551
    the binary representation of the metadata from scratch. It does not
552
    attempt "non-intrusive", i.e., in-place updating. It's better to use
553
    the other encode() method, if the metadata is already available in
554
    binary format, in order to allow for "non-intrusive" updating of the
555
    existing binary representation.
556
557
    This is just an inline wrapper for
558
    ExifParser::encode(blob, 0, 0, byteOrder, exifData).
559
560
    @param blob      Container for the binary Exif data.
561
    @param byteOrder Byte order to use.
562
    @param exifData  Exif metadata container.
563
  */
564
4.22k
  static void encode(Blob& blob, ByteOrder byteOrder, ExifData& exifData) {
565
4.22k
    encode(blob, nullptr, 0, byteOrder, exifData);
566
4.22k
  }
567
568
};  // class ExifParser
569
570
}  // namespace Exiv2
571
572
#endif  // EXIV2_EXIF_HPP