diff --git a/doc/exiv2.dot b/doc/exiv2.dot index dd174ccb..4c60f8cd 100644 --- a/doc/exiv2.dot +++ b/doc/exiv2.dot @@ -3,52 +3,64 @@ # Version : $Rev$ # Author(s): Andreas Huggel (ahu) # History : 18-Feb-04, ahu: created +# 19-Mar-05, ahu: updated after inside-out change # # Description: -# Dot file for a graph showing the component dependencies of the -# Exiv2 library. Run the following command to get the image: +# Dot file for a graph showing the component dependencies ("uses in the +# interface") of the Exiv2 library. +# Run the following command to get the image: # $ dot -Tgif -oexiv2.gif exiv2.dot ################################################################################ -digraph G { +digraph "Exiv2 component dependencies" { -L1 [shape=plaintext] ; -L2 [shape=plaintext] ; -L3 [shape=plaintext] ; -L4 [shape=plaintext] ; -L5 [shape=plaintext] ; + L1 [shape=plaintext] ; + L2 [shape=plaintext] ; + L3 [shape=plaintext] ; + L4 [shape=plaintext] ; + L5 [shape=plaintext] ; + L6 [shape=plaintext] ; -"L5" -> "L4" -> "L3" -> "L2" -> "L1" [style=invis] ; + "L6" -> "L5" -> "L4" -> "L3" -> "L2" -> "L1" [style=invis] ; -"exif" [shape=box] ; -"iptc" [shape=box] ; -"metadatum" [shape=box] ; -"ifd" [shape=box] ; -"image" [shape=box] ; -"tags" [shape=box] ; -"datasets" [shape=box] ; -"value" [shape=box] ; -"types" [shape=box] ; -"error" [shape=box] ; -"makernote" [shape=box] ; + "exif" [shape=box] ; + "iptc" [shape=box] ; + "metadatum" [shape=box] ; + "ifd" [shape=box] ; + "image" [shape=box] ; + "tags" [shape=box] ; + "datasets" [shape=box] ; + "value" [shape=box] ; + "types" [shape=box] ; + "error" [shape=box] ; + "makernote" [shape=box] ; + "basicio" [shape=box] ; + "*mn" [shape=box] ; + "jpgimage" [shape=box] ; -"exif" -> "tags" ; -"exif" -> "makernote" ; -"exif" -> "image" ; -"iptc" -> "datasets" ; -"iptc" -> "image" ; -"metadatum" -> "value" ; -"metadatum" -> "error" ; -"makernote" -> "ifd" ; -"makernote" -> "value" ; -"ifd" -> "error" ; -"ifd" -> "types" ; -"image" -> "types" ; -"tags" -> "metadatum"; -"datasets" -> "metadatum" ; -"value" -> "types" ; + clusterrank="local"; + "basicio" -> "error" + "basicio" -> "types" + "*mn" -> "makernote" + "*mn" -> "tags" + "datasets" -> "metadatum" + "exif" -> "ifd" + "exif" -> "tags" + "exif" -> "error" + "ifd" -> "types" + "image" -> "basicio" + "iptc" -> "datasets" + "iptc" -> "error" + "jpgimage" -> "exif" + "jpgimage" -> "image" + "jpgimage" -> "iptc" + "makernote" -> "ifd" + "metadatum" -> "value" + "tags" -> "metadatum" + "value" -> "types" -{ rank=same; L1 error types } -{ rank=same; L2 image value ifd } + { rank=same; L1 "types" } + { rank=same; L2 "value" "ifd" } + { rank=same; L5 "image" "iptc" } } diff --git a/doc/exiv2.gif b/doc/exiv2.gif index 8549f803..f3bf7c03 100644 Binary files a/doc/exiv2.gif and b/doc/exiv2.gif differ diff --git a/src/exif.cpp b/src/exif.cpp index 6fb69878..b0d2072c 100644 --- a/src/exif.cpp +++ b/src/exif.cpp @@ -308,14 +308,14 @@ namespace Exiv2 { ExifData::ExifData() : pTiffHeader_(0), pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), - size_(0), pData_(0), compatible_(true) + pMakerNote_(0), size_(0), pData_(0), compatible_(true) { } ExifData::ExifData(const ExifData& rhs) : exifMetadata_(rhs.exifMetadata_), pTiffHeader_(0), pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), - size_(0), pData_(0), compatible_(rhs.compatible_) + pMakerNote_(0), size_(0), pData_(0), compatible_(rhs.compatible_) { pData_ = new byte[rhs.size_]; size_ = rhs.size_; @@ -324,10 +324,6 @@ namespace Exiv2 { if (rhs.pTiffHeader_) { pTiffHeader_ = new TiffHeader(*rhs.pTiffHeader_); } - if (rhs.makerNote_.get() != 0) { - makerNote_ = rhs.makerNote_->clone(); - makerNote_->updateBase(pData_); - } if (rhs.pIfd0_) { pIfd0_ = new Ifd(*rhs.pIfd0_); pIfd0_->updateBase(pData_); @@ -348,6 +344,10 @@ namespace Exiv2 { pIfd1_ = new Ifd(*rhs.pIfd1_); pIfd1_->updateBase(pData_); } + if (rhs.pMakerNote_) { + pMakerNote_ = rhs.pMakerNote_->clone().release(); + pMakerNote_->updateBase(pData_); + } } ExifData::~ExifData() @@ -358,6 +358,7 @@ namespace Exiv2 { delete pIopIfd_; delete pGpsIfd_; delete pIfd1_; + delete pMakerNote_; delete[] pData_; } @@ -378,13 +379,6 @@ namespace Exiv2 { if (rhs.pTiffHeader_) { pTiffHeader_ = new TiffHeader(*rhs.pTiffHeader_); } - - makerNote_.reset(); - if (rhs.makerNote_.get() != 0) { - makerNote_ = rhs.makerNote_->clone(); - makerNote_->updateBase(pData_); - } - delete pIfd0_; pIfd0_ = 0; if (rhs.pIfd0_) { @@ -415,6 +409,12 @@ namespace Exiv2 { pIfd1_ = new Ifd(*rhs.pIfd1_); pIfd1_->updateBase(pData_); } + delete pMakerNote_; + pMakerNote_ = 0; + if (rhs.pMakerNote_) { + pMakerNote_ = rhs.pMakerNote_->clone().release(); + pMakerNote_->updateBase(pData_); + } compatible_ = rhs.compatible_; return *this; @@ -471,30 +471,31 @@ namespace Exiv2 { MakerNoteFactory& mnf = MakerNoteFactory::instance(); // Todo: The conversion to string assumes that there is a \0 at the end // Todo: How to avoid the cast (is that a MSVC thing?) - makerNote_ = mnf.create(reinterpret_cast(make->data()), - reinterpret_cast(model->data()), - false, - pos->data(), - pos->size(), - byteOrder(), - pExifIfd_->offset() + pos->offset()); + pMakerNote_ = mnf.create(reinterpret_cast(make->data()), + reinterpret_cast(model->data()), + false, + pos->data(), + pos->size(), + byteOrder(), + pExifIfd_->offset() + pos->offset()).release(); } // Read the MakerNote - if (makerNote_.get() != 0) { - rc = makerNote_->read(pos->data(), - pos->size(), - byteOrder(), - pExifIfd_->offset() + pos->offset()); + if (pMakerNote_) { + rc = pMakerNote_->read(pos->data(), + pos->size(), + byteOrder(), + pExifIfd_->offset() + pos->offset()); if (rc) { // Todo: How to handle debug output like this std::cerr << "Warning: Failed to read Makernote, rc = " << rc << "\n"; - makerNote_.reset(); + delete pMakerNote_; + pMakerNote_ = 0; } } // If we successfully parsed the MakerNote, delete the raw MakerNote, // the parsed MakerNote is the primary MakerNote from now on - if (makerNote_.get() != 0) { + if (pMakerNote_) { pExifIfd_->erase(pos); } @@ -539,8 +540,8 @@ namespace Exiv2 { exifMetadata_.clear(); add(pIfd0_->begin(), pIfd0_->end(), byteOrder()); add(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); - if (makerNote_.get() != 0) { - add(makerNote_->begin(), makerNote_->end(), makerNote_->byteOrder()); + if (pMakerNote_) { + add(pMakerNote_->begin(), pMakerNote_->end(), pMakerNote_->byteOrder()); } add(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); add(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); @@ -585,12 +586,12 @@ namespace Exiv2 { Ifd exifIfd(exifIfdId); addToIfd(exifIfd, begin(), end(), byteOrder()); MakerNote::AutoPtr makerNote; - if (makerNote_.get() != 0) { + if (pMakerNote_) { // Build MakerNote from metadata - makerNote = makerNote_->create(); + makerNote = pMakerNote_->create(); addToMakerNote(makerNote.get(), begin(), end(), - makerNote_->byteOrder()); + pMakerNote_->byteOrder()); // Create a placeholder MakerNote entry of the correct size and // add it to the Exif IFD (because we don't know the offset yet) Entry e; @@ -722,9 +723,9 @@ namespace Exiv2 { void ExifData::add(const Exifdatum& exifdatum) { if (ExifTags::isMakerIfd(exifdatum.ifdId())) { - if (makerNote_.get() == 0) { + if (pMakerNote_ == 0) { MakerNoteFactory& mnf = MakerNoteFactory::instance(); - makerNote_ = mnf.create(exifdatum.ifdId()); + pMakerNote_ = mnf.create(exifdatum.ifdId()).release(); } } // allow duplicates @@ -852,9 +853,9 @@ namespace Exiv2 { maxOffset = std::max(maxOffset, pExifIfd_->offset()); maxOffset = std::max(maxOffset, pExifIfd_->dataOffset() + pExifIfd_->dataSize()); - if (makerNote_.get() != 0) { - maxOffset = std::max(maxOffset, makerNote_->offset() - + makerNote_->size()); + if (pMakerNote_) { + maxOffset = std::max(maxOffset, pMakerNote_->offset() + + pMakerNote_->size()); } maxOffset = std::max(maxOffset, pIopIfd_->offset()); maxOffset = std::max(maxOffset, pIopIfd_->dataOffset() @@ -954,10 +955,10 @@ namespace Exiv2 { bool compatible = true; compatible &= updateRange(pIfd0_->begin(), pIfd0_->end(), byteOrder()); compatible &= updateRange(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); - if (makerNote_.get() != 0) { - compatible &= updateRange(makerNote_->begin(), - makerNote_->end(), - makerNote_->byteOrder()); + if (pMakerNote_) { + compatible &= updateRange(pMakerNote_->begin(), + pMakerNote_->end(), + pMakerNote_->byteOrder()); } compatible &= updateRange(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); compatible &= updateRange(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); @@ -1046,9 +1047,9 @@ namespace Exiv2 { Entries::const_iterator entry; std::pair rc(false, entry); - if (ExifTags::isMakerIfd(ifdId) && makerNote_.get() != 0) { - entry = makerNote_->findIdx(idx); - if (entry != makerNote_->end()) { + if (ExifTags::isMakerIfd(ifdId) && pMakerNote_) { + entry = pMakerNote_->findIdx(idx); + if (entry != pMakerNote_->end()) { rc.first = true; rc.second = entry; } diff --git a/src/exif.hpp b/src/exif.hpp index 0043bc87..3ba55729 100644 --- a/src/exif.hpp +++ b/src/exif.hpp @@ -838,14 +838,15 @@ namespace Exiv2 { // DATA ExifMetadata exifMetadata_; + // The pointers below are used only if Exif data is read from a + // raw data buffer TiffHeader* pTiffHeader_; //! Pointer to the TIFF header - //! Pointer to the MakerNote - std::auto_ptr makerNote_; Ifd* pIfd0_; //! Pointer to Ifd0 Ifd* pExifIfd_; //! Pointer to ExifIfd Ifd* pIopIfd_; //! Pointer to IopIfd Ifd* pGpsIfd_; //! Pointer to GpsIfd Ifd* pIfd1_; //! Pointer to Ifd1 + MakerNote* pMakerNote_; //! Pointer to the MakerNote, if any long size_; //!< Size of the Exif raw data in bytes byte* pData_; //!< Exif raw data buffer diff --git a/test/data/write-test-debug.out b/test/data/write-test-debug.out new file mode 100644 index 00000000..73a14e8e --- /dev/null +++ b/test/data/write-test-debug.out @@ -0,0 +1,188 @@ +------------------------------------------------------------ +Case 1: Non-intrusive change to the standard Exif metadata +---> Reading file ./exiv2-canon-powershot-s40.jpg +---> Modifying Exif data +---> Writing Exif data to file test1.jpg +->>>>>> using non-intrusive writing <<<<<<- +---> Reading file test1.jpg +---> Writing Exif thumbnail to file thumb1.* +13c13 +< Exif.Photo.DateTimeOriginal 0x9003 2003:12:14 12:01:44 +--- +> Exif.Photo.DateTimeOriginal 0x9003 1999:11:22 00:11:22 +------------------------------------------------------------ +Case 2: Non-intrusive change to the makernote metadata +---> Reading file ./exiv2-canon-powershot-s40.jpg +---> Modifying Exif data +---> Writing Exif data to file test2.jpg +->>>>>> using non-intrusive writing <<<<<<- +---> Reading file test2.jpg +---> Writing Exif thumbnail to file thumb2.* +49c49 +< Exif.Canon.OwnerName 0x0009 Andreas Huggel +--- +> Exif.Canon.OwnerName 0x0009 Chan YeeSend +------------------------------------------------------------ +Case 3: Non-intrusive change to the Exif metadata (w/o makernote) +---> Reading file ./exiv2-kodak-dc210.jpg +---> Modifying Exif data +---> Writing Exif data to file test3.jpg +->>>>>> using non-intrusive writing <<<<<<- +---> Reading file test3.jpg +---> Writing Exif thumbnail to file thumb3.* +14c14 +< Exif.Photo.DateTimeOriginal 0x9003 2000:10:26 16:46:51 +--- +> Exif.Photo.DateTimeOriginal 0x9003 1999:11:22 00:11:22 +------------------------------------------------------------ +Case 4: Intrusive change to the standard Exif metadata +---> Reading file ./exiv2-canon-powershot-s40.jpg +---> Modifying Exif data +---> Writing Exif data to file test4.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test4.jpg +---> Writing Exif thumbnail to file thumb4.* +9c9 +< Exif.Image.ExifTag 0x8769 196 +--- +> Exif.Image.ExifTag 0x8769 184 +13c13 +< Exif.Photo.DateTimeOriginal 0x9003 2003:12:14 12:01:44 +--- +> Exif.Photo.DateTimeOriginal 0x9003 1999:11:22 00:11:22 and twenty seconds +29c29 +< Exif.Photo.InteroperabilityTag 0xa005 1416 +--- +> Exif.Photo.InteroperabilityTag 0xa005 1423 +------------------------------------------------------------ +Case 5: Intrusive change to the Canon makernote metadata +---> Reading file ./exiv2-canon-powershot-s40.jpg +---> Modifying Exif data +---> Writing Exif data to file test5.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test5.jpg +---> Writing Exif thumbnail to file thumb5.* +9c9 +< Exif.Image.ExifTag 0x8769 196 +--- +> Exif.Image.ExifTag 0x8769 184 +29c29 +< Exif.Photo.InteroperabilityTag 0xa005 1416 +--- +> Exif.Photo.InteroperabilityTag 0xa005 1414 +49c49 +< Exif.Canon.OwnerName 0x0009 Andreas Huggel +--- +> Exif.Canon.OwnerName 0x0009 Frau Chan YeeSend und Herr Andreas Huggel +------------------------------------------------------------ +Case 6: Intrusive change to the Exif metadata (w/o makernote) +---> Reading file ./exiv2-kodak-dc210.jpg +---> Modifying Exif data +---> Writing Exif data to file test6.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test6.jpg +---> Writing Exif thumbnail to file thumb6.* +10c10 +< Exif.Image.ExifTag 0x8769 374 +--- +> Exif.Image.ExifTag 0x8769 192 +14c14 +< Exif.Photo.DateTimeOriginal 0x9003 2000:10:26 16:46:51 +--- +> Exif.Photo.DateTimeOriginal 0x9003 1999:11:22 00:11:22 and twenty seconds +------------------------------------------------------------ +Case 7: Intrusive change to the Fujifilm makernote metadata +---> Reading file ./exiv2-fujifilm-finepix-s2pro.jpg +---> Modifying Exif data +---> Writing Exif data to file test7.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test7.jpg +---> Writing Exif thumbnail to file thumb7.* +11c11 +< Exif.Image.ExifTag 0x8769 248 +--- +> Exif.Image.ExifTag 0x8769 245 +33c33 +< Exif.Photo.InteroperabilityTag 0xa005 1056 +--- +> Exif.Photo.InteroperabilityTag 0xa005 1070 +50c50 +< Exif.Fujifilm.Quality 0x1000 NORMAL +--- +> Exif.Fujifilm.Quality 0x1000 Typical Fujifilm Quality +------------------------------------------------------------ +Case 8: Intrusive change to the Sigma makernote metadata +---> Reading file ./exiv2-sigma-d10.jpg +---> Modifying Exif data +---> Writing Exif data to file test8.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test8.jpg +---> Writing Exif thumbnail to file thumb8.* +10c10 +< Exif.Image.ExifTag 0x8769 12317 +--- +> Exif.Image.ExifTag 0x8769 213 +38c38 +< Exif.Sigma.ResolutionMode 0x0004 HI +--- +> Exif.Sigma.ResolutionMode 0x0004 Sigma HI resolution +------------------------------------------------------------ +Case 9: Intrusive change to the Nikon1 makernote metadata +---> Reading file ./exiv2-nikon-e990.jpg +---> Modifying Exif data +---> Writing Exif data to file test9.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test9.jpg +---> Writing Exif thumbnail to file thumb9.* +11c11 +< Exif.Image.ExifTag 0x8769 284 +--- +> Exif.Image.ExifTag 0x8769 213 +32c32 +< Exif.Photo.InteroperabilityTag 0xa005 886 +--- +> Exif.Photo.InteroperabilityTag 0xa005 1214 +38c38 +< Exif.Nikon1.Quality 0x0004 FINE +--- +> Exif.Nikon1.Quality 0x0004 Typical Nikon1 Quality +------------------------------------------------------------ +Case 10: Intrusive change to the Nikon2 makernote metadata +---> Reading file ./exiv2-nikon-e950.jpg +---> Modifying Exif data +---> Writing Exif data to file test10.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test10.jpg +---> Writing Exif thumbnail to file thumb10.* +11c11 +< Exif.Image.ExifTag 0x8769 284 +--- +> Exif.Image.ExifTag 0x8769 212 +32c32 +< Exif.Photo.InteroperabilityTag 0xa005 886 +--- +> Exif.Photo.InteroperabilityTag 0xa005 1038 +35c35 +< Exif.Nikon2.0x0002 0x0002 08.00 +--- +> Exif.Nikon2.0x0002 0x0002 Nikon2 Version 2 +------------------------------------------------------------ +Case 11: Intrusive change to the Nikon3 makernote metadata +---> Reading file ./exiv2-nikon-d70.jpg +---> Modifying Exif data +---> Writing Exif data to file test11.jpg +->>>>>> writing from metadata <<<<<<- +---> Reading file test11.jpg +---> Writing Exif thumbnail to file thumb11.* +13c13 +< Exif.Image.ExifTag 0x8769 340 +--- +> Exif.Image.ExifTag 0x8769 332 +36c36 +< Exif.Photo.InteroperabilityTag 0xa005 30306 +--- +> Exif.Photo.InteroperabilityTag 0xa005 2402 +55c55 +< Exif.Nikon3.Quality 0x0004 FINE +--- +> Exif.Nikon3.Quality 0x0004 Typical Nikon3 Quality diff --git a/test/data/write-test.out b/test/data/write-test.out index 73a14e8e..4804a2d2 100644 --- a/test/data/write-test.out +++ b/test/data/write-test.out @@ -3,7 +3,6 @@ Case 1: Non-intrusive change to the standard Exif metadata ---> Reading file ./exiv2-canon-powershot-s40.jpg ---> Modifying Exif data ---> Writing Exif data to file test1.jpg -->>>>>> using non-intrusive writing <<<<<<- ---> Reading file test1.jpg ---> Writing Exif thumbnail to file thumb1.* 13c13 @@ -15,7 +14,6 @@ Case 2: Non-intrusive change to the makernote metadata ---> Reading file ./exiv2-canon-powershot-s40.jpg ---> Modifying Exif data ---> Writing Exif data to file test2.jpg -->>>>>> using non-intrusive writing <<<<<<- ---> Reading file test2.jpg ---> Writing Exif thumbnail to file thumb2.* 49c49 @@ -27,7 +25,6 @@ Case 3: Non-intrusive change to the Exif metadata (w/o makernote) ---> Reading file ./exiv2-kodak-dc210.jpg ---> Modifying Exif data ---> Writing Exif data to file test3.jpg -->>>>>> using non-intrusive writing <<<<<<- ---> Reading file test3.jpg ---> Writing Exif thumbnail to file thumb3.* 14c14 @@ -39,7 +36,6 @@ Case 4: Intrusive change to the standard Exif metadata ---> Reading file ./exiv2-canon-powershot-s40.jpg ---> Modifying Exif data ---> Writing Exif data to file test4.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test4.jpg ---> Writing Exif thumbnail to file thumb4.* 9c9 @@ -59,7 +55,6 @@ Case 5: Intrusive change to the Canon makernote metadata ---> Reading file ./exiv2-canon-powershot-s40.jpg ---> Modifying Exif data ---> Writing Exif data to file test5.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test5.jpg ---> Writing Exif thumbnail to file thumb5.* 9c9 @@ -79,7 +74,6 @@ Case 6: Intrusive change to the Exif metadata (w/o makernote) ---> Reading file ./exiv2-kodak-dc210.jpg ---> Modifying Exif data ---> Writing Exif data to file test6.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test6.jpg ---> Writing Exif thumbnail to file thumb6.* 10c10 @@ -95,7 +89,6 @@ Case 7: Intrusive change to the Fujifilm makernote metadata ---> Reading file ./exiv2-fujifilm-finepix-s2pro.jpg ---> Modifying Exif data ---> Writing Exif data to file test7.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test7.jpg ---> Writing Exif thumbnail to file thumb7.* 11c11 @@ -115,7 +108,6 @@ Case 8: Intrusive change to the Sigma makernote metadata ---> Reading file ./exiv2-sigma-d10.jpg ---> Modifying Exif data ---> Writing Exif data to file test8.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test8.jpg ---> Writing Exif thumbnail to file thumb8.* 10c10 @@ -131,7 +123,6 @@ Case 9: Intrusive change to the Nikon1 makernote metadata ---> Reading file ./exiv2-nikon-e990.jpg ---> Modifying Exif data ---> Writing Exif data to file test9.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test9.jpg ---> Writing Exif thumbnail to file thumb9.* 11c11 @@ -151,7 +142,6 @@ Case 10: Intrusive change to the Nikon2 makernote metadata ---> Reading file ./exiv2-nikon-e950.jpg ---> Modifying Exif data ---> Writing Exif data to file test10.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test10.jpg ---> Writing Exif thumbnail to file thumb10.* 11c11 @@ -171,7 +161,6 @@ Case 11: Intrusive change to the Nikon3 makernote metadata ---> Reading file ./exiv2-nikon-d70.jpg ---> Modifying Exif data ---> Writing Exif data to file test11.jpg -->>>>>> writing from metadata <<<<<<- ---> Reading file test11.jpg ---> Writing Exif thumbnail to file thumb11.* 13c13