1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the painting module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "private/qxbmhandler_p.h"
32
#include <qiodevice.h>
39
/*****************************************************************************
40
X bitmap image read/write functions
41
*****************************************************************************/
43
static inline int hex2byte(register char *p)
45
return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) |
46
(isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10);
49
static bool read_xbm_image(QIODevice *device, QImage *outImage)
51
const int buflen = 300;
53
QRegExp r1(QLatin1String("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+"));
54
QRegExp r2(QLatin1String("[0-9]+"));
60
// "#define .._width <num>"
61
readBytes = device->readLine(buf, buflen);
64
buf[readBytes] = '\0';
66
// skip initial comment, if any
67
while (buf[0] != '#' && (readBytes = device->readLine( buf, buflen )) > 0);
71
buf[readBytes] = '\0';
73
sbuf = QString::fromLatin1(buf);
75
if (r1.indexIn(sbuf) == 0 &&
76
r2.indexIn(sbuf, r1.matchedLength()) == r1.matchedLength())
77
w = QString(&buf[r1.matchedLength()]).toInt();
79
// "#define .._height <num>"
80
readBytes = device->readLine(buf, buflen);
83
buf[readBytes] = '\0';
85
sbuf = QString::fromLatin1(buf);
87
if (r1.indexIn(sbuf) == 0 &&
88
r2.indexIn(sbuf, r1.matchedLength()) == r1.matchedLength())
89
h = QString(&buf[r1.matchedLength()]).toInt();
92
if (w <= 0 || w > 32767 || h <= 0 || h > 32767)
97
if ((readBytes = device->readLine(buf, buflen)) <= 0) {
102
buf[readBytes] = '\0';
103
if (QByteArray::fromRawData(buf, readBytes).contains("0x"))
107
image = QImage(w, h, QImage::Format_MonoLSB);
111
image.setNumColors(2);
112
image.setColor(0, qRgb(255,255,255)); // white
113
image.setColor(1, qRgb(0,0,0)); // black
116
uchar *b = image.scanLine(0);
117
char *p = buf + QByteArray::fromRawData(buf, readBytes).indexOf("0x");
118
w = (w+7)/8; // byte width
120
while (y < h) { // for all encoded bytes...
121
if (p) { // p = "0x.."
122
*b++ = hex2byte(p+2);
124
if (++x == w && ++y < h) {
125
b = image.scanLine(y);
129
} else { // read another line
130
if ((readBytes = device->readLine(buf,buflen)) <= 0) // EOF ==> truncated image
132
p = buf + QByteArray::fromRawData(buf, readBytes).indexOf("0x");
140
static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const QString &fileName)
142
QImage image = sourceImage;
143
int w = image.width();
144
int h = image.height();
146
QString s = fileName; // get file base name
147
char *buf = new char[s.length() + 100];
149
sprintf(buf, "#define %s_width %d\n", s.toAscii().data(), w);
150
device->write(buf, qstrlen(buf));
151
sprintf(buf, "#define %s_height %d\n", s.toAscii().data(), h);
152
device->write(buf, qstrlen(buf));
153
sprintf(buf, "static char %s_bits[] = {\n ", s.toAscii().data());
154
device->write(buf, qstrlen(buf));
156
if (image.format() != QImage::Format_MonoLSB)
157
image = image.convertToFormat(QImage::Format_MonoLSB);
159
bool invert = qGray(image.color(0)) < qGray(image.color(1));
163
for (i=10; i<16; i++)
164
hexrep[i] = 'a' -10 + i;
167
for (i=0; i<8; i++) {
169
hexrep[15-i] = hexrep[i];
174
register char *p = buf;
176
for (int y = 0; y < h; ++y) {
177
uchar *b = image.scanLine(y);
178
for (i = 0; i < bpl; ++i) {
179
*p++ = '0'; *p++ = 'x';
180
*p++ = hexrep[*b >> 4];
181
*p++ = hexrep[*b++ & 0xf];
183
if (i < bpl - 1 || y < h - 1) {
189
if ((int)qstrlen(buf) != device->write(buf, qstrlen(buf))) {
200
if ((int)qstrlen(buf) != device->write(buf, qstrlen(buf))) {
209
bool QXbmHandler::canRead() const
211
return canRead(device());
214
bool QXbmHandler::canRead(QIODevice *device)
218
// it's impossible to tell whether we can load an XBM or not when
219
// it's from a sequential device, as the only way to do it is to
220
// attempt to parse the whole image.
221
if (device->isSequential())
224
qint64 oldPos = device->pos();
225
bool success = read_xbm_image(device, &image);
226
device->seek(oldPos);
231
bool QXbmHandler::read(QImage *image)
233
return read_xbm_image(device(), image);
236
bool QXbmHandler::write(const QImage &image)
238
return write_xbm_image(image, device(), fileName);
241
bool QXbmHandler::supportsOption(ImageOption option) const
243
return option == Name;
246
QVariant QXbmHandler::option(ImageOption option) const
248
return option == Name ? fileName : QString();
251
void QXbmHandler::setOption(ImageOption option, const QVariant &value)
254
fileName = value.toString();
257
QByteArray QXbmHandler::name() const