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

Last change on this file since 463 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 20.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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 multimedia
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
118QT_BEGIN_NAMESPACE
119
120#if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
121Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
122 (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
123#endif
124
125static 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 handler = plugin->create(device, testFormat);
201 break;
202 }
203 }
204 }
205#endif
206
207 if (!handler)
208 return 0;
209
210 handler->setDevice(device);
211 if (!testFormat.isEmpty())
212 handler->setFormat(testFormat);
213 return handler;
214}
215
216class QImageWriterPrivate
217{
218public:
219 QImageWriterPrivate(QImageWriter *qq);
220
221 // device
222 QByteArray format;
223 QIODevice *device;
224 bool deleteDevice;
225 QImageIOHandler *handler;
226
227 // image options
228 int quality;
229 int compression;
230 float gamma;
231 QString description;
232 QString text;
233
234 // error
235 QImageWriter::ImageWriterError imageWriterError;
236 QString errorString;
237
238 QImageWriter *q;
239};
240
241/*!
242 \internal
243*/
244QImageWriterPrivate::QImageWriterPrivate(QImageWriter *qq)
245{
246 device = 0;
247 deleteDevice = false;
248 handler = 0;
249 quality = -1;
250 compression = 0;
251 gamma = 0.0;
252 imageWriterError = QImageWriter::UnknownError;
253 errorString = QT_TRANSLATE_NOOP(QImageWriter, QLatin1String("Unknown error"));
254
255 q = qq;
256}
257
258/*!
259 Constructs an empty QImageWriter object. Before writing, you must
260 call setFormat() to set an image format, then setDevice() or
261 setFileName().
262*/
263QImageWriter::QImageWriter()
264 : d(new QImageWriterPrivate(this))
265{
266}
267
268/*!
269 Constructs a QImageWriter object using the device \a device and
270 image format \a format.
271*/
272QImageWriter::QImageWriter(QIODevice *device, const QByteArray &format)
273 : d(new QImageWriterPrivate(this))
274{
275 d->device = device;
276 d->format = format;
277}
278
279/*!
280 Constructs a QImageWriter objects that will write to a file with
281 the name \a fileName, using the image format \a format. If \a
282 format is not provided, QImageWriter will detect the image format
283 by inspecting the extension of \a fileName.
284*/
285QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
286 : d(new QImageWriterPrivate(this))
287{
288 QFile *file = new QFile(fileName);
289 d->device = file;
290 d->deleteDevice = true;
291 d->format = format;
292}
293
294/*!
295 Destructs the QImageWriter object.
296*/
297QImageWriter::~QImageWriter()
298{
299 if (d->deleteDevice)