1 /* exif.hxx 2 * 3 * Copyright 2002,2003 Hans Meine <hans_meine@gmx.net> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301 USA. 19 */ 20 21 #ifndef EXIF_HXX 22 #define EXIF_HXX 23 24 #include <libexif/exif-entry.h> 25 #include <libexif/exif-content.h> 26 #include <libexif/exif-ifd.h> 27 #include <libexif/exif-data.h> 28 #include <libexif/exif-format.h> 29 #include <libexif/exif-utils.h> 30 #include <stdexcept> 31 #include <string> 32 33 namespace Exif { 34 35 #ifndef EXIF_NO_EXCEPTIONS 36 struct InvalidIndex : std::runtime_error 37 { InvalidIndexExif::InvalidIndex38 InvalidIndex(const std::string& s) 39 : std::runtime_error(s) {} 40 }; 41 42 struct InvalidFormat : std::runtime_error 43 { InvalidFormatExif::InvalidFormat44 InvalidFormat(const std::string& s) 45 : std::runtime_error(s) {} 46 }; 47 48 struct IOError : std::runtime_error 49 { IOErrorExif::IOError50 IOError(const std::string& s) 51 : std::runtime_error(s) {} 52 }; 53 #endif // EXIF_NO_EXCEPTIONS 54 55 struct Entry 56 { 57 ExifEntry *entry_; 58 59 // construct an empty entry, FIXME: is this needed in the public API? EntryExif::Entry60 Entry() 61 : entry_(exif_entry_new()) 62 {} 63 64 // construct an entry for the given tag EntryExif::Entry65 Entry(ExifTag tag) 66 : entry_(exif_entry_new()) 67 { 68 exif_entry_initialize(entry_, tag); 69 } 70 71 // copy constructor EntryExif::Entry72 Entry(Entry const &other) 73 : entry_(other.entry_) 74 { 75 exif_entry_ref(entry_); 76 } 77 78 // internal, do not use directly EntryExif::Entry79 Entry(ExifEntry *entry) 80 : entry_(entry) 81 { 82 exif_entry_ref(entry_); 83 } 84 ~EntryExif::Entry85 ~Entry() 86 { 87 exif_entry_unref(entry_); 88 } 89 operator =Exif::Entry90 Entry &operator=(Entry const &other) 91 { 92 exif_entry_unref(entry_); 93 entry_ = other.entry_; 94 exif_entry_ref(entry_); 95 return *this; 96 } 97 tagExif::Entry98 ExifTag tag() const 99 { 100 return entry_->tag; 101 } 102 103 /* 104 void setTag(ExifTag tag) 105 { 106 entry_->tag = tag; 107 } 108 */ 109 formatExif::Entry110 ExifFormat format() const 111 { 112 return entry_->format; 113 } 114 115 /* 116 void setFormat(ExifFormat format) 117 { 118 entry_->format = format; 119 } 120 */ 121 componentsExif::Entry122 unsigned long components() const 123 { 124 return entry_->components; 125 } 126 127 /* 128 void setComponents(unsigned long components) 129 { 130 entry_->components = components; 131 } 132 133 void initialize(ExifTag tag) 134 { 135 exif_entry_initialize(entry_, tag); 136 } 137 */ 138 getByteExif::Entry139 ExifByte getByte(unsigned int index) const 140 { 141 #ifndef EXIF_NO_EXCEPTIONS 142 if(entry_->format != EXIF_FORMAT_BYTE) 143 throw InvalidFormat( 144 "Exif::Entry::getByte(): Format is not EXIF_FORMAT_BYTE"); 145 if(index >= components()) 146 throw InvalidIndex( 147 "Exif::getByte: component index out of range"); 148 #endif 149 return *(entry_->data 150 + index * exif_format_get_size(entry_->format)); 151 } 152 getAsciiExif::Entry153 const ExifAscii getAscii() const 154 { 155 #ifndef EXIF_NO_EXCEPTIONS 156 if(entry_->format != EXIF_FORMAT_ASCII) 157 throw InvalidFormat( 158 "Exif::Entry::getAscii(): Format is not EXIF_FORMAT_ASCII"); 159 #endif 160 return (ExifAscii)entry_->data; 161 } 162 getShortExif::Entry163 ExifShort getShort(unsigned int index) const 164 { 165 #ifndef EXIF_NO_EXCEPTIONS 166 if(entry_->format != EXIF_FORMAT_SHORT) 167 throw InvalidFormat( 168 "Exif::Entry::getShort(): Format is not EXIF_FORMAT_SHORT"); 169 if(index >= components()) 170 throw InvalidIndex( 171 "Exif::getShort: component index out of range"); 172 #endif 173 return exif_get_short(entry_->data 174 + index * exif_format_get_size(entry_->format), 175 exif_data_get_byte_order(entry_->parent->parent)); 176 } 177 getLongExif::Entry178 ExifLong getLong(unsigned int index) const 179 { 180 #ifndef EXIF_NO_EXCEPTIONS 181 if(entry_->format != EXIF_FORMAT_LONG) 182 throw InvalidFormat( 183 "Exif::Entry::getLong(): Format is not EXIF_FORMAT_LONG"); 184 if(index >= components()) 185 throw InvalidIndex( 186 "Exif::getLong: component index out of range"); 187 #endif 188 return exif_get_long(entry_->data 189 + index * exif_format_get_size(entry_->format), 190 exif_data_get_byte_order(entry_->parent->parent)); 191 } 192 getSLongExif::Entry193 ExifSLong getSLong(unsigned int index) const 194 { 195 #ifndef EXIF_NO_EXCEPTIONS 196 if(entry_->format != EXIF_FORMAT_SLONG) 197 throw InvalidFormat( 198 "Exif::Entry::getSLong(): Format is not EXIF_FORMAT_SLONG"); 199 if(index >= components()) 200 throw InvalidIndex( 201 "Exif::getSLong: component index out of range"); 202 #endif 203 return exif_get_slong(entry_->data 204 + index * exif_format_get_size(entry_->format), 205 exif_data_get_byte_order(entry_->parent->parent)); 206 } 207 getRationalExif::Entry208 ExifRational getRational(unsigned int index) const 209 { 210 #ifndef EXIF_NO_EXCEPTIONS 211 if(entry_->format != EXIF_FORMAT_RATIONAL) 212 throw InvalidFormat( 213 "Exif::Entry::getRational(): Format is not EXIF_FORMAT_RATIONAL"); 214 if(index >= components()) 215 throw InvalidIndex( 216 "Exif::getRational: component index out of range"); 217 #endif 218 return exif_get_rational(entry_->data 219 + index * exif_format_get_size(entry_->format), 220 exif_data_get_byte_order(entry_->parent->parent)); 221 } 222 getSRationalExif::Entry223 ExifSRational getSRational(unsigned int index) const 224 { 225 #ifndef EXIF_NO_EXCEPTIONS 226 if(entry_->format != EXIF_FORMAT_SRATIONAL) 227 throw InvalidFormat( 228 "Exif::Entry::getSRational(): Format is not EXIF_FORMAT_SRATIONAL"); 229 if(index >= components()) 230 throw InvalidIndex( 231 "Exif::getSRational: component index out of range"); 232 #endif 233 return exif_get_srational(entry_->data 234 + index * exif_format_get_size(entry_->format), 235 exif_data_get_byte_order(entry_->parent->parent)); 236 } 237 setByteExif::Entry238 void setByte(unsigned int index, ExifByte value) const 239 { 240 #ifndef EXIF_NO_EXCEPTIONS 241 if(entry_->format != EXIF_FORMAT_BYTE) 242 throw InvalidFormat( 243 "Exif::Entry::setByte(): Format is not EXIF_FORMAT_BYTE"); 244 if(index >= components()) 245 throw InvalidIndex( 246 "Exif::setByte: component index out of range"); 247 #endif 248 *(entry_->data 249 + index * exif_format_get_size(entry_->format)) = value; 250 } 251 252 /* 253 const ExifAscii setAscii() const 254 { 255 #ifndef EXIF_NO_EXCEPTIONS 256 if(entry_->format != EXIF_FORMAT_ASCII) 257 throw InvalidFormat( 258 "Exif::Entry::setAscii(): Format is not EXIF_FORMAT_ASCII"); 259 #endif 260 return (ExifAscii)entry_->data; 261 } 262 */ 263 setShortExif::Entry264 void setShort(unsigned int index, ExifShort value) const 265 { 266 #ifndef EXIF_NO_EXCEPTIONS 267 if(entry_->format != EXIF_FORMAT_SHORT) 268 throw InvalidFormat( 269 "Exif::Entry::setShort(): Format is not EXIF_FORMAT_SHORT"); 270 if(index >= components()) 271 throw InvalidIndex( 272 "Exif::setShort: component index out of range"); 273 #endif 274 return exif_set_short(entry_->data 275 + index * exif_format_get_size(entry_->format), 276 exif_data_get_byte_order(entry_->parent->parent), 277 value); 278 } 279 setLongExif::Entry280 void setLong(unsigned int index, ExifLong value) const 281 { 282 #ifndef EXIF_NO_EXCEPTIONS 283 if(entry_->format != EXIF_FORMAT_LONG) 284 throw InvalidFormat( 285 "Exif::Entry::setLong(): Format is not EXIF_FORMAT_LONG"); 286 if(index >= components()) 287 throw InvalidIndex( 288 "Exif::setLong: component index out of range"); 289 #endif 290 return exif_set_long(entry_->data 291 + index * exif_format_get_size(entry_->format), 292 exif_data_get_byte_order(entry_->parent->parent), 293 value); 294 } 295 setSLongExif::Entry296 void setSLong(unsigned int index, ExifSLong value) const 297 { 298 #ifndef EXIF_NO_EXCEPTIONS 299 if(entry_->format != EXIF_FORMAT_SLONG) 300 throw InvalidFormat( 301 "Exif::Entry::setSLong(): Format is not EXIF_FORMAT_SLONG"); 302 if(index >= components()) 303 throw InvalidIndex( 304 "Exif::setSLong: component index out of range"); 305 #endif 306 return exif_set_slong(entry_->data 307 + index * exif_format_get_size(entry_->format), 308 exif_data_get_byte_order(entry_->parent->parent), 309 value); 310 } 311 setRationalExif::Entry312 void setRational(unsigned int index, ExifRational value) const 313 { 314 #ifndef EXIF_NO_EXCEPTIONS 315 if(entry_->format != EXIF_FORMAT_RATIONAL) 316 throw InvalidFormat( 317 "Exif::Entry::setRational(): Format is not EXIF_FORMAT_RATIONAL"); 318 if(index >= components()) 319 throw InvalidIndex( 320 "Exif::setRational: component index out of range"); 321 #endif 322 return exif_set_rational(entry_->data 323 + index * exif_format_get_size(entry_->format), 324 exif_data_get_byte_order(entry_->parent->parent), 325 value); 326 } 327 setSRationalExif::Entry328 void setSRational(unsigned int index, ExifSRational value) const 329 { 330 #ifndef EXIF_NO_EXCEPTIONS 331 if(entry_->format != EXIF_FORMAT_SRATIONAL) 332 throw InvalidFormat( 333 "Exif::Entry::setSRational(): Format is not EXIF_FORMAT_SRATIONAL"); 334 if(index >= components()) 335 throw InvalidIndex( 336 "Exif::setSRational: component index out of range"); 337 #endif 338 return exif_set_srational(entry_->data 339 + index * exif_format_get_size(entry_->format), 340 exif_data_get_byte_order(entry_->parent->parent), 341 value); 342 } 343 valueExif::Entry344 const char *value() 345 { 346 return exif_entry_get_value(entry_); 347 } 348 briefValueExif::Entry349 const char *briefValue() 350 { 351 return exif_entry_get_value_brief(entry_); 352 } 353 dumpExif::Entry354 void dump(unsigned int indent = 0) const 355 { 356 exif_entry_dump(entry_, indent); 357 } 358 }; 359 360 struct Content 361 { 362 ExifContent *content_; 363 ContentExif::Content364 Content() 365 : content_(exif_content_new()) 366 {} 367 ContentExif::Content368 Content(Content const &other) 369 : content_(other.content_) 370 { 371 exif_content_ref(content_); 372 } 373 374 // internal, do not use directly ContentExif::Content375 Content(ExifContent *content) 376 : content_(content) 377 { 378 exif_content_ref(content_); 379 } 380 ~ContentExif::Content381 ~Content() 382 { 383 exif_content_unref(content_); 384 } 385 operator =Exif::Content386 Content &operator=(Content const &other) 387 { 388 exif_content_unref(content_); 389 content_ = other.content_; 390 exif_content_ref(content_); 391 return *this; 392 } 393 operator []Exif::Content394 Entry operator[](ExifTag tag) 395 { 396 ExifEntry *result = exif_content_get_entry(content_, tag); 397 if(result) 398 return Entry(result); 399 #ifndef EXIF_NO_EXCEPTIONS 400 throw InvalidIndex( 401 "Exif::Content: IFD does not contain given tag"); 402 #endif 403 return Entry(); 404 } 405 operator []Exif::Content406 Entry operator[](unsigned int index) 407 { 408 if(index < size()) 409 return Entry(content_->entries[index]); 410 #ifndef EXIF_NO_EXCEPTIONS 411 throw InvalidIndex( 412 "Exif::Content: numeric entry index out of range"); 413 #endif // EXIF_NO_EXCEPTIONS 414 return Entry(); 415 } 416 sizeExif::Content417 unsigned int size() const 418 { 419 // FIXME: content_ should never be NULL, so this is unneeded!? 420 return content_ ? content_->count : 0; 421 } 422 addExif::Content423 void add(Entry &entry) 424 { 425 exif_content_add_entry(content_, entry.entry_); 426 } 427 removeExif::Content428 void remove(Entry &entry) 429 { 430 exif_content_remove_entry(content_, entry.entry_); 431 } 432 433 // for your convenience valueExif::Content434 const char *value(ExifTag tag) 435 { 436 return exif_content_get_value(content_, tag); 437 } 438 439 // for your convenience briefValueExif::Content440 const char *briefValue(ExifTag tag) 441 { 442 return exif_content_get_value_brief(content_, tag); 443 } 444 dumpExif::Content445 void dump(unsigned int indent = 0) const 446 { 447 exif_content_dump(content_, indent); 448 } 449 }; 450 451 struct Data 452 { 453 ExifData *data_; 454 DataExif::Data455 Data() 456 : data_(exif_data_new()) 457 {} 458 DataExif::Data459 Data(const char *path, bool *success = 0) 460 : data_(exif_data_new_from_file(path)) 461 { 462 if(success) 463 *success = data_; 464 #ifndef EXIF_NO_EXCEPTIONS 465 else 466 if(!data_) 467 throw IOError("Exif::Data: Could not load file"); 468 #endif // EXIF_NO_EXCEPTIONS 469 if(!data_) 470 exif_data_new(); 471 } 472 DataExif::Data473 Data(const unsigned char *data, 474 unsigned int size) 475 : data_(exif_data_new_from_data(data, size)) 476 {} 477 DataExif::Data478 Data(Data const &other) 479 : data_(other.data_) 480 { 481 exif_data_ref(data_); 482 } 483 ~DataExif::Data484 ~Data() 485 { 486 exif_data_unref(data_); 487 } 488 operator =Exif::Data489 Data &operator=(Data const &other) 490 { 491 exif_data_unref(data_); 492 data_ = other.data_; 493 exif_data_ref(data_); 494 return *this; 495 } 496 saveExif::Data497 void save(unsigned char **d, unsigned int *size) 498 { 499 exif_data_save_data(data_, d, size); 500 } 501 sizeExif::Data502 unsigned int size() const 503 { 504 return EXIF_IFD_COUNT; 505 } 506 operator []Exif::Data507 Content operator[](unsigned int index) 508 { 509 if(index < size()) 510 return Content(data_->ifd[index]); 511 #ifndef EXIF_NO_EXCEPTIONS 512 throw InvalidIndex( 513 "Exif::Data: IFD index out of range"); 514 #endif // EXIF_NO_EXCEPTIONS 515 return Content(); 516 } 517 byteOrderExif::Data518 ExifByteOrder byteOrder() const 519 { 520 return exif_data_get_byte_order(data_); 521 } 522 setByteOrderExif::Data523 void setByteOrder(ExifByteOrder bo) const 524 { 525 exif_data_set_byte_order(data_, bo); 526 } 527 dumpExif::Data528 void dump() 529 { 530 exif_data_dump(data_); 531 } 532 }; 533 534 } // namespace Exif 535 536 #endif // EXIF_HXX 537