Using QMeta to extract Exif data in your Qt applications
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.
Like this:
Filed under: C++, Ollix, Programming, Qt | 12 Comments
Tags: C, cplusplus, exif, information, library, metadata, Ollix, photograph, Programming, QMeta, Qt, toolkit
About Me
I'm a freelancer but only working for my own projects. I'm also an amateur microstock photographer.
Twitter Updates
- had 1 commits across 1 Git repositories with 0 files created, 0 files deleted, 1 files changed, 6 insertions, and 18 deletions. 1 day ago
- had 6 commits across 1 Git repositories with 0 files created, 0 files deleted, 5 files changed, 95 insertions, and 30 deletions. 2 days ago
- had 11 commits across 3 Git repositories with 133 files created, 1 files deleted, 139 files changed, 1320 insertions, and 2589 deletions. 1 week ago
- I sold an image today through @shutterstock! My gallery is here: http://t.co/cXdZJ8d5 1 week ago
- I sold an image today through @shutterstock! My gallery is here: http://t.co/cXdZJ8d5 1 week ago
-
Recent Comments
-
Flickr Photos



More Photos -
Blog Stats
- 18,465 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.
Hello,
can you write a qmeta.pro file (QT-Project file) please.
I have some problems to include this library into my project.
Hi, I think you need to add something like the following code to your QT’s `pro` file. However, the following code is used under Unix environment.
unix {INCLUDEPATH *= /usr/include
LIBS += -lqmeta
}
You are required to compile and install the qmeta library at first.
Hi Olli,
This is the error message that I am getting from qt while running the program
error while loading shared libraries: libqmeta.so: cannot open shared object file: No such file or directory.
These are the important bits in my .pro file
LIBS += -lhighgui \
-lm \
-lcv \
-lhighgui \
-lcvaux \
-lqitty \
-lqmeta
INCLUDEPATH += /usr/local/include/opencv -L /usr/local/lib \
/usr/local/include/qitty -L /usr/local/lib \
/usr/local/include/qmeta -L /usr/local/lib
Do you know why I am getting this error message? I compiled and installed both qitty and qmeta without error.
You need to tell QT the location of your compiled qmeta library. It seems that you installed it to the `/usr/local/lib` directory instead of the normal `/usr/lib` directory.
I followed the instructions on the README and it seems to have installed it there by default. I am really new at this, but is qmeta.so the compiled library? It is in my /usr/local/lib directory.
hello.
I want toi use your library, under QT4 on Debian Squeeze with QT Creator. I’ve download it, mais I don’t now how to add it in project ? Can you help me ?
I find alone. Thanks for your work.
I find an error in exif.cpp :
———————————
if(data->mid(6,2) == “II”){ // Exif section in Intel order
//qDebug() <mid(6,2);
MotorolaOrder = 0;
}else{
if(data->mid(6,2) == “II”){ // Exif section in Motorola order
//qDebug() <mid(6,2);
————————————–
is better with ‘MM’for Motorola :
—————————————
if(data->mid(6,2) == “II”){ // Exif section in Intel order
//qDebug() <mid(6,2);
MotorolaOrder = 0;
}else{
if(data->mid(6,2) == “MM”){ // Exif section in Motorola order
//qDebug() <mid(6,2);
—————————————
Fabrice
contact@opendent.fr