In the C++ world, there are not too many options to extract Exif data from images. So far, I have found only two considerable libraries, they are libexif in C and Exiv2 in C++, respectively. However, both of them are not easy to be integrated into Qt applications in my opinion.
Qt is a great framework for C++ programmers, especially for Qt applications. Unfortunately, there is no built-in metadata support for images. Therefore, I decided to write my own one based on the QtCore library, and it’s called QMeta. Its goal is to provide the easiest way to manipulate metadata with various metadata standards and image types in Qt applications. And now, it supports reading Exif data from images. In the rest of the article, I’ll show you how easily you can use QMeta to extract Exif metadata saved in JPEG and TIFF images.
As a note, currently QMeta is at very early state and does not have any official document. Its APIs are not stable as well, which means what I’ll talk about in this article may be out of date in the future. However, you can always get the latest information about this project at http://github.com/ollix/qmeta, and I’ll try to keep its APIs as simple as possible as you will see.
Now let’s assume that you have a JPEG file and want to know the “Artist” value saved in its Exif. You can achieve this using the following code:
#include <QtGui>
#include "qmeta/exif.h"
#include "qmeta/jpeg.h"
int main (int argc, char *argv[])
{
qmeta::Jpeg jpeg("path/to/file");
if (jpeg.IsValid()) {
qDebug() << "The supplied file is a valid JPEG file";
if (jpeg.exif()) {
qDebug() << "This file contains Exif information";
// Prints something like "Artist: Olli Wang" in your console.
qDebug() << "Artist:" << jpeg.exif()->Value(qmeta::Exif::kArtist);
}
}
return 0;
}
See? It’s really easy to use. The `qmeta::Exif::kArtist` is the Exif Tag that we want to query, and you can find the full list of supported Exif tags at http://github.com/ollix/qmeta/blob/master/src/exif.h (see the `enum Tag` type). Actually, the code `jpeg.exif()->Value(qmeta::Exif::kArtist)` returns the value with the ExifData type which inherits the QByteArray class. So, you can use it as a normal QByteArray object, like this:
qmeta::ExifData value = jpeg.exif()->Value(qmeta::Exif::kArtist); qDebug() << value.data(); // Olli Wang qDebug() << value.toHex(); // 4f6c6c692057616e6700 qDebug() << value.size(); // 10
However, sometimes it’s not convient to use QByteArray directly. For example, the image width saved in Exif may use SHORT (a 16-bit unsigned integer) or LONG (a 32-bit unsigned integer) types defined in the Exif specification. If you want to get this value, you may need to do something like this:
qmeta::ExifData value = jpeg.exif()->Value(qmeta::Exif::kImageWidth); qDebug() << value.size(); // 2 (2 bytes, which means its type is SHORT) qDebug() << value.toHex(); // 0fd0 (represented in hexidecimal) qDebug() << value.toHex().toUInt(NULL, 16); // 4048 (coverted to decimal)
As you can see, in most case, the value of image width is useless unless converted to integer, and that requires two steps in QByteArray. Fortunately, the actual returned type is ExifData, and it was born to remedy this situation. See the following example.
qDebug() << value.toHex().toUInt(NULL, 16); // 4048 (the old method) qDebug() << value.ToUInt(); // 4048 (same as above, but much more cleaner)
Currently, the ExifData class does not provide too much fancy work. But in the future, it will provide more useful functions to represent the data, and it can always be subclassed to adapt particular Exif tags. You can find more about ExifData at http://github.com/ollix/qmeta/blob/master/src/exif_data.cc.
The next example I want to show you is thumbnail. Most digital cameras store pictures with their thumbnails for quick displaying. Let’s see how it works.
// Saves the embeded thumbnail to a new JPEG file.
QByteArray thumbnail = jpeg.Thumbnail();
if (thumbnail.size()) {
QFile file("thumbnail.jpg");
file.open(QIODevice::WriteOnly);
file.write(thumbnail);
}
Once again, it’s really not a big deal to extract thumbnails using QMeta. The Jpeg::Thumbnail() is a quick access to the thumbnail saved in metadata. It will try to return the thumbnail as QByteArray stored in Exif, IPTC, or XMP. However, currently QMeta only supports Exif.
The Exif metadata can be extracted from both JPEG and TIFF files. Extracting Exif data from TIFF files is just like extracting from JPEG files, the only difference is the class to be instantiated. For example:
qmeta::Tiff tiff("/path/to/file");
if (tiff.IsValid()) {
if (tiff.exif()) {
qmeta::ExifData data = tiff.exif()->Value(qmeta::Exif::kModel);
qDebug() << "Model:" << data.ToString(); // ex: Model: "DSLR-A350"
}
Another more interesting example is to let QMeta guess what file type it should be. In this case, you only need to use a general “Image” class, and only one header file is required. Take this example:
#include <QtGui>
#include "qmeta/image.h"
int main (int argc, char *argv[])
{
// Opens a JPEG file.
qmeta::Image jpeg("path/to/file.jpg");
if (jpeg.IsValid()) {
if (jpeg.exif()) {
// Do whatever you like with the JPEG file.
}
}
// Opens a JPEG file.
qmeta::Image tiff("path/to/file.tif");
if (tiff.IsValid()) {
if (tiff.exif()) {
// Do whatever you like with the TIFF file.
}
}
return 0;
}
And… that’s it. Currently QMeta only supports the Exif standard but will include IPTC and XMP in the future. I also need to figure out what’s the best way to store/update metadata stored in the file without destroying other metadata QMeta supports or not. As you know, there are many fields stored with offsets and actually, this is my first project relating to image processing. So, any suggestion or contribution would be appreciated.
Filed under: C++, Ollix, Programming, Qt | 4 Comments
Tags: library, Qt, Programming, toolkit, Ollix, C, photograph, cplusplus, QMeta, exif, metadata, information
About Me
Hi, I'm Olli. I'm a programmer as well as a microstock photographer. This blog is all about my life and my work. Please leave a message if you have any idea of my posts. Thanks.
Twitter Updates
- The new database update logic is done. Now it's time to rewrite the whole C library. 1 day ago
- I sold an image today through @shutterstock! My gallery is here: http://tinyurl.com/kmxffb 3 days ago
- New Website Launch | Ollix Blog http://t.co/5CweVRx via @ollixsoft 6 days ago
- RT @unbit: uWSGI 0.9.6 announce http://lists.unbit.it/pipermail/uwsgi/2010-August/000604.html 1 week ago
- I sold an image today through @shutterstock! My gallery is here: http://tinyurl.com/kmxffb 1 week ago
-
Recent Comments
-
Flickr Photos



More Photos -
Blog Stats
- 8,406 hits

Hi,
Do you have idea , how to write Exif in jpeg file ?
Well, I was wondering what’s the best way to add/modify metadata.
Actually my basic photo have no metadata so I’ve to add them. It seem to be more difficult then modify it.
Thanks.
hello,
When I use your function to read exif from jpeg file, I encounter an infinite loop problem with a jpeg picture. It seems occured in Exif::ReadIfds of exif.cc. I send this jpeg picture to your email, could you please give me some suggestion about this problem? Thanks a lot.