// ========================================================== // Simple metadata reader // // Design and implementation by // - Hervé Drolon // // This file is part of FreeImage 3 // // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER // THIS DISCLAIMER. // // Use at own risk! // ========================================================== // // This example shows how to easily parse all metadata // contained in a JPEG, TIFF or PNG image. // Comments, Exif and IPTC/NAA metadata tags are written to a HTML file // for later reading, and Adobe XMP XML packets are written // in a file whose extension is '.xmp'. This file can be later // processed using a XML parser. // // Metadata functions showed in this sample : // FreeImage_GetMetadataCount, FreeImage_FindFirstMetadata, FreeImage_FindNextMetadata, // FreeImage_FindCloseMetadata, FreeImage_TagToString, FreeImage_GetMetadata // // ========================================================== #include #include #include using namespace std; #include "FreeImage.h" // ---------------------------------------------------------- /** Generic image loader @param lpszPathName Pointer to the full file name @param flag Optional load flag constant @return Returns the loaded dib if successful, returns NULL otherwise */ FIBITMAP* GenericLoader(const char* lpszPathName, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; // check the file signature and deduce its format // (the second argument is currently not used by FreeImage) fif = FreeImage_GetFileType(lpszPathName, 0); if(fif == FIF_UNKNOWN) { // no signature ? // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); } // check that the plugin has reading capabilities ... if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { // ok, let's load the file FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag); // unless a bad file format, we are done ! return dib; } return NULL; } /** Generic image writer @param dib Pointer to the dib to be saved @param lpszPathName Pointer to the full file name @param flag Optional save flag constant @return Returns true if successful, returns false otherwise */ bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) { FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; BOOL bSuccess = FALSE; if(dib) { // try to guess the file format from the file extension fif = FreeImage_GetFIFFromFilename(lpszPathName); if(fif != FIF_UNKNOWN ) { // check that the plugin has sufficient writing and export capabilities ... WORD bpp = FreeImage_GetBPP(dib); if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) { // ok, we can save the file bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag); // unless an abnormal bug, we are done ! } } } return (bSuccess == TRUE) ? true : false; } // ---------------------------------------------------------- /** FreeImage error handler @param fif Format / Plugin responsible for the error @param message Error message */ void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) { cout << "\n*** "; if(fif != FIF_UNKNOWN) { cout << FreeImage_GetFormatFromFIF(fif) << " Format\n"; } cout << message; cout << " ***\n"; } // ---------------------------------------------------------- /** Print a basic HTML header */ void PrintHTMLHeader(iostream& ios) { ios << "\n\n
\n"; ios << "\n"; } /** Print a HTML footer */ void PrintHTMLFooter(iostream& ios) { ios << "
\n\n\n\n"; } /** Print a table header */ void PrintTableHeader(iostream& ios, const char *title) { ios << "\n"; ios << "\n"; } /** Print a table section */ void PrintTableSection(iostream& ios, const char *title) { ios << "\n"; ios << ""; } /** Print a table footer */ void PrintTableFooter(iostream& ios) { ios << "
" << title << "
" << title << "
Tag nameTag valueDescription
\n"; } /** Print the metadata tags to a HTML file */ void PrintMetadata(iostream& ios, const char *sectionTitle, FIBITMAP *dib, FREE_IMAGE_MDMODEL model) { FITAG *tag = NULL; FIMETADATA *mdhandle = NULL; mdhandle = FreeImage_FindFirstMetadata(model, dib, &tag); if(mdhandle) { // Print a table section PrintTableSection(ios, sectionTitle); do { // convert the tag value to a string const char *value = FreeImage_TagToString(model, tag); // print the tag // note that most tags do not have a description, // especially when the metadata specifications are not available if(FreeImage_GetTagDescription(tag)) { ios << "" << FreeImage_GetTagKey(tag) << "" << value << "" << FreeImage_GetTagDescription(tag) << "\n"; } else { ios << "" << FreeImage_GetTagKey(tag) << "" << value << "" << " " << "\n"; } } while(FreeImage_FindNextMetadata(mdhandle, &tag)); } FreeImage_FindCloseMetadata(mdhandle); } int main(int argc, char *argv[]) { unsigned count; // call this ONLY when linking with FreeImage as a static library #ifdef FREEIMAGE_LIB FreeImage_Initialise(); #endif // FREEIMAGE_LIB // initialize your own FreeImage error handler FreeImage_SetOutputMessage(FreeImageErrorHandler); // print version & copyright infos cout << "FreeImage " << FreeImage_GetVersion() << "\n"; cout << FreeImage_GetCopyrightMessage() << "\n\n"; if(argc != 2) { cout << "Usage : ShowMetadata \n"; return 0; } // Load the bitmap FIBITMAP *dib = GenericLoader(argv[1], 0); if(!dib) return 0; // Create a HTML file std::string html_file(strtok(argv[1], ".") + std::string(".html")); fstream metadataFile(html_file.c_str(), ios::out); // Print the header PrintHTMLHeader(metadataFile); PrintTableHeader(metadataFile, argv[1]); // Parse and print metadata if(count = FreeImage_GetMetadataCount(FIMD_COMMENTS, dib)) { cout << "\nFIMD_COMMENTS (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "Comments", dib, FIMD_COMMENTS); } if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) { cout << "\nFIMD_EXIF_MAIN (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "Exif - main info", dib, FIMD_EXIF_MAIN); } if(count = FreeImage_GetMetadataCount(FIMD_EXIF_EXIF, dib)) { cout << "\nFIMD_EXIF_EXIF (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "Exif - advanced info", dib, FIMD_EXIF_EXIF); } if(count = FreeImage_GetMetadataCount(FIMD_EXIF_GPS, dib)) { cout << "\nFIMD_EXIF_GPS (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "Exif GPS", dib, FIMD_EXIF_GPS); } if(count = FreeImage_GetMetadataCount(FIMD_EXIF_INTEROP, dib)) { cout << "\nFIMD_EXIF_INTEROP (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "Exif interoperability", dib, FIMD_EXIF_INTEROP); } if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAKERNOTE, dib)) { cout << "\nFIMD_EXIF_MAKERNOTE (" << count << " data)\n-----------------------------------------\n"; // Get the camera model FITAG *tagMake = NULL; FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake); std::string buffer((char*)FreeImage_GetTagValue(tagMake)); buffer += " Makernote"; PrintMetadata(metadataFile, buffer.c_str(), dib, FIMD_EXIF_MAKERNOTE); } if(count = FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { cout << "\nFIMD_IPTC (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "IPTC/NAA", dib, FIMD_IPTC); } if(count = FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib)) { cout << "\nFIMD_GEOTIFF (" << count << " data)\n-----------------------------------------\n"; PrintMetadata(metadataFile, "GEOTIFF", dib, FIMD_GEOTIFF); } // Print the footer PrintTableFooter(metadataFile); PrintHTMLFooter(metadataFile); // close the HTML file metadataFile.close(); // print XMP data if(count = FreeImage_GetMetadataCount(FIMD_XMP, dib)) { cout << "\nFIMD_XMP (" << count << " packet)\n-----------------------------------------\n"; std::string xmp_file(strtok(argv[1], ".") + std::string(".xmp")); metadataFile.open(xmp_file.c_str(), ios::out); FITAG *tag = NULL; FreeImage_GetMetadata(FIMD_XMP, dib, "XMLPacket", &tag); if(tag) { metadataFile << (char*)FreeImage_GetTagValue(tag); } metadataFile.close(); } // Unload the bitmap FreeImage_Unload(dib); // call this ONLY when linking with FreeImage as a static library #ifdef FREEIMAGE_LIB FreeImage_DeInitialise(); #endif // FREEIMAGE_LIB return 0; }