Creating thumbnail images in Qt
Recently I need to create thumbnail images in one of my Qt applications, so I googled the Internet and found an article called Creating thumbnail preview by Ariya Hidayat. Ariya introduced three methods to create thumbnail images, all of them uses the QImage::scaled() function. Here’s a quick review of the three methods he introduced respectively.
The first method is using the nearest-neighborhood algorithm as following:
QImage image("/path/to/image");
QImage thumbnail = image.scaled(200, 200, Qt::KeepAspectRatio, Qt::FastTransformation);
The second is using the bilinear filtering to get a better quality, but the drawback is that it’s slower compared to the previous method:
QImage image("/path/to/image");
QImage thumbnail = image.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
The third is tricky, Ariya mixed the previous two methods as he claimed this method has the similar quality to the second method but is even faster than the first method, and he called this method as “cheat scaling”, as following:
QImage image("/path/to/image");
QImage thumbnail = image.scaled(800, 800, Qt::KeepAspectRatio, Qt::FastTransformation).scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
However, after I tried all of these methods, I found that the performance is actually unacceptable even though I used the third method. My original images are usually at size around 4MB, and it spends too much time to create thumbnail images using any of above methods. Therefore, I tried to find other ways to improve the performance, and I did it. The answer is QImageReader class. Here’s the code I implemented to do the same thing as above:
int length = 200;
QImageReader image_reader("/path/to/image");
int image_width = image_reader.size().width();
int image_height = image_reader.size().height();
if (image_width > image_height) {
image_height = static_cast<double>(length) / image_width * image_height;
image_width = length;
} else if (image_width < image_height) {
image_width = static_cast<double>(length) / image_height * image_width;
image_height = length;
} else {
image_width = length;
image_height = length;
}
image_reader.setScaledSize(QSize(image_width, image_height));
QImage thumbnail = image_reader.read();
The code is much longer than using the QImage::scaled() function, but its performance is much better. Here’s the benchmark I tried to create thumbnail images for 10 jpeg images, and each of them has the size around 4MB.
![]()
As you can see, all three methods using QImage::scaled() are actually no much difference, but by using the QImageReader class, we got 46% performance improvement than using the Qt::FastTransformation. The algorithm QImageReader::setScaledSize() used for scaling depends on the image format. However, in this experiment, the quality of created thumbnail images are no difference between Qt::SmoothTransformation and cheat scaling and QImageReader methods.
For convenience, I implemented this function in my open source Qitty library. You can find this project at http://github.com/ollix/qitty. To create thumbnail images using this library, you’ll need to include the header file in your source code:
#include <qitty/image.h>
And use the qitty_utils::SacledImage() function:
QImage thumbnail = qitty_utils:ScaledImage("/path/to/image", 200);
Filed under: C++, Programming, Qt | 1 Comment
Tags: algorithm, C, cplusplus, function, image, library, processing, Qitty, Qt, thumbnail, toolkit
MicroAgent debuted at late 2009

Yesterday I introduced my new project, MicroAgent, in my data mining class. I designed an algorithm to find relevant keywords, titles, descriptions, and categories for images according to only a few of keywords, and it works pretty well. I think this application would be very useful for all microstock photographers because in my experience, to submit photos to microstock agencies is always a time consuming mess, as we need to figure out what keywords, titles, descriptions, or categories would best fit our images, and further help us increase the selling rate.
MicroAgent is the perfect solution for you, anyone who want to add metadata to their images would benefit from MicroAgent. However, MicroAgent is still at early state because I’d like to add more useful features to it (auto submission, statistics, etc). So, it may take a while to publish an official release. In the mean time, any idea or suggestion would be welcomed. By the way, MicroAgent will be available for Windows, Mac OS X, and Linux, so most people could take advantage of it. Just wait and see.
Filed under: Ollix | Leave a Comment
Tags: analyzing, application, auto submission, keywording, microagent, microstock, Ollix, photograph, photographer, software, tool
AES Implementation in RPython
I implemented the Advanced Encryption Standard (AES)[4] using Restricted Python (RPython)[1], which is a subset of the standard Python programming language and comes from the PyPy[2] project. By using RPython, we can write our code in high level programming language similar to Python and later be translated to various backends such as C, Java Virtual Machine (JVM), or Common Language Infrastructure (CLI). As a result, we can develop our programs very quickly and get the performance similar to the one written in pure C, Java, or C# .NET.
However, RPython is not as powerful as standard CPython, so that’s why it is called “Restricted” Python. There are some restrictions in RPython. For example, you can’t use most Python packages comes from the CPython world because they are not written in RPython. Also, translated code are compiled to executables, not compiled Python modules, neither Python packages. Fortunately, these restrictions are trivial in this simple program because I’m intend to create executables and I don’t need libraries not supported by PyPy. Most importantly, performance matters.
In my experiments, to encrypt and decrypt a file on my iMac (Early 2008), the translated C executable is about 150 times faster than the pure Python code running on top of CPython, and the translated Java bytecode is about 16 times faster. Consequently, RPython should be very useful in case we don’t need serious dependencies. We just need to figure out a better way to integrate it with pure Python code, much like the C extensions for Python.
The AES algorithm implemented in this project is mostly following the AES Tutorial[3] and the Advanced Encryption Standard[4]; the values of Rijndael’s S-box and Inverse S-box are copied from [5]; and the implementation of Rijndael key schedule is following [6].
To test the program, you can use executables put under the bin directory shipped with the source code. There are 4 executables compiled in C, one compiled to Java bytecode as a JAR file (JVM), and one translated to C# and compiled for .NET framework (CLI). Now say that you want to encrypt a file under Mac OS X using the C executable. You can do this by:
bin/aes-mac-c encrypt mypassword path_to_input_file path_to_encrypted_file
To decrypt the file on a Java Virtual Machine, you can then run:
java -jar bin/aes-jvm.jar decrypt mypassword path_to_encrypted_file path_to_decrypted_file
You can also run the pure Python code on top of CPython or other Python implementation, but you’ll need to get the PyPy’s source code. You can find its repository at their website[2].
Here’s some benchmarks I made on Snow Leopard, Windows XP, and Gentoo Linux respectively.
- iMac (Early 2008)
- Mac OS X 10.6.2 (Snow Leopard)
- 2.8 GHz Intel Core 2 Duo
- 4 GB 800 MHz DDR2 SDRAM
- GCC version: 4.2.1
- CPython version: 2.6.1
- Java version: 1.6.0_17 (JVM)
- Mono version: 2.6.1 (CLI)
- Windows XP 32-bit
- Running in VirtualBox on iMac (Early 2008)
- 1 GB RAM
- Microsoft Visual Studio 2008 Express Edition
- Java version: 1.6.0_17
- CPython version: 2.6.4
- Gentoo Linux 2008 (amd64)
- AMD Athlon 64 Processor 3500+
- 2GB DDR 400 SDRAM
- GCC version: 4.1.2
- Java version: 1.6.0_17
- Mono version: 2.4.2.3
- CPython version: 2.6.4
References:
[1] Restricted Python: http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#restricted-python
[2] PyPy: http://codespeak.net/pypy/
[3] AES Tutorial: http://www.progressive-coding.com/tutorial.php
[4] Advanced Encryption Standard: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
[5] Rijndael S-box: http://en.wikipedia.org/wiki/Rijndael_S-box
[6] Rijndael key schedule: http://en.wikipedia.org/wiki/Rijndael_key_schedule
Filed under: PyPy, Python | 3 Comments
Tags: .NET, Advanced Encryption Standard, AES, C, CLI, CPython, decryption, encryption, executable, file, implementation, JIT, JVM, performance, PyPy, Python, Rijndael, RPython, S-box
Qt Designer is an important tool for designing and building graphical user interface from Qt components. However, if you are a Java programmer and want to use Qt Designer with Qt Jambi in Mac, you can’t simply double-click the Designer app bundle shipped with Qt Jambi SDK. If you do so, you can still invoke the Designer, but… with the C++ environments, it’s useless for Java programmers. Instead, if you want to use Qt Designer with Qt Jambi. You have to start the program from a `designer.sh` script placed in your Qt directory. It’s pretty annoying because you’ll need a Terminal to run this script until you turn it off. Also, it’s not intuitive.
So, I checked the script code and found what it does is simply to set some environment variables and then execute the Designer binary within the Designer app bundle. Therefore, I decided to make a “real” app bundle for the Qt Designer with Qt Jambi. It’s pretty easy to do this job by using Jump, one of my open source projects. Here’s the instructions.
- Go to the `QTDIR/bin` directory in Finder.
- Right-click the `Designer` app bundle, select `Show Package Contents`, and it will open a new Finder window.
- In the new opened Finder window, go to the `Contents/MacOS` directory, then copy the `Designer` binary back to `QTDIR/bin`.
- Now pick a location to start writing our wrapper. I simply make a directory called `designer` in my home directory, then open a Terminal and switch to it.
- Back to the new opened Finder window, copy the `Contents/Resources/designer.icns` file to our new created `designer` directory.
- Create a Python module named `designer.py` in `designer` directory, and its content looks like this:
import os # Replace this path to your QTDIR qt_home = '/Users/olliwang/workspace/qtjambi-mac-lgpl-4.5.2_01' def main(): os.environ['QTDIR'] = qt_home os.environ['DYLD_LIBRARY_PATH'] = os.path.join(qt_home, 'lib') os.environ['QT_PLUGIN_PATH'] = os.path.join(qt_home, 'plugins') os.environ['PATH'] = os.path.join(qt_home, 'bin') classpaths = [] for filename in os.listdir(qt_home): if filename.endswith('.jar'): classpath = os.path.join(qt_home, filename) classpaths.append(classpath) os.environ['CLASSPATH'] = ':'.join(classpaths) os.system(os.path.join(qt_home, 'bin/Designer')) - Create a `config.jp` file with following content:
dist_name = Designer main_entry_point = designer:main icns = designer.icns
- Run `jump app` in your Terminal, and you’ll see a new created directory called `dist`, our new app bundle is in there.
- Copy the created app bundle back to the `QTDIR/bin` directory, now double-click the `Designer` app bundle and everything should work fine. Cheers!
I use Python to write this wrapper for easy, you can of course do the same thing in Java. Just remember to modify the `main_entry_point` to the `Main Class` in config file.
Filed under: Jython, Programming, Python, Qt | Leave a Comment
Tags: App Bundle, bundle, Jump, Jython, Mac, Mac OS X, native, Programming, Python, Qt, Qt Designer, Qt Jambi, tutorial, wrapper
ANN: Jump 0.9.5.1 released!
I am proud to announce that Jump 0.9.5.1 is released!
You can find the Jump project and its documentation at http://opensource.ollix.com/jump.
Jump is a build tool for distributing Jython applications in a really easy step.
Features:
- Distributing Jython applications into a single, independent JAR file. [New in v0.9.5]
- Distributing Jython libraries into a single JAR file.
- Distributing native Mac OS X application bundles, Windows .exe executables, WAR files for Python WSGI applications. [New in v0.9.5]
- Supporting Java source code and third-party JAR files.
- Supporting Java Native Interface files for distributing JAR files. [New in v0.9.5]
- Starting the created distribution from either Jython or Java code.
- Packaging **only required** Python modules into the final distribution **automatically**, which means you don’t have to worry about using Python third-party libraries as long as they can be found in your `sys.path`.
- Importing specified Python packages explicitly. [New in v0.9.5]
- All Python modules (except Python’s standard library) packaged into the final distribution are compiled to `$py.class` files, which means your source code is not public.
If you have any question or bug report, please post it to our mailing list at http://groups.google.com/group/ollix-jump, contributions are welcome as well.
Filed under: Java, Jython, Ollix, Python | Leave a Comment
Tags: ANN, applications, build, distributing, free software, GPLv3, Java, Jump, Jython, open source, Python, tool
OK, I know it’s been a while, but I received my first Carl Zeiss lens a half month ago. Unfortunately, I didn’t have too much time to go out and take pictures recently because I’m a little busy with my new projects.
However, I did find a problem with this lens, that is, the focusing system doesn’t work well when using the wide-angle side. The camera will tell you it already focuses but it actually doesn’t. This occurs when the camera body focuses an object at the shortest length. I tried this with my A350 and new model A550, and three different 16-80mm lenses from three different stores, two of them are even SonyStyle stores, but the result is all the same. You need to step back about 1-5 centimeters to the object you are taking to make sure you won’t take out-of-focus pictures. I still don’t know why this happened, neither do the salesclerks.
Besides the only problem I found, this lens is still fine, it has a longer focal length than my previous one. The image quality is sharp from center to edge, and has nice color. More excited, it’s a Carl Zeiss lens!
I also bought a MC protector with Carl Zeiss T* coating, but I still have no idea about what does “MC” mean. Can anyone tell me, please? It would be appreciated.
Filed under: Photography, Stuff | Leave a Comment
Tags: 16-80, 16-80mm, 1680, box, Carl Zeiss, DSLR, F3.5-4.5, lens, lens cap, object, package, Photography, Sony, zoom lens
Qt Jambi on Jython
In my previous post, Hello World! Qt Jambi, I showed you my brief experience with GUI toolkits for Python, and my idea to integrate Qt Jambi with Jython. Thus, we can take advantage of both Java and Python to use Qt library in Python. This is possible because Jython is an implementation of Python written in Java.
I’ve heard about Jython about over one year ago, but at that time, Jython only supported Python 2.2 features while Python 2.4 was already released for a long time, and because there is a big difference between Python 2.2 and Python 2.4, I never thought Jython is my option. But something is different, the Jython development team has released Jython 2.5 about two months ago and it seems that Jython is extremely useful for me now, to integrate with Qt Jambi.
To illustrate my idea of using Qt Jambi library in Jython, I firstly wrote the Jython equivalent code to the “Hello World” example written in Java in my previous post. Here is the original Java source code:
import com.trolltech.qt.gui.*;
public class HelloWorld
{
public static void main(String[] args) {
QApplication.initialize(args);
QPushButton hello = new QPushButton("Hello World!");
hello.resize(120, 40);
hello.setWindowTitle("Hello World");
hello.show();
QApplication.exec();
}
}
And here is the Jython equivalent to Java:
import sys
from com.trolltech.qt.gui import *
def main():
QApplication.initialize(sys.argv)
hello = QPushButton("Hello World!")
hello.resize(120, 40)
hello.setWindowTitle("Hello World")
hello.show()
QApplication.exec()
if __name__ == '__main__':
main()
To execute this script, I just simply run the following instruction, and the result should be nothing different.
jython -J-d32 -J-XstartOnFirstThread helloworld.py
To further demonstrate if signals are working correctly in Jython, I borrowed the source code from tutorial 2 in Qt Jambi official documentation. Here’s the original Java source code:
import com.trolltech.qt.gui.*;
public class Quit
{
public static void main(String args[])
{
QApplication.initialize(args);
QPushButton quit = new QPushButton("Quit");
quit.resize(80, 40);
quit.setFont(new QFont("Times", 18, QFont.Weight.Bold.value()));
quit.clicked.connect(QApplication.instance(), "quit()");
quit.setWindowTitle("Calling It Quits");
quit.show();
QApplication.exec();
}
}
And here’s the Jython equivalent I rewrote:
import sys
from com.trolltech.qt.gui import *
def main():
QApplication.initialize(sys.argv)
quit = QPushButton("Quit")
quit.resize(80, 40)
quit.setFont(QFont("Times", 18, QFont.Weight.Bold.value()))
quit.clicked.connect(QApplication.instance(), "quit()")
quit.setWindowTitle("Calling It Quits")
quit.show()
QApplication.exec()
if __name__ == '__main__':
main()
As usual, I executed the script by running instruction like this:
jython -J-d32 -J-XstartOnFirstThread quit.py

As you can see the result above, everything is just working fine. As long as I click the Quit button in the window, it quits normally, nothing wrong happened. Perfect!
Note that I add `-J-XstartOnFirstThread` parameter because I use Mac OS X operating system and I add `-J-d32` parameter because I use “Snow Leopard”. You don’t need these parameters if you are not a Mac user.
Filed under: Java, Jython, Mac, Programming, Qt | 5 Comments
Tags: GUI, Jython, Programming, Python, Qt, Qt Jambi, toolkit, tutorial
Hello World! Qt Jambi
Let me clear first. I am a Python guy, most of my projects are written in Python programming language. I only had a few small projects written in Java before, I was never a Java guy. However, I do know the power of Java and now, I think it’s time to take advantage of Java, for powerful GUI toolkit.
People who want to develop GUI applications in Python always come into a question, “Which GUI toolkit should I use?” I tried Tk a few years ago, which comes with Python standard library, but definitely is not a good choice for large projects. Then I switched to wxPython, which is much better than Tk, but I was still unsatisfying with its GUI design tool. Finally, I met Qt.
Qt probably is the best GUI toolkit right there in my opinion. Though there are some Python bindings for Qt like PyQt and PySide, I found that both of them are not useful for me because PyQt is still only available under GPL and commercial licenses even though Qt is available under LGPL license since version 4.5, and PySide just seems not ready for Windows and Mac users.
Finally, I decided to use Qt Jambi, which is the Qt library made available for Java, and is officially supported by Nokia Corporation. My original thought was to use Qt Jambi with Jython, so I can take advantage of both Java and Python, and able to develop my applications under LGPL license.
The first step to a new programming language or library is always a simple “Hello World!” application, but I found that I was in trouble when I was following the official documentation, and that’s why I wrote this article. Here’s my working environment:
Before you start writing your “Hello World” application. You should make sure everything is working fine, this could be done by launching the Demo Launcher application included in Qt Jambi. Go open a Terminal window and change directory to the Qt Jambi installation directory. Then try to execute the `qtjambi.sh` script. If something is going wrong, simply open the `qtjambi.sh` file and find a line near the end of the file:
java -XstartOnFirstThread -cp $CP com.trolltech.launcher.Launcher
Then, add `-d32` after `java` like this:
java -d32 -XstartOnFirstThread -cp $CP com.trolltech.launcher.Launcher
Now execute the `qtjambi.sh` script again and everything should work fine now.
Next, we need to setup the environment for our Jambi applications. I made this by adding some lines to `.profile` file under my user’s home directory. You need to create one if you don’t have it yet. Once you have this file, add following lines to the button of the file:
# Qt Jambi
export QTDIR=/Users/olliwang/workspace/qtjambi-mac-lgpl-4.5.2_01
export DYLD_LIBRARY_PATH=$QTDIR/lib:$DYLD_LIBRARY_PATH
export QT_PLUGIN_PATH=$QTDIR/plugins
for lib in $(ls $QTDIR/qtjambi*.jar); do
CLASSPATH=$lib:$CLASSPATH
done
export CLASSPATH
Note that only the `QTDIR` variable located in second line should be modified to point to your Qt Jambi installation directory. After you done, we can start make our “Hello World” application now.
Before you write your “Hello World” application, you need to choose a directory to place your Java source code, not the Qt Jambi installation directory, please. I created a new directory and switched directory to it in my Terminal window. Now you can create a file called “HelloWorld.java” and write the following code (borrowed from the Qt Jambi official documentation):
import com.trolltech.qt.gui.*;
public class HelloWorld
{
public static void main(String[] args)
{
QApplication.initialize(args);
QPushButton hello = new QPushButton("Hello World!");
hello.resize(120, 40);
hello.setWindowTitle("Hello World");
hello.show();
QApplication.exec();
}
}
After saving that file, back to your Terminal window, and compile the source code by running
javac HelloWorld.java
Finally, you can execute the application by running
java -d32 -XstartOnFirstThread HelloWorld
And the result should look like this:

Done!
Filed under: Java, Mac, Programming, Qt | 4 Comments
Tags: GUI, Hello World, Java, Mac, Programming, PyQt, PySide, Python, Qt, Qt Jambi, Snow Leopard, Tk, toolkit, tutorial, wxPython
Recent Entries
- An example to extract IPTC data using QMeta
- Using QMeta to extract Exif data in your Qt applications
- Creating thumbnail images in Qt
- MicroAgent debuted at late 2009
- AES Implementation in RPython
- Make a native Mac App Bundle of Qt Designer with Qt Jambi
- ANN: Jump 0.9.5.1 released!
- My first Carl Zeiss lens – 16-80mm F3.5-4.5
- Qt Jambi on Jython
- Hello World! Qt Jambi
- My first prime lens – Sony 50mm F2.8 Macro





