Coverage Report

Created: 2026-10-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/image/qimagereader.cpp
Line
Count
Source
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
133
QT_BEGIN_NAMESPACE
134
135
Q_STATIC_LOGGING_CATEGORY(lcImageReader, "qt.gui.imageio.reader")
136
137
using namespace QImageReaderWriterHelpers;
138
using namespace Qt::StringLiterals;
139
140
Q_TRACE_POINT(qtgui, QImageReader_read_before_reading, QImageReader *reader, const QString &filename);
141
Q_TRACE_POINT(qtgui, QImageReader_read_after_reading, QImageReader *reader, bool result);
142
143
static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
144
                                                const QByteArray &format,
145
                                                bool autoDetectImageFormat,
146
                                                bool ignoresFormatAndExtension)
147
13.5k
{
148
13.5k
    if (!autoDetectImageFormat && format.isEmpty())
149
0
        return nullptr;
150
151
13.5k
    QByteArray form = format.toLower();
152
13.5k
    QImageIOHandler *handler = nullptr;
153
13.5k
    QByteArray suffix;
154
155
13.5k
    qCDebug(lcImageReader) << "Finding read handler for" << device << "and format" << format;
156
157
13.5k
#if QT_CONFIG(imageformatplugin)
158
13.5k
    Q_CONSTINIT static QBasicMutex mutex;
159
13.5k
    const auto locker = qt_scoped_lock(mutex);
160
161
13.5k
    typedef QMultiMap<int, QString> PluginKeyMap;
162
163
    // check if we have plugins that support the image format
164
13.5k
    auto l = QImageReaderWriterHelpers::pluginLoader();
165
13.5k
    const PluginKeyMap keyMap = l->keyMap();
166
167
13.5k
    qCDebug(lcImageReader) << keyMap.uniqueKeys().size() << "plugins available:" << keyMap.values();
168
169
13.5k
    int testFormatPluginIndex = -1;
170
13.5k
#endif // QT_CONFIG(imageformatplugin)
171
172
13.5k
    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
0
        if (QFile *file = qobject_cast<QFile *>(device)) {
175
0
            suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1();
176
0
            qCDebug(lcImageReader) << "Resolved format" << suffix << "from file name suffix";
177
0
        }
178
0
    }
179
180
13.5k
    QByteArray testFormat = !form.isEmpty() ? form : suffix;
181
13.5k
    if (ignoresFormatAndExtension)
182
0
        testFormat = QByteArray();
183
184
13.5k
#if QT_CONFIG(imageformatplugin)
185
13.5k
    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
13.5k
        qCDebug(lcImageReader) << "Checking if any plugins have explicitly declared support"
189
0
                               << "for the format" << testFormat;
190
13.5k
        const qint64 pos = device ? device->pos() : 0;
191
13.5k
        const auto keyList = keyMap.keys(QLatin1StringView(testFormat));
192
13.5k
        for (int testIndex : keyList) {
193
0
            QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(testIndex));
194
0
            if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
195
0
                qCDebug(lcImageReader) << plugin << "can read the format" << testFormat;
196
0
                handler = plugin->create(device, testFormat);
197
0
                testFormatPluginIndex = testIndex;
198
0
                break;
199
0
            }
200
0
        }
201
13.5k
        if (device && !device->isSequential())
202
13.5k
            device->seek(pos); // Should not have moved, but guard against buggy plugins
203
13.5k
    }
204
13.5k
#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
13.5k
    if (!handler && !testFormat.isEmpty()) {
209
13.5k
        qCDebug(lcImageReader) << "Checking if any built in handlers recognize the format"
210
0
                               << testFormat;
211
13.5k
        if (false) {
212
0
#ifndef QT_NO_IMAGEFORMAT_PNG
213
13.5k
        } else if (testFormat == "png") {
214
5.42k
            handler = new QPngHandler;
215
5.42k
#endif
216
5.42k
#ifndef QT_NO_IMAGEFORMAT_BMP
217
8.16k
        } else if (testFormat == "bmp") {
218
0
            handler = new QBmpHandler;
219
8.16k
        } else if (testFormat == "dib") {
220
0
            handler = new QBmpHandler(QBmpHandler::DibFormat);
221
0
#endif
222
0
#ifndef QT_NO_IMAGEFORMAT_XPM
223
8.16k
        } else if (testFormat == "xpm") {
224
0
            handler = new QXpmHandler;
225
0
#endif
226
0
#ifndef QT_NO_IMAGEFORMAT_XBM
227
8.16k
        } else if (testFormat == "xbm") {
228
0
            handler = new QXbmHandler;
229
0
            handler->setOption(QImageIOHandler::SubType, testFormat);
230
0
#endif
231
0
#ifndef QT_NO_IMAGEFORMAT_PPM
232
8.16k
        } else if (testFormat == "pbm" || testFormat == "pbmraw" || testFormat == "pgm"
233
8.16k
                   || testFormat == "pgmraw" || testFormat == "ppm" || testFormat == "ppmraw") {
234
0
            handler = new QPpmHandler;
235
0
            handler->setOption(QImageIOHandler::SubType, testFormat);
236
0
#endif
237
0
        }
238
239
13.5k
        if (handler)
240
5.42k
            qCDebug(lcImageReader) << "Using the built-in handler for format" << testFormat;
241
13.5k
    }
242
243
13.5k
#if QT_CONFIG(imageformatplugin)
244
13.5k
    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
8.16k
        qCDebug(lcImageReader) << "Checking if any plugins recognize the format" << testFormat;
248
249
8.16k
        const qint64 pos = device ? device->pos() : 0;
250
251
8.16k
        const int keyCount = keyMap.size();
252
8.16k
        for (int i = 0; i < keyCount; ++i) {
253
0
            if (i != testFormatPluginIndex) {
254
0
                QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i));
255
0
                if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
256
0
                    qCDebug(lcImageReader) << plugin << "can read the format" << testFormat;
257
0
                    handler = plugin->create(device, testFormat);
258
0
                    break;
259
0
                }
260
0
            }
261
0
        }
262
8.16k
        if (device && !device->isSequential())
263
8.16k
            device->seek(pos);  // Should not have moved, but guard against buggy plugins
264
8.16k
    }
265
13.5k
#endif // QT_CONFIG(imageformatplugin)
266
267
13.5k
    if (handler && device && !suffix.isEmpty()) {
268
0
        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
0
        const qint64 pos = device->pos();
272
0
        handler->setDevice(device);
273
0
        if (!form.isEmpty())
274
0
            handler->setFormat(form);
275
0
        bool canRead = handler->canRead();
276
0
        device->seek(pos);
277
0
        if (canRead) {
278
            // ok, we're done.
279
0
            return handler;
280
0
        }
281
0
        qCDebug(lcImageReader) << handler << "claimed support for" << suffix
282
0
                               << "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
0
        delete handler;
286
0
        handler = nullptr;
287
0
    }
288
289
13.5k
#if QT_CONFIG(imageformatplugin)
290
13.5k
    if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
291
        // check if any of our plugins recognize the file from its contents.
292
8.16k
        qCDebug(lcImageReader) << "Checking if any plugins recognize the format"
293
0
                               << "based on the contents in" << device;
294
8.16k
        const qint64 pos = device ? device->pos() : 0;
295
8.16k
        const int keyCount = keyMap.size();
296
8.16k
        for (int i = 0; i < keyCount; ++i) {
297
0
            if (i != testFormatPluginIndex) {
298
0
                QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i));
299
0
                if (plugin && plugin->capabilities(device, QByteArray()) & QImageIOPlugin::CanRead) {
300
0
                    handler = plugin->create(device, testFormat);
301
0
                    qCDebug(lcImageReader) << plugin << "can read the data in" << device;
302
0
                    break;
303
0
                }
304
0
            }
305
0
        }
306
8.16k
        if (device && !device->isSequential())
307
8.16k
            device->seek(pos);
308
8.16k
    }
309
13.5k
#endif // QT_CONFIG(imageformatplugin)
310
311
13.5k
    if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) {
312
        // check if any of our built-in handlers recognize the file from its
313
        // contents.
314
8.16k
        qCDebug(lcImageReader) << "Checking if any built in handlers recognize the format"
315
0
                               << "based on the contents in" << device;
316
8.16k
        int currentFormat = 0;
317
8.16k
        if (!suffix.isEmpty()) {
318
            // If reading from a file with a suffix, start testing our
319
            // built-in handler for that suffix first.
320
0
            for (int i = 0; i < _qt_NumFormats; ++i) {
321
0
                if (_qt_BuiltInFormats[i].extension == suffix) {
322
0
                    currentFormat = i;
323
0
                    break;
324
0
                }
325
0
            }
326
0
        }
327
328
8.16k
        QByteArray subType;
329
8.16k
        int numFormats = _qt_NumFormats;
330
34.7k
        while (device && numFormats >= 0) {
331
33.9k
            const qint64 pos = device->pos();
332
33.9k
            switch (currentFormat) {
333
0
#ifndef QT_NO_IMAGEFORMAT_PNG
334
9.03k
            case _qt_PngFormat:
335
9.03k
                if (QPngHandler::canRead(device))
336
2.60k
                    handler = new QPngHandler;
337
9.03k
                break;
338
0
#endif
339
0
#ifndef QT_NO_IMAGEFORMAT_BMP
340
5.55k
            case _qt_BmpFormat:
341
5.55k
                if (QBmpHandler::canRead(device))
342
1.13k
                    handler = new QBmpHandler;
343
5.55k
                break;
344
0
#endif
345
0
#ifndef QT_NO_IMAGEFORMAT_XPM
346
3.65k
            case _qt_XpmFormat:
347
3.65k
                if (QXpmHandler::canRead(device))
348
2.78k
                    handler = new QXpmHandler;
349
3.65k
                break;
350
0
#endif
351
0
#ifndef QT_NO_IMAGEFORMAT_PPM
352
3.75k
            case _qt_PbmFormat:
353
7.50k
            case _qt_PgmFormat:
354
11.9k
            case _qt_PpmFormat:
355
11.9k
                if (QPpmHandler::canRead(device, &subType)) {
356
662
                    handler = new QPpmHandler;
357
662
                    handler->setOption(QImageIOHandler::SubType, subType);
358
662
                }
359
11.9k
                break;
360
0
#endif
361
0
#ifndef QT_NO_IMAGEFORMAT_XBM
362
3.75k
            case _qt_XbmFormat:
363
3.75k
                if (QXbmHandler::canRead(device))
364
98
                    handler = new QXbmHandler;
365
3.75k
                break;
366
0
#endif
367
0
            default:
368
0
                break;
369
33.9k
            }
370
33.9k
            if (!device->isSequential())
371
33.9k
                device->seek(pos);
372
373
33.9k
            if (handler) {
374
7.29k
                qCDebug(lcImageReader, "The %s built-in handler can read this data",
375
7.29k
                       _qt_BuiltInFormats[currentFormat].extension);
376
7.29k
                break;
377
7.29k
            }
378
379
26.6k
            --numFormats;
380
26.6k
            ++currentFormat;
381
26.6k
            if (currentFormat >= _qt_NumFormats)
382
868
                currentFormat = 0;
383
26.6k
        }
384
8.16k
    }
385
386
13.5k
    if (!handler) {
387
868
        qCDebug(lcImageReader, "No handlers found. Giving up.");
388
        // no handler: give up.
389
868
        return nullptr;
390
868
    }
391
392
12.7k
    handler->setDevice(device);
393
12.7k
    if (!form.isEmpty())
394
12.7k
        handler->setFormat(form);
395
12.7k
    return handler;
396
13.5k
}
397
398
class QImageReaderPrivate
399
{
400
public:
401
    QImageReaderPrivate(QImageReader *qq);
402
    ~QImageReaderPrivate();
403
404
    // device
405
    QByteArray format;
406
    bool autoDetectImageFormat;
407
    bool ignoresFormatAndExtension;
408
    QIODevice *device;
409
    bool deleteDevice;
410
    QImageIOHandler *handler;
411
    bool initHandler();
412
413
    // image options
414
    QRect clipRect;
415
    QSize scaledSize;
416
    QRect scaledClipRect;
417
    int quality;
418
    QMap<QString, QString> text;
419
    void getText();
420
    enum {
421
        UsePluginDefault,
422
        ApplyTransform,
423
        DoNotApplyTransform
424
    } autoTransform;
425
426
    // error
427
    QImageReader::ImageReaderError imageReaderError;
428
    QString errorString;
429
430
    QImageReader *q;
431
432
    static int maxAlloc;
433
};
434
435
int QImageReaderPrivate::maxAlloc = 256; // 256 MB is enough for an 8K 64bpp image
436
437
/*!
438
    \internal
439
*/
440
QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
441
13.5k
    : autoDetectImageFormat(true), ignoresFormatAndExtension(false)
442
13.5k
{
443
13.5k
    device = nullptr;
444
13.5k
    deleteDevice = false;
445
13.5k
    handler = nullptr;
446
13.5k
    quality = -1;
447
13.5k
    imageReaderError = QImageReader::UnknownError;
448
13.5k
    autoTransform = UsePluginDefault;
449
450
13.5k
    q = qq;
451
13.5k
}
452
453
/*!
454
    \internal
455
*/
456
QImageReaderPrivate::~QImageReaderPrivate()
457
13.5k
{
458
13.5k
    delete handler;
459
13.5k
    if (deleteDevice)
460
0
        delete device;
461
13.5k
}
462
463
/*!
464
    \internal
465
*/
466
bool QImageReaderPrivate::initHandler()
467
64.4k
{
468
64.4k
    if (handler)
469
50.8k
        return true;
470
471
    // check some preconditions
472
13.5k
    if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
473
0
        imageReaderError = QImageReader::DeviceError;
474
0
        errorString = QImageReader::tr("Invalid device");
475
0
        return false;
476
0
    }
477
478
    // probe the file extension
479
13.5k
    if (deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly) && autoDetectImageFormat) {
480
0
        Q_ASSERT(qobject_cast<QFile*>(device) != nullptr); // future-proofing; for now this should always be the case, so...
481
0
        QFile *file = static_cast<QFile *>(device);
482
483
0
        if (file->error() == QFileDevice::ResourceError) {
484
            // this is bad. we should abort the open attempt and note the failure.
485
0
            imageReaderError = QImageReader::DeviceError;
486
0
            errorString = file->errorString();
487
0
            return false;
488
0
        }
489
490
0
        QList<QByteArray> extensions = QImageReader::supportedImageFormats();
491
0
        if (!format.isEmpty()) {
492
            // Try the most probable extension first
493
0
            int currentFormatIndex = extensions.indexOf(format.toLower());
494
0
            if (currentFormatIndex > 0)
495
0
                extensions.swapItemsAt(0, currentFormatIndex);
496
0
        }
497
498
0
        int currentExtension = 0;
499
500
0
        QString fileName = file->fileName();
501
0
        bool fileIsOpen;
502
503
0
        do {
504
0
            file->setFileName(fileName + u'.'
505
0
                    + QLatin1StringView(extensions.at(currentExtension++).constData()));
506
0
            fileIsOpen = file->open(QIODevice::ReadOnly);
507
0
        } while (!fileIsOpen && currentExtension < extensions.size());
508
509
0
        if (!fileIsOpen) {
510
0
            imageReaderError = QImageReader::FileNotFoundError;
511
0
            errorString = QImageReader::tr("File not found");
512
0
            file->setFileName(fileName); // restore the old file name
513
0
            return false;
514
0
        }
515
0
    }
516
517
    // assign a handler
518
13.5k
    if ((handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
519
868
        imageReaderError = QImageReader::UnsupportedFormatError;
520
868
        errorString = QImageReader::tr("Unsupported image format");
521
868
        return false;
522
868
    }
523
12.7k
    return true;
524
13.5k
}
525
526
/*!
527
    \internal
528
*/
529
void QImageReaderPrivate::getText()
530
0
{
531
0
    if (text.isEmpty() && q->supportsOption(QImageIOHandler::Description))
532
0
        text = qt_getImageTextFromDescription(handler->option(QImageIOHandler::Description).toString());
533
0
}
534
535
/*!
536
    Constructs an empty QImageReader object. Before reading an image,
537
    call setDevice() or setFileName().
538
*/
539
QImageReader::QImageReader()
540
0
    : d(new QImageReaderPrivate(this))
541
0
{
542
0
}
543
544
/*!
545
    Constructs a QImageReader object with the device \a device and the
546
    image format \a format.
547
*/
548
QImageReader::QImageReader(QIODevice *device, const QByteArray &format)
549
13.5k
    : d(new QImageReaderPrivate(this))
550
13.5k
{
551
13.5k
    d->device = device;
552
13.5k
    d->format = format;
553
13.5k
}
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
*/
561
QImageReader::QImageReader(const QString &fileName, const QByteArray &format)
562
0
    : QImageReader(new QFile(fileName), format)
563
0
{
564
0
    d->deleteDevice = true;
565
0
}
566
567
/*!
568
    Destructs the QImageReader object.
569
*/
570
QImageReader::~QImageReader()
571
13.5k
{
572
13.5k
    delete d;
573
13.5k
}
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
*/
586
void QImageReader::setFormat(const QByteArray &format)
587
0
{
588
0
    d->format = format;
589
0
}
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
*/
605
QByteArray QImageReader::format() const
606
0
{
607
0
    if (d->format.isEmpty()) {
608
0
        if (!d->initHandler())
609
0
            return QByteArray();
610
0
        return d->handler->canRead() ? d->handler->format() : QByteArray();
611
0
    }
612
613
0
    return d->format;
614
0
}
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
*/
655
void QImageReader::setAutoDetectImageFormat(bool enabled)
656
0
{
657
0
    d->autoDetectImageFormat = enabled;
658
0
}
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
*/
666
bool QImageReader::autoDetectImageFormat() const
667
0
{
668
0
    return d->autoDetectImageFormat;
669
0
}
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
686
void QImageReader::setDecideFormatFromContent(bool ignored)
687
0
{
688
0
    d->ignoresFormatAndExtension = ignored;
689
0
}
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
700
bool QImageReader::decideFormatFromContent() const
701
0
{
702
0
    return d->ignoresFormatAndExtension;
703
0
}
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
*/
719
void QImageReader::setDevice(QIODevice *device)
720
0
{
721
0
    delete d->handler;
722
0
    d->handler = nullptr;
723
0
    if (d->device && d->deleteDevice)
724
0
        delete d->device;
725
0
    d->device = device;
726
0
    d->deleteDevice = false;
727
0
    d->text.clear();
728
0
}
729
730
/*!
731
    Returns the device currently assigned to QImageReader, or \nullptr
732
    if no device has been assigned.
733
*/
734
QIODevice *QImageReader::device() const
735
0
{
736
0
    return d->device;
737
0
}
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
*/
750
void QImageReader::setFileName(const QString &fileName)
751
0
{
752
0
    setDevice(new QFile(fileName));
753
0
    d->deleteDevice = true;
754
0
}
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
*/
765
QString QImageReader::fileName() const
766
12.7k
{
767
12.7k
    QFile *file = qobject_cast<QFile *>(d->device);
768
12.7k
    return file ? file->fileName() : QString();
769
12.7k
}
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
*/
789
void QImageReader::setQuality(int quality)
790
0
{
791
0
    d->quality = quality;
792
0
}
793
794
/*!
795
    Returns the quality setting of the image format.
796
797
    \sa setQuality()
798
*/
799
int QImageReader::quality() const
800
0
{
801
0
    return d->quality;
802
0
}
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
*/
815
QSize QImageReader::size() const
816
0
{
817
0
    if (supportsOption(QImageIOHandler::Size))
818
0
        return d->handler->option(QImageIOHandler::Size).toSize();
819
820
0
    return QSize();
821
0
}
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
 */
834
QSize QImageReader::effectiveSize() const
835
0
{
836
    // ### Qt 7: Consider deprecating and following this behaviour in QImageReader::size()
837
838
0
    QSize size = QImageReader::size();
839
840
0
    if (autoTransform() && transformation().testFlag(QImageIOHandler::TransformationRotate90))
841
0
        size.transpose();
842
843
0
    return size;
844
0
}
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
*/
856
QImage::Format QImageReader::imageFormat() const
857
0
{
858
0
    if (supportsOption(QImageIOHandler::ImageFormat))
859
0
        return (QImage::Format)d->handler->option(QImageIOHandler::ImageFormat).toInt();
860
861
0
    return QImage::Format_Invalid;
862
0
}
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
*/
874
QStringList QImageReader::textKeys() const
875
0
{
876
0
    d->getText();
877
0
    return d->text.keys();
878
0
}
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
*/
888
QString QImageReader::text(const QString &key) const
889
0
{
890
0
    d->getText();
891
0
    return d->text.value(key);
892
0
}
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
*/
901
void QImageReader::setClipRect(const QRect &rect)
902
0
{
903
0
    d->clipRect = rect;
904
0
}
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
*/
913
QRect QImageReader::clipRect() const
914
0
{
915
0
    return d->clipRect;
916
0
}
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
*/
932
void QImageReader::setScaledSize(const QSize &size)
933
0
{
934
0
    d->scaledSize = size;
935
0
}
936
937
/*!
938
    Returns the scaled size of the image.
939
940
    \sa setScaledSize()
941
*/
942
QSize QImageReader::scaledSize() const
943
0
{
944
0
    return d->scaledSize;
945
0
}
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
*/
954
void QImageReader::setScaledClipRect(const QRect &rect)
955
0
{
956
0
    d->scaledClipRect = rect;
957
0
}
958
959
/*!
960
    Returns the scaled clip rect of the image.
961
962
    \sa setScaledClipRect()
963
*/
964
QRect QImageReader::scaledClipRect() const
965
0
{
966
0
    return d->scaledClipRect;
967
0
}
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
*/
976
void QImageReader::setBackgroundColor(const QColor &color)
977
0
{
978
0
    if (supportsOption(QImageIOHandler::BackgroundColor))
979
0
        d->handler->setOption(QImageIOHandler::BackgroundColor, color);
980
0
}
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
*/
989
QColor QImageReader::backgroundColor() const
990
0
{
991
0
    if (supportsOption(QImageIOHandler::BackgroundColor))
992
0
        return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor));
993
0
    return QColor();
994
0
}
995
996
/*!
997
    Returns \c true if the image format supports animation;
998
    otherwise, false is returned.
999
1000
    \sa QMovie::supportedFormats()
1001
*/
1002
bool QImageReader::supportsAnimation() const
1003
0
{
1004
0
    if (supportsOption(QImageIOHandler::Animation))
1005
0
        return d->handler->option(QImageIOHandler::Animation).toBool();
1006
0
    return false;
1007
0
}
1008
1009
/*!
1010
    \since 5.4
1011
1012
    Returns the subtype of the image.
1013
*/
1014
QByteArray QImageReader::subType() const
1015
0
{
1016
0
    if (supportsOption(QImageIOHandler::SubType))
1017
0
        return d->handler->option(QImageIOHandler::SubType).toByteArray();
1018
0
    return QByteArray();
1019
0
}
1020
1021
/*!
1022
    \since 5.4
1023
1024
    Returns the list of subtypes supported by an image.
1025
*/
1026
QList<QByteArray> QImageReader::supportedSubTypes() const
1027
0
{
1028
0
    if (supportsOption(QImageIOHandler::SupportedSubTypes))
1029
0
        return qvariant_cast<QList<QByteArray> >(d->handler->option(QImageIOHandler::SupportedSubTypes));
1030
0
    return QList<QByteArray>();
1031
0
}
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
*/
1041
QImageIOHandler::Transformations QImageReader::transformation() const
1042
0
{
1043
0
    int option = QImageIOHandler::TransformationNone;
1044
0
    if (supportsOption(QImageIOHandler::ImageTransformation))
1045
0
        option = d->handler->option(QImageIOHandler::ImageTransformation).toInt();
1046
0
    return QImageIOHandler::Transformations(option);
1047
0
}
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
*/
1057
void QImageReader::setAutoTransform(bool enabled)
1058
0
{
1059
0
    d->autoTransform = enabled ? QImageReaderPrivate::ApplyTransform
1060
0
                               : QImageReaderPrivate::DoNotApplyTransform;
1061
0
}
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
*/
1071
bool QImageReader::autoTransform() const
1072
1.07k
{
1073
1.07k
    switch (d->autoTransform) {
1074
0
    case QImageReaderPrivate::ApplyTransform:
1075
0
        return true;
1076
0
    case QImageReaderPrivate::DoNotApplyTransform:
1077
0
        return false;
1078
1.07k
    case QImageReaderPrivate::UsePluginDefault:
1079
1.07k
        Q_FALLTHROUGH();
1080
1.07k
    default:
1081
1.07k
        break;
1082
1.07k
    }
1083
1.07k
    return false;
1084
1.07k
}
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
*/
1103
bool QImageReader::canRead() const
1104
0
{
1105
0
    if (!d->initHandler())
1106
0
        return false;
1107
1108
0
    return d->handler->canRead();
1109
0
}
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
*/
1123
QImage QImageReader::read()
1124
13.5k
{
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
13.5k
    QImage image;
1128
13.5k
    return read(&image) ? image : QImage();
1129
13.5k
}
1130
1131
extern 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
*/
1153
bool QImageReader::read(QImage *image)
1154
13.5k
{
1155
13.5k
    if (!image) {
1156
0
        qWarning("QImageReader::read: cannot read into null pointer");
1157
0
        return false;
1158
0
    }
1159
1160
13.5k
    if (!d->initHandler())
1161
868
        return false;
1162
1163
12.7k
    QSize scaledSize = d->scaledSize;
1164
12.7k
    if ((scaledSize.width() <= 0 && scaledSize.height() > 0) ||
1165
12.7k
        (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
0
        if (const QSize originalSize = size(); !originalSize.isEmpty()) {
1169
0
            if (scaledSize.width() <= 0) {
1170
0
                const auto ratio = qreal(scaledSize.height()) / originalSize.height();
1171
0
                scaledSize.setWidth(qRound(originalSize.width() * ratio));
1172
0
            } else {
1173
0
                const auto ratio = qreal(scaledSize.width()) / originalSize.width();
1174
0
                scaledSize.setHeight(qRound(originalSize.height() * ratio));
1175
0
            }
1176
0
        }
1177
0
    }
1178
1179
12.7k
    const bool supportScaledSize = supportsOption(QImageIOHandler::ScaledSize) && scaledSize.isValid();
1180
12.7k
    const bool supportClipRect = supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull();
1181
12.7k
    const bool supportScaledClipRect = supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull();
1182
1183
    // set the handler specific options.
1184
12.7k
    if (supportScaledSize) {
1185
0
        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
0
            d->handler->setOption(QImageIOHandler::ScaledSize, scaledSize);
1189
0
        }
1190
0
    }
1191
12.7k
    if (supportClipRect)
1192
0
        d->handler->setOption(QImageIOHandler::ClipRect, d->clipRect);
1193
12.7k
    if (supportScaledClipRect)
1194
0
        d->handler->setOption(QImageIOHandler::ScaledClipRect, d->scaledClipRect);
1195
12.7k
    if (supportsOption(QImageIOHandler::Quality))
1196
8.02k
        d->handler->setOption(QImageIOHandler::Quality, d->quality);
1197
1198
    // read the image
1199
12.7k
    QString filename = fileName();
1200
12.7k
    if (Q_TRACE_ENABLED(QImageReader_read_before_reading)) {
1201
0
        Q_TRACE(QImageReader_read_before_reading, this, filename.isEmpty() ? u"unknown"_s : filename);
1202
0
    }
1203
1204
12.7k
    const bool result = d->handler->read(image);
1205
1206
12.7k
    Q_TRACE(QImageReader_read_after_reading, this, result);
1207
1208
12.7k
    if (!result) {
1209
11.6k
        d->imageReaderError = InvalidDataError;
1210
11.6k
        d->errorString = QImageReader::tr("Unable to read image data");
1211
11.6k
        return false;
1212
11.6k
    }
1213
1214
    // provide default implementations for any unsupported image
1215
    // options
1216
1.07k
    if (supportClipRect) {
1217
0
        if (supportScaledSize) {
1218
0
            if (supportScaledClipRect) {
1219
                // all features are supported by the handler; nothing to do.
1220
0
            } else {
1221
                // the image is already scaled, so apply scaled clipping.
1222
0
                if (!d->scaledClipRect.isNull())
1223
0
                    *image = image->copy(d->scaledClipRect);
1224
0
            }
1225
0
        } else {
1226
0
            if (supportScaledClipRect) {
1227
                // supports scaled clipping but not scaling, most
1228
                // likely a broken handler.
1229
0
            } else {
1230
0
                if (scaledSize.isValid()) {
1231
0
                    *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1232
0
                }
1233
0
                if (d->scaledClipRect.isValid()) {
1234
0
                    *image = image->copy(d->scaledClipRect);
1235
0
                }
1236
0
            }
1237
0
        }
1238
1.07k
    } else {
1239
1.07k
        if (supportScaledSize && d->clipRect.isNull()) {
1240
0
            if (supportScaledClipRect) {
1241
                // nothing to do (ClipRect is ignored!)
1242
0
            } else {
1243
                // provide all workarounds.
1244
0
                if (d->scaledClipRect.isValid()) {
1245
0
                    *image = image->copy(d->scaledClipRect);
1246
0
                }
1247
0
            }
1248
1.07k
        } else {
1249
1.07k
            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
1.07k
            } else {
1254
                // provide all workarounds.
1255
1.07k
                if (d->clipRect.isValid())
1256
0
                    *image = image->copy(d->clipRect);
1257
1.07k
                if (scaledSize.isValid())
1258
0
                    *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
1259
1.07k
                if (d->scaledClipRect.isValid())
1260
0
                    *image = image->copy(d->scaledClipRect);
1261
1.07k
            }
1262
1.07k
        }
1263
1.07k
    }
1264
1265
    // successful read; check for "@Nx" file name suffix and set device pixel ratio.
1266
1.07k
    static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
1267
1.07k
    if (!disableNxImageLoading) {
1268
1.07k
        const QByteArray suffix = QFileInfo(filename).baseName().right(3).toLatin1();
1269
1.07k
        if (suffix.size() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
1270
0
            image->setDevicePixelRatio(suffix[1] - '0');
1271
1.07k
    }
1272
1.07k
    if (autoTransform())
1273
0
        qt_imageTransform(*image, transformation());
1274
1275
1.07k
    return true;
1276
12.7k
}
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
*/
1289
bool QImageReader::jumpToNextImage()
1290
0
{
1291
0
    if (!d->initHandler())
1292
0
        return false;
1293
0
    return d->handler->jumpToNextImage();
1294
0
}
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
*/
1305
bool QImageReader::jumpToImage(int imageNumber)
1306
0
{
1307
0
    if (!d->initHandler())
1308
0
        return false;
1309
0
    return d->handler->jumpToImage(imageNumber);
1310
0
}
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
*/
1320
int QImageReader::loopCount() const
1321
0
{
1322
0
    if (!d->initHandler())
1323
0
        return -1;
1324
0
    return d->handler->loopCount();
1325
0
}
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
*/
1336
int QImageReader::imageCount() const
1337
0
{
1338
0
    if (!d->initHandler())
1339
0
        return -1;
1340
0
    return d->handler->imageCount();
1341
0
}
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
*/
1352
int QImageReader::nextImageDelay() const
1353
0
{
1354
0
    if (!d->initHandler())
1355
0
        return -1;
1356
0
    return d->handler->nextImageDelay();
1357
0
}
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
*/
1368
int QImageReader::currentImageNumber() const
1369
0
{
1370
0
    if (!d->initHandler())
1371
0
        return -1;
1372
0
    return d->handler->currentImageNumber();
1373
0
}
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
*/
1381
QRect QImageReader::currentImageRect() const
1382
0
{
1383
0
    if (!d->initHandler())
1384
0
        return QRect();
1385
0
    return d->handler->currentImageRect();
1386
0
}
1387
1388
/*!
1389
    Returns the type of error that occurred last.
1390
1391
    \sa ImageReaderError, errorString()
1392
*/
1393
QImageReader::ImageReaderError QImageReader::error() const
1394
0
{
1395
0
    return d->imageReaderError;
1396
0
}
1397
1398
/*!
1399
    Returns a human readable description of the last error that
1400
    occurred.
1401
1402
    \sa error()
1403
*/
1404
QString QImageReader::errorString() const
1405
0
{
1406
0
    if (d->errorString.isEmpty())
1407
0
        return QImageReader::tr("Unknown error");
1408
0
    return d->errorString;
1409
0
}
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
*/
1425
bool QImageReader::supportsOption(QImageIOHandler::ImageOption option) const
1426
50.8k
{
1427
50.8k
    if (!d->initHandler())
1428
0
        return false;
1429
50.8k
    return d->handler->supportsOption(option);
1430
50.8k
}
1431
1432
/*!
1433
    If supported, this function returns the image format of the file
1434
    \a fileName. Otherwise, an empty string is returned.
1435
*/
1436
QByteArray QImageReader::imageFormat(const QString &fileName)
1437
0
{
1438
0
    QFile file(fileName);
1439
0
    if (!file.open(QFile::ReadOnly))
1440
0
        return QByteArray();
1441
1442
0
    return imageFormat(&file);
1443
0
}
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
*/
1451
QByteArray QImageReader::imageFormat(QIODevice *device)
1452
0
{
1453
0
    QByteArray format;
1454
0
    QImageIOHandler *handler = createReadHandlerHelper(device, format, /* autoDetectImageFormat = */ true, false);
1455
0
    if (handler) {
1456
0
        if (handler->canRead())
1457
0
            format = handler->format();
1458
0
        delete handler;
1459
0
    }
1460
0
    return format;
1461
0
}
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
1491
QList<QByteArray> QImageReader::supportedImageFormats()
1492
0
{
1493
0
    return QImageReaderWriterHelpers::supportedImageFormats(QImageReaderWriterHelpers::CanRead);
1494
0
}
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
1505
QList<QByteArray> QImageReader::supportedMimeTypes()
1506
0
{
1507
0
    return QImageReaderWriterHelpers::supportedMimeTypes(QImageReaderWriterHelpers::CanRead);
1508
0
}
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
1521
QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeType)
1522
0
{
1523
0
    return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType,
1524
0
                                                              QImageReaderWriterHelpers::CanRead);
1525
0
}
1526
1527
/*!
1528
    \since 6.0
1529
1530
    Returns the current allocation limit, in megabytes.
1531
1532
    \sa setAllocationLimit()
1533
*/
1534
int QImageReader::allocationLimit()
1535
167k
{
1536
167k
    static int envLimit = []() {
1537
24
        bool ok = false;
1538
24
        int res = qEnvironmentVariableIntValue("QT_IMAGEIO_MAXALLOC", &ok);
1539
24
        return ok ? res : -1;
1540
24
    }();
1541
1542
167k
    return envLimit >= 0 ? envLimit : QImageReaderPrivate::maxAlloc;
1543
167k
}
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
*/
1564
void QImageReader::setAllocationLimit(int mbLimit)
1565
164k
{
1566
164k
    if (mbLimit >= 0)
1567
164k
        QImageReaderPrivate::maxAlloc = mbLimit;
1568
164k
}
1569
1570
QT_END_NAMESPACE