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// Qt-Security score:critical reason:data-parser
4
5//#define QIMAGEREADER_DEBUG
6
7/*!
8 \class QImageReader
9 \brief The QImageReader class provides a format independent interface
10 for reading images from files or other devices.
11
12 \inmodule QtGui
13 \reentrant
14 \ingroup painting
15
16 The most common way to read images is through QImage and QPixmap's
17 constructors, or by calling QImage::load() and
18 QPixmap::load(). QImageReader is a specialized class which gives
19 you more control when reading images. For example, you can read an
20 image into a specific size by calling setScaledSize(), and you can
21 select a clip rect, effectively loading only parts of an image, by
22 calling setClipRect(). Depending on the underlying support in the
23 image format, this can save memory and speed up loading of images.
24
25 To read an image, you start by constructing a QImageReader object.
26 Pass either a file name or a device pointer, and the image format
27 to QImageReader's constructor. You can then set several options,
28 such as the clip rect (by calling setClipRect()) and scaled size
29 (by calling setScaledSize()). canRead() returns the image if the
30 QImageReader can read the image (i.e., the image format is
31 supported and the device is open for reading). Call read() to read
32 the image.
33
34 If any error occurs when reading the image, read() will return a
35 null QImage. You can then call error() to find the type of error
36 that occurred, or errorString() to get a human readable
37 description of what went wrong.
38
39 \note QImageReader assumes exclusive control over the file or
40 device that is assigned. Any attempts to modify the assigned file
41 or device during the lifetime of the QImageReader object will
42 yield undefined results.
43
44 \section1 Formats
45
46 Call supportedImageFormats() for a list of formats that
47 QImageReader can read. QImageReader supports all built-in image
48 formats, in addition to any image format plugins that support
49 reading. Call supportedMimeTypes() to obtain a list of supported MIME
50 types, which for example can be passed to QFileDialog::setMimeTypeFilters().
51
52 QImageReader autodetects the image format by default, by looking at the
53 provided (optional) format string, the file name suffix, and the data
54 stream contents. You can enable or disable this feature, by calling
55 setAutoDetectImageFormat().
56
57 \section1 High Resolution Versions of Images
58
59 It is possible to provide high resolution versions of images should a scaling
60 between \e{device pixels} and \e{device independent pixels} be in effect.
61
62 The high resolution version is marked by the suffix \c @2x on the base name.
63 The image read will have its \e{device pixel ratio} set to a value of 2.
64
65 This can be disabled by setting the environment variable
66 \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING.
67
68 \sa QImageWriter, QImageIOHandler, QImageIOPlugin, QMimeDatabase, QColorSpace
69 \sa QImage::devicePixelRatio(), QPixmap::devicePixelRatio(), QIcon, QPainter::drawPixmap(), QPainter::drawImage()
70*/
71
72/*!
73 \enum QImageReader::ImageReaderError
74
75 This enum describes the different types of errors that can occur
76 when reading images with QImageReader.
77
78 \value FileNotFoundError QImageReader was used with a file name,
79 but not file was found with that name. This can also happen if the
80 file name contained no extension, and the file with the correct
81 extension is not supported by Qt.
82
83 \value DeviceError QImageReader encountered a device error when
84 reading the image. You can consult your particular device for more
85 details on what went wrong.
86
87 \value UnsupportedFormatError Qt does not support the requested
88 image format.
89
90 \value InvalidDataError The image data was invalid, and
91 QImageReader was unable to read an image from it. The can happen
92 if the image file is damaged.
93
94 \value UnknownError An unknown error occurred. If you get this
95 value after calling read(), it is most likely caused by a bug in
96 QImageReader.
97*/
98#include "qimagereader.h"
99
100#include <qbytearray.h>
101#ifdef QIMAGEREADER_DEBUG
102#include <qdebug.h>
103#endif
104#include <qfile.h>
105#include <qfileinfo.h>
106#include <qimage.h>
107#include <qimageiohandler.h>
108#include <qlist.h>
109#include <qrect.h>
110#include <qsize.h>
111#include <qcolor.h>
112#include <qvariant.h>
113
114// factory loader
115#include <qcoreapplication.h>
116#include <private/qfactoryloader_p.h>
117#include <QtCore/private/qlocking_p.h>
118
119// for qt_getImageText
120#include <private/qimage_p.h>
121
122// image handlers
123#include <private/qbmphandler_p.h>
124#include <private/qppmhandler_p.h>
125#include <private/qxbmhandler_p.h>
126#include <private/qxpmhandler_p.h>
127#ifndef QT_NO_IMAGEFORMAT_PNG
128#include <private/qpnghandler_p.h>
129#endif
130
131#include <private/qimagereaderwriterhelpers_p.h>
132#include <qtgui_tracepoints_p.h>
133
134#include <algorithm>
135
136QT_BEGIN_NAMESPACE
137
138using namespace QImageReaderWriterHelpers;
139using namespace Qt::StringLiterals;
140
141Q_TRACE_POINT(qtgui, QImageReader_read_before_reading, QImageReader *reader, const QString &filename);
142Q_TRACE_POINT(qtgui, QImageReader_read_after_reading, QImageReader *reader, bool result);
143
144static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
145 const QByteArray &format,
146 bool autoDetectImageFormat,
147 bool ignoresFormatAndExtension)
148{
149 if (!autoDetectImageFormat && format.isEmpty())
150 return nullptr;
151
152 QByteArray form = format.toLower();
153 QImageIOHandler *handler = nullptr;
154 QByteArray suffix;
155
156#if QT_CONFIG(imageformatplugin)
157 Q_CONSTINIT static QBasicMutex mutex;
158 const auto locker = qt_scoped_lock(mutex);
159
160 typedef QMultiMap<int, QString> PluginKeyMap;
161
162 // check if we have plugins that support the image format
163 auto l = QImageReaderWriterHelpers::pluginLoader();
164 const PluginKeyMap keyMap = l->keyMap();
165
166#ifdef QIMAGEREADER_DEBUG
167 qDebug() << "QImageReader::createReadHandler( device =" << (void *)device << ", format =" << format << "),"
168 << keyMap.uniqueKeys().size() << "plugins available: " << keyMap;
169#endif
170
171 int testFormatPluginIndex = -1;
172#endif // QT_CONFIG(imageformatplugin)
173
174 if (device && format.isEmpty() && autoDetectImageFormat && !ignoresFormatAndExtension) {
175 // if there's no format, see if \a device is a file, and if so, find the file suffix
176 if (QFile *file = qobject_cast<QFile *>(object: device)) {
177 suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1();
178#ifdef QIMAGEREADER_DEBUG
179 qDebug() << "QImageReader::createReadHandler: device file suffix:" << suffix;
180#endif
181 }
182 }
183
184 QByteArray testFormat = !form.isEmpty() ? form : suffix;
185 if (ignoresFormatAndExtension)
186 testFormat = QByteArray();
187
188#if QT_CONFIG(imageformatplugin)
189 if (!testFormat.isEmpty()) {
190 // Check first support for the given format name or suffix among our plugins' registered
191 // formats. This allows plugins to override our built-in handlers.
192 const qint64 pos = device ? device->pos() : 0;
193 for (int testIndex : keyMap.keys(value: QLatin1StringView(testFormat))) {
194 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(object: l->instance(index: testIndex));
195 if (plugin && plugin->capabilities(device, format: testFormat) & QImageIOPlugin::CanRead) {
196#ifdef QIMAGEREADER_DEBUG
197 qDebug() << "QImageReader::createReadHandler: format" << testFormat
198 << "recognized, the" << keyMap.values(testIndex) << "plugin can read this format.";
199#endif
200 handler = plugin->create(device, format: testFormat);
201 testFormatPluginIndex = testIndex;
202 break;
203 }
204 }
205 if (device && !device->isSequential())
206 device->seek(pos); // Should not have moved, but guard against buggy plugins
207 }
208#endif // QT_CONFIG(imageformatplugin)
209
210 // if we don't have a handler yet, check if we have built-in support for
211 // the format
212 if (!handler && !testFormat.isEmpty()) {
213 if (false) {
214#ifndef QT_NO_IMAGEFORMAT_PNG
215 } else if (testFormat == "png") {
216 handler = new QPngHandler;
217#endif
218#ifndef QT_NO_IMAGEFORMAT_BMP
219 } else if (testFormat == "bmp") {
220 handler = new QBmpHandler;
221 } else if (testFormat == "dib") {
222 handler = new QBmpHandler(QBmpHandler::DibFormat);
223#endif
224#ifndef QT_NO_IMAGEFORMAT_XPM
225 } else if (testFormat == "xpm") {
226 handler = new QXpmHandler;
227#endif
228#ifndef QT_NO_IMAGEFORMAT_XBM
229 } else if (testFormat == "xbm") {
230 handler = new QXbmHandler;
231 handler->setOption(option: QImageIOHandler::SubType, value: testFormat);
232#endif
233#ifndef QT_NO_IMAGEFORMAT_PPM
234 } else if (testFormat == "pbm" || testFormat == "pbmraw" || testFormat == "pgm"
235 || testFormat == "pgmraw" || testFormat == "ppm" || testFormat == "ppmraw") {
236 handler = new QPpmHandler;
237 handler->setOption(option: QImageIOHandler::SubType, value: testFormat);
238#endif
239 }
240
241#ifdef QIMAGEREADER_DEBUG
242 if (handler)
243 qDebug() << "QImageReader::createReadHandler: using the built-in handler for" << testFormat;
244#endif
245 }
246
247#if QT_CONFIG(imageformatplugin)
248 if (!handler && !testFormat.isEmpty() && autoDetectImageFormat) {
249 // check if any other plugin supports the format name (they are not allowed to
250 // read from the device yet).
251 const qint64 pos = device ? device->pos() : 0;
252
253 const int keyCount = keyMap.size();
254 for (int i = 0; i < keyCount; ++i) {
255 if (i != testFormatPluginIndex) {
256 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(object: l->instance(index: i));
257 if (plugin && plugin->capabilities(device, format: testFormat) & QImageIOPlugin::CanRead) {
258#ifdef QIMAGEREADER_DEBUG
259 qDebug() << "QImageReader::createReadHandler: the" << keyMap.values(i) << "plugin can read this format";
260#endif
261 handler = plugin->create(device, format: testFormat);
262 break;
263 }
264 }
265 }
266 if (device && !device->isSequential())
267 device->seek(pos); // Should not have moved, but guard against buggy plugins
268 }
269#endif // QT_CONFIG(imageformatplugin)
270
271 if (handler && device && !suffix.isEmpty()) {
272 Q_ASSERT(qobject_cast<QFile *>(device));
273 // We have a file claiming to be of a recognized format. Now confirm that
274 // the handler also recognizes the file contents.
275 const qint64 pos = device->pos();
276 handler->setDevice(device);
277 if (!form.isEmpty())
278 handler->setFormat(form);
279 bool canRead = handler->canRead();
280 device->seek(pos);
281 if (canRead) {
282 // ok, we're done.
283 return handler;
284 }
285#ifdef QIMAGEREADER_DEBUG
286 qDebug() << "QImageReader::createReadHandler: the" << suffix << "handler can not read this file";
287#endif
288 // File may still be valid, just with wrong suffix, so fall back to
289 // finding a handler based on contents, below.
290 delete handler;
291 handler = nullptr;
292 }
293
294#if QT_CONFIG(imageformatplugin)
295 if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
296 // check if any of our plugins recognize the file from its contents.
297 const qint64 pos = device ? device->pos() : 0;
298 const int keyCount = keyMap.size();
299 for (int i = 0; i < keyCount; ++i) {
300 if (i != testFormatPluginIndex) {
301 QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(object: l->instance(index: i));
302 if (plugin && plugin->capabilities(device, format: QByteArray()) & QImageIOPlugin::CanRead) {
303 handler = plugin->create(device, format: testFormat);
304#ifdef QIMAGEREADER_DEBUG
305 qDebug() << "QImageReader::createReadHandler: the" << keyMap.values(i) << "plugin can read this data";
306#endif
307 break;
308 }
309 }
310 }
311 if (device && !device->isSequential())
312 device->seek(pos);
313 }
314#endif // QT_CONFIG(imageformatplugin)
315
316 if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
317 // check if any of our built-in handlers recognize the file from its
318 // contents.
319 int currentFormat = 0;
320 if (!suffix.isEmpty()) {
321 // If reading from a file with a suffix, start testing our
322 // built-in handler for that suffix first.
323 for (int i = 0; i < _qt_NumFormats; ++i) {
324 if (_qt_BuiltInFormats[i].extension == suffix) {
325 currentFormat = i;
326 break;
327 }
328 }
329 }
330
331 QByteArray subType;
332 int numFormats = _qt_NumFormats;
333 while (device && numFormats >= 0) {
334 const qint64 pos = device->pos();
335 switch (currentFormat) {
336#ifndef QT_NO_IMAGEFORMAT_PNG
337 case _qt_PngFormat:
338 if (QPngHandler::canRead(device))
339 handler = new QPngHandler;
340 break;
341#endif
342#ifndef QT_NO_IMAGEFORMAT_BMP
343 case _qt_BmpFormat:
344 if (QBmpHandler::canRead(device))
345 handler = new QBmpHandler;
346 break;
347#endif
348#ifndef QT_NO_IMAGEFORMAT_XPM
349 case _qt_XpmFormat:
350 if (QXpmHandler::canRead(device))
351 handler = new QXpmHandler;
352 break;
353#endif
354#ifndef QT_NO_IMAGEFORMAT_PPM
355 case _qt_PbmFormat:
356 case _qt_PgmFormat:
357 case _qt_PpmFormat:
358 if (QPpmHandler::canRead(device, subType: &subType)) {
359 handler = new QPpmHandler;
360 handler->setOption(option: QImageIOHandler::SubType, value: subType);
361 }
362 break;
363#endif
364#ifndef QT_NO_IMAGEFORMAT_XBM
365 case _qt_XbmFormat:
366 if (QXbmHandler::canRead(device))
367 handler = new QXbmHandler;
368 break;
369#endif
370 default:
371 break;
372 }
373 if (!device->isSequential())
374 device->seek(pos);
375
376 if (handler) {
377#ifdef QIMAGEREADER_DEBUG
378 qDebug("QImageReader::createReadHandler: the %s built-in handler can read this data",
379 _qt_BuiltInFormats[currentFormat].extension);
380#endif
381 break;
382 }
383
384 --numFormats;
385 ++currentFormat;
386 if (currentFormat >= _qt_NumFormats)
387 currentFormat = 0;
388 }
389 }
390
391 if (!handler) {
392#ifdef QIMAGEREADER_DEBUG
393 qDebug("QImageReader::createReadHandler: no handlers found. giving up.");
394#endif
395 // no handler: give up.
396 return nullptr;
397 }
398
399 handler->setDevice(device);
400 if (!form.isEmpty())
401 handler->setFormat(form);
402 return handler;
403}
404
405class QImageReaderPrivate
406{
407public:
408 QImageReaderPrivate(QImageReader *qq);
409 ~QImageReaderPrivate();
410
411 // device
412 QByteArray format;
413 bool autoDetectImageFormat;
414 bool ignoresFormatAndExtension;
415 QIODevice *device;
416 bool deleteDevice;
417 QImageIOHandler *handler;
418 bool initHandler();
419
420 // image options
421 QRect clipRect;
422 QSize scaledSize;
423 QRect scaledClipRect;
424 int quality;
425 QMap<QString, QString> text;
426 void getText();
427 enum {
428 UsePluginDefault,
429 ApplyTransform,
430 DoNotApplyTransform
431 } autoTransform;
432
433 // error
434 QImageReader::ImageReaderError imageReaderError;
435 QString errorString;
436
437 QImageReader *q;
438
439 static int maxAlloc;
440};
441
442int QImageReaderPrivate::maxAlloc = 256; // 256 MB is enough for an 8K 64bpp image
443
444/*!
445 \internal
446*/
447QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
448 : autoDetectImageFormat(true), ignoresFormatAndExtension(false)
449{
450 device = nullptr;
451 deleteDevice = false;
452 handler = nullptr;
453 quality = -1;
454 imageReaderError = QImageReader::UnknownError;
455 autoTransform = UsePluginDefault;
456
457 q = qq;
458}
459
460/*!
461 \internal
462*/
463QImageReaderPrivate::~QImageReaderPrivate()
464{
465 delete handler;
466 if (deleteDevice)
467 delete device;
468}
469
470/*!
471 \internal
472*/
473bool QImageReaderPrivate::initHandler()
474{
475 if (handler)
476 return true;
477
478 // check some preconditions
479 if (!device || (!deleteDevice && !device->isOpen() && !device->open(mode: QIODevice::ReadOnly))) {
480 imageReaderError = QImageReader::DeviceError;
481 errorString = QImageReader::tr(sourceText: "Invalid device");
482 return false;
483 }
484
485 // probe the file extension
486 if (deleteDevice && !device->isOpen() && !device->open(mode: QIODevice::ReadOnly) && autoDetectImageFormat) {
487 Q_ASSERT(qobject_cast<QFile*>(device) != nullptr); // future-proofing; for now this should always be the case, so...
488 QFile *file = static_cast<QFile *>(device);
489
490 if (file->error() == QFileDevice::ResourceError) {
491 // this is bad. we should abort the open attempt and note the failure.
492 imageReaderError = QImageReader::DeviceError;
493 errorString = file->errorString();
494 return false;
495 }
496
497 QList<QByteArray> extensions = QImageReader::supportedImageFormats();
498 if (!format.isEmpty()) {
499 // Try the most probable extension first
500 int currentFormatIndex = extensions.indexOf(t: format.toLower());
501 if (currentFormatIndex > 0)
502 extensions.swapItemsAt(i: 0, j: currentFormatIndex);
503 }
504
505 int currentExtension = 0;
506
507 QString fileName = file->fileName();
508 bool fileIsOpen;
509
510 do {
511 file->setFileName(fileName + u'.'
512 + QLatin1StringView(extensions.at(i: currentExtension++).constData()));
513 fileIsOpen = file->open(flags: QIODevice::ReadOnly);
514 } while (!fileIsOpen && currentExtension < extensions.size());
515
516 if (!fileIsOpen) {
517 imageReaderError = QImageReader::FileNotFoundError;
518 errorString = QImageReader::tr(sourceText: "File not found");
519 file->setFileName(fileName); // restore the old file name
520 return false;
521 }
522 }
523
524 // assign a handler
525 if ((handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
526 imageReaderError = QImageReader::UnsupportedFormatError;
527 errorString = QImageReader::tr(sourceText: "Unsupported image format");
528 return false;
529 }
530 return true;
531}
532
533/*!
534 \internal
535*/
536void QImageReaderPrivate::getText()
537{
538 if (text.isEmpty() && q->supportsOption(option: QImageIOHandler::Description))
539 text = qt_getImageTextFromDescription(description: handler->option(option: QImageIOHandler::Description).toString());
540}
541
542/*!
543 Constructs an empty QImageReader object. Before reading an image,
544 call setDevice() or setFileName().
545*/
546QImageReader::QImageReader()
547 : d(new QImageReaderPrivate(this))
548{
549}
550
551/*!
552 Constructs a QImageReader object with the device \a device and the
553 image format \a format.
554*/
555QImageReader::QImageReader(QIODevice *device, const QByteArray &format)
556 : d(new QImageReaderPrivate(this))
557{
558 d->device = device;
559 d->format = format;
560}
561
562/*!
563 Constructs a QImageReader object with the file name \a fileName
564 and the image format \a format.
565
566 \sa setFileName()
567*/
568QImageReader::QImageReader(const QString &fileName, const QByteArray &format)
569 : QImageReader(new QFile(fileName), format)
570{
571 d->deleteDevice = true;
572}
573
574/*!
575 Destructs the QImageReader object.
576*/
577QImageReader::~QImageReader()
578{
579 delete d;
580}
581
582/*!
583 Sets the format QImageReader will use when reading images, to \a
584 format. \a format is a case insensitive text string. Example:
585
586 \snippet code/src_gui_image_qimagereader.cpp 0
587
588 You can call supportedImageFormats() for the full list of formats
589 QImageReader supports.
590
591 \sa format()
592*/
593void QImageReader::setFormat(const QByteArray &format)
594{
595 d->format = format;
596}
597
598/*!
599 Returns the format QImageReader uses for reading images.
600
601 You can call this function after assigning a device to the
602 reader to determine the format of the device. For example:
603
604 \snippet code/src_gui_image_qimagereader.cpp 1
605
606 If the reader cannot read any image from the device (e.g., there is no
607 image there, or the image has already been read), or if the format is
608 unsupported, this function returns an empty QByteArray().
609
610 \sa setFormat(), supportedImageFormats()
611*/
612QByteArray QImageReader::format() const
613{
614 if (d->format.isEmpty()) {
615 if (!d->initHandler())
616 return QByteArray();
617 return d->handler->canRead() ? d->handler->format() : QByteArray();
618 }
619
620 return d->format;
621}
622
623/*!
624 If \a enabled is true, image format autodetection is enabled; otherwise,
625 it is disabled. By default, autodetection is enabled.
626
627 QImageReader uses an extensive approach to detecting the image format;
628 firstly, if you pass a file name to QImageReader, it will attempt to
629 detect the file extension if the given file name does not point to an
630 existing file, by appending supported default extensions to the given file
631 name, one at a time. It then uses the following approach to detect the
632 image format:
633
634 \list
635
636 \li Image plugins are queried first, based on either the optional format
637 string, or the file name suffix (if the source device is a file). No
638 content detection is done at this stage. QImageReader will choose the
639 first plugin that supports reading for this format.
640
641 \li If no plugin supports the image format, Qt's built-in handlers are
642 checked based on either the optional format string, or the file name
643 suffix.
644
645 \li If no capable plugins or built-in handlers are found, each plugin is
646 tested by inspecting the content of the data stream.
647
648 \li If no plugins could detect the image format based on data contents,
649 each built-in image handler is tested by inspecting the contents.
650
651 \li Finally, if all above approaches fail, QImageReader will report failure
652 when trying to read the image.
653
654 \endlist
655
656 By disabling image format autodetection, QImageReader will only query the
657 plugins and built-in handlers based on the format string (i.e., no file
658 name extensions are tested).
659
660 \sa QImageIOHandler::canRead(), QImageIOPlugin::capabilities()
661*/
662void QImageReader::setAutoDetectImageFormat(bool enabled)
663{
664 d->autoDetectImageFormat = enabled;
665}
666
667/*!
668 Returns \c true if image format autodetection is enabled on this image
669 reader; otherwise returns \c false. By default, autodetection is enabled.
670
671 \sa setAutoDetectImageFormat()
672*/
673bool QImageReader::autoDetectImageFormat() const
674{
675 return d->autoDetectImageFormat;
676}
677
678
679/*!
680 If \a ignored is set to true, then the image reader will ignore
681 specified formats or file extensions and decide which plugin to
682 use only based on the contents in the datastream.
683
684 Setting this flag means that all image plugins gets loaded. Each
685 plugin will read the first bytes in the image data and decide if
686 the plugin is compatible or not.
687
688 This also disables auto detecting the image format.
689
690 \sa decideFormatFromContent()
691*/
692
693void QImageReader::setDecideFormatFromContent(bool ignored)
694{
695 d->ignoresFormatAndExtension = ignored;
696}
697
698
699/*!
700 Returns whether the image reader should decide which plugin to use
701 only based on the contents of the datastream rather than on the file
702 extension.
703
704 \sa setDecideFormatFromContent()
705*/
706
707bool QImageReader::decideFormatFromContent() const
708{
709 return d->ignoresFormatAndExtension;
710}
711
712
713/*!
714 Sets QImageReader's device to \a device. If a device has already
715 been set, the old device is removed from QImageReader and is
716 otherwise left unchanged.
717
718 If the device is not already open, QImageReader will attempt to
719 open the device in \l {QIODeviceBase::}{ReadOnly} mode by calling
720 open(). Note that this does not work for certain devices, such as
721 QProcess, QTcpSocket and QUdpSocket, where more logic is required
722 to open the device.
723
724 \sa device(), setFileName()
725*/
726void QImageReader::setDevice(QIODevice *device)
727{
728 delete d->handler;
729 d->handler = nullptr;
730 if (d->device && d->deleteDevice)
731 delete d->device;
732 d->device = device;
733 d->deleteDevice = false;
734 d->text.clear();
735}
736
737/*!
738 Returns the device currently assigned to QImageReader, or \nullptr
739 if no device has been assigned.
740*/
741QIODevice *QImageReader::device() const
742{
743 return d->device;
744}
745
746/*!
747 Sets the file name of QImageReader to \a fileName. Internally,
748 QImageReader will create a QFile object and open it in \l
749 {QIODeviceBase::}{ReadOnly} mode, and use this when reading images.
750
751 If \a fileName does not include a file extension (e.g., .png or .bmp),
752 QImageReader will cycle through all supported extensions until it finds
753 a matching file.
754
755 \sa fileName(), setDevice(), supportedImageFormats()
756*/
757void QImageReader::setFileName(const QString &fileName)
758{
759 setDevice(new QFile(fileName));
760 d->deleteDevice = true;
761}
762
763/*!
764 If the currently assigned device is a QFile, or if setFileName()
765 has been called, this function returns the name of the file
766 QImageReader reads from. Otherwise (i.e., if no device has been
767 assigned or the device is not a QFile), an empty QString is
768 returned.
769
770 \sa setFileName(), setDevice()
771*/
772QString QImageReader::fileName() const
773{
774 QFile *file = qobject_cast<QFile *>(object: d->device);
775 return file ? file->fileName() : QString();
776}
777
778/*!
779 Sets the quality setting of the image format to \a quality.
780
781 Some image formats, in particular lossy ones, entail a tradeoff between a)
782 visual quality of the resulting image, and b) decoding execution time.
783 This function sets the level of that tradeoff for image formats that
784 support it.
785
786 In case of scaled image reading, the quality setting may also influence the
787 tradeoff level between visual quality and execution speed of the scaling
788 algorithm.
789
790 The value range of \a quality depends on the image format. For example,
791 the "jpeg" format supports a quality range from 0 (low visual quality) to
792 100 (high visual quality).
793
794 \sa quality() setScaledSize()
795*/
796void QImageReader::setQuality(int quality)
797{
798 d->quality = quality;
799}
800
801/*!
802 Returns the quality setting of the image format.
803
804 \sa setQuality()
805*/
806int QImageReader::quality() const
807{
808 return d->quality;
809}
810
811
812/*!
813 Returns the size of the image, without actually reading the image
814 contents.
815
816 If the image format does not support this feature, this function returns
817 an invalid size. Qt's built-in image handlers all support this feature,
818 but custom image format plugins are not required to do so.
819
820 \sa QImageIOHandler::ImageOption, QImageIOHandler::option(), QImageIOHandler::supportsOption()
821*/
822QSize QImageReader::size() const
823{
824 if (supportsOption(option: QImageIOHandler::Size))
825 return d->handler->option(option: QImageIOHandler::Size).toSize();
826
827 return QSize();
828}
829
830/*!
831 Returns the format of the image, without actually reading the image
832 contents. The format describes the image format \l QImageReader::read()
833 returns, not the format of the actual image.
834
835 If the image format does not support this feature, this function returns
836 an invalid format.
837
838 \sa QImageIOHandler::ImageOption, QImageIOHandler::option(), QImageIOHandler::supportsOption()
839*/
840QImage::Format QImageReader::imageFormat() const
841{
842 if (supportsOption(option: QImageIOHandler::ImageFormat))
843 return (QImage::Format)d->handler->option(option: QImageIOHandler::ImageFormat).toInt();
844
845 return QImage::Format_Invalid;
846}
847
848/*!
849 Returns the text keys for this image. You can use
850 these keys with text() to list the image text for
851 a certain key.
852
853 Support for this option is implemented through
854 QImageIOHandler::Description.
855
856 \sa text(), QImageWriter::setText(), QImage::textKeys()
857*/
858QStringList QImageReader::textKeys() const
859{
860 d->getText();
861 return d->text.keys();
862}
863
864/*!
865 Returns the image text associated with \a key.
866
867 Support for this option is implemented through
868 QImageIOHandler::Description.
869
870 \sa textKeys(), QImageWriter::setText()
871*/
872QString QImageReader::text(const QString &key) const
873{
874 d->getText();
875 return d->text.value(key);
876}
877
878/*!
879 Sets the image clip rect (also known as the ROI, or Region Of
880 Interest) to \a rect. The coordinates of \a rect are relative to
881 the untransformed image size, as returned by size().
882
883 \sa clipRect(), setScaledSize(), setScaledClipRect()
884*/
885void QImageReader::setClipRect(const QRect &rect)
886{
887 d->clipRect = rect;
888}
889
890/*!
891 Returns the clip rect (also known as the ROI, or Region Of
892 Interest) of the image. If no clip rect has been set, an invalid
893 QRect is returned.
894
895 \sa setClipRect()
896*/
897QRect QImageReader::clipRect() const
898{
899 return d->clipRect;
900}
901
902/*!
903 Sets the scaled size of the image to \a size. The scaling is
904 performed after the initial clip rect, but before the scaled clip
905 rect is applied. The algorithm used for scaling depends on the
906 image format. By default (i.e., if the image format does not
907 support scaling), QImageReader will use QImage::scale() with
908 Qt::SmoothScaling.
909
910 If only one dimension is set in \a size, the other one will be
911 computed from the image's \l {size()} {natural size} so as to
912 maintain the aspect ratio.
913
914 \sa scaledSize(), setClipRect(), setScaledClipRect()
915*/
916void QImageReader::setScaledSize(const QSize &size)
917{
918 d->scaledSize = size;
919}
920
921/*!
922 Returns the scaled size of the image.
923
924 \sa setScaledSize()
925*/
926QSize QImageReader::scaledSize() const
927{
928 return d->scaledSize;
929}
930
931/*!
932 Sets the scaled clip rect to \a rect. The scaled clip rect is the
933 clip rect (also known as ROI, or Region Of Interest) that is
934 applied after the image has been scaled.
935
936 \sa scaledClipRect(), setScaledSize()
937*/
938void QImageReader::setScaledClipRect(const QRect &rect)
939{
940 d->scaledClipRect = rect;
941}
942
943/*!
944 Returns the scaled clip rect of the image.
945
946 \sa setScaledClipRect()
947*/
948QRect QImageReader::scaledClipRect() const
949{
950 return d->scaledClipRect;
951}
952
953/*!
954 Sets the background color to \a color.
955 Image formats that support this operation are expected to
956 initialize the background to \a color before reading an image.
957
958 \sa backgroundColor(), read()
959*/
960void QImageReader::setBackgroundColor(const QColor &color)
961{
962 if (supportsOption(option: QImageIOHandler::BackgroundColor))
963 d->handler->setOption(option: QImageIOHandler::BackgroundColor, value: color);
964}
965
966/*!
967 Returns the background color that's used when reading an image.
968 If the image format does not support setting the background color
969 an invalid color is returned.
970
971 \sa setBackgroundColor(), read()
972*/
973QColor QImageReader::backgroundColor() const
974{
975 if (supportsOption(option: QImageIOHandler::BackgroundColor))
976 return qvariant_cast<QColor>(v: d->handler->option(option: QImageIOHandler::BackgroundColor));
977 return QColor();
978}
979
980/*!
981 Returns \c true if the image format supports animation;
982 otherwise, false is returned.
983
984 \sa QMovie::supportedFormats()
985*/
986bool QImageReader::supportsAnimation() const
987{
988 if (supportsOption(option: QImageIOHandler::Animation))
989 return d->handler->option(option: QImageIOHandler::Animation).toBool();
990 return false;
991}
992
993/*!
994 \since 5.4
995
996 Returns the subtype of the image.
997*/
998QByteArray QImageReader::subType() const
999{
1000 if (supportsOption(option: QImageIOHandler::SubType))
1001 return d->handler->option(option: QImageIOHandler::SubType).toByteArray();
1002 return QByteArray();
1003}
1004
1005/*!
1006 \since 5.4
1007
1008 Returns the list of subtypes supported by an image.
1009*/
1010QList<QByteArray> QImageReader::supportedSubTypes() const
1011{
1012 if (supportsOption(option: QImageIOHandler::SupportedSubTypes))
1013 return qvariant_cast<QList<QByteArray> >(v: d->handler->option(option: QImageIOHandler::SupportedSubTypes));
1014 return QList<QByteArray>();
1015}
1016
1017/*!
1018 \since 5.5
1019
1020 Returns the transformation metadata of the image, including image orientation. If the format
1021 does not support transformation metadata, QImageIOHandler::TransformationNone is returned.
1022
1023 \sa setAutoTransform(), autoTransform()
1024*/
1025QImageIOHandler::Transformations QImageReader::transformation() const
1026{
1027 int option = QImageIOHandler::TransformationNone;
1028 if (supportsOption(option: QImageIOHandler::ImageTransformation))
1029 option = d->handler->option(option: QImageIOHandler::ImageTransformation).toInt();
1030 return QImageIOHandler::Transformations(option);
1031}
1032
1033/*!
1034 \since 5.5
1035
1036 Determines that images returned by read() should have transformation metadata automatically
1037 applied if \a enabled is \c true.
1038
1039 \sa autoTransform(), transformation(), read()
1040*/
1041void QImageReader::setAutoTransform(bool enabled)
1042{
1043 d->autoTransform = enabled ? QImageReaderPrivate::ApplyTransform
1044 : QImageReaderPrivate::DoNotApplyTransform;
1045}
1046
1047/*!
1048 \since 5.5
1049
1050 Returns \c true if the image handler will apply transformation metadata on read().
1051
1052 \sa setAutoTransform(), transformation(), read()
1053*/
1054bool QImageReader::autoTransform() const
1055{
1056 switch (d->autoTransform) {
1057 case QImageReaderPrivate::ApplyTransform:
1058 return true;
1059 case QImageReaderPrivate::DoNotApplyTransform:
1060 return false;
1061 case QImageReaderPrivate::UsePluginDefault:
1062 Q_FALLTHROUGH();
1063 default:
1064 break;
1065 }
1066 return false;
1067}
1068
1069/*!
1070 Returns \c true if an image can be read for the device (i.e., the
1071 image format is supported, and the device seems to contain valid
1072 data); otherwise returns \c false.
1073
1074 canRead() is a lightweight function that only does a quick test to
1075 see if the image data is valid. read() may still return false
1076 after canRead() returns \c true, if the image data is corrupt.
1077
1078 \note A QMimeDatabase lookup is normally a better approach than this
1079 function for identifying potentially non-image files or data.
1080
1081 For images that support animation, canRead() returns \c false when
1082 all frames have been read.
1083
1084 \sa read(), supportedImageFormats(), QMimeDatabase
1085*/
1086bool QImageReader::canRead() const
1087{
1088 if (!d->initHandler())
1089 return false;
1090
1091 return d->handler->canRead();
1092}
1093
1094/*!
1095 Reads an image from the device. On success, the image that was
1096 read is returned; otherwise, a null QImage is returned. You can
1097 then call error() to find the type of error that occurred, or
1098 errorString() to get a human readable description of the error.
1099
1100 For image formats that support animation, calling read()
1101 repeatedly will return the next frame. When all frames have been
1102 read, a null image will be returned.
1103
1104 \sa canRead(), supportedImageFormats(), supportsAnimation(), QMovie
1105*/
1106QImage QImageReader::read()
1107{
1108 // Because failed image reading might have side effects, we explicitly
1109 // return a null image instead of the image we've just created.
1110 QImage image;
1111 return read(image: &image) ? image : QImage();
1112}
1113
1114extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient);
1115
1116/*!
1117 \overload
1118
1119 Reads an image from the device into \a image, which must point to a
1120 QImage. Returns \c true on success; otherwise, returns \c false.
1121
1122 If \a image has same format and size as the image data that is about to be
1123 read, this function may not need to allocate a new image before
1124 reading. Because of this, it can be faster than the other read() overload,
1125 which always constructs a new image; especially when reading several
1126 images with the same format and size.
1127
1128 \snippet code/src_gui_image_qimagereader.cpp 2
1129
1130 For image formats that support animation, calling read() repeatedly will
1131 return the next frame. When all frames have been read, a null image will
1132 be returned.
1133
1134 \sa canRead(), supportedImageFormats(), supportsAnimation(), QMovie
1135*/
1136bool QImageReader::read(QImage *image)
1137{
1138 if (!image) {
1139 qWarning(msg: "QImageReader::read: cannot read into null pointer");
1140 return false;
1141 }
1142
1143 if (!d->initHandler())
1144 return false;
1145
1146 QSize scaledSize = d->scaledSize;
1147 if ((scaledSize.width() <= 0 && scaledSize.height() > 0) ||
1148 (scaledSize.height() <= 0 && scaledSize.width() > 0)) {
1149 // if only one dimension is given, let's try to calculate the second one
1150 // based on the original image size and maintaining the aspect ratio
1151 if (const QSize originalSize = size(); !originalSize.isEmpty()) {
1152 if (scaledSize.width() <= 0) {
1153 const auto ratio = qreal(scaledSize.height()) / originalSize.height();
1154 scaledSize.setWidth(qRound(d: originalSize.width() * ratio));
1155 } else {
1156 const auto ratio = qreal(scaledSize.width()) / originalSize.width();
1157 scaledSize.setHeight(qRound(d: originalSize.height() * ratio));
1158 }
1159 }
1160 }
1161
1162 const bool supportScaledSize = supportsOption(option: QImageIOHandler::ScaledSize) && scaledSize.isValid();
1163 const bool supportClipRect = supportsOption(option: QImageIOHandler::ClipRect) && !d->clipRect.isNull();
1164 const bool supportScaledClipRect = supportsOption(option: QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull();
1165
1166 // set the handler specific options.
1167 if (supportScaledSize) {
1168 if (supportClipRect || d->clipRect.isNull()) {
1169 // Only enable the ScaledSize option if there is no clip rect, or
1170 // if the handler also supports ClipRect.
1171 d->handler->setOption(option: QImageIOHandler::ScaledSize, value: scaledSize);
1172 }
1173 }
1174 if (supportClipRect)
1175 d->handler->setOption(option: QImageIOHandler::ClipRect, value: d->clipRect);
1176 if (supportScaledClipRect)
1177 d->handler->setOption(option: QImageIOHandler::ScaledClipRect, value: d->scaledClipRect);
1178 if (supportsOption(option: QImageIOHandler::Quality))
1179 d->handler->setOption(option: QImageIOHandler::Quality, value: d->quality);
1180
1181 // read the image
1182 QString filename = fileName();
1183 if (Q_TRACE_ENABLED(QImageReader_read_before_reading)) {
1184 Q_TRACE(QImageReader_read_before_reading, this, filename.isEmpty() ? u"unknown"_s : filename);
1185 }
1186
1187 const bool result = d->handler->read(image);
1188
1189 Q_TRACE(QImageReader_read_after_reading, this, result);
1190
1191 if (!result) {
1192 d->imageReaderError = InvalidDataError;
1193 d->errorString = QImageReader::tr(sourceText: "Unable to read image data");
1194 return false;
1195 }
1196
1197 // provide default implementations for any unsupported image
1198 // options
1199 if (supportClipRect) {
1200 if (supportScaledSize) {
1201 if (supportScaledClipRect) {
1202 // all features are supported by the handler; nothing to do.
1203 } else {
1204 // the image is already scaled, so apply scaled clipping.
1205 if (!d->scaledClipRect.isNull())
1206 *image = image->copy(rect: d->scaledClipRect);
1207 }
1208 } else {
1209 if (supportScaledClipRect) {
1210 // supports scaled clipping but not scaling, most
1211 // likely a broken handler.
1212 } else {
1213 if (scaledSize.isValid()) {
1214 *image = image->scaled(s: scaledSize, aspectMode: Qt::IgnoreAspectRatio, mode: Qt::SmoothTransformation);
1215 }
1216 if (d->scaledClipRect.isValid()) {
1217 *image = image->copy(rect: d->scaledClipRect);
1218 }
1219 }
1220 }
1221 } else {
1222 if (supportScaledSize && d->clipRect.isNull()) {
1223 if (supportScaledClipRect) {
1224 // nothing to do (ClipRect is ignored!)
1225 } else {
1226 // provide all workarounds.
1227 if (d->scaledClipRect.isValid()) {
1228 *image = image->copy(rect: d->scaledClipRect);
1229 }
1230 }
1231 } else {
1232 if (supportScaledClipRect) {
1233 // this makes no sense; a handler that supports
1234 // ScaledClipRect but not ScaledSize is broken, and we
1235 // can't work around it.
1236 } else {
1237 // provide all workarounds.
1238 if (d->clipRect.isValid())
1239 *image = image->copy(rect: d->clipRect);
1240 if (scaledSize.isValid())
1241 *image = image->scaled(s: scaledSize, aspectMode: Qt::IgnoreAspectRatio, mode: Qt::SmoothTransformation);
1242 if (d->scaledClipRect.isValid())
1243 *image = image->copy(rect: d->scaledClipRect);
1244 }
1245 }
1246 }
1247
1248 // successful read; check for "@Nx" file name suffix and set device pixel ratio.
1249 static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty(varName: "QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
1250 if (!disableNxImageLoading) {
1251 const QByteArray suffix = QFileInfo(filename).baseName().right(n: 3).toLatin1();
1252 if (suffix.size() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
1253 image->setDevicePixelRatio(suffix[1] - '0');
1254 }
1255 if (autoTransform())
1256 qt_imageTransform(src&: *image, orient: transformation());
1257
1258 return true;
1259}
1260
1261/*!
1262 For image formats that support animation, this function steps over the
1263 current image, returning true if successful or false if there is no
1264 following image in the animation.
1265
1266 The default implementation calls read(), then discards the resulting
1267 image, but the image handler may have a more efficient way of implementing
1268 this operation.
1269
1270 \sa jumpToImage(), QImageIOHandler::jumpToNextImage()
1271*/
1272bool QImageReader::jumpToNextImage()
1273{
1274 if (!d->initHandler())
1275 return false;
1276 return d->handler->jumpToNextImage();
1277}
1278
1279/*!
1280 For image formats that support animation, this function skips to the image
1281 whose sequence number is \a imageNumber, returning true if successful
1282 or false if the corresponding image cannot be found.
1283
1284 The next call to read() will attempt to read this image.
1285
1286 \sa jumpToNextImage(), QImageIOHandler::jumpToImage()
1287*/
1288bool QImageReader::jumpToImage(int imageNumber)
1289{
1290 if (!d->initHandler())
1291 return false;
1292 return d->handler->jumpToImage(imageNumber);
1293}
1294
1295/*!
1296 For image formats that support animation, this function returns the number
1297 of times the animation should loop. If this function returns -1, it can
1298 either mean the animation should loop forever, or that an error occurred.
1299 If an error occurred, canRead() will return false.
1300
1301 \sa supportsAnimation(), QImageIOHandler::loopCount(), canRead()
1302*/
1303int QImageReader::loopCount() const
1304{
1305 if (!d->initHandler())
1306 return -1;
1307 return d->handler->loopCount();
1308}
1309
1310/*!
1311 For image formats that support animation, this function returns the total
1312 number of images in the animation. If the format does not support
1313 animation, 0 is returned.
1314
1315 This function returns -1 if an error occurred.
1316
1317 \sa supportsAnimation(), QImageIOHandler::imageCount(), canRead()
1318*/
1319int QImageReader::imageCount() const
1320{
1321 if (!d->initHandler())
1322 return -1;
1323 return d->handler->imageCount();
1324}
1325
1326/*!
1327 For image formats that support animation, this function returns the number
1328 of milliseconds to wait until displaying the next frame in the animation.
1329 If the image format doesn't support animation, 0 is returned.
1330
1331 This function returns -1 if an error occurred.
1332
1333 \sa supportsAnimation(), QImageIOHandler::nextImageDelay(), canRead()
1334*/
1335int QImageReader::nextImageDelay() const
1336{
1337 if (!d->initHandler())
1338 return -1;
1339 return d->handler->nextImageDelay();
1340}
1341
1342/*!
1343 For image formats that support animation, this function returns the
1344 sequence number of the current frame. If the image format doesn't support
1345 animation, 0 is returned.
1346
1347 This function returns -1 if an error occurred.
1348
1349 \sa supportsAnimation(), QImageIOHandler::currentImageNumber(), canRead()
1350*/
1351int QImageReader::currentImageNumber() const
1352{
1353 if (!d->initHandler())
1354 return -1;
1355 return d->handler->currentImageNumber();
1356}
1357
1358/*!
1359 For image formats that support animation, this function returns
1360 the rect for the current frame. Otherwise, a null rect is returned.
1361
1362 \sa supportsAnimation(), QImageIOHandler::currentImageRect()
1363*/
1364QRect QImageReader::currentImageRect() const
1365{
1366 if (!d->initHandler())
1367 return QRect();
1368 return d->handler->currentImageRect();
1369}
1370
1371/*!
1372 Returns the type of error that occurred last.
1373
1374 \sa ImageReaderError, errorString()
1375*/
1376QImageReader::ImageReaderError QImageReader::error() const
1377{
1378 return d->imageReaderError;
1379}
1380
1381/*!
1382 Returns a human readable description of the last error that
1383 occurred.
1384
1385 \sa error()
1386*/
1387QString QImageReader::errorString() const
1388{
1389 if (d->errorString.isEmpty())
1390 return QImageReader::tr(sourceText: "Unknown error");
1391 return d->errorString;
1392}
1393
1394/*!
1395 Returns \c true if the reader supports \a option; otherwise returns
1396 false.
1397
1398 Different image formats support different options. Call this function to
1399 determine whether a certain option is supported by the current format. For
1400 example, the PNG format allows you to embed text into the image's metadata
1401 (see text()), and the BMP format allows you to determine the image's size
1402 without loading the whole image into memory (see size()).
1403
1404 \snippet code/src_gui_image_qimagereader.cpp 3
1405
1406 \sa QImageWriter::supportsOption()
1407*/
1408bool QImageReader::supportsOption(QImageIOHandler::ImageOption option) const
1409{
1410 if (!d->initHandler())
1411 return false;
1412 return d->handler->supportsOption(option);
1413}
1414
1415/*!
1416 If supported, this function returns the image format of the file
1417 \a fileName. Otherwise, an empty string is returned.
1418*/
1419QByteArray QImageReader::imageFormat(const QString &fileName)
1420{
1421 QFile file(fileName);
1422 if (!file.open(flags: QFile::ReadOnly))
1423 return QByteArray();
1424
1425 return imageFormat(device: &file);
1426}
1427
1428/*!
1429 If supported, this function returns the image format of the device
1430 \a device. Otherwise, an empty string is returned.
1431
1432 \sa QImageReader::autoDetectImageFormat()
1433*/
1434QByteArray QImageReader::imageFormat(QIODevice *device)
1435{
1436 QByteArray format;
1437 QImageIOHandler *handler = createReadHandlerHelper(device, format, /* autoDetectImageFormat = */ true, ignoresFormatAndExtension: false);
1438 if (handler) {
1439 if (handler->canRead())
1440 format = handler->format();
1441 delete handler;
1442 }
1443 return format;
1444}
1445
1446/*!
1447 Returns the list of image formats supported by QImageReader.
1448
1449 By default, Qt can read the following formats:
1450
1451 \table
1452 \header \li Format \li MIME type \li Description
1453 \row \li BMP \li image/bmp \li Windows Bitmap
1454 \row \li GIF \li image/gif \li Graphic Interchange Format (optional)
1455 \row \li JPG \li image/jpeg \li Joint Photographic Experts Group
1456 \row \li PNG \li image/png \li Portable Network Graphics
1457 \row \li PBM \li image/x-portable-bitmap \li Portable Bitmap
1458 \row \li PGM \li image/x-portable-graymap \li Portable Graymap
1459 \row \li PPM \li image/x-portable-pixmap \li Portable Pixmap
1460 \row \li XBM \li image/x-xbitmap \li X11 Bitmap
1461 \row \li XPM \li image/x-xpixmap \li X11 Pixmap
1462 \row \li SVG \li image/svg+xml \li Scalable Vector Graphics
1463 \endtable
1464
1465 Reading and writing SVG files is supported through the \l{Qt SVG} module.
1466 The \l{Qt Image Formats} module provides support for additional image formats.
1467
1468 Note that the QCoreApplication instance must be created before this function is
1469 called.
1470
1471 \sa setFormat(), QImageWriter::supportedImageFormats(), QImageIOPlugin
1472*/
1473
1474QList<QByteArray> QImageReader::supportedImageFormats()
1475{
1476 return QImageReaderWriterHelpers::supportedImageFormats(cap: QImageReaderWriterHelpers::CanRead);
1477}
1478
1479/*!
1480 Returns the list of MIME types supported by QImageReader.
1481
1482 Note that the QApplication instance must be created before this function is
1483 called.
1484
1485 \sa supportedImageFormats(), QImageWriter::supportedMimeTypes()
1486*/
1487
1488QList<QByteArray> QImageReader::supportedMimeTypes()
1489{
1490 return QImageReaderWriterHelpers::supportedMimeTypes(cap: QImageReaderWriterHelpers::CanRead);
1491}
1492
1493/*!
1494 \since 5.12
1495
1496 Returns the list of image formats corresponding to \a mimeType.
1497
1498 Note that the QGuiApplication instance must be created before this function is
1499 called.
1500
1501 \sa supportedImageFormats(), supportedMimeTypes()
1502*/
1503
1504QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeType)
1505{
1506 return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType,
1507 cap: QImageReaderWriterHelpers::CanRead);
1508}
1509
1510/*!
1511 \since 6.0
1512
1513 Returns the current allocation limit, in megabytes.
1514
1515 \sa setAllocationLimit()
1516*/
1517int QImageReader::allocationLimit()
1518{
1519 static int envLimit = []() {
1520 bool ok = false;
1521 int res = qEnvironmentVariableIntValue(varName: "QT_IMAGEIO_MAXALLOC", ok: &ok);
1522 return ok ? res : -1;
1523 }();
1524
1525 return envLimit >= 0 ? envLimit : QImageReaderPrivate::maxAlloc;
1526}
1527
1528/*!
1529 \since 6.0
1530
1531 Sets the allocation limit to \a mbLimit megabytes. Images that would
1532 require a QImage memory allocation above this limit will be rejected.
1533 If \a mbLimit is 0, the allocation size check will be disabled.
1534
1535 This limit helps applications avoid unexpectedly large memory usage from
1536 loading corrupt image files. It is normally not needed to change it. The
1537 default limit is large enough for all commonly used image sizes.
1538
1539 At runtime, this value may be overridden by the environment variable \c QT_IMAGEIO_MAXALLOC.
1540
1541 \note The memory requirements are calculated for a minimum of 32 bits per pixel, since Qt will
1542 typically convert an image to that depth when it is used in GUI. This means that the effective
1543 allocation limit is significantly smaller than \a mbLimit when reading 1 bpp and 8 bpp images.
1544
1545 \sa allocationLimit()
1546*/
1547void QImageReader::setAllocationLimit(int mbLimit)
1548{
1549 if (mbLimit >= 0)
1550 QImageReaderPrivate::maxAlloc = mbLimit;
1551}
1552
1553QT_END_NAMESPACE
1554

source code of qtbase/src/gui/image/qimagereader.cpp