source: trunk/src/gui/image/qimagewriter.cpp@ 855

Last change on this file since 855 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 21.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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#ifndef QT_NO_IMAGEFORMAT_JPEG
118#include <private/qjpeghandler_p.h>
119#endif
120#ifndef QT_NO_IMAGEFORMAT_MNG
121#include <private/qmnghandler_p.h>
122#endif
123#ifndef QT_NO_IMAGEFORMAT_TIFF
124#include <private/qtiffhandler_p.h>
125#endif
126#ifdef QT_BUILTIN_GIF_READER
127#include <private/qgifhandler_p.h>
128#endif
129
130QT_BEGIN_NAMESPACE
131
132#ifndef QT_NO_LIBRARY
133Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
134 (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
135#endif
136
137static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
138 const QByteArray &format)
139{
140 QByteArray form = format.toLower();
141 QByteArray suffix;
142 QImageIOHandler *handler = 0;
143
144#ifndef QT_NO_LIBRARY
145 // check if any plugins can write the image
146 QFactoryLoader *l = loader();
147 QStringList keys = l->keys();
148 int suffixPluginIndex = -1;
149#endif
150
151 if (device && format.isEmpty()) {
152 // if there's no format, see if \a device is a file, and if so, find
153 // the file suffix and find support for that format among our plugins.
154 // this allows plugins to override our built-in handlers.
155 if (QFile *file = qobject_cast<QFile *>(device)) {
156 if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
157#ifndef QT_NO_LIBRARY
158 int index = keys.indexOf(QString::fromLatin1(suffix));
159 if (index != -1)
160 suffixPluginIndex = index;
161#endif
162 }
163 }
164 }
165
166 QByteArray testFormat = !form.isEmpty() ? form : suffix;
167
168#ifndef QT_NO_LIBRARY
169 if (suffixPluginIndex != -1) {
170 // when format is missing, check if we can find a plugin for the
171 // suffix.
172 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(QString::fromLatin1(suffix)));
173 if (plugin && (plugin->capabilities(device, suffix) & QImageIOPlugin::CanWrite))
174 handler = plugin->create(device, suffix);
175 }
176#endif // QT_NO_LIBRARY
177
178 // check if any built-in handlers can write the image
179 if (!handler && !testFormat.isEmpty()) {
180 if (false) {
181#ifndef QT_NO_IMAGEFORMAT_PNG
182 } else if (testFormat == "png") {
183 handler = new QPngHandler;
184#endif
185#ifndef QT_NO_IMAGEFORMAT_JPEG
186 } else if (testFormat == "jpg" || testFormat == "jpeg") {
187 handler = new QJpegHandler;
188#endif
189#ifndef QT_NO_IMAGEFORMAT_MNG
190 } else if (testFormat == "mng") {
191 handler = new QMngHandler;
192#endif
193#ifndef QT_NO_IMAGEFORMAT_TIFF
194 } else if (testFormat == "tif" || testFormat == "tiff") {
195 handler = new QTiffHandler;
196#endif
197#ifdef QT_BUILTIN_GIF_READER
198 } else if (testFormat == "gif") {
199 handler = new QGifHandler;
200#endif
201#ifndef QT_NO_IMAGEFORMAT_BMP
202 } else if (testFormat == "bmp") {
203 handler = new QBmpHandler;
204#endif
205#ifndef QT_NO_IMAGEFORMAT_XPM
206 } else if (testFormat == "xpm") {
207 handler = new QXpmHandler;
208#endif
209#ifndef QT_NO_IMAGEFORMAT_XBM
210 } else if (testFormat == "xbm") {
211 handler = new QXbmHandler;
212 handler->setOption(QImageIOHandler::SubType, testFormat);
213#endif
214#ifndef QT_NO_IMAGEFORMAT_PPM
215 } else if (testFormat == "pbm" || testFormat == "pbmraw" || testFormat == "pgm"
216 || testFormat == "pgmraw" || testFormat == "ppm" || testFormat == "ppmraw") {
217 handler = new QPpmHandler;
218 handler->setOption(QImageIOHandler::SubType, testFormat);
219#endif
220 }
221 }
222
223#ifndef QT_NO_LIBRARY
224 if (!testFormat.isEmpty()) {
225 for (int i = 0; i < keys.size(); ++i) {
226 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
227 if (plugin && (plugin->capabilities(device, testFormat) & QImageIOPlugin::CanWrite)) {
228 delete handler;
229 handler = plugin->create(device, testFormat);
230 break;
231 }
232 }
233 }
234#endif // QT_NO_LIBRARY
235
236 if (!handler)
237 return 0;
238
239 handler->setDevice(device);
240 if (!testFormat.isEmpty())
241 handler->setFormat(testFormat);
242 return handler;
243}
244
245class QImageWriterPrivate
246{
247public:
248 QImageWriterPrivate(QImageWriter *qq);
249
250 // device
251 QByteArray format;
252 QIODevice *device;
253 bool deleteDevice;
254 QImageIOHandler *handler;
255
256 // image options
257 int quality;
258 int compression;
259 float gamma;
260 QString description;
261 QString text;
262
263 // error
264 QImageWriter::ImageWriterError imageWriterError;
265 QString errorString;
266
267 QImageWriter *q;
268};
269
270/*!
271 \internal
272*/
273QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
274{
275 device = 0;
276 deleteDevice = false;
277 handler = 0;
278 quality = -1;
279 compression = 0;
280 gamma = 0.0;
281 imageWriterError = QImageWriter::UnknownError;
282 errorString = QT_TRANSLATE_NOOP(QImageWriter, QLatin1String("Unknown error"));
283
284 q = qq;
285}
286
287/*!
288 Constructs an empty QImageWriter object. Before writing, you must
289 call setFormat() to set an image format, then setDevice() or
290 setFileName().
291*/
292QImageWriter::QImageWriter()
293 : d(new QImageWriterPrivate(this))
294{
295}
296
297/*!
298 Constructs a QImageWriter object using the device \a device and
299 image format \a format.
300*/
301QImageWriter::QImageWriter(QIODevice *device, const QByteArray &format)
302 : d(new QImageWriterPrivate(this))
303{
304 d->device = device;
305 d->format = format;
306}
307
308/*!
309 Constructs a QImageWriter objects that will write to a file with
310 the name \a fileName, using the image format \a format. If \a
311 format is not provided, QImageWriter will detect the image format
312 by inspecting the extension of \a fileName.
313*/
314QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
315 : d(new QImageWriterPrivate(this))
316{
317 QFile *file = new QFile(fileName);
318 d->device = file;
319 d->deleteDevice = true;
320 d->format = format;
321}
322
323/*!
324 Destructs the QImageWriter object.
325*/
326QImageWriter::~QImageWriter()
327{
328 if (d->deleteDevice)
329 delete d->device;
330 delete d->handler;
331 delete d;
332}
333
334/*!
335 Sets the format QImageWriter will use when writing images, to \a
336 format. \a format is a case insensitive text string. Example:
337
338 \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 0
339
340 You can call supportedImageFormats() for the full list of formats
341 QImageWriter supports.
342
343 \sa format()
344*/
345void QImageWriter::setFormat(const QByteArray &format)
346{
347 d->format = format;
348}
349
350/*!
351 Returns the format QImageWriter uses for writing images.
352
353 \sa setFormat()
354*/
355QByteArray QImageWriter::format() const
356{
357 return d->format;
358}
359
360/*!
361 Sets QImageWriter's device to \a device. If a device has already
362 been set, the old device is removed from QImageWriter and is
363 otherwise left unchanged.
364
365 If the device is not already open, QImageWriter will attempt to
366 open the device in \l QIODevice::WriteOnly mode by calling
367 open(). Note that this does not work for certain devices, such as
368 QProcess, QTcpSocket and QUdpSocket, where more logic is required
369 to open the device.
370
371 \sa device(), setFileName()
372*/
373void QImageWriter::setDevice(QIODevice *device)
374{
375 if (d->device && d->deleteDevice)
376 delete d->device;
377
378 d->device = device;
379 d->deleteDevice = false;
380 delete d->handler;
381 d->handler = 0;
382}
383
384/*!
385 Returns the device currently assigned to QImageWriter, or 0 if no
386 device has been assigned.
387*/
388QIODevice *QImageWriter::device() const
389{
390 return d->device;
391}
392
393/*!
394 Sets the file name of QImageWriter to \a fileName. Internally,
395 QImageWriter will create a QFile and open it in \l
396 QIODevice::WriteOnly mode, and use this file when writing images.
397
398 \sa fileName(), setDevice()
399*/
400void QImageWriter::setFileName(const QString &fileName)
401{
402 setDevice(new QFile(fileName));
403 d->deleteDevice = true;
404}
405
406/*!
407 If the currently assigned device is a QFile, or if setFileName()
408 has been called, this function returns the name of the file
409 QImageWriter writes to. Otherwise (i.e., if no device has been
410 assigned or the device is not a QFile), an empty QString is
411 returned.
412
413 \sa setFileName(), setDevice()
414*/
415QString QImageWriter::fileName() const
416{
417 QFile *file = qobject_cast<QFile *>(d->device);
418 return file ? file->fileName() : QString();
419}
420
421/*!
422 This is an image format specific function that sets the quality
423 level of the image to \a quality. For image formats that do not
424 support setting the quality, this value is ignored.
425
426 The value range of \a quality depends on the image format. For
427 example, the "jpeg" format supports a quality range from 0 (low
428 quality, high compression) to 100 (high quality, low compression).
429
430 \sa quality()
431*/
432void QImageWriter::setQuality(int quality)
433{
434 d->quality = quality;
435}
436
437/*!
438 Returns the quality level of the image.
439
440 \sa setQuality()
441*/
442int QImageWriter::quality() const
443{
444 return d->quality;
445}
446
447/*!
448 This is an image format specific function that set the compression
449 of an image. For image formats that do not support setting the
450 compression, this value is ignored.
451
452 The value range of \a compression depends on the image format. For
453 example, the "tiff" format supports two values, 0(no compression) and
454 1(LZW-compression).
455
456 \sa compression()
457*/
458void QImageWriter::setCompression(int compression)
459{
460 d->compression = compression;
461}
462
463/*!
464 Returns the compression of the image.
465
466 \sa setCompression()
467*/
468int QImageWriter::compression() const
469{
470 return d->compression;
471}
472
473/*!
474 This is an image format specific function that sets the gamma
475 level of the image to \a gamma. For image formats that do not
476 support setting the gamma level, this value is ignored.
477
478 The value range of \a gamma depends on the image format. For
479 example, the "png" format supports a gamma range from 0.0 to 1.0.
480
481 \sa quality()
482*/
483void QImageWriter::setGamma(float gamma)
484{
485 d->gamma = gamma;
486}
487
488/*!
489 Returns the gamma level of the image.
490
491 \sa setGamma()
492*/
493float QImageWriter::gamma() const
494{
495 return d->gamma;
496}
497
498/*!
499 \obsolete
500
501 Use setText() instead.
502
503 This is an image format specific function that sets the
504 description of the image to \a description. For image formats that
505 do not support setting the description, this value is ignored.
506
507 The contents of \a description depends on the image format.
508
509 \sa description()
510*/
511void QImageWriter::setDescription(const QString &description)
512{
513 d->description = description;
514}
515
516/*!
517 \obsolete
518
519 Use QImageReader::text() instead.
520
521 Returns the description of the image.
522
523 \sa setDescription()
524*/
525QString QImageWriter::description() const
526{
527 return d->description;
528}
529
530/*!
531 \since 4.1
532
533 Sets the image text associated with the key \a key to
534 \a text. This is useful for storing copyright information
535 or other information about the image. Example:
536
537 \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 1
538
539 If you want to store a single block of data
540 (e.g., a comment), you can pass an empty key, or use
541 a generic key like "Description".
542
543 The key and text will be embedded into the
544 image data after calling write().
545
546 Support for this option is implemented through
547 QImageIOHandler::Description.
548
549 \sa QImage::setText(), QImageReader::text()
550*/
551void QImageWriter::setText(const QString &key, const QString &text)
552{
553 if (!d->description.isEmpty())
554 d->description += QLatin1String("\n\n");
555 d->description += key.simplified() + QLatin1String(": ") + text.simplified();
556}
557
558/*!
559 Returns true if QImageWriter can write the image; i.e., the image
560 format is supported and the assigned device is open for reading.
561
562 \sa write(), setDevice(), setFormat()
563*/
564bool QImageWriter::canWrite() const
565{
566 if (d->device && !d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
567 d->imageWriterError = QImageWriter::UnsupportedFormatError;
568 d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
569 QLatin1String("Unsupported image format"));
570 return false;
571 }
572 if (d->device && !d->device->isOpen())
573 d->device->open(QIODevice::WriteOnly);
574 if (!d->device || !d->device->isWritable()) {
575 d->imageWriterError = QImageWriter::DeviceError;
576 d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
577 QLatin1String("Device not writable"));
578 return false;
579 }
580 return true;
581}
582
583/*!
584 Writes the image \a image to the assigned device or file
585 name. Returns true on success; otherwise returns false. If the
586 operation fails, you can call error() to find the type of error
587 that occurred, or errorString() to get a human readable
588 description of the error.
589
590 \sa canWrite(), error(), errorString()
591*/
592bool QImageWriter::write(const QImage &image)
593{
594 if (!canWrite())
595 return false;
596
597 if (d->handler->supportsOption(QImageIOHandler::Quality))
598 d->handler->setOption(QImageIOHandler::Quality, d->quality);
599 if (d->handler->supportsOption(QImageIOHandler::CompressionRatio))
600 d->handler->setOption(QImageIOHandler::CompressionRatio, d->compression);
601 if (d->handler->supportsOption(QImageIOHandler::Gamma))
602 d->handler->setOption(QImageIOHandler::Gamma, d->gamma);
603 if (!d->description.isEmpty() && d->handler->supportsOption(QImageIOHandler::Description))
604 d->handler->setOption(QImageIOHandler::Description, d->description);
605
606 if (!d->handler->write(image))
607 return false;
608 if (QFile *file = qobject_cast<QFile *>(d->device))
609 file->flush();
610 return true;
611}
612
613/*!
614 Returns the type of error that last occurred.
615
616 \sa ImageWriterError, errorString()
617*/
618QImageWriter::ImageWriterError QImageWriter::error() const
619{
620 return d->imageWriterError;
621}
622
623/*!
624 Returns a human readable description of the last error that occurred.
625
626 \sa error()
627*/
628QString QImageWriter::errorString() const
629{
630 return d->errorString;
631}
632
633/*!
634 \since 4.2
635
636 Returns true if the writer supports \a option; otherwise returns
637 false.
638
639 Different image formats support different options. Call this function to
640 determine whether a certain option is supported by the current format. For
641 example, the PNG format allows you to embed text into the image's metadata
642 (see text()).
643
644 \snippet doc/src/snippets/code/src_gui_image_qimagewriter.cpp 2
645
646 Options can be tested after the writer has been associated with a format.
647
648 \sa QImageReader::supportsOption(), setFormat()
649*/
650bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const
651{
652 if (!d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == 0) {
653 d->imageWriterError = QImageWriter::UnsupportedFormatError;
654 d->errorString = QT_TRANSLATE_NOOP(QImageWriter,
655 QLatin1String("Unsupported image format"));
656 return false;
657 }
658
659 return d->handler->supportsOption(option);
660}
661
662/*!
663 Returns the list of image formats supported by QImageWriter.
664
665 By default, Qt can write the following formats:
666
667 \table
668 \header \o Format \o Description
669 \row \o BMP \o Windows Bitmap
670 \row \o JPG \o Joint Photographic Experts Group
671 \row \o JPEG \o Joint Photographic Experts Group
672 \row \o PNG \o Portable Network Graphics
673 \row \o PPM \o Portable Pixmap
674 \row \o TIFF \o Tagged Image File Format
675 \row \o XBM \o X11 Bitmap
676 \row \o XPM \o X11 Pixmap
677 \endtable
678
679 Reading and writing SVG files is supported through Qt's
680 \l{QtSvg Module}{SVG Module}.
681
682 \sa setFormat(), QImageReader::supportedImageFormats(), QImageIOPlugin
683*/
684QList<QByteArray> QImageWriter::supportedImageFormats()
685{
686 QSet<QByteArray> formats;
687 formats << "bmp";
688#ifndef QT_NO_IMAGEFORMAT_PPM
689 formats << "ppm";
690#endif
691#ifndef QT_NO_IMAGEFORMAT_XBM
692 formats << "xbm";
693#endif
694#ifndef QT_NO_IMAGEFORMAT_XPM
695 formats << "xpm";
696#endif
697#ifndef QT_NO_IMAGEFORMAT_PNG
698 formats << "png";
699#endif
700#ifndef QT_NO_IMAGEFORMAT_JPEG
701 formats << "jpg" << "jpeg";
702#endif
703#ifndef QT_NO_IMAGEFORMAT_MNG
704 formats << "mng";
705#endif
706#ifndef QT_NO_IMAGEFORMAT_TIFF
707 formats << "tif" << "tiff";
708#endif
709#ifdef QT_BUILTIN_GIF_READER
710 formats << "gif";
711#endif
712
713#ifndef QT_NO_LIBRARY
714 QFactoryLoader *l = loader();
715 QStringList keys = l->keys();
716 for (int i = 0; i < keys.count(); ++i) {
717 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(keys.at(i)));
718 if (plugin && (plugin->capabilities(0, keys.at(i).toLatin1()) & QImageIOPlugin::CanWrite) != 0)
719 formats << keys.at(i).toLatin1();
720 }
721#endif // QT_NO_LIBRARY
722
723 QList<QByteArray> sortedFormats;
724 for (QSet<QByteArray>::ConstIterator it = formats.constBegin(); it != formats.constEnd(); ++it)
725 sortedFormats << *it;
726
727 qSort(sortedFormats);
728 return sortedFormats;
729}
730
731QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.