1/*
2 Copyright (C) 2009 Canonical
3 Author: Aurélien Gâteau <aurelien.gateau@canonical.com>
4
5 This program is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 2 or 3 of the License.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
12 General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include "imageconverter.h"
18
19#include <QDBusArgument>
20#include <QDBusMetaType>
21#include <QImage>
22
23namespace ImageConverter
24{
25
26/**
27 * A structure representing an image which can be marshalled to fit the
28 * notification spec.
29 */
30struct SpecImage
31{
32 int width, height, rowStride;
33 bool hasAlpha;
34 int bitsPerSample, channels;
35 QByteArray data;
36};
37
38QDBusArgument &operator<<(QDBusArgument &argument, const SpecImage &image)
39{
40 argument.beginStructure();
41 argument << image.width << image.height << image.rowStride << image.hasAlpha;
42 argument << image.bitsPerSample << image.channels << image.data;
43 argument.endStructure();
44 return argument;
45}
46
47const QDBusArgument &operator>>(const QDBusArgument &argument, SpecImage &image)
48{
49 argument.beginStructure();
50 argument >> image.width >> image.height >> image.rowStride >> image.hasAlpha;
51 argument >> image.bitsPerSample >> image.channels >> image.data;
52 argument.endStructure();
53 return argument;
54}
55
56} // namespace
57
58// This must be before the QVariant::fromValue below (#211726)
59Q_DECLARE_METATYPE(ImageConverter::SpecImage)
60
61namespace ImageConverter
62{
63QVariant variantForImage(const QImage &_image)
64{
65 qDBusRegisterMetaType<SpecImage>();
66
67 QImage image = _image.convertToFormat(QImage::Format_ARGB32);
68
69 int rowStride = image.width() * 4;
70
71 // Notification spec stores pixels in R,G,B,A order, regardless of
72 // endianess
73 // Qt represents pixels as 32 bit unsigned int. So the order depend on
74 // endianess:
75 // - In big endian the order is A,R,G,B
76 // - In little endian the order is B,G,R,A
77 QByteArray data;
78 data.resize(rowStride * image.height());
79 char* dst = data.data();
80 for (int y=0; y<image.height(); ++y) {
81 QRgb* src = (QRgb*)image.scanLine(y);
82 QRgb* end = src + image.width();
83 for (;src != end; ++src) {
84 // Probably slow, but free of endianess issues
85 *dst++ = qRed(*src);
86 *dst++ = qGreen(*src);
87 *dst++ = qBlue(*src);
88 *dst++ = qAlpha(*src);
89 }
90 }
91
92 SpecImage specImage;
93 specImage.width = image.width();
94 specImage.height = image.height();
95 specImage.rowStride = rowStride;
96 specImage.hasAlpha = true;
97 specImage.bitsPerSample = 8;
98 specImage.channels = 4;
99 specImage.data = data;
100
101 return QVariant::fromValue(specImage);
102}
103
104} // namespace
105
106