/src/exiv2/src/tiffvisitor_int.hpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | |
3 | | #ifndef TIFFVISITOR_INT_HPP_ |
4 | | #define TIFFVISITOR_INT_HPP_ |
5 | | |
6 | | // ***************************************************************************** |
7 | | // included header files |
8 | | #include "exif.hpp" |
9 | | #include "types.hpp" |
10 | | |
11 | | #include "tiffcomposite_int.hpp" |
12 | | |
13 | | #include <array> |
14 | | #include <cstddef> |
15 | | #include <cstdint> |
16 | | #include <map> |
17 | | #include <string> |
18 | | #include <vector> |
19 | | |
20 | | // ***************************************************************************** |
21 | | // namespace extensions |
22 | | namespace Exiv2 { |
23 | | class IptcData; |
24 | | class XmpData; |
25 | | |
26 | | namespace Internal { |
27 | | // ***************************************************************************** |
28 | | // class definitions |
29 | | |
30 | | /*! |
31 | | @brief Abstract base class defining the interface for TIFF composite |
32 | | visitors (Visitor pattern) |
33 | | |
34 | | A concrete visitor class is used as shown in the example below. Accept() |
35 | | will invoke the member function corresponding to the concrete type of each |
36 | | component in the composite. |
37 | | |
38 | | @code |
39 | | void visitorExample(Exiv2::TiffComponent* tiffComponent, Exiv2::TiffVisitor& visitor) |
40 | | { |
41 | | tiffComponent->accept(visitor); |
42 | | } |
43 | | @endcode |
44 | | */ |
45 | | class TiffVisitor { |
46 | | public: |
47 | | //! Events for the stop/go flag. See setGo(). |
48 | | enum GoEvent { |
49 | | //! Signal to control traversing of the composite tree. |
50 | | geTraverse = 0, |
51 | | //! Signal used by TiffReader to signal an unknown makernote. |
52 | | geKnownMakernote = 1 |
53 | | // Note: If you add more events here, adjust the events_ constant too! |
54 | | }; |
55 | | |
56 | | private: |
57 | | static const int events_ = 2; //!< The number of stop/go flags. |
58 | | std::array<bool, events_> go_{true, true}; //!< Array of stop/go flags. See setGo(). |
59 | | |
60 | | public: |
61 | | //! @name Creators |
62 | | //@{ |
63 | 65.0k | TiffVisitor() = default; |
64 | | //! Virtual destructor |
65 | 20.6k | virtual ~TiffVisitor() = default; |
66 | | TiffVisitor(const TiffVisitor&) = delete; |
67 | | TiffVisitor& operator=(const TiffVisitor&) = delete; |
68 | | //@} |
69 | | |
70 | | //! @name Manipulators |
71 | | //@{ |
72 | | /*! |
73 | | @brief Set the stop/go flag: true for go, false for stop. |
74 | | |
75 | | This mechanism is used by visitors and components to signal special |
76 | | events. Specifically, TiffFinder sets the geTraverse flag as soon as |
77 | | it finds the correct component to signal to components that the search |
78 | | should be aborted. TiffReader uses geKnownMakernote to signal problems |
79 | | reading a makernote to the TiffMnEntry component. There is an array |
80 | | of flags, one for each defined \em event, so different signals can be |
81 | | used independent of each other. |
82 | | */ |
83 | | void setGo(GoEvent event, bool go); |
84 | | //! Operation to perform for a TIFF entry |
85 | | virtual void visitEntry(TiffEntry* object) = 0; |
86 | | //! Operation to perform for a TIFF data entry |
87 | | virtual void visitDataEntry(TiffDataEntry* object) = 0; |
88 | | //! Operation to perform for a TIFF image entry |
89 | | virtual void visitImageEntry(TiffImageEntry* object) = 0; |
90 | | //! Operation to perform for a TIFF size entry |
91 | | virtual void visitSizeEntry(TiffSizeEntry* object) = 0; |
92 | | //! Operation to perform for a TIFF directory |
93 | | virtual void visitDirectory(TiffDirectory* object) = 0; |
94 | | /*! |
95 | | @brief Operation to perform for a TIFF directory, after all components |
96 | | and before the next entry is processed. |
97 | | */ |
98 | | virtual void visitDirectoryNext(TiffDirectory* object); |
99 | | /*! |
100 | | @brief Operation to perform for a TIFF directory, at the end of the |
101 | | processing. |
102 | | */ |
103 | | virtual void visitDirectoryEnd(TiffDirectory* object); |
104 | | //! Operation to perform for a TIFF sub-IFD |
105 | | virtual void visitSubIfd(TiffSubIfd* object) = 0; |
106 | | //! Operation to perform for the makernote component |
107 | | virtual void visitMnEntry(TiffMnEntry* object) = 0; |
108 | | //! Operation to perform for an IFD makernote |
109 | | virtual void visitIfdMakernote(TiffIfdMakernote* object) = 0; |
110 | | //! Operation to perform after processing an IFD makernote |
111 | | virtual void visitIfdMakernoteEnd(TiffIfdMakernote* object); |
112 | | //! Operation to perform for a binary array |
113 | | virtual void visitBinaryArray(TiffBinaryArray* object) = 0; |
114 | | /*! |
115 | | @brief Operation to perform for a TIFF binary array, at the end |
116 | | of the processing. |
117 | | */ |
118 | | virtual void visitBinaryArrayEnd(TiffBinaryArray* object); |
119 | | //! Operation to perform for an element of a binary array |
120 | | virtual void visitBinaryElement(TiffBinaryElement* object) = 0; |
121 | | //@} |
122 | | |
123 | | //! @name Accessors |
124 | | //@{ |
125 | | //! Check if stop flag for \em event is clear, return true if it's clear. |
126 | | [[nodiscard]] bool go(GoEvent event) const; |
127 | | //@} |
128 | | |
129 | | }; // class TiffVisitor |
130 | | |
131 | | /*! |
132 | | @brief Search the composite for a component with \em tag and \em group. |
133 | | Return a pointer to the component or 0, if not found. The class |
134 | | is ready for a first search after construction and can be |
135 | | re-initialized with init(). |
136 | | */ |
137 | | class TiffFinder : public TiffVisitor { |
138 | | public: |
139 | | //! @name Creators |
140 | | //@{ |
141 | | //! Constructor, taking \em tag and \em group of the component to find. |
142 | 44.3k | constexpr TiffFinder(uint16_t tag, IfdId group) : tag_(tag), group_(group) { |
143 | 44.3k | } |
144 | | //@} |
145 | | |
146 | | //! @name Manipulators |
147 | | //@{ |
148 | | //! Find tag and group in a TIFF entry |
149 | | void visitEntry(TiffEntry* object) override; |
150 | | //! Find tag and group in a TIFF data entry |
151 | | void visitDataEntry(TiffDataEntry* object) override; |
152 | | //! Find tag and group in a TIFF image entry |
153 | | void visitImageEntry(TiffImageEntry* object) override; |
154 | | //! Find tag and group in a TIFF size entry |
155 | | void visitSizeEntry(TiffSizeEntry* object) override; |
156 | | //! Find tag and group in a TIFF directory |
157 | | void visitDirectory(TiffDirectory* object) override; |
158 | | //! Find tag and group in a TIFF sub-IFD |
159 | | void visitSubIfd(TiffSubIfd* object) override; |
160 | | //! Find tag and group in a TIFF makernote |
161 | | void visitMnEntry(TiffMnEntry* object) override; |
162 | | //! Find tag and group in an IFD makernote |
163 | | void visitIfdMakernote(TiffIfdMakernote* object) override; |
164 | | //! Find tag and group in a binary array |
165 | | void visitBinaryArray(TiffBinaryArray* object) override; |
166 | | //! Find tag and group in an element of a binary array |
167 | | void visitBinaryElement(TiffBinaryElement* object) override; |
168 | | |
169 | | //! Check if \em object matches \em tag and \em group |
170 | | void findObject(TiffComponent* object); |
171 | | //! Initialize the Finder for a new search. |
172 | | void init(uint16_t tag, IfdId group); |
173 | | //@} |
174 | | |
175 | | //! @name Accessors |
176 | | //@{ |
177 | | /*! |
178 | | @brief Return the search result. 0 if no TIFF component was found |
179 | | for the tag and group combination. |
180 | | */ |
181 | 44.3k | [[nodiscard]] TiffComponent* result() const { |
182 | 44.3k | return tiffComponent_; |
183 | 44.3k | } |
184 | | //@} |
185 | | |
186 | | private: |
187 | | uint16_t tag_; |
188 | | IfdId group_; |
189 | | TiffComponent* tiffComponent_{}; |
190 | | }; // class TiffFinder |
191 | | |
192 | | /*! |
193 | | @brief Copy all image tags from the source tree (the tree that is traversed) to a |
194 | | target tree, which is empty except for the root element provided in the |
195 | | constructor. |
196 | | */ |
197 | | class TiffCopier : public TiffVisitor { |
198 | | public: |
199 | | //! @name Creators |
200 | | //@{ |
201 | | /*! |
202 | | @brief Constructor |
203 | | |
204 | | @param pRoot Pointer to the root element of the (empty) target tree. |
205 | | @param root Actual root element |
206 | | @param pHeader Pointer to the TIFF header of the source image. |
207 | | @param pPrimaryGroups Pointer to the list of primary groups. |
208 | | */ |
209 | | TiffCopier(TiffComponent* pRoot, uint32_t root, const TiffHeaderBase* pHeader, PrimaryGroups pPrimaryGroups); |
210 | | //@} |
211 | | |
212 | | //! @name Manipulators |
213 | | //@{ |
214 | | //! Copy a TIFF entry if it is an image tag |
215 | | void visitEntry(TiffEntry* object) override; |
216 | | //! Copy a TIFF data entry if it is an image tag |
217 | | void visitDataEntry(TiffDataEntry* object) override; |
218 | | //! Copy a TIFF image entry if it is an image tag |
219 | | void visitImageEntry(TiffImageEntry* object) override; |
220 | | //! Copy a TIFF size entry if it is an image tag |
221 | | void visitSizeEntry(TiffSizeEntry* object) override; |
222 | | //! Copy a TIFF directory if it is an image tag |
223 | | void visitDirectory(TiffDirectory* object) override; |
224 | | //! Copy a TIFF sub-IFD if it is an image tag |
225 | | void visitSubIfd(TiffSubIfd* object) override; |
226 | | //! Copy a TIFF makernote if it is an image tag |
227 | | void visitMnEntry(TiffMnEntry* object) override; |
228 | | //! Copy an IFD makernote if it is an image tag |
229 | | void visitIfdMakernote(TiffIfdMakernote* object) override; |
230 | | //! Copy a binary array if it is an image tag |
231 | | void visitBinaryArray(TiffBinaryArray* object) override; |
232 | | //! Copy an element of a binary array if it is an image tag |
233 | | void visitBinaryElement(TiffBinaryElement* object) override; |
234 | | |
235 | | //! Check if \em object is an image tag and if so, copy it to the target tree. |
236 | | void copyObject(const TiffComponent* object); |
237 | | //@} |
238 | | |
239 | | private: |
240 | | TiffComponent* pRoot_; |
241 | | uint32_t root_; |
242 | | const TiffHeaderBase* pHeader_; |
243 | | PrimaryGroups pPrimaryGroups_; |
244 | | }; // class TiffCopier |
245 | | |
246 | | /*! |
247 | | @brief TIFF composite visitor to decode metadata from the TIFF tree and |
248 | | add it to an Image, which is supplied in the constructor (Visitor |
249 | | pattern). Used by TiffParser to decode the metadata from a |
250 | | TIFF composite. |
251 | | */ |
252 | | class TiffDecoder : public TiffVisitor { |
253 | | public: |
254 | | //! @name Creators |
255 | | //@{ |
256 | | /*! |
257 | | @brief Constructor, taking metadata containers to add the metadata to, |
258 | | the root element of the composite to decode and a FindDecoderFct |
259 | | function to get the decoder function for each tag. |
260 | | */ |
261 | | TiffDecoder(ExifData& exifData, IptcData& iptcData, XmpData& xmpData, TiffComponent* pRoot, |
262 | | FindDecoderFct findDecoderFct); |
263 | | //@} |
264 | | |
265 | | //! @name Manipulators |
266 | | //@{ |
267 | | //! Decode a TIFF entry |
268 | | void visitEntry(TiffEntry* object) override; |
269 | | //! Decode a TIFF data entry |
270 | | void visitDataEntry(TiffDataEntry* object) override; |
271 | | //! Decode a TIFF image entry |
272 | | void visitImageEntry(TiffImageEntry* object) override; |
273 | | //! Decode a TIFF size entry |
274 | | void visitSizeEntry(TiffSizeEntry* object) override; |
275 | | //! Decode a TIFF directory |
276 | | void visitDirectory(TiffDirectory* object) override; |
277 | | //! Decode a TIFF sub-IFD |
278 | | void visitSubIfd(TiffSubIfd* object) override; |
279 | | //! Decode a TIFF makernote |
280 | | void visitMnEntry(TiffMnEntry* object) override; |
281 | | //! Decode an IFD makernote |
282 | | void visitIfdMakernote(TiffIfdMakernote* object) override; |
283 | | //! Decode a binary array |
284 | | void visitBinaryArray(TiffBinaryArray* object) override; |
285 | | //! Decode an element of a binary array |
286 | | void visitBinaryElement(TiffBinaryElement* object) override; |
287 | | |
288 | | //! Entry function, determines how to decode each tag |
289 | | void decodeTiffEntry(const TiffEntryBase* object); |
290 | | //! Decode a standard TIFF entry |
291 | | void decodeStdTiffEntry(const TiffEntryBase* object); |
292 | | //! Decode IPTC data from an IPTCNAA tag or Photoshop ImageResources |
293 | | void decodeIptc(const TiffEntryBase* object); |
294 | | //! Decode XMP packet from an XMLPacket tag |
295 | | void decodeXmp(const TiffEntryBase* object); |
296 | | //! Decode Exif.Canon.AFInfo |
297 | | void decodeCanonAFInfo(const TiffEntryBase* object); |
298 | | //@} |
299 | | |
300 | | private: |
301 | | //! @name Manipulators |
302 | | //@{ |
303 | | /*! |
304 | | @brief Get the data for a \em tag and \em group, either from the |
305 | | \em object provided, if it matches or from the matching element |
306 | | in the hierarchy. |
307 | | |
308 | | Populates \em pData and \em size with the result. If no matching |
309 | | element is found the function leaves both of these parameters unchanged. |
310 | | */ |
311 | | void getObjData(const byte*& pData, size_t& size, uint16_t tag, IfdId group, const TiffEntryBase* object); |
312 | | //@} |
313 | | |
314 | | // DATA |
315 | | ExifData& exifData_; //!< Exif metadata container |
316 | | IptcData& iptcData_; //!< IPTC metadata container |
317 | | XmpData& xmpData_; //!< XMP metadata container |
318 | | TiffComponent* pRoot_; //!< Root element of the composite |
319 | | FindDecoderFct findDecoderFct_; //!< Ptr to the function to find special decoding functions |
320 | | std::string make_; //!< Camera make, determined from the tags to decode |
321 | | bool decodedIptc_{false}; //!< Indicates if IPTC has been decoded yet |
322 | | |
323 | | }; // class TiffDecoder |
324 | | |
325 | | /*! |
326 | | @brief TIFF composite visitor to encode metadata from an image to the TIFF |
327 | | tree. The metadata containers and root element of the tree are |
328 | | supplied in the constructor. Used by TiffParserWorker to encode the |
329 | | metadata into a TIFF composite. |
330 | | |
331 | | For non-intrusive writing, the encoder is used as a visitor (by |
332 | | passing it to the accept() member of a TiffComponent). The |
333 | | composite tree is then traversed and metadata from the image is |
334 | | used to encode each existing component. |
335 | | |
336 | | For intrusive writing, add() is called, which loops through the |
337 | | metadata and creates and populates corresponding TiffComponents |
338 | | as needed. |
339 | | */ |
340 | | class TiffEncoder : public TiffVisitor { |
341 | | public: |
342 | | //! @name Creators |
343 | | //@{ |
344 | | /*! |
345 | | @brief Constructor, taking the root element of the composite to encode |
346 | | to, the image with the metadata to encode and a function to |
347 | | find special encoders. |
348 | | */ |
349 | | TiffEncoder(ExifData exifData, const IptcData& iptcData, const XmpData& xmpData, TiffComponent* pRoot, |
350 | | bool isNewImage, PrimaryGroups pPrimaryGroups, const TiffHeaderBase* pHeader, |
351 | | FindEncoderFct findEncoderFct); |
352 | | TiffEncoder(const TiffEncoder&) = delete; |
353 | | TiffEncoder& operator=(const TiffEncoder&) = delete; |
354 | | //! Virtual destructor |
355 | 2.73k | ~TiffEncoder() override = default; |
356 | | //@} |
357 | | |
358 | | //! @name Manipulators |
359 | | //@{ |
360 | | //! Encode a TIFF entry |
361 | | void visitEntry(TiffEntry* object) override; |
362 | | //! Encode a TIFF data entry |
363 | | void visitDataEntry(TiffDataEntry* object) override; |
364 | | //! Encode a TIFF image entry |
365 | | void visitImageEntry(TiffImageEntry* object) override; |
366 | | //! Encode a TIFF size entry |
367 | | void visitSizeEntry(TiffSizeEntry* object) override; |
368 | | //! Encode a TIFF directory |
369 | | void visitDirectory(TiffDirectory* object) override; |
370 | | //! Update directory entries |
371 | | void visitDirectoryNext(TiffDirectory* object) override; |
372 | | //! Encode a TIFF sub-IFD |
373 | | void visitSubIfd(TiffSubIfd* object) override; |
374 | | //! Encode a TIFF makernote |
375 | | void visitMnEntry(TiffMnEntry* object) override; |
376 | | //! Encode an IFD makernote |
377 | | void visitIfdMakernote(TiffIfdMakernote* object) override; |
378 | | //! Reset encoder to its original state, undo makernote specific settings |
379 | | void visitIfdMakernoteEnd(TiffIfdMakernote* object) override; |
380 | | //! Encode a binary array |
381 | | void visitBinaryArray(TiffBinaryArray* object) override; |
382 | | //! Re-encrypt binary array if necessary |
383 | | void visitBinaryArrayEnd(TiffBinaryArray* object) override; |
384 | | //! Encode an element of a binary array |
385 | | void visitBinaryElement(TiffBinaryElement* object) override; |
386 | | |
387 | | /*! |
388 | | @brief Top level encoder function. Determines how to encode each TIFF |
389 | | component. This function is called by the visit methods of the |
390 | | encoder as well as the add() method. |
391 | | |
392 | | If no \em datum is provided, search the metadata based on tag and |
393 | | group of the \em object. This is the case if the function is called |
394 | | from a visit method. |
395 | | |
396 | | Then check if a special encoder function is registered for the tag, |
397 | | and if so use it to encode the \em object. Else use the callback |
398 | | encoder function at the object (which results in a double-dispatch to |
399 | | the appropriate encoding function of the encoder. |
400 | | |
401 | | @param object Object in the TIFF component tree to encode. |
402 | | @param datum The corresponding metadatum with the updated value. |
403 | | |
404 | | @note Encoder functions may use metadata other than \em datum. |
405 | | */ |
406 | | void encodeTiffComponent(TiffEntryBase* object, const Exifdatum* datum = nullptr); |
407 | | |
408 | | //! Callback encoder function for an element of a binary array. |
409 | | void encodeBinaryElement(TiffBinaryElement* object, const Exifdatum* datum); |
410 | | //! Callback encoder function for a binary array. |
411 | | void encodeBinaryArray(TiffBinaryArray* object, const Exifdatum* datum); |
412 | | //! Callback encoder function for a data entry. |
413 | | void encodeDataEntry(TiffDataEntry* object, const Exifdatum* datum); |
414 | | //! Callback encoder function for a standard TIFF entry |
415 | | void encodeTiffEntry(TiffEntry* object, const Exifdatum* datum); |
416 | | //! Callback encoder function for an image entry. |
417 | | void encodeImageEntry(TiffImageEntry* object, const Exifdatum* datum); |
418 | | //! Callback encoder function for a %Makernote entry. |
419 | | void encodeMnEntry(TiffMnEntry* object, const Exifdatum* datum); |
420 | | //! Callback encoder function for a size entry. |
421 | | void encodeSizeEntry(TiffSizeEntry* object, const Exifdatum* datum); |
422 | | //! Callback encoder function for a sub-IFD entry. |
423 | | void encodeSubIfd(TiffSubIfd* object, const Exifdatum* datum); |
424 | | |
425 | | //! Special encoder function for the base part of a TIFF entry. |
426 | | void encodeTiffEntryBase(TiffEntryBase* object, const Exifdatum* datum); |
427 | | //! Special encoder function for an offset entry. |
428 | | void encodeOffsetEntry(TiffEntryBase* object, const Exifdatum* datum); |
429 | | |
430 | | //! Special encoder function to encode SubIFD contents to Image group if it contains primary image data |
431 | | // Todo void encodeNikonSubIfd(TiffEntryBase* object, const Exifdatum* datum); |
432 | | |
433 | | //! Special encoder function to encode IPTC data to an IPTCNAA or Photoshop ImageResources tag. |
434 | | void encodeIptc(TiffEntryBase* object, const Exifdatum* datum); |
435 | | /*! |
436 | | @brief Add metadata from image to the TIFF composite. |
437 | | |
438 | | For each Exif metadatum, the corresponding TiffComponent is created |
439 | | if necessary and populated using encodeTiffComponent(). The add() function |
440 | | is used during intrusive writing, to create a new TIFF structure. |
441 | | |
442 | | @note For non-intrusive writing, the encoder is used as a visitor (by |
443 | | passing it to the accept() member of a TiffComponent). The composite |
444 | | tree is then traversed and metadata from the image is used to encode |
445 | | each existing component. |
446 | | */ |
447 | | void add(TiffComponent* pRootDir, TiffComponent::UniquePtr pSourceDir, uint32_t root); |
448 | | //! Set the dirty flag and end of traversing signal. |
449 | | void setDirty(bool flag = true); |
450 | | //@} |
451 | | |
452 | | //! @name Accessors |
453 | | //@{ |
454 | | /*! |
455 | | @brief Return the applicable byte order. May be different for |
456 | | the Makernote and the rest of the TIFF entries. |
457 | | */ |
458 | 173k | [[nodiscard]] ByteOrder byteOrder() const { |
459 | 173k | return byteOrder_; |
460 | 173k | } |
461 | | /*! |
462 | | @brief True if any tag was deleted or allocated in the process of |
463 | | visiting a TIFF composite tree. |
464 | | */ |
465 | | [[nodiscard]] bool dirty() const; |
466 | | //! Return the write method used. |
467 | 981 | [[nodiscard]] WriteMethod writeMethod() const { |
468 | 981 | return writeMethod_; |
469 | 981 | } |
470 | | //@} |
471 | | |
472 | | private: |
473 | | //! @name Manipulators |
474 | | //@{ |
475 | | /*! |
476 | | Encode IPTC data. Updates or adds tag Exif.Image.IPTCNAA, updates but |
477 | | never adds tag Exif.Image.ImageResources. |
478 | | This method is called from the constructor. |
479 | | */ |
480 | | void encodeIptc(); |
481 | | /*! |
482 | | Encode XMP data. Adds tag Exif.Image.XMLPacket with the XMP packet. |
483 | | This method is called from the constructor. |
484 | | */ |
485 | | void encodeXmp(); |
486 | | //@} |
487 | | |
488 | | //! @name Accessors |
489 | | //@{ |
490 | | /*! |
491 | | @brief Update a directory entry. This is called after all directory |
492 | | entries are encoded. It takes care of type and count changes |
493 | | and size shrinkage for non-intrusive writing. |
494 | | */ |
495 | | static uint32_t updateDirEntry(byte* buf, ByteOrder byteOrder, const TiffComponent::SharedPtr& tiffComponent); |
496 | | /*! |
497 | | @brief Check if the tag is an image tag of an existing image. Such |
498 | | tags are copied from the original image and can't be modified. |
499 | | |
500 | | The condition is true if there is an existing image (as |
501 | | opposed to a newly created TIFF image) and \em tag, \em group |
502 | | is considered an image tag of this image - whether or not |
503 | | it's actually present in the existing image doesn't matter. |
504 | | */ |
505 | | [[nodiscard]] bool isImageTag(uint16_t tag, IfdId group) const; |
506 | | //@} |
507 | | |
508 | | // DATA |
509 | | ExifData exifData_; //!< Copy of the Exif data to encode |
510 | | const IptcData& iptcData_; //!< IPTC data to encode, just a reference |
511 | | const XmpData& xmpData_; //!< XMP data to encode, just a reference |
512 | | bool del_{true}; //!< Indicates if Exif data entries should be deleted after encoding |
513 | | const TiffHeaderBase* pHeader_; //!< TIFF image header |
514 | | TiffComponent* pRoot_; //!< Root element of the composite |
515 | | bool isNewImage_; //!< True if the TIFF image is created from scratch |
516 | | PrimaryGroups pPrimaryGroups_; //!< List of primary image groups |
517 | | TiffComponent::UniquePtr pSourceTree_; //!< Parsed source tree for reference |
518 | | ByteOrder byteOrder_; //!< Byteorder for encoding |
519 | | ByteOrder origByteOrder_; //!< Byteorder as set in the c'tor |
520 | | FindEncoderFct findEncoderFct_; //!< Ptr to the function to find special encoding functions |
521 | | std::string make_; //!< Camera make, determined from the tags to encode |
522 | | bool dirty_{false}; //!< Signals if any tag is deleted or allocated |
523 | | WriteMethod writeMethod_{wmNonIntrusive}; //!< Write method used. |
524 | | |
525 | | }; // class TiffEncoder |
526 | | |
527 | | /*! |
528 | | @brief Simple state class containing relevant state information for |
529 | | the TIFF reader. This is in a separate class so that the |
530 | | reader can change state if needed (e.g., to read certain complex |
531 | | makernotes). |
532 | | */ |
533 | | class TiffRwState { |
534 | | public: |
535 | | //! @name Creators |
536 | | //@{ |
537 | | //! Constructor. |
538 | 9.43k | constexpr TiffRwState(ByteOrder byteOrder, size_t baseOffset) : byteOrder_(byteOrder), baseOffset_(baseOffset) { |
539 | 9.43k | } |
540 | | //@} |
541 | | |
542 | | //! @name Accessors |
543 | | //@{ |
544 | | /*! |
545 | | @brief Return the applicable byte order. May be different for |
546 | | the Makernote and the rest of the TIFF entries. |
547 | | */ |
548 | 3.01M | [[nodiscard]] ByteOrder byteOrder() const { |
549 | 3.01M | return byteOrder_; |
550 | 3.01M | } |
551 | | /*! |
552 | | @brief Return the base offset. |
553 | | |
554 | | TIFF standard format uses byte offsets which are always relative to |
555 | | the start of the TIFF file, i.e., relative to the start of the TIFF |
556 | | image header. In this case, the base offset is 0. However, some |
557 | | camera vendors encode their makernotes in TIFF IFDs using offsets |
558 | | relative to (somewhere near) the start of the makernote data. In this |
559 | | case, base offset added to the start of the TIFF image header points |
560 | | to the basis for such makernote offsets. |
561 | | */ |
562 | 506k | [[nodiscard]] size_t baseOffset() const { |
563 | 506k | return baseOffset_; |
564 | 506k | } |
565 | | //@} |
566 | | |
567 | | private: |
568 | | ByteOrder byteOrder_; |
569 | | size_t baseOffset_; |
570 | | }; // TiffRwState |
571 | | |
572 | | /*! |
573 | | @brief TIFF composite visitor to read the TIFF structure from a block of |
574 | | memory and build the composite from it (Visitor pattern). Used by |
575 | | TiffParser to read the TIFF data from a block of memory. |
576 | | */ |
577 | | class TiffReader : public TiffVisitor { |
578 | | public: |
579 | | //! @name Creators |
580 | | //@{ |
581 | | /*! |
582 | | @brief Constructor. The data buffer and table describing the TIFF |
583 | | structure of the data are set in the constructor. |
584 | | @param pData Pointer to the data buffer, starting with a TIFF header. |
585 | | @param size Number of bytes in the data buffer. |
586 | | @param pRoot Root element of the TIFF composite. |
587 | | @param state State object for creation function, byte order and |
588 | | base offset. |
589 | | */ |
590 | | TiffReader(const byte* pData, size_t size, TiffComponent* pRoot, TiffRwState state); |
591 | | //@} |
592 | | |
593 | | //! @name Manipulators |
594 | | //@{ |
595 | | //! Read a TIFF entry from the data buffer |
596 | | void visitEntry(TiffEntry* object) override; |
597 | | //! Read a TIFF data entry from the data buffer |
598 | | void visitDataEntry(TiffDataEntry* object) override; |
599 | | //! Read a TIFF image entry from the data buffer |
600 | | void visitImageEntry(TiffImageEntry* object) override; |
601 | | //! Read a TIFF size entry from the data buffer |
602 | | void visitSizeEntry(TiffSizeEntry* object) override; |
603 | | //! Read a TIFF directory from the data buffer |
604 | | void visitDirectory(TiffDirectory* object) override; |
605 | | //! Read a TIFF sub-IFD from the data buffer |
606 | | void visitSubIfd(TiffSubIfd* object) override; |
607 | | //! Read a TIFF makernote entry from the data buffer |
608 | | void visitMnEntry(TiffMnEntry* object) override; |
609 | | //! Read an IFD makernote from the data buffer |
610 | | void visitIfdMakernote(TiffIfdMakernote* object) override; |
611 | | //! Reset reader to its original state, undo makernote specific settings |
612 | | void visitIfdMakernoteEnd(TiffIfdMakernote* object) override; |
613 | | //! Read a binary array from the data buffer |
614 | | void visitBinaryArray(TiffBinaryArray* object) override; |
615 | | //! Read an element of a binary array from the data buffer |
616 | | void visitBinaryElement(TiffBinaryElement* object) override; |
617 | | |
618 | | //! Read a standard TIFF entry from the data buffer |
619 | | void readTiffEntry(TiffEntryBase* object); |
620 | | //! Read a TiffDataEntryBase from the data buffer |
621 | | void readDataEntryBase(TiffDataEntryBase* object); |
622 | | /*! |
623 | | @brief Set the \em state of the reader to one suitable for the Makernote. |
624 | | |
625 | | Uses the \em state passed in, if any, and remembers it for use during |
626 | | subsequent calls without any argument. |
627 | | */ |
628 | | void setMnState(const TiffRwState* state = nullptr); |
629 | | //! Set the state to the original state as set in the constructor. |
630 | | void setOrigState(); |
631 | | //! Check IFD directory pointer \em start for circular reference |
632 | | bool circularReference(const byte* start, IfdId group); |
633 | | //! Return the next idx sequence number for \em group |
634 | | int nextIdx(IfdId group); |
635 | | |
636 | | /*! |
637 | | @brief Read deferred components. |
638 | | |
639 | | This function is called after the TIFF composite is read by passing a |
640 | | TiffReader to the accept() function of the root component. It reads |
641 | | all components for which reading was deferred during that pass. This |
642 | | is usually done to make sure that all other components are accessible |
643 | | at the time the deferred components are processed. |
644 | | */ |
645 | | void postProcess(); |
646 | | //@} |
647 | | |
648 | | //! @name Accessors |
649 | | //@{ |
650 | | //! Return the byte order. |
651 | | [[nodiscard]] ByteOrder byteOrder() const; |
652 | | //! Return the base offset. See class TiffRwState for details |
653 | | [[nodiscard]] size_t baseOffset() const; |
654 | | //@} |
655 | | |
656 | | private: |
657 | | using DirList = std::map<const byte*, IfdId>; |
658 | | using IdxSeq = std::map<IfdId, int>; |
659 | | using PostList = std::vector<TiffComponent*>; |
660 | | |
661 | | // DATA |
662 | | const byte* pData_; //!< Pointer to the memory buffer |
663 | | size_t size_; //!< Size of the buffer |
664 | | const byte* pLast_; //!< Pointer to the last byte |
665 | | TiffComponent* pRoot_; //!< Root element of the composite |
666 | | TiffRwState* pState_; //!< Pointer to the state in effect (origState_ or mnState_) |
667 | | TiffRwState origState_; //!< State class as set in the c'tor |
668 | | TiffRwState mnState_; //!< State class as set in the c'tor or by setMnState() |
669 | | DirList dirList_; //!< List of IFD pointers and their groups |
670 | | IdxSeq idxSeq_; //!< Sequences for group, used for the entry's idx |
671 | | PostList postList_; //!< List of components with deferred reading |
672 | | bool postProc_{false}; //!< True in postProcessList() |
673 | | }; |
674 | | |
675 | | } // namespace Internal |
676 | | } // namespace Exiv2 |
677 | | |
678 | | #endif // #ifndef TIFFVISITOR_INT_HPP_ |