/src/exiv2/include/exiv2/iptc.hpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | |
3 | | /*! |
4 | | @file iptc.hpp |
5 | | @brief Encoding and decoding of IPTC data |
6 | | */ |
7 | | #ifndef EXIV2_IPTC_HPP |
8 | | #define EXIV2_IPTC_HPP |
9 | | |
10 | | // ***************************************************************************** |
11 | | #include "exiv2lib_export.h" |
12 | | |
13 | | // included header files |
14 | | #include "datasets.hpp" |
15 | | #include "metadatum.hpp" |
16 | | |
17 | | // ***************************************************************************** |
18 | | // namespace extensions |
19 | | namespace Exiv2 { |
20 | | // ***************************************************************************** |
21 | | // class declarations |
22 | | class ExifData; |
23 | | |
24 | | // ***************************************************************************** |
25 | | // class definitions |
26 | | |
27 | | /*! |
28 | | @brief An IPTC metadatum ("dataset"), consisting of an IptcKey and a |
29 | | Value and methods to manipulate these. |
30 | | |
31 | | This is referred in the standard as a property. |
32 | | */ |
33 | | class EXIV2API Iptcdatum : public Metadatum { |
34 | | public: |
35 | | //! @name Creators |
36 | | //@{ |
37 | | /*! |
38 | | @brief Constructor for new tags created by an application. The |
39 | | %Iptcdatum is created from a key / value pair. %Iptcdatum |
40 | | copies (clones) the value if one is provided. Alternatively, a |
41 | | program can create an 'empty' %Iptcdatum with only a key and |
42 | | set the value using setValue(). |
43 | | |
44 | | @param key The key of the %Iptcdatum. |
45 | | @param pValue Pointer to a %Iptcdatum value. |
46 | | @throw Error if the key cannot be parsed and converted |
47 | | to a tag number and record id. |
48 | | */ |
49 | | explicit Iptcdatum(const IptcKey& key, const Value* pValue = nullptr); |
50 | | //! Copy constructor |
51 | | Iptcdatum(const Iptcdatum& rhs); |
52 | | //! Destructor |
53 | | ~Iptcdatum() override; |
54 | | //@} |
55 | | |
56 | | //! @name Manipulators |
57 | | //@{ |
58 | | //! Assignment operator |
59 | | Iptcdatum& operator=(const Iptcdatum& rhs); |
60 | | /*! |
61 | | @brief Assign \em value to the %Iptcdatum. The type of the new Value |
62 | | is set to UShortValue. |
63 | | */ |
64 | | Iptcdatum& operator=(const uint16_t& value); |
65 | | /*! |
66 | | @brief Assign \em value to the %Iptcdatum. |
67 | | Calls setValue(const std::string&). |
68 | | */ |
69 | | Iptcdatum& operator=(const std::string& value); |
70 | | /*! |
71 | | @brief Assign \em value to the %Iptcdatum. |
72 | | Calls setValue(const Value*). |
73 | | */ |
74 | | Iptcdatum& operator=(const Value& value); |
75 | | void setValue(const Value* pValue) override; |
76 | | /*! |
77 | | @brief Set the value to the string \em value, using |
78 | | Value::read(const std::string&). |
79 | | If the %Iptcdatum does not have a Value yet, then a %Value of |
80 | | the correct type for this %Iptcdatum is created. If that |
81 | | fails (because of an unknown dataset), a StringValue is |
82 | | created. Return 0 if the value was read successfully. |
83 | | */ |
84 | | int setValue(const std::string& value) override; |
85 | | //@} |
86 | | |
87 | | //! @name Accessors |
88 | | //@{ |
89 | | size_t copy(byte* buf, ByteOrder byteOrder) const override; |
90 | | std::ostream& write(std::ostream& os, const ExifData* pMetadata = nullptr) const override; |
91 | | /*! |
92 | | @brief Return the key of the Iptcdatum. The key is of the form |
93 | | '<b>Iptc</b>.recordName.datasetName'. Note however that the key |
94 | | is not necessarily unique, i.e., an IptcData object may contain |
95 | | multiple metadata with the same key. |
96 | | */ |
97 | | [[nodiscard]] std::string key() const override; |
98 | | /*! |
99 | | @brief Return the name of the record |
100 | | @return record name |
101 | | @deprecated This function is deprecated. |
102 | | */ |
103 | | [[deprecated]] [[nodiscard]] std::string recordName() const; |
104 | | /*! |
105 | | @brief Return the record id |
106 | | @return record id |
107 | | */ |
108 | | [[nodiscard]] uint16_t record() const; |
109 | | [[nodiscard]] const char* familyName() const override; |
110 | | [[nodiscard]] std::string groupName() const override; |
111 | | /*! |
112 | | @brief Return the name of the tag (aka dataset) |
113 | | @return tag name |
114 | | */ |
115 | | [[nodiscard]] std::string tagName() const override; |
116 | | [[nodiscard]] std::string tagLabel() const override; |
117 | | [[nodiscard]] std::string tagDesc() const override; |
118 | | //! Return the tag (aka dataset) number |
119 | | [[nodiscard]] uint16_t tag() const override; |
120 | | [[nodiscard]] TypeId typeId() const override; |
121 | | [[nodiscard]] const char* typeName() const override; |
122 | | [[nodiscard]] size_t typeSize() const override; |
123 | | [[nodiscard]] size_t count() const override; |
124 | | [[nodiscard]] size_t size() const override; |
125 | | [[nodiscard]] std::string toString() const override; |
126 | | [[nodiscard]] std::string toString(size_t n) const override; |
127 | | [[nodiscard]] int64_t toInt64(size_t n = 0) const override; |
128 | | [[nodiscard]] float toFloat(size_t n = 0) const override; |
129 | | [[nodiscard]] Rational toRational(size_t n = 0) const override; |
130 | | [[nodiscard]] std::unique_ptr<Value> getValue() const override; |
131 | | [[nodiscard]] const Value& value() const override; |
132 | | //@} |
133 | | |
134 | | private: |
135 | | // DATA |
136 | | IptcKey::UniquePtr key_; //!< Key |
137 | | std::unique_ptr<Value> value_; //!< Value |
138 | | |
139 | | }; // class Iptcdatum |
140 | | |
141 | | //! Container type to hold all metadata |
142 | | using IptcMetadata = std::vector<Iptcdatum>; |
143 | | |
144 | | /*! |
145 | | @brief A container for IPTC data. This is a top-level class of the %Exiv2 library. |
146 | | |
147 | | Provide high-level access to the IPTC data of an image: |
148 | | - read IPTC information from JPEG files |
149 | | - access metadata through keys and standard C++ iterators |
150 | | - add, modify and delete metadata |
151 | | - write IPTC data to JPEG files |
152 | | - extract IPTC metadata to files, insert from these files |
153 | | */ |
154 | | class EXIV2API IptcData { |
155 | | public: |
156 | | //! IptcMetadata iterator type |
157 | | using iterator = IptcMetadata::iterator; |
158 | | //! IptcMetadata const iterator type |
159 | | using const_iterator = IptcMetadata::const_iterator; |
160 | | |
161 | | // Use the compiler generated constructors and assignment operator |
162 | | |
163 | | //! @name Manipulators |
164 | | //@{ |
165 | | /*! |
166 | | @brief Returns a reference to the %Iptcdatum that is associated with a |
167 | | particular \em key. If %IptcData does not already contain such |
168 | | an %Iptcdatum, operator[] adds object \em Iptcdatum(key). |
169 | | |
170 | | @note Since operator[] might insert a new element, it can't be a const |
171 | | member function. |
172 | | */ |
173 | | Iptcdatum& operator[](const std::string& key); |
174 | | /*! |
175 | | @brief Add an %Iptcdatum from the supplied key and value pair. This |
176 | | method copies (clones) the value. A check for non-repeatable |
177 | | datasets is performed. |
178 | | @return 0 if successful;<BR> |
179 | | 6 if the dataset already exists and is not repeatable |
180 | | */ |
181 | | int add(const IptcKey& key, const Value* value); |
182 | | /*! |
183 | | @brief Add a copy of the Iptcdatum to the IPTC metadata. A check |
184 | | for non-repeatable datasets is performed. |
185 | | @return 0 if successful;<BR> |
186 | | 6 if the dataset already exists and is not repeatable;<BR> |
187 | | */ |
188 | | int add(const Iptcdatum& iptcDatum); |
189 | | /*! |
190 | | @brief Delete the Iptcdatum at iterator position pos, return the |
191 | | position of the next Iptcdatum. Note that iterators into |
192 | | the metadata, including pos, are potentially invalidated |
193 | | by this call. |
194 | | */ |
195 | | iterator erase(iterator pos); |
196 | | /*! |
197 | | @brief Delete all Iptcdatum instances resulting in an empty container. |
198 | | */ |
199 | 69.0k | void clear() { |
200 | 69.0k | iptcMetadata_.clear(); |
201 | 69.0k | } |
202 | | //! Sort metadata by key |
203 | | void sortByKey(); |
204 | | //! Sort metadata by tag (aka dataset) |
205 | | void sortByTag(); |
206 | | //! Begin of the metadata |
207 | 0 | iterator begin() { |
208 | 0 | return iptcMetadata_.begin(); |
209 | 0 | } |
210 | | //! End of the metadata |
211 | 2.00k | iterator end() { |
212 | 2.00k | return iptcMetadata_.end(); |
213 | 2.00k | } |
214 | | /*! |
215 | | @brief Find the first Iptcdatum with the given key, return an iterator |
216 | | to it. |
217 | | */ |
218 | | iterator findKey(const IptcKey& key); |
219 | | /*! |
220 | | @brief Find the first Iptcdatum with the given record and dataset it, |
221 | | return a const iterator to it. |
222 | | */ |
223 | | iterator findId(uint16_t dataset, uint16_t record = IptcDataSets::application2); |
224 | | //@} |
225 | | |
226 | | //! @name Accessors |
227 | | //@{ |
228 | | //! Begin of the metadata |
229 | 0 | [[nodiscard]] const_iterator begin() const { |
230 | 0 | return iptcMetadata_.begin(); |
231 | 0 | } |
232 | | //! End of the metadata |
233 | 0 | [[nodiscard]] const_iterator end() const { |
234 | 0 | return iptcMetadata_.end(); |
235 | 0 | } |
236 | | /*! |
237 | | @brief Find the first Iptcdatum with the given key, return a const |
238 | | iterator to it. |
239 | | */ |
240 | | [[nodiscard]] const_iterator findKey(const IptcKey& key) const; |
241 | | /*! |
242 | | @brief Find the first Iptcdatum with the given record and dataset |
243 | | number, return a const iterator to it. |
244 | | */ |
245 | | [[nodiscard]] const_iterator findId(uint16_t dataset, uint16_t record = IptcDataSets::application2) const; |
246 | | //! Return true if there is no IPTC metadata |
247 | 21.3k | [[nodiscard]] bool empty() const { |
248 | 21.3k | return iptcMetadata_.empty(); |
249 | 21.3k | } |
250 | | |
251 | | //! Get the number of metadata entries |
252 | 0 | [[nodiscard]] size_t count() const { |
253 | 0 | return iptcMetadata_.size(); |
254 | 0 | } |
255 | | |
256 | | //! @brief Return the exact size of all contained IPTC metadata |
257 | | [[nodiscard]] size_t size() const; |
258 | | |
259 | | //! @brief Return the metadata charset name or 0 |
260 | | [[nodiscard]] const char* detectCharset() const; |
261 | | |
262 | | //! @brief dump iptc formatted binary data (used by printStructure kpsRecursive) |
263 | | static void printStructure(std::ostream& out, const Slice<byte*>& bytes, size_t depth); |
264 | | //@} |
265 | | |
266 | | private: |
267 | | // DATA |
268 | | IptcMetadata iptcMetadata_; |
269 | | }; // class IptcData |
270 | | |
271 | | /*! |
272 | | @brief Stateless parser class for IPTC data. Images use this class to |
273 | | decode and encode binary IPTC data. |
274 | | */ |
275 | | class EXIV2API IptcParser { |
276 | | public: |
277 | | /*! |
278 | | @brief Decode binary IPTC data in IPTC IIM4 format from a buffer \em pData |
279 | | of length \em size to the provided metadata container. |
280 | | |
281 | | @param iptcData Metadata container to add the decoded IPTC datasets to. |
282 | | @param pData Pointer to the data buffer to read from. |
283 | | @param size Number of bytes in the data buffer. |
284 | | |
285 | | @return 0 if successful;<BR> |
286 | | 5 if the binary IPTC data is invalid or corrupt |
287 | | */ |
288 | | static int decode(IptcData& iptcData, const byte* pData, size_t size); |
289 | | |
290 | | /*! |
291 | | @brief Encode the IPTC datasets from \em iptcData to a binary representation in IPTC IIM4 format. |
292 | | |
293 | | Convert the IPTC datasets to binary format and return it. Caller owns |
294 | | the returned buffer. The copied data follows the IPTC IIM4 standard. |
295 | | |
296 | | @return Data buffer containing the binary IPTC data in IPTC IIM4 format. |
297 | | */ |
298 | | static DataBuf encode(const IptcData& iptcData); |
299 | | |
300 | | private: |
301 | | // Constant data |
302 | | static constexpr byte marker_ = 0x1C; // Dataset marker |
303 | | |
304 | | }; // class IptcParser |
305 | | |
306 | | } // namespace Exiv2 |
307 | | |
308 | | #endif // EXIV2_IPTC_HPP |