Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries. Thanks for all your past and future contributions.

Photomosaic App with Qt

From Wiki
Jump to: navigation, search

This article explains how to create an app that will take a photo, upload it to a server, wait for a response image, and display it on the phone. This application uses Nokia N9 (MeeGo Harmattan), is written in Qt and QML, and uses MeeGo Touch Framework. The image created on the server is a photomosaic, and there are many other features to the application: uploading photos from galleries, viewing the photomosaic with pinch zooming, uploading the result to Facebook, and more. The server setup is explained as well.

Note.pngNote: This is an entry in the PureView Imaging Competition 2012Q2

Article Metadata
Code ExampleTested with
SDK: Qt SDK 1.2.1
Devices(s): Nokia N9
Platform(s): MeeGo harmattan 1.2
Created: martaskolda (09 May 2012)
Last edited: kiran10182 (31 Oct 2013)



The app described in this article uses a database of 100000 open source photos from the Internet to convert any picture to a photomosaic. The images below show a photo taken using a mobile device and the resulting photomosaic.

PhotoMosaicScreenshot01.jpg PhotoMosaicScreenshot02.jpg

The following sections describe the code for the application and the server.

Server setup

Since the photomosaic requires a large number of images and a lot of processing power, it cannot be run on the phone directly. In this section we describe how to set-up a Linux server with Apache and PHP that will accept requests from the phone, create the photomosaic using metapixel, and send back the image.

Image database with Metapixel

The image tiles on our test server are created from public images downloaded from Flickr® via the Flickr® API. For example, use the following script with the Ruby flickraw API:

require 'rubygems'
require 'flickraw'
require 'active_support'
require 'open-uri'
for j in 1..200 #number of pages of images to get
photos = :per_page => 500, :page => j #get another 500 images (500 is the maximum allowed number of images per page)
photos.each { |x| f.puts "id:#{} \"title:#{x.title}\" (#{x.latitude},#{x.longitude},#{x.accuracy}) - #{x.tags}""images/" + + ".jpg",'w') do |i| #save each image in the images folder
open("http://farm#{}{x.server}/#{}_#{x.secret}_z.jpg") { |wimage| i.puts }

Once you have a large collection of images, use the metapixel bash script to create a database of tiles for photomosaics. First, install metapixel and imagemagick

sudo yum install metapixel imagemagick

and then run metapixel-prepare to prepare the tiles (This will take a while)

metapixel-prepare -r /home/bob/Documents/images/ /home/bob/Documents/metapixel_tiles/ --width=50 --height=50

LAMP setup

This is explained in various tutorials over the net. Depending on your server architecture, use one of the following:
LAMP on Ubuntu
LAMP of Fedora
LAMP on Arch
LAMP on CentOS

Make sure that uploading is enabled!

PHP script

Once you have the metapixel image tiles and the server running, use a script as follows to receive a POST request, use exec to run the bash command, and keep the file available in the mosaics folder. This ensures that if the images are sent or linked from Facebook (for example), they will stay available.

if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg")
|| ($_FILES["file"]["type"] == "image/png"))
&& ($_FILES["file"]["size"] < 2000000)) { //file is an image, and has at most 2 Mb
if ($_FILES["file"]["error"] > 0) { //the file could not be uploaded
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
} else {
if (file_exists("upload/" . $_FILES["file"]["name"])) {
echo $_FILES["file"]["name"] . " already exists. ";
} else {
move_uploaded_file($_FILES["file"]["tmp_name"], "/var/www/upload/" . $_FILES["file"]["name"]); //move the uploaded file
exec ("./ ". escapeshellarg($_FILES["file"]["name"]), &$output); //run the script that creates the photomosaic, and wait for its output. This is in /var/www
echo "".$output[0].".jpg"; //the mosaic is now in mosaics for later use, with a random name
} else {
echo "Invalid file";

This script requires the bash script

rand=$RANDOM$RANDOM$RANDOM$RANDOM #generate a random and unique name
convert -resize 640x640 upload/$1 image_${rand}.jpg #make the image to a standard format
#generate the photomosaic
metapixel --metapixel /var/www/upload/image_${rand}.jpg /var/www/upload/tmp_${rand}.jpg --library /home/bob/Documents/metapixel_tiles/ --scale=3 --distance=50
convert -resize 80% tmp_${rand}.jpg mosaics/${rand}.jpg #make the photomosaic smaller and move it to the mosaics folder
mv upload/$1 mosaics/original_${rand}.jpg #move the original image to mosaics (not necessary)
rm image_${rand}.jpg tmp_${rand}.jpg #delete temporary files

Smartphone setup


This section describes how to implement the key features of the Qt application on the Smartphone. Basic knowledge of QML and Qt programming is expected. For an introduction to these, look here for QML, and here for Qt.

QML Camera

This example uses the QML Camera Element to obtain the image from the camera. At time of writing this only supports still photos using the rear camera - however that is all that is needed for this app. Its captureImage() method is used to capture the image - implement the callback onImageCaptured() and set the Image displayed to take the value of the preview variable. We also implement the callback to onImageSaved() to save the image to a file whose location is set by capturedImagePath. The preview is available before the image is saved, so it is useful to display it to the user instead of waiting for the saved image. Naturally, the saved image is in higher quality, so the preview image is not ideal for all applications. For more information, look at the documentation for these: [1]

import QtMultimediaKit 1.1
Page {
orientationLock: PageOrientation.LockLandscape ;
Camera {
anchors.fill: parent;
captureResolution: "1152x648" /* 16:9 resolution suitable for n9 full screen */
onImageCaptured: { /* "preview" of captured image is available */
previewImage.source = preview
onImageSaved: { /* capturedImage is available */
uploader.attachment = capturedImagePath;
Image {
id: previewImage
anchors.fill: parent;
visible: !rearcam.visible
Button {
width : 100; height : 100;
anchors.right : parent.right;
anchors.verticalCenter : parent.verticalCenter
iconSource : "image://theme/icon-l-camera-standby"
onClicked: {


In order to upload the image via HTTP to the server, the image data are sent in binary format using HTTP POST. The response from the server is sent back to the mobile device. The image is rescaled to a smaller resolution, so that the uploaded size is ~25Kb.

The uploader code is written using Qt C++ and exposed to QML as the "Uploader" type. The connection between QML and Qt is implemented in C++ using:

qmlRegisterType<Uploader>("", 1, 0, "Uploader");

where <Uploader> is the class name, "" is the namespace, followed by the version, and "Uploader" is the class name.

This is then used in QML as shown:

import 1.0
Uploader {

Saving the image and sharing on Facebook is done similarly. (see source: Media:PhotoMosaicSource.tar.gz)

#ifndef UPLOADER_H
#define UPLOADER_H
#include <QtNetwork>
#include <QObject>
#include <QImage>
class Uploader : public QObject
QString m_attachment;
QImage m_image;
QString m_response;
QNetworkAccessManager *manager;
QNetworkReply* mainReply;
explicit Uploader(QObject *parent = 0);
Q_INVOKABLE void send();
Q_PROPERTY(QString attachment READ getAttachment WRITE setAttachment) // local name of uploaded file e.g. "/home/user/MyDocs/DCIM/Image0001.jpeg"
Q_PROPERTY(QString response READ getResponse WRITE setResponse NOTIFY uploadFinished) // the http response
// methods required by Q_PROPERTYs
QString getResponse() { return m_response; }
void setResponse(QString _response) { m_response = _response; }
QString getAttachment() { return m_attachment; }
void setAttachment(QString _attachment) { m_attachment = _attachment; }
public slots:
void finished(QNetworkReply *reply);
void uploadFinished(); // signal for busyIndicator
void uploadStarted(); // signal for busyIndicator
#endif // UPLOADER_H
#include <QDebug>
#include <QtNetwork>
#include <QtGui>
#include <QtDeclarative>
#include "uploader.h"
Uploader::Uploader(QObject *parent) :
manager = new QNetworkAccessManager;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));
* The method which handles server http responses

void Uploader::finished(QNetworkReply *reply) {
if (reply->error() != QNetworkReply::NoError) {
qDebug() << reply->errorString();
emit uploadFinished();
// qDebug() << reply->readAll();
* method which sends the data to server
* it is necessary to set ".attachment" property before.

void Uploader::send() {
if (mainReply)
char boundary[] = "AyV04a234DsHeKHcvNds"; //random unique divider
// loads image from file
if (m_image.isNull()) {
emit uploadStarted();
QImage tmpImage = m_image.scaled ( QSize(640, 480),Qt::KeepAspectRatio, Qt::FastTransformation );
// save image into the buffer
QByteArray body;
QBuffer buffer(&body);;, "JPG");
qDebug() << "image size" << tmpImage.size();
QByteArray b;
b.append("Content-Disposition: form-data; name=\"file\"; filename=\"camera.jpeg\"\r\n");
b.append("Content-Type: image/jpeg\r\n");
QNetworkRequest req = QNetworkRequest(QUrl(""));
req.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(QString("multipart/form-data; boundary=")+boundary));
req.setHeader(QNetworkRequest::ContentLengthHeader, QString::number(b.size()));
req.setRawHeader("Connection", "Close");
req.setRawHeader("Cache-Control", "no-cache");
req.setRawHeader("Keep-Alive", "1");
manager->post(req, b); //POST

QML ZoomableImage

The returned image has ~250KB and is much larger than the smartphone display. In order to display the it effectively, use the ZoomableImage component from the project QuickFlickr. This component displays the image and allows zooming and scrolling using Pinch and Pan gestures.


Using the QML element Image you can view the image from its source, but there is no direct interface to the image itself. Saving the image locally, or accessing it pixel-by-pixel is therefore difficult. The following code show typical usage of the Image object.

Image {
source: ""

In order to access the image directly, the Image can be extended by the ImageSaver [2] wrapper, which copies the image to the QImage structure.

id: saver
Image {
id: photo
source: ""
onStatusChanged: {
if (status == Image.Ready) {,"/home/user/MyDocs/Pictures/mosaic.jpeg")


To share the photomosaic in a social network (including Facebook, Twitter, DropBox, and all others compatible with the Sharing API), use the ShareHelper wrapper around the MDataUri class. ShareHelper provides a QML API for this.

PhotoMosaicScreenshot04.png PhotoMosaicScreenshot05.png

CONFIG += meegotouch
CONFIG += shareuiinterface-maemo-meegotouch mdatauri

The code below is based on In order to see the full c++ code in context, the rest of the interface can be found in the source: Media:PhotoMosaicSource.tar.gz

#include <QObject>
class ShareHelper : public QObject {
explicit ShareHelper(QObject *parent =
public slots:
void share(QString title, QString url);
#include <QDeclarativeContext>
#include <maemo-meegotouch-interfaces/shareuiinterface.h>
#include <MDataUri>
ShareHelper::ShareHelper(QObject *parent) :
QObject(parent) {
void ShareHelper::share(QString title, QString url) {
/* First, the data as a title, description, url i.e. "content", and its mime type are setted */
MDataUri dataUri;
dataUri.setAttribute("title", title);
dataUri.setAttribute("description", tr("Photo Mosaic"));
QStringList items;
items << dataUri.toString();
/* ShareUIInterface is using N9 accounts to share data to internet */
ShareUiInterface shareIf("");
if (shareIf.isValid()) {
} else {
qCritical() << "Invalid interface";

The following code uses the same method as the similar code it the Upload section.

qmlRegisterType<ShareHelper>("", 1, 0, "ShareHelper");
import 1.0
ShareHelper {
id: shareHelper
onClicked: {
shareHelper.share("Photo Mosaic", result)


This tutorial demonstrates how simple it is to make an application that uploads an image to a server and displays the response. Many interesting features can be implemented with this, such as image search by similarity, object recognition, face recognition, an many others. It demonstrates some of the many features of the QML and Qt Mobility framework, such as social sharing, multi-touch picture browsing, and communication with a server.

We created a short video to demonstrate this application, available here: The media player is loading...

This page was last modified on 31 October 2013, at 21:27.
160 page views in the last 30 days.