ExifTool Forum

ExifTool => Developers => Topic started by: Phil Harvey on December 02, 2013, 07:37:31 AM

Title: New C++ interface for ExifTool
Post by: Phil Harvey on December 02, 2013, 07:37:31 AM
I have just released version 1.00 of a C++ interface for ExifTool (http://owl.phy.queensu.ca/~phil/cpp_exiftool/).  I wrote this set of objects to make it easier to call exiftool from a C++ application.  It uses the exiftool -stay_open feature to keep the exiftool process running, which eliminates the startup latency associated with launching the exiftool application for each command.

I used standard C process and pipe controls so it should be fairly portable, and have tested it on Mac, Linux and Cygwin, although there is a niggling problem with the write pipe on Cygwin that makes it so you can't queue as many commands while exiftool is busy (it doesn't seem to work in non-blocking mode for some reason, but I'm hopeful that I'll find a way around this).

Anyway, I hope this turns out to be useful for someone.  It was more work than I anticipated.

It still needs some improvement in the documentation of the numerical error messages. Currently the only way to determine the meaning of an error is from the comments in the source code.  But I may wait to see if there is any interest in this before I do any more work on it.

- Phil
Title: Re: New C++ interface for ExifTool
Post by: Maurizio.Loreti on December 16, 2013, 09:33:39 AM
I wrote in the last days a C++ toy-program intended for geotagging my jpeg images; the GPS coordinates come directly from Google Maps, while the file names are given as arguments in the command line.  The main loop looks like:

  while (--argc) {
    if (access(*(++argv), W_OK) != 0) {
      cerr << progName << ": couldn't access file \"" << *argv
           << "\" for writing\n";
      perror("access");
      continue;
    }

    pET->WriteInfo(*argv, "-overwrite_original");

    if (pET->Complete() > 0) {
      cout << progName << ": geotagged file \"" << *argv
           << '\"' << endl;
    } else {
      cerr << progName << ": error from exiftool, on file \""
           << *argv << "\"\n";
      cerr << pET->GetError();
      break;
    }
  }


To test the error return from exiftool, I gave as file name the source of my program, geotag.cxx - and, to my surprise, the output has been:

...
geotag: geotagged file "geotag.cxx"


Shouldn't that code trigger an error?  Of course, exiftool -l geotag.cxx from the command line gives the output

...
Error
      Unknown file type


Thank you in advance for your help; and, if somebody is interested in the code, it is free (under GPL) - just ask.
Title: Re: New C++ interface for ExifTool
Post by: Phil Harvey on December 16, 2013, 09:57:06 AM
I should probably be more clear in the documentation, but Complete() returns a success code if the command was completed properly (ie. the communication with the exiftool process completed without errors), even if the command itself gave errors.  If Complete() returns a positive number, then GetOutput() and GetError() may be called to obtain the command output.

Determining whether the command was successful then involves a bit of work.  For this command, you could check GetOutput() for "# image files updated" and make sure that "#" is "1", or check GetError() for any line beginning with "Error:" since this will indicate a write failure.  I should probably add some helper functions to make this easier.

- Phil

Edit: I added a note to the documentation (http://owl.phy.queensu.ca/~phil/cpp_exiftool/#Complete) to empahsize this point.
Title: Re: New C++ interface for ExifTool
Post by: Maurizio.Loreti on December 16, 2013, 10:39:02 AM
Thank you for the very quick and exhaustive answer.  I changed the relevant statements to
Quote
    if (pET->Complete() > 0) {
      cout << progName << ": file \"" << *argv
           << "\":" << pET->GetOutput();
    } else {
and the output seems to be self-explanatory.

And, btw, thank you for maintaining such an useful package.
Title: Re: New C++ interface for ExifTool
Post by: Phil Harvey on December 16, 2013, 12:48:48 PM
Just to make things a bit easier, I have added a new helper method called GetSummary() (http://owl.phy.queensu.ca/~phil/cpp_exiftool/index.html#GetSummary) that allows easier access to the exiftool summary statistics if necessary from your program.

- Phil
Title: Re: New C++ interface for ExifTool
Post by: Maurizio.Loreti on December 17, 2013, 12:24:22 AM
Final version:

    if (pET->Complete() > 0) {
      cout << progName << ": ";
      if (pET->GetSummary(SUMMARY_IMAGE_FILES_UPDATED)) {
        cout << "file \"" << *argv << "\" geotagged" << endl;
      } else {
        cout << pET->GetError();
      }
    } else {
      cerr << progName
           << ": couldn't connect to exiftool process, file \""
           << *argv << "\"\n";
      cerr << pET->GetError();
      break;
    }

Thank you, for your impeccable interactions with my needs  ;D  (and sorry for the bad english)
Title: Re: New C++ interface for ExifTool
Post by: Phil Harvey on December 17, 2013, 07:15:34 AM
Excellent.  Just one minor suggestion.  I would test for a number greater than 0 here:

      if (pET->GetSummary(SUMMARY_IMAGE_FILES_UPDATED) > 0) {

because GetSummary() will return -1 if the summary information isn't available.  For your command, this should never happen, but better safe than sorry.

Also, if Compete() returns <= 0, then GetError() will return NULL, so you can remove the GetError() call from inside your "else" block.

- Phil

Title: Re: New C++ interface for ExifTool
Post by: west suhanic on January 21, 2014, 03:27:02 PM
Hello All:

I just started using cpp_exiftool. I am trying to replicate the exiftool command:

./exiftool -b -previewImage -w %d%f.tif ~/IMG_0643.CR2

by writing a program using cpp_exiftool. I am able to replicate the above command using
the following:

    // create our ExifTool object
    ExifTool et;
    int cmdNum = et.Command("-b\n-previewImage\n-w\n%d%f.tif\n/home/wsuhanic/IMG_0643.CR2");
    if (cmdNum < 0) {
             puts("\nError extracting information\n");
             return -1;
    }
    puts("\nDone.\n");
    return 0;


Is there any other way to accomplish this by using calls other than Commnand? I have attempted to replicate the command by using the sample code from exampl4.cpp .
However this has not been successful. So I have a question. After I make the following call:

TagInfo *info = et->ImageInfo(argv[1], "-b\n-previewImage", 10);

which call do I make to actually write out the preview image? Using WriteInfo
is not, given my limited understanding, not the proper call.

All help is appreciated.

regards,

west suhanic
Title: Re: New C++ interface for ExifTool
Post by: Phil Harvey on January 21, 2014, 06:14:58 PM
Hi West,

After the ImageInfo call, the "info" pointer will point to a linked list of TagInfo structures.  You would need to scan through them until you found one with the name "PreviewImage", then open an output file for writing and write the tag value like this:

    for (TagInfo *i=info; i; i=i->next) {
        if (strcmp(i->name, "PreviewImage")) continue;
        FILE *fp = fopen(outfile, "wb");
        fwrite(ti->value, 1, ti->valueLen, fp);
        fclose(fp);
        break;
    }
    delete info;


However, using the Command function is probably simpler since it will write the output file for you.  But note that the PreviewImage is JPG, not TIFF format.  Also, technically you should call Compete after Command, but in this case it isn't necessary because the ExifTool object will do this automatically when it is deleted.

- Phil
Title: Re: New C++ interface for ExifTool
Post by: west suhanic on January 22, 2014, 10:09:11 AM
Hi Phil:

Thank you for your answer. It is appreciated.

One other question. I also use exiv2. The following command:

exiv2 -pp ~/IMG_0643.CR2

lists three previews, two jpgs and one tiff.

I can use the following command to extract the tif file:

exiv2 -ep2 ~/IMG_0643.CR2

Can exiftool find this tiff preview image?
I, because of my limited knowledge of exiftool, cannot figure out how to do this.
I am hoping that the tiff preview file can be extracted using the cpp_exiftool.

regards,

west
Title: Re: New C++ interface for ExifTool
Post by: Phil Harvey on January 22, 2014, 10:29:48 AM
Hi West,

ExifTool currently only extracts JPEG previews.

- Phil