Coverage Report

Created: 2026-02-26 07:48

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