1
/****************************************************************************
2
**
3
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
** All rights reserved.
5
** Contact: Nokia Corporation (qt-info@nokia.com)
6
**
7
** This file is part of the QtGui module of the Qt Toolkit.
8
**
9
** $QT_BEGIN_LICENSE:LGPL$
10
** No Commercial Usage
11
** This file contains pre-release code and may not be distributed.
12
** You may use this file in accordance with the terms and conditions
13
** contained in the Technology Preview License Agreement accompanying
14
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
** Alternatively, this file may be used under the terms of the GNU Lesser
18
** General Public License version 2.1 as published by the Free Software
19
** Foundation and appearing in the file LICENSE.LGPL included in the
20
** packaging of this file.  Please review the following information to
21
** ensure the GNU Lesser General Public License version 2.1 requirements
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
**
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights.  These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27
**
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
**
31
**
32
**
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
42
/*!
43
    \class QImageWriter
44
    \brief The QImageWriter class provides a format independent interface
45
    for writing images to files or other devices.
46
47
    \reentrant
48
    \ingroup painting
49
    \ingroup io
50
51
    QImageWriter supports setting format specific options, such as the
52
    gamma level, compression level and quality, prior to storing the
53
    image. If you do not need such options, you can use QImage::save()
54
    or QPixmap::save() instead.
55
56
    To store an image, you start by constructing a QImageWriter
57
    object.  Pass either a file name or a device pointer, and the
58
    image format to QImageWriter's constructor. You can then set
59
    several options, such as the gamma level (by calling setGamma())
60
    and quality (by calling setQuality()). canWrite() returns true if
61
    QImageWriter can write the image (i.e., the image format is
62
    supported and the device is open for writing). Call write() to
63
    write the image to the device.
64
65
    If any error occurs when writing the image, write() will return
66
    false. You can then call error() to find the type of error that
67
    occurred, or errorString() to get a human readable description of
68
    what went wrong.
69
70
    Call supportedImageFormats() for a list of formats that
71
    QImageWriter can write. QImageWriter supports all built-in image
72
    formats, in addition to any image format plugins that support
73
    writing.
74
75
    \sa QImageReader, QImageIOHandler, QImageIOPlugin
76
*/
77
78
/*!
79
    \enum QImageWriter::ImageWriterError
80
81
    This enum describes errors that can occur when writing images with
82
    QImageWriter.
83
84
    \value DeviceError QImageWriter encountered a device error when
85
    writing the image data. Consult your device for more details on
86
    what went wrong.
87
88
    \value UnsupportedFormatError Qt does not support the requested
89
    image format.
90
91
    \value UnknownError An unknown error occurred. If you get this
92
    value after calling write(), it is most likely caused by a bug in
93
    QImageWriter.
94
*/
95
96
#include "qimagewriter.h"
97
98
#include <qbytearray.h>
99
#include <qfile.h>
100
#include <qfileinfo.h>
101
#include <qimageiohandler.h>
102
#include <qset.h>
103
#include <qvariant.h>
104
105
// factory loader
106
#include <qcoreapplication.h>
107
#include <private/qfactoryloader_p.h>
108
109
// image handlers
110
#include <private/qbmphandler_p.h>
111
#include <private/qppmhandler_p.h>
112
#include <private/qxbmhandler_p.h>
113
#include <private/qxpmhandler_p.h>
114
#ifndef QT_NO_IMAGEFORMAT_PNG
115
#include <private/qpnghandler_p.h>
116
#endif
117
118
QT_BEGIN_NAMESPACE
119
120
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
121
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
122
                          (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
123
#endif
124
125
static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
126
    const QByteArray &format)
127
{
128
    QByteArray form = format.toLower();
129
    QByteArray suffix;
130
    QImageIOHandler *handler = 0;
131
132
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
133
    // check if any plugins can write the image
134
    QFactoryLoader *l = loader();
135
    QStringList keys = l->keys();
136
    int suffixPluginIndex = -1;
137
#endif
138
139
    if (device && format.isEmpty()) {
140
        // if there's no format, see if \a device is a file, and if so, find
141
        // the file suffix and find support for that format among our plugins.
142
        // this allows plugins to override our built-in handlers.
143
        if (QFile *file = qobject_cast<QFile *>(device)) {
144
            if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
145
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
146
                int index = keys.indexOf(QString::fromLatin1(suffix));
147
                if (index != -1)
148
                    suffixPluginIndex = index;
149
#endif
150
            }
151
        }
152
    }
153
154
    QByteArray testFormat = !form.isEmpty() ? form : suffix;
155
156
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
157
    if (suffixPluginIndex != -1) {
158
        // when format is missing, check if we can find a plugin for the
159
        // suffix.
160
        QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(QString::fromLatin1(suffix)));
161
        if (plugin && (plugin->capabilities(device, suffix) & QImageIOPlugin::CanWrite))
162
            handler = plugin->create(device, suffix);
163
    }
164
#endif // Q_NO_LIBRARY
165
166
    // check if any built-in handlers can write the image
167
    if (!handler && !testFormat.isEmpty()) {
168
        if (false) {
169
#ifndef QT_NO_IMAGEFORMAT_PNG
170
        } else if (testFormat == "png") {
171
            handler = new QPngHandler;
172
#endif
173
#ifndef QT_NO_IMAGEFORMAT_BMP
174
        } else if (testFormat == "bmp") {
175
            handler = new QBmpHandler;
176
#endif
177
#ifndef QT_NO_IMAGEFORMAT_XPM
178
        } else if (testFormat == "xpm") {
179
            handler = new QXpmHandler;
180
#endif
181
#ifndef QT_NO_IMAGEFORMAT_XBM
182
        } else if (testFormat == "xbm") {
183
            handler = new QXbmHandler;
184
            handler->setOption(QImageIOHandler::SubType, testFormat);
185
#endif
186
#ifndef QT_NO_IMAGEFORMAT_PPM
187
        } else if (testFormat == "pbm" || testFormat == "pbmraw" || testFormat == "pgm"
188
                 || testFormat == "pgmraw" || testFormat == "ppm" || testFormat == "ppmraw") {
189
            handler = new QPpmHandler;
190
            handler->setOption(QImageIOHandler::SubType, testFormat);
191
#endif
192
        }
193
    }
194
195
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
196
    if (!testFormat.isEmpty()) {
197
        for (int i = 0; i < keys.size(); ++i) {
198
            QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
199
            if (plugin && (plugin->capabilities(device, testFormat) & QImageIOPlugin::CanWrite)) {
200
                delete handler;
201
                handler = plugin->create(device, testFormat);
202
                break;
203
            }
204
        }
205
    }
206
#endif
207
208
    if (!handler)
209
        return 0;
210
211
    handler->setDevice(device);
212
    if (!testFormat.isEmpty())
213
        handler->setFormat(testFormat);
214
    return handler;
215
}
216
217
class QImageWriterPrivate
218
{
219
public:
220
    QImageWriterPrivate(QImageWriter *qq);
221
222
    // device
223
    QByteArray format;
224
    QIODevice *device;
225
    bool deleteDevice;
226
    QImageIOHandler *handler;
227
228
    // image options
229
    int quality;
230
    int compression;
231
    float gamma;
232
    QString description;
233
    QString text;
234
235
    // error
236
    QImageWriter::ImageWriterError imageWriterError;
237
    QString errorString;
238
239
    QImageWriter *q;
240
};
241
242
/*!
243
    \internal
244
*/
245
QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
246
{
247
    device = 0;
248
    deleteDevice = false;
249
    handler = 0;
250
    quality = -1;
251
    compression = 0;
252
    gamma = 0.0;
253
    imageWriterError = QImageWriter::UnknownError;
254
    errorString = QT_TRANSLATE_NOOP(QImageWriter, QLatin1String("Unknown error"));
255
256
    q = qq;
257
}
258
259
/*!
260
    Constructs an empty QImageWriter object. Before writing, you must
261
    call setFormat() to set an image format, then setDevice() or
262
    setFileName().
263
*/
264
QImageWriter::QImageWriter()
265
    : d(new QImageWriterPrivate(this))
266
{
267
}
268
269
/*!
270
    Constructs a QImageWriter object using the device \a device and
271
    image format \a format.
272
*/
273
QImageWriter::QImageWriter(QIODevice *device, const QByteArray &format)
274
    : d(new QImageWriterPrivate(this))
275
{
276
    d->device = device;
277
    d->format = format;
278
}
279
280
/*!
281
    Constructs a QImageWriter objects that will write to a file with
282
    the name \a fileName, using the image format \a format. If \a
283
    format is not provided, QImageWriter will detect the image format
284
    by inspecting the extension of \a fileName.
285
*/
286
QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
287
    : d(new QImageWriterPrivate(this))
288
{
289
    QFile *file = new QFile(fileName);
290
    d->device = file;
291
    d->deleteDevice = true;
292
    d->format = format;
293
}
294
295
/*!
296
    Destructs the QImageWriter object.
297
*/
298
QImageWriter::~QImageWriter()
299
{
300
    if (d->deleteDevice)
301
        delete d->device;
302
    delete d->handler;
303
    delete d;
304
}
305
306
/*!
307
    Sets the format QImageWriter will use when writing images, to \a
308
    format. \a format is a case insensitive text string. Example:
309
310
    \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 0
311
312
    You can call supportedImageFormats() for the full list of formats
313
    QImageWriter supports.
314
315
    \sa format()
316
*/
317
void QImageWriter::setFormat(const QByteArray &format)
318
{
319
    d->format = format;
320
}
321
322
/*!
323
    Returns the format QImageWriter uses for writing images.
324
325
    \sa setFormat()
326
*/
327
QByteArray QImageWriter::format() const
328
{
329
    return d->format;
330
}
331
332
/*!
333
    Sets QImageWriter's device to \a device. If a device has already
334
    been set, the old device is removed from QImageWriter and is
335
    otherwise left unchanged.
336
337
    If the device is not already open, QImageWriter will attempt to
338
    open the device in \l QIODevice::WriteOnly mode by calling
339
    open(). Note that this does not work for certain devices, such as
340
    QProcess, QTcpSocket and QUdpSocket, where more logic is required
341
    to open the device.
342
343
    \sa device(), setFileName()
344
*/
345
void QImageWriter::setDevice(QIODevice *device)
346
{
347
    if (d->device && d->deleteDevice)
348
        delete d->device;
349
350
    d->device = device;
351
    d->deleteDevice = false;
352
    delete d->handler;
353
    d->handler = 0;
354
}
355
356
/*!
357
    Returns the device currently assigned to QImageWriter, or 0 if no
358
    device has been assigned.
359
*/
360
QIODevice *QImageWriter::device() const
361
{
362
    return d->device;
363
}
364
365
/*!
366
    Sets the file name of QImageWriter to \a fileName. Internally,
367
    QImageWriter will create a QFile and open it in \l
368
    QIODevice::WriteOnly mode, and use this file when writing images.
369
370
    \sa fileName(), setDevice()
371
*/
372
void QImageWriter::setFileName(const QString &fileName)
373
{
374
    setDevice(new QFile(fileName));
375
    d->deleteDevice = true;
376
}
377
378
/*!
379
    If the currently assigned device is a QFile, or if setFileName()
380
    has been called, this function returns the name of the file
381
    QImageWriter writes to. Otherwise (i.e., if no device has been
382
    assigned or the device is not a QFile), an empty QString is
383
    returned.
384
385
    \sa setFileName(), setDevice()
386
*/
387
QString QImageWriter::fileName() const
388
{
389
    QFile *file = qobject_cast<QFile *>(d->device);
390
    return file ? file->fileName() : QString();
391
}
392
393
/*!
394
    This is an image format specific function that sets the quality
395
    level of the image to \a quality. For image formats that do not
396
    support setting the quality, this value is ignored.
397
398
    The value range of \a quality depends on the image format. For
399
    example, the "jpeg" format supports a quality range from 0 (low
400
    quality, high compression) to 100 (high quality, low compression).
401
402
    \sa quality()
403
*/
404
void QImageWriter::setQuality(int quality)
405
{
406
    d->quality = quality;
407
}
408
409
/*!
410
    Returns the quality level of the image.
411
412
    \sa setQuality()
413
*/
414
int QImageWriter::quality() const
415
{
416
    return d->quality;
417
}
418
419
/*!
420
    This is an image format specific function that set the compression
421
    of an image. For image formats that do not support setting the
422
    compression, this value is ignored.
423
424
    The value range of \a compression depends on the image format. For
425
    example, the "tiff" format supports two values, 0(no compression) and
426
    1(LZW-compression).
427
428
    \sa compression()
429
*/
430
void QImageWriter::setCompression(int compression)
431
{
432
    d->compression = compression;
433
}
434
435
/*!
436
    Returns the compression of the image.
437
438
    \sa setCompression()
439
*/
440
int QImageWriter::compression() const
441
{
442
    return d->compression;
443
}
444
445
/*!
446
    This is an image format specific function that sets the gamma
447
    level of the image to \a gamma. For image formats that do not
448
    support setting the gamma level, this value is ignored.
449
450
    The value range of \a gamma depends on the image format. For
451
    example, the "png" format supports a gamma range from 0.0 to 1.0.
452
453
    \sa quality()
454
*/
455
void QImageWriter::setGamma(float gamma)
456
{
457
    d->gamma = gamma;
458
}
459
460
/*!
461
    Returns the gamma level of the image.
462
463
    \sa setGamma()
464
*/
465
float QImageWriter::gamma() const
466
{
467
    return d->gamma;
468
}
469
470
/*!
471
    \obsolete
472
473
    Use setText() instead.
474
475
    This is an image format specific function that sets the
476
    description of the image to \a description. For image formats that
477
    do not support setting the description, this value is ignored.
478
479
    The contents of \a description depends on the image format.
480
481
    \sa description()
482
*/
483
void QImageWriter::setDescription(const QString &description)
484
{
485
    d->description = description;
486
}
487
488
/*!
489
    \obsolete
490
491
    Use QImageReader::text() instead.
492
493
    Returns the description of the image.
494
495
    \sa setDescription()
496
*/
497
QString QImageWriter::description() const
498
{
499
    return d->description;
500
}
501
502
/*!
503
    \since 4.1
504
505
    Sets the image text associated with the key \a key to
506
    \a text. This is useful for storing copyright information
507
    or other information about the image. Example:
508
509
    \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 1
510
511
    If you want to store a single block of data
512
    (e.g., a comment), you can pass an empty key, or use
513
    a generic key like "Description".
514
515
    The key and text will be embedded into the
516
    image data after calling write().
517
518
    Support for this option is implemented through
519
    QImageIOHandler::Description.
520
521
    \sa QImage::setText(), QImageReader::text()
522
*/
523
void QImageWriter::setText(const QString &key, const QString &text)
524
{
525
    if (!d->description.isEmpty())
526
        d->description += QLatin1String("\n\n");
527
    d->description += key.simplified() + QLatin1String(": ") + text.simplified();
528
}
529
530
/*!
531
    Returns true if QImageWriter can write the image; i.e., the image
532
    format is supported and the assigned device is open for reading.
533
534
    \sa write(), setDevice(), setFormat()
535
*/
536
bool QImageWriter::canWrite() const
537
{
538
    if (d->device && !d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
539
        d->imageWriterError = QImageWriter::UnsupportedFormatError;
540
        d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
541
                                           QLatin1String("Unsupported image format"));
542
        return false;
543
    }
544
    if (d->device && !d->device->isOpen())
545
        d->device->open(QIODevice::WriteOnly);
546
    if (!d->device || !d->device->isWritable()) {
547
        d->imageWriterError = QImageWriter::DeviceError;
548
        d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
549
                                           QLatin1String("Device not writable"));
550
        return false;
551
    }
552
    return true;
553
}
554
555
/*!
556
    Writes the image \a image to the assigned device or file
557
    name. Returns true on success; otherwise returns false. If the
558
    operation fails, you can call error() to find the type of error
559
    that occurred, or errorString() to get a human readable
560
    description of the error.
561
562
    \sa canWrite(), error(), errorString()
563
*/
564
bool QImageWriter::write(const QImage &image)
565
{
566
    if (!canWrite())
567
        return false;
568
569
    if (d->handler->supportsOption(QImageIOHandler::Quality))
570
        d->handler->setOption(QImageIOHandler::Quality, d->quality);
571
    if (d->handler->supportsOption(QImageIOHandler::CompressionRatio))
572
        d->handler->setOption(QImageIOHandler::CompressionRatio, d->compression);
573
    if (d->handler->supportsOption(QImageIOHandler::Gamma))
574
        d->handler->setOption(QImageIOHandler::Gamma, d->gamma);
575
    if (!d->description.isEmpty() && d->handler->supportsOption(QImageIOHandler::Description))
576
        d->handler->setOption(QImageIOHandler::Description, d->description);
577
578
    if (!d->handler->write(image))
579
        return false;
580
    if (QFile *file = qobject_cast<QFile *>(d->device))
581
        file->flush();
582
    return true;
583
}
584
585
/*!
586
    Returns the type of error that last occurred.
587
588
    \sa ImageWriterError, errorString()
589
*/
590
QImageWriter::ImageWriterError QImageWriter::error() const
591
{
592
    return d->imageWriterError;
593
}
594
595
/*!
596
    Returns a human readable description of the last error that occurred.
597
598
    \sa error()
599
*/
600
QString QImageWriter::errorString() const
601
{
602
    return d->errorString;
603
}
604
605
/*!
606
    \since 4.2
607
608
    Returns true if the writer supports \a option; otherwise returns
609
    false.
610
611
    Different image formats support different options. Call this function to
612
    determine whether a certain option is supported by the current format. For
613
    example, the PNG format allows you to embed text into the image's metadata
614
    (see text()).
615
616
    \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 2
617
618
    Options can be tested after the writer has been associated with a format.
619
620
    \sa QImageReader::supportsOption(), setFormat()
621
*/
622
bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
623
{
624
    if (!d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
625
        d->imageWriterError = QImageWriter::UnsupportedFormatError;
626
        d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
627
                                           QLatin1String("Unsupported image format"));
628
        return false;
629
    }
630
631
    return d->handler->supportsOption(option);
632
}
633
634
/*!
635
    Returns the list of image formats supported by QImageWriter.
636
637
    By default, Qt can write the following formats:
638
639
    \table
640
    \header \o Format \o Description
641
    \row    \o BMP    \o Windows Bitmap
642
    \row    \o JPG    \o Joint Photographic Experts Group
643
    \row    \o JPEG   \o Joint Photographic Experts Group
644
    \row    \o PNG    \o Portable Network Graphics
645
    \row    \o PPM    \o Portable Pixmap
646
    \row    \o TIFF   \o Tagged Image File Format
647
    \row    \o XBM    \o X11 Bitmap
648
    \row    \o XPM    \o X11 Pixmap
649
    \endtable
650
651
    Reading and writing SVG files is supported through Qt's
652
    \l{QtSvg Module}{SVG Module}.
653
654
    \sa setFormat(), QImageReader::supportedImageFormats(), QImageIOPlugin
655
*/
656
QList<QByteArray> QImageWriter::supportedImageFormats()
657
{
658
    QSet<QByteArray> formats;
659
    formats << "bmp";
660
#ifndef QT_NO_IMAGEFORMAT_PPM
661
    formats << "ppm";
662
#endif
663
#ifndef QT_NO_IMAGEFORMAT_XBM
664
    formats << "xbm";
665
#endif
666
#ifndef QT_NO_IMAGEFORMAT_XPM
667
    formats << "xpm";
668
#endif
669
#ifndef QT_NO_IMAGEFORMAT_PNG
670
    formats << "png";
671
#endif
672
673
#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
674
    QFactoryLoader *l = loader();
675
    QStringList keys = l->keys();
676
    for (int i = 0; i < keys.count(); ++i) {
677
        QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
678
        if (plugin && (plugin->capabilities(0, keys.at(i).toLatin1()) & QImageIOPlugin::CanWrite) != 0)
679
            formats << keys.at(i).toLatin1();
680
    }
681
#endif // QT_NO_LIBRARY
682
683
    QList<QByteArray> sortedFormats;
684
    for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
685
        sortedFormats << *it;
686
687
    qSort(sortedFormats);
688
    return sortedFormats;
689
}
690
691
QT_END_NAMESPACE