Project

General

Profile

Metadata XML?

Added by Mikayel Egibyan over 6 years ago

Hi,

I am curious if there is an automatic way to write the metadata (EXIF, XMP, IPTC) to XML?

Thanks in advance!
Mikayel


Replies (9)

RE: Metadata XML? - Added by Robin Mills over 6 years ago

Mikayel

Please take a look at samples/exifprint.cpp and exiv2json.cpp. exifprint formats to the terminal, exiv2json formats in JSON. It's a small job to write exiv2xml.cpp from these samples.

A more complex puzzle is "what XML schema should be used?". I'll leave you to decide what to do about that. If you write exiv2xml.cpp, please attach the code to this thread to help another user in the future.

I don't really want to add exif2xml to our samples directory as I don't believe it illustrates any new aspect of our API. I wrote and added exiv2json because I wanted to use JSON as the network data payload for a daemon/server program to be called exiv2d. The program exiv2d is part of the "cloud ready" project in 2013. However, exiv2d was not implemented due to lack of time. However exiv2json remains in the samples because it illustrates how to use the Jzon code which resides inside the exiv2 library.

Robin

RE: Metadata XML? - Added by Mikayel Egibyan over 6 years ago

Robin,

I don't think I have exiv2json in the downloaded source files. Is it added recently?

Mikayel

RE: Metadata XML? - Added by Robin Mills over 6 years ago

It's on the trunk and you'll need to build the trunk library to use it. It uses a very nice 2-file JSON library (Jzon. cpp/hpp) written be very clever Swedish Engineer. I don't remember much about this, I wrote it a couple years ago.

I attach a copy of exiv2json.cpp from the trunk to this issue.

RE: Metadata XML? - Added by Mikayel Egibyan over 6 years ago

Thanks!

Mikayel

RE: Metadata XML? - Added by Robin Mills over 6 years ago

I've written a program which I've call showkeys. It format Exif metadata as JSON or CSV or Wolfram or XML. Use at your own risk. I think I'd like to add it to samples. I'll add it, if you agree to join Team Exiv2 and support this little application.

// ***************************************************************** -*- C++ -*-
// showkeys.cpp, $Rev: 3090 $
// Sample program to print the Exif metadata of an image

#include <exiv2/exiv2.hpp>

#include <iostream>
#include <iomanip>
#include <cassert>
#include <string>

typedef std::map<std::string,int> format_t;
typedef format_t::const_iterator  format_i;
typedef enum  { wolf ,  csv , json , xml } format_e;

void syntax(const char* argv[],format_t& formats)
{
    std::cout << "Usage: " << argv[0] << " file format\nformats: ";
    int count = 0;
    for ( format_i i = formats.begin() ; i != formats.end() ; i++ ) {
        std::cout << ( count++ ? " | " : "") << i->first ;
    }
    std::cout << std::endl;
}

size_t formatInit(Exiv2::ExifData& exifData)
{
    size_t result = 0;
    for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifData.end() ; ++i) {
        result ++ ;
    }
    if ( result > 5 ) result = 5;
    return result ;
}

///////////////////////////////////////////////////////////////////////
std::string escapeCSV(Exiv2::ExifData::const_iterator it,bool bValue)
{
    std::string   result ;

    std::ostringstream os;
    if ( bValue ) os << it->value() ; else os << it->key() ;

    std::string s = os.str();
    for ( size_t i = 0 ;i < s.length() ; i ++ ) {
        if ( s[i] == ',' ) result += '\\';
        result += s[i];
    }

    return result ;
}

std::string formatCSV(Exiv2::ExifData& exifData)
{
    size_t count  = 0;
    size_t length = formatInit(exifData);
    std::ostringstream result;

    for (Exiv2::ExifData::const_iterator i = exifData.begin(); count++ < length; ++i) {
        result << escapeCSV(i,false) << (count != length ? ", " : "" ) ;
    }
    result << std::endl;

    count = 0;
    for (Exiv2::ExifData::const_iterator i = exifData.begin(); count++ < length ; ++i) {
        result << escapeCSV(i,true) << (count != length ? ", " : "" ) ;
    }
    return result.str();
}

///////////////////////////////////////////////////////////////////////
std::string formatWolf(Exiv2::ExifData& exifData)
{
    size_t count  = 0;
    size_t length = formatInit(exifData);
    std::ostringstream result;

    result << "{ " << std::endl;
    for (Exiv2::ExifData::const_iterator i = exifData.begin(); count++ < length ; ++i) {
        result << "  " << i->key()  << " -> " << i->value()  << (count != length ? "," : "" ) << std::endl ;
    }
    result << "}";
    return result.str();
}

///////////////////////////////////////////////////////////////////////
std::string escapeJSON(Exiv2::ExifData::const_iterator it,bool bValue=true)
{
    std::string   result ;

    std::ostringstream os;
    if ( bValue ) os << it->value() ; else os << it->key() ;

    std::string s = os.str();
    for ( size_t i = 0 ;i < s.length() ; i ++ ) {
        if ( s[i] == '"' ) result += "\\\"";
        result += s[i];
    }

    std::string q = "\"";
    return q + result + q ;
}

std::string formatJSON(Exiv2::ExifData& exifData)
{
    size_t count  = 0;
    size_t length = formatInit(exifData);
    std::ostringstream result;

    result << "{" << std::endl ;
    for (Exiv2::ExifData::const_iterator i = exifData.begin(); count++ < length ; ++i) {
        result << "  " << escapeJSON(i,false)  << ":" << escapeJSON(i,true) << ( count != length ? "," : "" ) << std::endl ;
    }
    result << "}";
    return result.str();
}

///////////////////////////////////////////////////////////////////////
std::string escapeXML(Exiv2::ExifData::const_iterator it,bool bValue=true)
{
    std::string   result ;

    std::ostringstream os;
    if ( bValue ) os << it->value() ; else os << it->key() ;

    std::string s = os.str();
    for ( size_t i = 0 ;i < s.length() ; i ++ ) {
        if ( s[i] == '<' ) result += "&lg;";
        if ( s[i] == '>' ) result += "&gt;";
        result += s[i];
    }

    return result ;
}

std::string formatXML(Exiv2::ExifData& exifData)
{
    size_t count  = 0;
    size_t length = formatInit(exifData);
    std::ostringstream result;

    result << "<exif>" << std::endl;
    for (Exiv2::ExifData::const_iterator i = exifData.begin(); count++ < length ; ++i) {
        std::string key   = escapeXML(i,false);
        std::string value = escapeXML(i,true);
        result << "  <" << key << ">" << value << "<" << key << "/>" << std::endl ;
    }
    result << "</exif>" << std::endl;
    return result.str();
}

///////////////////////////////////////////////////////////////////////
int main(int argc,const char* argv[])
{
    format_t formats;
    formats["wolf"] = wolf;
    formats["csv" ] = csv ;
    formats["json"] = json;
    formats["xml" ] = xml ;

    if (argc != 3) {
        syntax(argv,formats) ;
        return 1;
    }

    const char* file   = argv[1];
    const char* format = argv[2];

    if ( formats.find(format) == formats.end() ) {
        std::cout << "Unrecognised format " << format << std::endl;
        syntax(argv,formats);
        return 2;
    }

    bool bOpen = false ;
    try {
        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file);
        assert(image.get() != 0);
        image->readMetadata();
        bOpen = true ;

        std::ostringstream out;
        Exiv2::ExifData &exifData = image->exifData();
        switch ( formats.find(format)->second ) {
            case wolf : std::cout << formatWolf(exifData) << std::endl; break;
            case csv  : std::cout << formatCSV (exifData) << std::endl; break;
            case json : std::cout << formatJSON(exifData) << std::endl; break;
            case xml  : std::cout << formatXML (exifData) << std::endl; break;

            default   : std::cout << "*** error: format not implemented yet: " << format << " ***" << std::endl; break;
        }
    } catch ( ... ) {
        std::cout << "*** error ";
        if ( bOpen ) std::cout << "reading the metadata from: ";
        else         std::cout << "unable to open the file: ";
        std::cout << file << " ***" << std::endl;
        syntax(argv,formats);
    }

    return 0;
}

RE: Metadata XML? - Added by Mikayel Egibyan over 6 years ago

Robin,

Sorry for belated reply. I will support it.

Mikayel

RE: Metadata XML? - Added by Robin Mills over 6 years ago

That's wonderful, Mikayel. Thank you so much. I'm enthusiastic to work with you.

RE: Metadata XML? - Added by Robin Mills over 6 years ago

Right, Mikayel. Here's a challenge. If you make a good job of this, I'll ask Andreas to grant you write-access to our repository. For the moment, you'll have to post your code, or email it to me.

Update this program to use the magic in exiv2json to do two things:

1) Write deeply recursive JSON using the Jzon library that's in Exiv2/trunk.
2) And do the same for the XML. Here's the current output:

539 rmills@rmillsmbp:~/gnu/exiv2/trunk $ bin/exifdata ~/temp/Baby.jpg xml 
<exif>
  <Exif.Image.Orientation>1<Exif.Image.Orientation/>
  <Exif.Image.XResolution>720090/10000<Exif.Image.XResolution/>
  <Exif.Image.YResolution>720090/10000<Exif.Image.YResolution/>
  <Exif.Image.ResolutionUnit>2<Exif.Image.ResolutionUnit/>
  <Exif.Image.Software>Adobe Photoshop CS5 Windows<Exif.Image.Software/>
  <Exif.Image.DateTime>2012:01:04 20:34:45<Exif.Image.DateTime/>
  <Exif.Image.ExifTag>164<Exif.Image.ExifTag/>
  <Exif.Photo.ColorSpace>1<Exif.Photo.ColorSpace/>
  <Exif.Photo.PixelXDimension>1600<Exif.Photo.PixelXDimension/>
  <Exif.Photo.PixelYDimension>800<Exif.Photo.PixelYDimension/>
  <Exif.Thumbnail.Compression>6<Exif.Thumbnail.Compression/>
  <Exif.Thumbnail.XResolution>72/1<Exif.Thumbnail.XResolution/>
  <Exif.Thumbnail.YResolution>72/1<Exif.Thumbnail.YResolution/>
  <Exif.Thumbnail.ResolutionUnit>2<Exif.Thumbnail.ResolutionUnit/>
  <Exif.Thumbnail.JPEGInterchangeFormat>302<Exif.Thumbnail.JPEGInterchangeFormat/>
  <Exif.Thumbnail.JPEGInterchangeFormatLength>3586<Exif.Thumbnail.JPEGInterchangeFormatLength/>
</exif>

540 rmills@rmillsmbp:~/gnu/exiv2/trunk $
And I'd like it to look like this:
539 rmills@rmillsmbp:~/gnu/exiv2/trunk $ bin/exifdata ~/temp/Baby.jpg xml 
<exif>
  <Exif>
    <Image>
      <Orientation>1</Orientation>
      <XResolution>720090/10000</XResolution>
      <YResolution>720090/10000</YResolution>
      <ResolutionUnit>2</ResolutionUnit>
      <Software>Adobe Photoshop CS5 Windows</Software>
      <DateTime>2012:01:04 20:34:45</DateTime>
      <ExifTag>164</ExifTag>
    </Image>
    <Photo>
      <ColorSpace>1<ColorSpace>
      <PixelXDimension>1600</PixelXDimension>
      <PixelYDimension>800</PixelYDimension>
    </Photo>
    <Thumbnail>
      <Compression>6</Compression>
      <XResolution>72/1</XResolution>
      <YResolution>72/1<YResolution>
      <ResolutionUnit>2</ResolutionUnit>
      <JPEGInterchangeFormat>302</ExifJPEGInterchangeFormat>
      <JPEGInterchangeFormatLength>3586</JPEGInterchangeFormatLength>
    </Thumbnail>
  </Exif>
</exif>
540 rmills@rmillsmbp:~/gnu/exiv2/trunk $ 

RE: Metadata XML? - Added by Robin Mills over 6 years ago

Com'on Mikayel. I always have the courtesy to reply quickly to you (not to mention doing lots of unpaid work). What are you thinking about this task?

    (1-9/9)