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