Guidance about serialising metadata using MemIo and ExvImage Classes

This article has been written to service #1183. Please see application samples/toexv.cpp which has three modes of behaviour:

Mode Command syntax
Read an image
serialize the metadata to a .exv file
$ bin/toexv test/data/Reagan.jpg foo.exv
Read an image
serialise the metadata into memory
$ bin/toexv test/data/Reagan.jpg -
Read an image
serialise the metadata into memory
deserialise back to an image
$ bin/toexv test/data/Reagan.jpg +

About .exv files

A .exv file is a JPEG formatted file which has no graphics. It is supported by exiv2 and exiftool. The following is a typical JPEG being examined with the option -pS (print Structure):

~/gnu/exiv2/ttt $ exiv2 -pS test/data/Reagan.jpg
STRUCTURE OF JPEG FILE: test/data/Reagan.jpg
 address | marker     | length  | data
       2 | 0xd8 SOI   |       0 
       4 | 0xe0 APP0  |      16 | JFIF.....,.,....
      22 | 0xe1 APP1  |    5671 | Exif..MM.*......................
    5695 | 0xed APP13 |    9594 | Photoshop 3.0.8BIM..........Z...
   15291 | 0xe1 APP1  |    7062 | http://ns.adobe.com/xap/1.0/.<?x
   22355 | 0xe2 APP2  |    3160 | ICC_PROFILE......HLino....mntrRG
   25517 | 0xee APP14 |      14 | Adobe.d@......
   25533 | 0xdb DQT   |     132 
   25667 | 0xc0 SOF0  |      17 
   25686 | 0xdd DRI   |       4 
   25692 | 0xc4 DHT   |     418 
   26112 | 0xda SOS   |      12 
~/gnu/exiv2/ttt $ 
The Exif metadata is stored in the APP1/Exif segment, XMP in APP1/http..xap segment, IPTC in APP13/Photoshop, ICC in APP2/ICC_PROFILE
~/gnu/exiv2/ttt $ bin/toexv test/data/Reagan.jpg foo.exv ; ls -alt foo.exv ; exiv2 -pS foo.exv 
foo.exv 13655
-rw-r--r--+ 1 rmills  staff  13655 11 May 09:16 foo.exv
STRUCTURE OF JPEG FILE: foo.exv
 address | marker     | length  | data
       2 | 0x01       |       0 
       9 | 0xe1 APP1  |    5658 | Exif..II*......................
    5669 | 0xe1 APP1  |    7024 | http://ns.adobe.com/xap/1.0/.<?x
   12695 | 0xed APP13 |     958 | Photoshop 3.0.8BIM..........Z...
   13655 | 0xd9 EOI  
~/gnu/exiv2/ttt $ 
The metadata has been preserved. There is no image data. The .exv file is small. You can investigate the data within the metadata structures using option -pR (printRecursive). For example:
~/gnu/exiv2/ttt $ exiv2 -pR foo.exv 
STRUCTURE OF JPEG FILE: foo.exv
 address | marker     | length  | data
       2 | 0x01       |       0 
       9 | 0xe1 APP1  |    5658 | Exif..II*......................
  STRUCTURE OF TIFF FILE (II): MemIo
   address |    tag                           |      type |    count |    offset | value
        10 | 0x0100 ImageWidth                |     SHORT |        1 |       200 | 200
        22 | 0x0101 ImageLength               |     SHORT |        1 |       130 | 130
       ...
       202 | 0x8769 ExifTag                   |      LONG |        1 |       780 | 780
    STRUCTURE OF TIFF FILE (II): MemIo
     address |    tag                           |      type |    count |    offset | value
         782 | 0x829a ExposureTime              |  RATIONAL |        1 |      1218 | 1218/0
         794 | 0x829d FNumber                   |  RATIONAL |        1 |      1226 | 1226/0
       ...
        1202 | 0xa420 ImageUniqueID             |     ASCII |       33 |      1314 | 127c ...
    END MemIo
       214 | 0x8825 GPSTag                    |      LONG |        1 |      1348 | 1348
       ...
      1428 | 0x0202 JPEGInterchangeFormatLeng |      LONG |        1 |      4189 | 4189
  END MemIo
    5669 | 0xe1 APP1  |    7024 | http://ns.adobe.com/xap/1.0/.<?x
   12695 | 0xed APP13 |     958 | Photoshop 3.0.8BIM..........Z...
  Record | DataSet | Name                     | Length | Data
       1 |      90 | CharacterSet             |      3 | .%G
       ...
       2 |      63 | DigitizationTime         |     11 | 233753-0400
   13655 | 0xd9 EOI
~/gnu/exiv2/ttt $ 

About BasicIo and Image Abstract Classes

Exiv2 has two base classes for IO and Image processing.

BasicIo is an abstract class for performing IO. It includes methods to open/read/write/close files. Concrete classes are derived for FileIo which are implemented using the Standard C FILE structure and functions. MemIo stores the data in memory. Classes are derived from RemoteIo to perform I/O using remote protocols such as HTTP, FTP and SSH.

Image is an abstract class to represent an image. It includes methods readMetadata() and writeMetadata() which actually read and write files. The metadata is represented by STL structures. Exiv2 has concrete classes for JpegImage, TiffImage, PngImage, ExvImage and other formats.

Selectively copying metadata

The Image abstract class provides the API to copy metadata. The catch all is image->setMetadata();. More control is provided with image->setXxxData(); methods which are demonstrated in samples/toexv.cpp:

void Params::copyMetadata(Exiv2::Image::AutoPtr& readImage,Exiv2::Image::AutoPtr& writeImage)
{
    if (all_    ) writeImage->setMetadata  (*readImage);
    if (iptc_   ) writeImage->setIptcData  ( readImage->iptcData());
    if (exif_   ) writeImage->setExifData  ( readImage->exifData());
    if (ICC_    ) writeImage->setIccProfile(*readImage->iccProfile());
    if (comment_) writeImage->setComment   ( readImage->comment());
    if (xmp_    ) writeImage->setXmpData   ( readImage->xmpData());

    writeImage->writeMetadata();
    if ( size_ ) std::cout << write_ << " " << writeImage->io().size() << std::endl;
}

Convert an image to a .exv file

The essential code to achieve this is:

    std::string readPath;
    std::string writePath;

    Exiv2::Image::AutoPtr readImage = Exiv2::ImageFactory::open(readPath);
    assert(readImage.get() != 0);
    readImage->readMetadata();

    // create a file, copy and write the metadata
    Exiv2::Image::AutoPtr writeImage = Exiv2::ImageFactory::create(Exiv2::ImageType::exv,writePath);
    writeImage->setMetadata(readImage);
    writeImage->writeMetadata();

Read an image and serialise it to memory

    std::string readPath;

    Exiv2::Image::AutoPtr readImage = Exiv2::ImageFactory::open(readPath);
    assert(readImage.get() != 0);
    readImage->readMetadata();

    // create an in-memory file
    Exiv2::BasicIo::AutoPtr memIo   (new Exiv2::MemIo());
    Exiv2::Image::AutoPtr   memImage(new Exiv2::ExvImage(memIo,true));
    memImage.setMetadata(*readImage);

    // read image metadata into memory
    size_t       size = memImage->io().size();
    Exiv2::byte  data[size];

    memImage->io().seek(0,Exiv2::BasicIo::beg);
    memImage->io().read(data,size);

Read an image, serialise it to memory, then deserialise back into an image

    std::string readPath;
    Exiv2::Image::AutoPtr readImage = Exiv2::ImageFactory::open(readPath);
    assert(readImage.get() != 0);
    readImage->readMetadata();

    // create an in-memory file and write the metadata
    Exiv2::BasicIo::AutoPtr memIo   (new Exiv2::MemIo());
    Exiv2::Image::AutoPtr   memImage(new Exiv2::ExvImage(memIo,true));
    memImage->setMetadata  (*readImage);
    memImage->writeMetadata();

    // serialize the in-memory file into buff
    size_t       size = memImage->io().size();
    Exiv2::byte  buff[size];
    memImage->io().seek(0,Exiv2::BasicIo::beg);
    memImage->io().read(buff,size);

    // create an in-memory file with buff and read the metadata into buffImage
    Exiv2::BasicIo::AutoPtr buffIo   (new Exiv2::MemIo(buff,size));
    Exiv2::Image::AutoPtr   buffImage(new Exiv2::ExvImage(buffIo,false));
    assert(buffImage.get() != 0);
    buffImage->readMetadata();

About application toexv

The basic operation is to extract the metadata from an image and serialise it into a file. Options are provided to selectively define the categories of metadata supported by exiv2. For v0.26, these are Exif, IPTC, XMP, ICC Profiles and JPEG/Comments.

~/gnu/exiv2/ttt $ bin/toexv -h
Reads and writes raw metadata. Use -h option for help.
Usage: toexv [-:iecCahsx] readfile {-|+|writefile}

Options:
   -i      Read Iptc data from readfile and write to writefile.
   -e      Read Exif data from readfile and write to writefile.
   -c      Read Jpeg comment from readfile and write to writefile.
   -C      Read ICC profile from readfile and write to writefile.
   -x      Read XMP data from readfile and write to writefile.
   -a      Read all metadata from readfile and write to writefile.
   -s      Print size of writefile.
   -h      Display this help and exit.
~/gnu/exiv2/ttt $ 

Redmine Appliance - Powered by TurnKey Linux