You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
318 lines
9.5 KiB
318 lines
9.5 KiB
// ==========================================================
|
|
// 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 <iostream>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
|
|
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 << "<HTML>\n<BODY>\n<CENTER>\n";
|
|
ios << "<FONT FACE = \"Arial\">\n";
|
|
}
|
|
|
|
/**
|
|
Print a HTML footer
|
|
*/
|
|
void PrintHTMLFooter(iostream& ios) {
|
|
ios << "</CENTER>\n</FONT>\n</BODY>\n</HTML>\n";
|
|
}
|
|
|
|
/**
|
|
Print a table header
|
|
*/
|
|
void PrintTableHeader(iostream& ios, const char *title) {
|
|
ios << "<TABLE BORDER=\"1\">\n";
|
|
ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#CCCCCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
|
|
}
|
|
|
|
/**
|
|
Print a table section
|
|
*/
|
|
void PrintTableSection(iostream& ios, const char *title) {
|
|
ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#FFFFCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
|
|
ios << "<TR><TD><B>Tag name</B></TD><TD><B>Tag value</B></TD><TD><B>Description</B></TD></TR>";
|
|
}
|
|
|
|
/**
|
|
Print a table footer
|
|
*/
|
|
void PrintTableFooter(iostream& ios) {
|
|
ios << "</TABLE>\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 << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << FreeImage_GetTagDescription(tag) << "</TD></TR>\n";
|
|
} else {
|
|
ios << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << " " << "</TD></TR>\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 <input file name>\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;
|
|
}
|
|
|
|
|
|
|