Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qimagewriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
70#include "qimagewriter.h"
71
72#include <qbytearray.h>
73#include <qfile.h>
74#include <qfileinfo.h>
75#include <qimage.h>
76#include <qimageiohandler.h>
77#include <qset.h>
78#include <qvariant.h>
79
80// factory loader
81#include <qcoreapplication.h>
82#include <private/qfactoryloader_p.h>
83
84// image handlers
85#include <private/qbmphandler_p.h>
86#include <private/qppmhandler_p.h>
87#include <private/qxbmhandler_p.h>
88#include <private/qxpmhandler_p.h>
89#ifndef QT_NO_IMAGEFORMAT_PNG
90#include <private/qpnghandler_p.h>
91#endif
92
93#include <private/qimagereaderwriterhelpers_p.h>
94
95#include <algorithm>
96
98
99using namespace Qt::StringLiterals;
100
102 const QByteArray &format)
103{
104 QByteArray form = format.toLower();
105 QByteArray suffix;
106 QImageIOHandler *handler = nullptr;
107
108#ifndef QT_NO_IMAGEFORMATPLUGIN
109 typedef QMultiMap<int, QString> PluginKeyMap;
110
111 // check if any plugins can write the image
113 const PluginKeyMap keyMap = l->keyMap();
114 int suffixPluginIndex = -1;
115#endif
116
117 if (device && format.isEmpty()) {
118 // if there's no format, see if \a device is a file, and if so, find
119 // the file suffix and find support for that format among our plugins.
120 // this allows plugins to override our built-in handlers.
121 if (QFileDevice *file = qobject_cast<QFileDevice *>(device)) {
122 if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
123#ifndef QT_NO_IMAGEFORMATPLUGIN
124 const int index = keyMap.key(QString::fromLatin1(suffix), -1);
125 if (index != -1)
126 suffixPluginIndex = index;
127#endif
128 }
129 }
130 }
131
132 QByteArray testFormat = !form.isEmpty() ? form : suffix;
133
134#ifndef QT_NO_IMAGEFORMATPLUGIN
135 if (suffixPluginIndex != -1) {
136 // when format is missing, check if we can find a plugin for the
137 // suffix.
138 const int index = keyMap.key(QString::fromLatin1(suffix), -1);
139 if (index != -1) {
140 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(index));
141 if (plugin && (plugin->capabilities(device, suffix) & QImageIOPlugin::CanWrite))
142 handler = plugin->create(device, suffix);
143 }
144 }
145#endif // QT_NO_IMAGEFORMATPLUGIN
146
147 // check if any built-in handlers can write the image
148 if (!handler && !testFormat.isEmpty()) {
149 if (false) {
150#ifndef QT_NO_IMAGEFORMAT_PNG
151 } else if (testFormat == "png") {
152 handler = new QPngHandler;
153#endif
154#ifndef QT_NO_IMAGEFORMAT_BMP
155 } else if (testFormat == "bmp") {
156 handler = new QBmpHandler;
157 } else if (testFormat == "dib") {
158 handler = new QBmpHandler(QBmpHandler::DibFormat);
159#endif
160#ifndef QT_NO_IMAGEFORMAT_XPM
161 } else if (testFormat == "xpm") {
162 handler = new QXpmHandler;
163#endif
164#ifndef QT_NO_IMAGEFORMAT_XBM
165 } else if (testFormat == "xbm") {
166 handler = new QXbmHandler;
167 handler->setOption(QImageIOHandler::SubType, testFormat);
168#endif
169#ifndef QT_NO_IMAGEFORMAT_PPM
170 } else if (testFormat == "pbm" || testFormat == "pbmraw" || testFormat == "pgm"
171 || testFormat == "pgmraw" || testFormat == "ppm" || testFormat == "ppmraw") {
172 handler = new QPpmHandler;
173 handler->setOption(QImageIOHandler::SubType, testFormat);
174#endif
175 }
176 }
177
178#ifndef QT_NO_IMAGEFORMATPLUGIN
179 if (!testFormat.isEmpty()) {
180 const int keyCount = keyMap.size();
181 for (int i = 0; i < keyCount; ++i) {
182 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i));
183 if (plugin && (plugin->capabilities(device, testFormat) & QImageIOPlugin::CanWrite)) {
184 delete handler;
185 handler = plugin->create(device, testFormat);
186 break;
187 }
188 }
189 }
190#endif // QT_NO_IMAGEFORMATPLUGIN
191
192 if (!handler)
193 return nullptr;
194
195 handler->setDevice(device);
196 if (!testFormat.isEmpty())
197 handler->setFormat(testFormat);
198 return handler;
199}
200
231
236{
237 device = nullptr;
238 deleteDevice = false;
239 handler = nullptr;
240 quality = -1;
241 compression = -1;
242 gamma = 0.0;
243 optimizedWrite = false;
244 progressiveScanWrite = false;
246 errorString = QImageWriter::tr("Unknown error");
248
249 q = qq;
250}
251
253{
254 if (!device) {
256 errorString = QImageWriter::tr("Device is not set");
257 return false;
258 }
259 if (!device->isOpen()) {
262 errorString = QImageWriter::tr("Cannot open device for writing: %1").arg(device->errorString());
263 return false;
264 }
265 }
266 if (!device->isWritable()) {
268 errorString = QImageWriter::tr("Device not writable");
269 return false;
270 }
271 if (!handler && (handler = createWriteHandlerHelper(device, format)) == nullptr) {
273 errorString = QImageWriter::tr("Unsupported image format");
274 return false;
275 }
276 return true;
277}
278
288
299
311
316{
317 delete d->handler;
318 if (d->deleteDevice)
319 delete d->device;
320 delete d;
321}
322
335{
336 d->format = format;
337}
338
345{
346 return d->format;
347}
348
363{
364 delete d->handler;
365 d->handler = nullptr;
366 if (d->device && d->deleteDevice)
367 delete d->device;
368
369 d->device = device;
370 d->deleteDevice = false;
371}
372
378{
379 return d->device;
380}
381
390{
392 d->deleteDevice = true;
393}
394
405{
406 QFileDevice *file = qobject_cast<QFileDevice *>(d->device);
407 return file ? file->fileName() : QString();
408}
409
425{
426 d->quality = quality;
427}
428
435{
436 return d->quality;
437}
438
450void QImageWriter::setCompression(int compression)
451{
453}
454
461{
462 return d->compression;
463}
464
478{
479 d->subType = type;
480}
481
490{
491 return d->subType;
492}
493
499QList<QByteArray> QImageWriter::supportedSubTypes() const
500{
502 return QList<QByteArray>();
503 return qvariant_cast<QList<QByteArray> >(d->handler->option(QImageIOHandler::SupportedSubTypes));
504}
505
518{
519 d->optimizedWrite = optimize;
520}
521
530{
531 return d->optimizedWrite;
532}
533
547{
548 d->progressiveScanWrite = progressive;
549}
550
559{
560 return d->progressiveScanWrite;
561}
562
573void QImageWriter::setTransformation(QImageIOHandler::Transformations transform)
574{
576}
577
585QImageIOHandler::Transformations QImageWriter::transformation() const
586{
587 return d->transformation;
588}
589
612{
613 if (!d->description.isEmpty())
614 d->description += "\n\n"_L1;
615 d->description += key.simplified() + ": "_L1 + text.simplified();
616}
617
625{
626 if (QFile *file = qobject_cast<QFile *>(d->device)) {
627 const bool remove = !file->isOpen() && !file->exists();
628 const bool result = d->canWriteHelper();
629
630 // This looks strange (why remove if it doesn't exist?) but the issue
631 // here is that canWriteHelper will create the file in the process of
632 // checking if the write can succeed. If it subsequently fails, we
633 // should remove that empty file.
634 if (!result && remove)
635 file->remove();
636 return result;
637 }
638
639 return d->canWriteHelper();
640}
641
642extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
643
654{
655 // Do this before canWrite, so it doesn't create a file if this fails.
656 if (Q_UNLIKELY(image.isNull())) {
658 d->errorString = QImageWriter::tr("Image is empty");
659 return false;
660 }
661
662 if (!canWrite())
663 return false;
664
665 QImage img = image;
682 else
684
685 if (!d->handler->write(img))
686 return false;
687 if (QFileDevice *file = qobject_cast<QFileDevice *>(d->device))
688 file->flush();
689 return true;
690}
691
701
708{
709 return d->errorString;
710}
711
730{
731 if (!d->handler && (d->handler = createWriteHandlerHelper(d->device, d->format)) == nullptr) {
733 d->errorString = QImageWriter::tr("Unsupported image format");
734 return false;
735 }
736
737 return d->handler->supportsOption(option);
738}
739
769
782
799
IOBluetoothDevice * device
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
\inmodule QtCore
Definition qfiledevice.h:32
bool flush()
Flushes any buffered data to the file.
QString suffix() const
Returns the suffix (extension) of the file.
\inmodule QtCore
Definition qfile.h:93
bool remove()
Removes the file specified by fileName().
Definition qfile.cpp:419
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Definition qfile.cpp:277
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
virtual bool isEmpty() const
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
bool isWritable() const
Returns true if data can be written to the device; otherwise returns false.
The QImageIOHandler class defines the common image I/O interface for all image formats in Qt.
ImageOption
This enum describes the different options supported by QImageIOHandler.
virtual bool write(const QImage &image)
Writes the image image to the assigned device.
virtual void setOption(ImageOption option, const QVariant &value)
Sets the option option with the value value.
virtual bool supportsOption(ImageOption option) const
Returns true if the QImageIOHandler supports the option option; otherwise returns false.
virtual QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.
void setDevice(QIODevice *device)
Sets the device of the QImageIOHandler to device.
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
\inmodule QtGui
virtual QImageIOHandler * create(QIODevice *device, const QByteArray &format=QByteArray()) const =0
Creates and returns a QImageIOHandler subclass, with device and format set.
virtual Capabilities capabilities(QIODevice *device, const QByteArray &format) const =0
Returns the capabilities of the plugin, based on the data in device and the format format.
QImageWriterPrivate(QImageWriter *qq)
QImageWriter::ImageWriterError imageWriterError
QImageIOHandler::Transformations transformation
QImageIOHandler * handler
The QImageWriter class provides a format independent interface for writing images to files or other d...
void setDevice(QIODevice *device)
Sets QImageWriter's device to device.
QString errorString() const
Returns a human readable description of the last error that occurred.
QString fileName() const
If the currently assigned device is a file, or if setFileName() has been called, this function return...
QIODevice * device() const
Returns the device currently assigned to QImageWriter, or \nullptr if no device has been assigned.
QImageWriter()
Constructs an empty QImageWriter object.
void setCompression(int compression)
This is an image format specific function that set the compression of an image.
bool write(const QImage &image)
Writes the image image to the assigned device or file name.
bool canWrite() const
Returns true if QImageWriter can write the image; i.e., the image format is supported and the assigne...
void setTransformation(QImageIOHandler::Transformations orientation)
bool supportsOption(QImageIOHandler::ImageOption option) const
static QList< QByteArray > supportedMimeTypes()
Returns the list of MIME types supported by QImageWriter.
int quality() const
Returns the quality setting of the image format.
ImageWriterError
This enum describes errors that can occur when writing images with QImageWriter.
void setSubType(const QByteArray &type)
void setFileName(const QString &fileName)
Sets the file name of QImageWriter to fileName.
bool optimizedWrite() const
QList< QByteArray > supportedSubTypes() const
bool progressiveScanWrite() const
QByteArray subType() const
~QImageWriter()
Destructs the QImageWriter object.
QByteArray format() const
Returns the format QImageWriter uses for writing images.
static QList< QByteArray > imageFormatsForMimeType(const QByteArray &mimeType)
void setOptimizedWrite(bool optimize)
static QList< QByteArray > supportedImageFormats()
Returns the list of image formats supported by QImageWriter.
void setQuality(int quality)
Sets the quality setting of the image format to quality.
ImageWriterError error() const
Returns the type of error that last occurred.
int compression() const
Returns the compression of the image.
void setFormat(const QByteArray &format)
Sets the format QImageWriter will use when writing images, to format.
void setProgressiveScanWrite(bool progressive)
void setText(const QString &key, const QString &text)
QImageIOHandler::Transformations transformation() const
\inmodule QtGui
Definition qimage.h:37
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
QString simplified() const &
Definition qstring.h:451
QString toLower() const &
Definition qstring.h:435
#define this
Definition dialogs.cpp:9
QString text
QList< QByteArray > imageFormatsForMimeType(QByteArrayView mimeType, Capability cap)
QSharedPointer< QFactoryLoader > pluginLoader()
QList< QByteArray > supportedImageFormats(Capability cap)
QList< QByteArray > supportedMimeTypes(Capability cap)
Combined button and popup list for selecting options.
Definition image.cpp:4
#define Q_UNLIKELY(x)
const char * mimeType
Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
Definition qimage.cpp:6410
static QImageIOHandler * createWriteHandlerHelper(QIODevice *device, const QByteArray &format)
void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
Definition qimage.cpp:6410
GLuint64 key
GLuint index
[2]
GLenum src
GLenum type
GLint GLsizei GLsizei GLenum format
GLuint GLenum GLenum transform
GLint void * img
Definition qopenglext.h:233
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLuint GLenum option
static const struct @450 keyMap[]
QFile file
[0]
settings remove("monkey")