bool TIFFOutput::write_exif_data () { #if defined(TIFF_VERSION_BIG) && TIFFLIB_VERSION >= 20120922 // Older versions of libtiff do not support writing Exif directories if (m_spec.get_int_attribute ("tiff:write_exif", 1) == 0) { // The special metadata "tiff:write_exif", if present and set to 0 // (the default is 1), will cause us to skip outputting Exif data. // This is useful in cases where we think the TIFF file will need to // be read by an app that links against an old version of libtiff // that will have trouble reading the Exif directory. return true; } // First, see if we have any Exif data at all bool any_exif = false; for (size_t i = 0, e = m_spec.extra_attribs.size(); i < e; ++i) { const ImageIOParameter &p (m_spec.extra_attribs[i]); int tag, tifftype, count; if (exif_tag_lookup (p.name(), tag, tifftype, count) && tifftype != TIFF_NOTYPE) { if (tag == EXIFTAG_SECURITYCLASSIFICATION || tag == EXIFTAG_IMAGEHISTORY || tag == EXIFTAG_ISOSPEEDRATINGS) continue; // libtiff doesn't understand these any_exif = true; break; } } if (! any_exif) return true; if (m_compression == COMPRESSION_JPEG) { // For reasons we don't understand, JPEG-compressed TIFF seems // to not output properly without a directory checkpoint here. TIFFCheckpointDirectory (m_tif); } // First, finish writing the current directory if (! TIFFWriteDirectory (m_tif)) { error ("failed TIFFWriteDirectory()"); return false; } // Create an Exif directory if (TIFFCreateEXIFDirectory (m_tif) != 0) { error ("failed TIFFCreateEXIFDirectory()"); return false; } for (size_t i = 0, e = m_spec.extra_attribs.size(); i < e; ++i) { const ImageIOParameter &p (m_spec.extra_attribs[i]); int tag, tifftype, count; if (exif_tag_lookup (p.name(), tag, tifftype, count) && tifftype != TIFF_NOTYPE) { if (tag == EXIFTAG_SECURITYCLASSIFICATION || tag == EXIFTAG_IMAGEHISTORY || tag == EXIFTAG_ISOSPEEDRATINGS) continue; // libtiff doesn't understand these bool ok = false; if (tifftype == TIFF_ASCII) { ok = TIFFSetField (m_tif, tag, *(char**)p.data()); } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && p.type() == TypeDesc::SHORT) { ok = TIFFSetField (m_tif, tag, (int)*(short *)p.data()); } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && p.type() == TypeDesc::INT) { ok = TIFFSetField (m_tif, tag, *(int *)p.data()); } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && p.type() == TypeDesc::FLOAT) { ok = TIFFSetField (m_tif, tag, *(float *)p.data()); } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && p.type() == TypeDesc::DOUBLE) { ok = TIFFSetField (m_tif, tag, *(double *)p.data()); } if (! ok) { // std::cout << "Unhandled EXIF " << p.name() << " " << p.type() << "\n"; } } } // Now write the directory of Exif data uint64 dir_offset = 0; if (! TIFFWriteCustomDirectory (m_tif, &dir_offset)) { error ("failed TIFFWriteCustomDirectory() of the Exif data"); return false; } // Go back to the first directory, and add the EXIFIFD pointer. // std::cout << "diffdir = " << tiffdir << "\n"; TIFFSetDirectory (m_tif, 0); TIFFSetField (m_tif, TIFFTAG_EXIFIFD, dir_offset); #endif return true; // all is ok }
bool TIFFOutput::write_exif_data () { #if defined(TIFF_VERSION_BIG) && TIFFLIB_VERSION >= 20120922 // Older versions of libtiff do not support writing Exif directories // First, see if we have any Exif data at all bool any_exif = false; for (size_t i = 0, e = m_spec.extra_attribs.size(); i < e; ++i) { const ImageIOParameter &p (m_spec.extra_attribs[i]); int tag, tifftype, count; if (exif_tag_lookup (p.name(), tag, tifftype, count) && tifftype != TIFF_NOTYPE) { if (tag == EXIFTAG_SECURITYCLASSIFICATION || tag == EXIFTAG_IMAGEHISTORY || tag == EXIFTAG_ISOSPEEDRATINGS) continue; // libtiff doesn't understand these any_exif = true; break; } } if (! any_exif) return true; // First, finish writing the current directory if (! TIFFWriteDirectory (m_tif)) { error ("failed TIFFWriteDirectory()"); return false; } // Create an Exif directory if (TIFFCreateEXIFDirectory (m_tif) != 0) { error ("failed TIFFCreateEXIFDirectory()"); return false; } for (size_t i = 0, e = m_spec.extra_attribs.size(); i < e; ++i) { const ImageIOParameter &p (m_spec.extra_attribs[i]); int tag, tifftype, count; if (exif_tag_lookup (p.name(), tag, tifftype, count) && tifftype != TIFF_NOTYPE) { if (tag == EXIFTAG_SECURITYCLASSIFICATION || tag == EXIFTAG_IMAGEHISTORY || tag == EXIFTAG_ISOSPEEDRATINGS) continue; // libtiff doesn't understand these bool ok = false; if (tifftype == TIFF_ASCII) { ok = TIFFSetField (m_tif, tag, *(char**)p.data()); } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && p.type() == TypeDesc::SHORT) { ok = TIFFSetField (m_tif, tag, (int)*(short *)p.data()); } else if ((tifftype == TIFF_SHORT || tifftype == TIFF_LONG) && p.type() == TypeDesc::INT) { ok = TIFFSetField (m_tif, tag, *(int *)p.data()); } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && p.type() == TypeDesc::FLOAT) { ok = TIFFSetField (m_tif, tag, *(float *)p.data()); } else if ((tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL) && p.type() == TypeDesc::DOUBLE) { ok = TIFFSetField (m_tif, tag, *(double *)p.data()); } if (! ok) { // std::cout << "Unhandled EXIF " << p.name() << " " << p.type() << "\n"; } } } // Now write the directory of Exif data uint64 dir_offset = 0; if (! TIFFWriteCustomDirectory (m_tif, &dir_offset)) { error ("failed TIFFWriteCustomDirectory() of the Exif data"); return false; } // Go back to the first directory, and add the EXIFIFD pointer. // std::cout << "diffdir = " << tiffdir << "\n"; TIFFSetDirectory (m_tif, 0); TIFFSetField (m_tif, TIFFTAG_EXIFIFD, dir_offset); #endif return true; // all is ok }