Coverage Report

Created: 2026-11-12 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/gui/image/qimage.cpp
Line
Count
Source
1
// Copyright (C) 2022 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
#include "qimage.h"
6
7
#include "qbuffer.h"
8
#include "qdatastream.h"
9
#include "qcolortransform.h"
10
#include "qfloat16.h"
11
#include "qmap.h"
12
#include "qtransform.h"
13
#include "qimagereader.h"
14
#include "qimagewriter.h"
15
#include "qrgbafloat.h"
16
#include "qstringlist.h"
17
#include "qvariant.h"
18
#include "qimagepixmapcleanuphooks_p.h"
19
#include <qpa/qplatformintegration.h>
20
#include <private/qguiapplication_p.h>
21
#include <ctype.h>
22
#include <stdlib.h>
23
#include <limits.h>
24
#include <qpa/qplatformpixmap.h>
25
#include <qalloc.h>
26
#include <private/qcolorspace_p.h>
27
#include <private/qcolortransform_p.h>
28
#include <private/qmemrotate_p.h>
29
#include <private/qimagescale_p.h>
30
#include <private/qpixellayout_p.h>
31
#include <private/qsimd_p.h>
32
33
#include <qhash.h>
34
35
#include <private/qpaintengine_raster_p.h>
36
37
#include <private/qimage_p.h>
38
#include <private/qfont_p.h>
39
40
#if QT_CONFIG(qtgui_threadpool)
41
#include <private/qlatch_p.h>
42
#include <qthreadpool.h>
43
#include <private/qthreadpool_p.h>
44
#endif
45
46
#include <qtgui_tracepoints_p.h>
47
48
#include <memory>
49
50
0
#define QT_XFORM_TYPE_MSBFIRST 0
51
0
#define QT_XFORM_TYPE_LSBFIRST 1
52
53
QT_BEGIN_NAMESPACE
54
class QCmyk32;
55
56
using namespace Qt::StringLiterals;
57
58
// MSVC 19.28 does show spurious warning "C4723: potential divide by 0" for code that divides
59
// by height() in release builds. Anyhow, all the code paths in this file are only executed
60
// for valid QImage's, where height() cannot be 0. Therefore disable the warning.
61
QT_WARNING_DISABLE_MSVC(4723)
62
63
#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
64
#pragma message disable narrowptr
65
#endif
66
67
68
#define QIMAGE_SANITYCHECK_MEMORY(image) \
69
0
    if ((image).isNull()) { \
70
0
        qWarning("QImage: out of memory, returning null image"); \
71
0
        return QImage(); \
72
0
    }
73
74
Q_TRACE_PREFIX(qtgui,
75
   "#include <qimagereader.h>"
76
);
77
78
Q_TRACE_METADATA(qtgui,
79
"ENUM { } QImage::Format;" \
80
"FLAGS { } Qt::ImageConversionFlags;"
81
);
82
83
Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode, int);
84
Q_TRACE_PARAM_REPLACE(Qt::TransformationMode, int);
85
86
static QImage rotated90(const QImage &src);
87
static QImage rotated180(const QImage &src);
88
static QImage rotated270(const QImage &src);
89
90
static int next_qimage_serial_number()
91
0
{
92
0
    Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
93
0
    return 1 + serial.fetchAndAddRelaxed(1);
94
0
}
95
96
QImageData::QImageData()
97
0
    : ref(0), width(0), height(0), depth(0), nbytes(0), devicePixelRatio(1.0), data(nullptr),
98
0
      format(QImage::Format_ARGB32), bytes_per_line(0),
99
0
      ser_no(next_qimage_serial_number()),
100
0
      detach_no(0),
101
0
      offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
102
0
      is_cached(false), cleanupFunction(nullptr), cleanupInfo(nullptr),
103
0
      paintEngine(nullptr)
104
0
{
105
0
    QPoint dpis = qt_defaultDpis();
106
0
    dpmx = dpis.x() * 100 / qreal(2.54);
107
0
    dpmy = dpis.y() * 100 / qreal(2.54);
108
0
}
109
110
/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format)
111
112
    \internal
113
114
    Creates a new image data.
115
    Returns \nullptr if invalid parameters are give or anything else failed.
116
*/
117
QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(const QSize &size, QImage::Format format)
118
0
{
119
0
    if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
120
0
        return nullptr;                             // invalid parameter(s)
121
122
0
    Q_TRACE_SCOPE(QImageData_create, size, format);
123
124
0
    int width = size.width();
125
0
    int height = size.height();
126
0
    int depth = qt_depthForFormat(format);
127
0
    auto params = calculateImageParameters(width, height, depth);
128
0
    if (!params.isValid())
129
0
        return nullptr;
130
131
0
    auto d = std::make_unique<QImageData>();
132
133
0
    switch (format) {
134
0
    case QImage::Format_Mono:
135
0
    case QImage::Format_MonoLSB:
136
0
        d->colortable.resize(2);
137
0
        d->colortable[0] = QColor(Qt::black).rgba();
138
0
        d->colortable[1] = QColor(Qt::white).rgba();
139
0
        break;
140
0
    default:
141
0
        break;
142
0
    }
143
144
0
    d->width = width;
145
0
    d->height = height;
146
0
    d->depth = depth;
147
0
    d->format = format;
148
0
    d->has_alpha_clut = false;
149
0
    d->is_cached = false;
150
151
0
    d->bytes_per_line = params.bytesPerLine;
152
0
    d->nbytes = params.totalSize;
153
0
    d->data  = (uchar *)malloc(d->nbytes);
154
155
0
    if (!d->data)
156
0
        return nullptr;
157
158
0
    d->ref.ref();
159
0
    return d.release();
160
0
}
161
162
QImageData::~QImageData()
163
0
{
164
0
    if (cleanupFunction)
165
0
        cleanupFunction(cleanupInfo);
166
0
    if (is_cached)
167
0
        QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
168
0
    delete paintEngine;
169
0
    if (data && own_data)
170
0
        QtPrivate::sizedFree(data, nbytes);
171
0
    data = nullptr;
172
0
}
173
174
#if defined(_M_ARM) && defined(_MSC_VER)
175
#pragma optimize("", off)
176
#endif
177
178
bool QImageData::checkForAlphaPixels() const
179
0
{
180
0
    bool has_alpha_pixels = false;
181
182
0
    switch (format) {
183
184
0
    case QImage::Format_Mono:
185
0
    case QImage::Format_MonoLSB:
186
0
    case QImage::Format_Indexed8:
187
0
        has_alpha_pixels = has_alpha_clut;
188
0
        break;
189
0
    case QImage::Format_Alpha8:
190
0
        has_alpha_pixels = true;
191
0
        break;
192
0
    case QImage::Format_ARGB32:
193
0
    case QImage::Format_ARGB32_Premultiplied: {
194
0
        const uchar *bits = data;
195
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
196
0
            uint alphaAnd = 0xff000000;
197
0
            for (int x=0; x<width; ++x)
198
0
                alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
199
0
            has_alpha_pixels = (alphaAnd != 0xff000000);
200
0
            bits += bytes_per_line;
201
0
        }
202
0
    } break;
203
204
0
    case QImage::Format_RGBA8888:
205
0
    case QImage::Format_RGBA8888_Premultiplied: {
206
0
        const uchar *bits = data;
207
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
208
0
            uchar alphaAnd = 0xff;
209
0
            for (int x=0; x<width; ++x)
210
0
                alphaAnd &= bits[x * 4+ 3];
211
0
            has_alpha_pixels = (alphaAnd != 0xff);
212
0
            bits += bytes_per_line;
213
0
        }
214
0
    } break;
215
216
0
    case QImage::Format_A2BGR30_Premultiplied:
217
0
    case QImage::Format_A2RGB30_Premultiplied: {
218
0
        const uchar *bits = data;
219
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
220
0
            uint alphaAnd = 0xc0000000;
221
0
            for (int x=0; x<width; ++x)
222
0
                alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
223
0
            has_alpha_pixels = (alphaAnd != 0xc0000000);
224
0
            bits += bytes_per_line;
225
0
        }
226
0
    } break;
227
228
0
    case QImage::Format_ARGB8555_Premultiplied:
229
0
    case QImage::Format_ARGB8565_Premultiplied: {
230
0
        const uchar *bits = data;
231
0
        const uchar *end_bits = data + bytes_per_line;
232
233
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
234
0
            uchar alphaAnd = 0xff;
235
0
            while (bits < end_bits) {
236
0
                alphaAnd &= bits[0];
237
0
                bits += 3;
238
0
            }
239
0
            has_alpha_pixels = (alphaAnd != 0xff);
240
0
            bits = end_bits;
241
0
            end_bits += bytes_per_line;
242
0
        }
243
0
    } break;
244
245
0
    case QImage::Format_ARGB6666_Premultiplied: {
246
0
        const uchar *bits = data;
247
0
        const uchar *end_bits = data + bytes_per_line;
248
249
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
250
0
            uchar alphaAnd = 0xfc;
251
0
            while (bits < end_bits) {
252
0
                alphaAnd &= bits[0];
253
0
                bits += 3;
254
0
            }
255
0
            has_alpha_pixels = (alphaAnd != 0xfc);
256
0
            bits = end_bits;
257
0
            end_bits += bytes_per_line;
258
0
        }
259
0
    } break;
260
261
0
    case QImage::Format_ARGB4444_Premultiplied: {
262
0
        const uchar *bits = data;
263
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
264
0
            ushort alphaAnd = 0xf000;
265
0
            for (int x=0; x<width; ++x)
266
0
                alphaAnd &= reinterpret_cast<const ushort*>(bits)[x];
267
0
            has_alpha_pixels = (alphaAnd != 0xf000);
268
0
            bits += bytes_per_line;
269
0
        }
270
0
    } break;
271
0
    case QImage::Format_RGBA64:
272
0
    case QImage::Format_RGBA64_Premultiplied: {
273
0
        uchar *bits = data;
274
0
        for (int y=0; y<height && !has_alpha_pixels; ++y) {
275
0
            for (int x=0; x<width; ++x) {
276
0
                has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
277
0
            }
278
0
            bits += bytes_per_line;
279
0
        }
280
0
    } break;
281
0
    case QImage::Format_RGBA16FPx4:
282
0
    case QImage::Format_RGBA16FPx4_Premultiplied: {
283
0
        uchar *bits = data;
284
0
        for (int y = 0; y < height && !has_alpha_pixels; ++y) {
285
0
            for (int x = 0; x < width; ++x)
286
0
                has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
287
0
            bits += bytes_per_line;
288
0
        }
289
0
    } break;
290
0
    case QImage::Format_RGBA32FPx4:
291
0
    case QImage::Format_RGBA32FPx4_Premultiplied: {
292
0
        uchar *bits = data;
293
0
        for (int y = 0; y < height && !has_alpha_pixels; ++y) {
294
0
            for (int x = 0; x < width; ++x)
295
0
                has_alpha_pixels |= ((float *)bits)[x * 4 + 3] < 1.0f;
296
0
            bits += bytes_per_line;
297
0
        }
298
0
    } break;
299
300
0
    case QImage::Format_RGB32:
301
0
    case QImage::Format_RGB16:
302
0
    case QImage::Format_RGB444:
303
0
    case QImage::Format_RGB555:
304
0
    case QImage::Format_RGB666:
305
0
    case QImage::Format_RGB888:
306
0
    case QImage::Format_BGR888:
307
0
    case QImage::Format_RGBX8888:
308
0
    case QImage::Format_BGR30:
309
0
    case QImage::Format_RGB30:
310
0
    case QImage::Format_Grayscale8:
311
0
    case QImage::Format_Grayscale16:
312
0
    case QImage::Format_RGBX64:
313
0
    case QImage::Format_RGBX16FPx4:
314
0
    case QImage::Format_RGBX32FPx4:
315
0
    case QImage::Format_CMYK8888:
316
0
        break;
317
0
    case QImage::Format_Invalid:
318
0
    case QImage::NImageFormats:
319
0
        Q_UNREACHABLE();
320
0
        break;
321
0
    }
322
323
0
    return has_alpha_pixels;
324
0
}
325
#if defined(_M_ARM) && defined(_MSC_VER)
326
#pragma optimize("", on)
327
#endif
328
329
/*!
330
    \class QImage
331
332
    \inmodule QtGui
333
    \ingroup painting
334
    \ingroup shared
335
336
    \reentrant
337
338
    \brief The QImage class provides a hardware-independent image
339
    representation that allows direct access to the pixel data, and
340
    can be used as a paint device.
341
342
    Qt provides four classes for handling image data: QImage, QPixmap,
343
    QBitmap and QPicture.  QImage is designed and optimized for I/O,
344
    and for direct pixel access and manipulation, while QPixmap is
345
    designed and optimized for showing images on screen. QBitmap is
346
    only a convenience class that inherits QPixmap, ensuring a
347
    depth of 1. Finally, the QPicture class is a paint device that
348
    records and replays QPainter commands.
349
350
    Because QImage is a QPaintDevice subclass, QPainter can be used to
351
    draw directly onto images.  When using QPainter on a QImage, the
352
    painting can be performed in another thread than the current GUI
353
    thread.
354
355
    The QImage class supports several image formats described by the
356
    \l Format enum. These include monochrome, 8-bit, 32-bit and
357
    alpha-blended images which are available in all versions of Qt
358
    4.x.
359
360
    QImage provides a collection of functions that can be used to
361
    obtain a variety of information about the image. There are also
362
    several functions that enables transformation of the image.
363
364
    QImage objects can be passed around by value since the QImage
365
    class uses \l{Implicit Data Sharing}{implicit data
366
    sharing}. QImage objects can also be streamed and compared.
367
368
    \note If you would like to load QImage objects in a static build of Qt,
369
    refer to the \l{How to Create Qt Plugins}{Plugin HowTo}.
370
371
    \warning Painting on a QImage with the format
372
    QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not supported.
373
374
    \section1 Reading and Writing Image Files
375
376
    QImage provides several ways of loading an image file: The file
377
    can be loaded when constructing the QImage object, or by using the
378
    load() or loadFromData() functions later on. QImage also provides
379
    the static fromData() function, constructing a QImage from the
380
    given data.  When loading an image, the file name can either refer
381
    to an actual file on disk or to one of the application's embedded
382
    resources. See \l{The Qt Resource System} overview for details
383
    on how to embed images and other resource files in the
384
    application's executable.
385
386
    Simply call the save() function to save a QImage object.
387
388
    The complete list of supported file formats are available through
389
    the QImageReader::supportedImageFormats() and
390
    QImageWriter::supportedImageFormats() functions. New file formats
391
    can be added as plugins. By default, Qt supports the following
392
    formats:
393
394
    \table
395
    \header \li Format \li Description                      \li Qt's support
396
    \row    \li BMP    \li Windows Bitmap                   \li Read/write
397
    \row    \li GIF    \li Graphic Interchange Format (optional) \li Read
398
    \row    \li JPG    \li Joint Photographic Experts Group \li Read/write
399
    \row    \li JPEG   \li Joint Photographic Experts Group \li Read/write
400
    \row    \li PNG    \li Portable Network Graphics        \li Read/write
401
    \row    \li PBM    \li Portable Bitmap                  \li Read
402
    \row    \li PGM    \li Portable Graymap                 \li Read
403
    \row    \li PPM    \li Portable Pixmap                  \li Read/write
404
    \row    \li XBM    \li X11 Bitmap                       \li Read/write
405
    \row    \li XPM    \li X11 Pixmap                       \li Read/write
406
    \endtable
407
408
    \section1 Image Information
409
410
    QImage provides a collection of functions that can be used to
411
    obtain a variety of information about the image:
412
413
    \table
414
    \header
415
    \li \li Available Functions
416
417
    \row
418
    \li Geometry
419
    \li
420
421
    The size(), width(), height(), dotsPerMeterX(), and
422
    dotsPerMeterY() functions provide information about the image size
423
    and aspect ratio.
424
425
    The rect() function returns the image's enclosing rectangle. The
426
    valid() function tells if a given pair of coordinates is within
427
    this rectangle. The offset() function returns the number of pixels
428
    by which the image is intended to be offset by when positioned
429
    relative to other images, which also can be manipulated using the
430
    setOffset() function.
431
432
    \row
433
    \li Colors
434
    \li
435
436
    The color of a pixel can be retrieved by passing its coordinates
437
    to the pixel() function.  The pixel() function returns the color
438
    as a QRgb value independent of the image's format.
439
440
    In case of monochrome and 8-bit images, the colorCount() and
441
    colorTable() functions provide information about the color
442
    components used to store the image data: The colorTable() function
443
    returns the image's entire color table. To obtain a single entry,
444
    use the pixelIndex() function to retrieve the pixel index for a
445
    given pair of coordinates, then use the color() function to
446
    retrieve the color. Note that if you create an 8-bit image
447
    manually, you have to set a valid color table on the image as
448
    well.
449
450
    The hasAlphaChannel() function tells if the image's format
451
    respects the alpha channel, or not. The allGray() and
452
    isGrayscale() functions tell whether an image's colors are all
453
    shades of gray.
454
455
    See also the \l {QImage#Pixel Manipulation}{Pixel Manipulation}
456
    and \l {QImage#Image Transformations}{Image Transformations}
457
    sections.
458
459
    \row
460
    \li Text
461
    \li
462
463
    The text() function returns the image text associated with the
464
    given text key. An image's text keys can be retrieved using the
465
    textKeys() function. Use the setText() function to alter an
466
    image's text.
467
468
    \row
469
    \li Low-level information
470
    \li
471
472
    The depth() function returns the depth of the image. The supported
473
    depths are 1 (monochrome), 8, 16, 24 and 32 bits. The
474
    bitPlaneCount() function tells how many of those bits that are
475
    used. For more information see the
476
    \l {QImage#Image Formats}{Image Formats} section.
477
478
    The format(), bytesPerLine(), and sizeInBytes() functions provide
479
    low-level information about the data stored in the image.
480
481
    The cacheKey() function returns a number that uniquely
482
    identifies the contents of this QImage object.
483
    \endtable
484
485
    \section1 Pixel Manipulation
486
487
    The functions used to manipulate an image's pixels depend on the
488
    image format. The reason is that monochrome and 8-bit images are
489
    index-based and use a color lookup table, while 32-bit images
490
    store ARGB values directly. For more information on image formats,
491
    see the \l {Image Formats} section.
492
493
    In case of a 32-bit image, the setPixel() function can be used to
494
    alter the color of the pixel at the given coordinates to any other
495
    color specified as an ARGB quadruplet. To make a suitable QRgb
496
    value, use the qRgb() (adding a default alpha component to the
497
    given RGB values, i.e. creating an opaque color) or qRgba()
498
    function. For example:
499
500
    \table
501
    \header
502
    \li {2,1}32-bit
503
    \row
504
    \li \inlineimage qimage-32bit_scaled.png
505
                     {3x3 pixel grid with ARGB color values}
506
    \li
507
    \snippet code/src_gui_image_qimage.cpp 0
508
    \endtable
509
510
    In case of a 8-bit and monchrome images, the pixel value is only
511
    an index from the image's color table. So the setPixel() function
512
    can only be used to alter the color of the pixel at the given
513
    coordinates to a predefined color from the image's color table,
514
    i.e. it can only change the pixel's index value. To alter or add a
515
    color to an image's color table, use the setColor() function.
516
517
    An entry in the color table is an ARGB quadruplet encoded as an
518
    QRgb value. Use the qRgb() and qRgba() functions to make a
519
    suitable QRgb value for use with the setColor() function. For
520
    example:
521
522
    \table
523
    \header
524
    \li {2,1} 8-bit
525
    \row
526
    \li \inlineimage qimage-8bit_scaled.png
527
                     {3x3 pixel grid with indexed colors and color table}
528
    \li
529
    \snippet code/src_gui_image_qimage.cpp 1
530
    \endtable
531
532
    For images with more than 8-bit per color-channel. The methods
533
    setPixelColor() and pixelColor() can be used to set and get
534
    with QColor values.
535
536
    QImage also provide the scanLine() function which returns a
537
    pointer to the pixel data at the scanline with the given index,
538
    and the bits() function which returns a pointer to the first pixel
539
    data (this is equivalent to \c scanLine(0)).
540
541
    \section1 Image Formats
542
543
    Each pixel stored in a QImage is represented by an integer. The
544
    size of the integer varies depending on the format. QImage
545
    supports several image formats described by the \l Format
546
    enum.
547
548
    Monochrome images are stored using 1-bit indexes into a color table
549
    with at most two colors. There are two different types of
550
    monochrome images: big endian (MSB first) or little endian (LSB
551
    first) bit order.
552
553
    8-bit images are stored using 8-bit indexes into a color table,
554
    i.e.  they have a single byte per pixel. The color table is a
555
    QList<QRgb>, and the QRgb typedef is equivalent to an unsigned
556
    int containing an ARGB quadruplet on the format 0xAARRGGBB.
557
558
    32-bit images have no color table; instead, each pixel contains an
559
    QRgb value. There are three different types of 32-bit images
560
    storing RGB (i.e. 0xffRRGGBB), ARGB and premultiplied ARGB
561
    values respectively. In the premultiplied format the red, green,
562
    and blue channels are multiplied by the alpha component divided by
563
    255.
564
565
    An image's format can be retrieved using the format()
566
    function. Use the convertToFormat() functions to convert an image
567
    into another format. The allGray() and isGrayscale() functions
568
    tell whether a color image can safely be converted to a grayscale
569
    image.
570
571
    \section1 Image Transformations
572
573
    QImage supports a number of functions for creating a new image
574
    that is a transformed version of the original: The
575
    createAlphaMask() function builds and returns a 1-bpp mask from
576
    the alpha buffer in this image, and the createHeuristicMask()
577
    function creates and returns a 1-bpp heuristic mask for this
578
    image. The latter function works by selecting a color from one of
579
    the corners, then chipping away pixels of that color starting at
580
    all the edges.
581
582
    The mirrored() function returns a mirror of the image in the
583
    desired direction, the scaled() returns a copy of the image scaled
584
    to a rectangle of the desired measures, and the rgbSwapped() function
585
    constructs a BGR image from a RGB image.
586
587
    The scaledToWidth() and scaledToHeight() functions return scaled
588
    copies of the image.
589
590
    The transformed() function returns a copy of the image that is
591
    transformed with the given transformation matrix and
592
    transformation mode: Internally, the transformation matrix is
593
    adjusted to compensate for unwanted translation,
594
    i.e. transformed() returns the smallest image containing all
595
    transformed points of the original image. The static trueMatrix()
596
    function returns the actual matrix used for transforming the
597
    image.
598
599
    There are also functions for changing attributes of an image
600
    in-place:
601
602
    \table
603
    \header \li Function \li Description
604
    \row
605
    \li setDotsPerMeterX()
606
    \li Defines the aspect ratio by setting the number of pixels that fit
607
    horizontally in a physical meter.
608
    \row
609
    \li setDotsPerMeterY()
610
    \li Defines the aspect ratio by setting the number of pixels that fit
611
    vertically in a physical meter.
612
    \row
613
    \li fill()
614
    \li Fills the entire image with the given pixel value.
615
    \row
616
    \li invertPixels()
617
    \li Inverts all pixel values in the image using the given InvertMode value.
618
    \row
619
    \li setColorTable()
620
    \li Sets the color table used to translate color indexes. Only
621
    monochrome and 8-bit formats.
622
    \row
623
    \li setColorCount()
624
    \li Resizes the color table. Only monochrome and 8-bit formats.
625
626
    \endtable
627
628
    \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer,
629
        {Image Composition Example}, {Scribble Example}
630
*/
631
632
/*!
633
    \fn QImage::QImage(QImage &&other)
634
635
    Move-constructs a QImage instance, making it point at the same
636
    object that \a other was pointing to.
637
638
    \since 5.2
639
*/
640
641
/*!
642
    \fn QImage &QImage::operator=(QImage &&other)
643
644
    Move-assigns \a other to this QImage instance.
645
646
    \since 5.2
647
*/
648
649
/*!
650
    \typedef QImageCleanupFunction
651
    \relates QImage
652
    \since 5.0
653
654
    A function with the following signature that can be used to
655
    implement basic image memory management:
656
657
    \code
658
    void myImageCleanupHandler(void *info);
659
    \endcode
660
*/
661
662
/*!
663
    \enum QImage::InvertMode
664
665
    This enum type is used to describe how pixel values should be
666
    inverted in the invertPixels() function.
667
668
    \value InvertRgb    Invert only the RGB values and leave the alpha
669
                        channel unchanged.
670
671
    \value InvertRgba   Invert all channels, including the alpha channel.
672
673
    \sa invertPixels()
674
*/
675
676
/*!
677
    \enum QImage::Format
678
679
    The following image formats are available in Qt.
680
    See the notes after the table.
681
682
    \value Format_Invalid   The image is invalid.
683
    \value Format_Mono      The image is stored using 1-bit per pixel. Bytes are
684
                            packed with the most significant bit (MSB) first.
685
    \value Format_MonoLSB   The image is stored using 1-bit per pixel. Bytes are
686
                            packed with the less significant bit (LSB) first.
687
688
    \value Format_Indexed8  The image is stored using 8-bit indexes
689
                            into a colormap.
690
691
    \value Format_RGB32     The image is stored using a 32-bit RGB format (0xffRRGGBB).
692
693
    \value Format_ARGB32    The image is stored using a 32-bit ARGB
694
                            format (0xAARRGGBB).
695
696
    \value Format_ARGB32_Premultiplied  The image is stored using a premultiplied 32-bit
697
                            ARGB format (0xAARRGGBB), i.e. the red,
698
                            green, and blue channels are multiplied
699
                            by the alpha component divided by 255. (If RR, GG, or BB
700
                            has a higher value than the alpha channel, the results are
701
                            undefined.) Certain operations (such as image composition
702
                            using alpha blending) are faster using premultiplied ARGB32
703
                            than with plain ARGB32.
704
705
    \value Format_RGB16     The image is stored using a 16-bit RGB format (5-6-5).
706
707
    \value Format_ARGB8565_Premultiplied  The image is stored using a
708
                            premultiplied 24-bit ARGB format (8-5-6-5).
709
    \value Format_RGB666    The image is stored using a 24-bit RGB format (6-6-6).
710
                            The unused most significant bits is always zero.
711
    \value Format_ARGB6666_Premultiplied  The image is stored using a
712
                            premultiplied 24-bit ARGB format (6-6-6-6).
713
    \value Format_RGB555    The image is stored using a 16-bit RGB format (5-5-5).
714
                            The unused most significant bit is always zero.
715
    \value Format_ARGB8555_Premultiplied  The image is stored using a
716
                            premultiplied 24-bit ARGB format (8-5-5-5).
717
    \value Format_RGB888    The image is stored using a 24-bit RGB format (8-8-8).
718
    \value Format_RGB444    The image is stored using a 16-bit RGB format (4-4-4).
719
                            The unused bits are always zero.
720
    \value Format_ARGB4444_Premultiplied  The image is stored using a
721
                            premultiplied 16-bit ARGB format (4-4-4-4).
722
    \value [since 5.2]
723
           Format_RGBX8888   The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
724
                             This is the same as the Format_RGBA8888 except alpha must always be 255.
725
    \value [since 5.2]
726
           Format_RGBA8888   The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
727
    \value [since 5.2]
728
           Format_RGBA8888_Premultiplied    The image is stored using a
729
                            premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
730
    \value [since 5.4]
731
           Format_BGR30      The image is stored using a 32-bit BGR format (x-10-10-10).
732
    \value [since 5.4]
733
           Format_A2BGR30_Premultiplied    The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
734
    \value [since 5.4]
735
           Format_RGB30      The image is stored using a 32-bit RGB format (x-10-10-10).
736
    \value [since 5.4]
737
           Format_A2RGB30_Premultiplied    The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
738
    \value [since 5.5]
739
           Format_Alpha8     The image is stored using an 8-bit alpha only format.
740
    \value [since 5.5]
741
           Format_Grayscale8 The image is stored using an 8-bit grayscale format.
742
    \value [since 5.13]
743
           Format_Grayscale16 The image is stored using an 16-bit grayscale format.
744
    \value [since 5.12]
745
           Format_RGBX64     The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
746
                             This is the same as the Format_RGBA64 except alpha must always be 65535.
747
    \value [since 5.12]
748
           Format_RGBA64     The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16).
749
    \value [since 5.12]
750
           Format_RGBA64_Premultiplied    The image is stored using a premultiplied 64-bit halfword-ordered
751
                             RGBA format (16-16-16-16).
752
    \value [since 5.14]
753
           Format_BGR888     The image is stored using a 24-bit BGR format.
754
    \value [since 6.2]
755
           Format_RGBX16FPx4 The image is stored using a four 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
756
                             This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0.
757
    \value [since 6.2]
758
           Format_RGBA16FPx4 The image is stored using a four 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP).
759
    \value [since 6.2]
760
           Format_RGBA16FPx4_Premultiplied    The image is stored using a premultiplied four 16-bit halfword floating point
761
                             RGBA format (16FP-16FP-16FP-16FP).
762
    \value [since 6.2]
763
           Format_RGBX32FPx4 The image is stored using a four 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
764
                             This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0.
765
    \value [since 6.2]
766
           Format_RGBA32FPx4 The image is stored using a four 32-bit floating point RGBA format (32FP-32FP-32FP-32FP).
767
    \value [since 6.2]
768
           Format_RGBA32FPx4_Premultiplied    The image is stored using a premultiplied four 32-bit floating point
769
                             RGBA format (32FP-32FP-32FP-32FP).
770
    \value [since 6.8]
771
           Format_CMYK8888   The image is stored using a 32-bit byte-ordered CMYK format.
772
773
    Byte-ordered formats have a QPixelFormat::typeInterpretation() of
774
    QPixelFormat::UnsignedByte, meaning the individual color components
775
    are stored in memory in a fixed order, e.g 0xRR, 0xGG, 0xBB, 0xAA,
776
    regardless of the endianness of the platform. These formats should be
777
    read as individual bytes, or interpreted as QPixelFormat::BigEndian
778
    if read in larger chunks.
779
780
    \note Drawing into a QImage with format QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not
781
    supported.
782
783
    \note Avoid most rendering directly to most of these formats using QPainter. Rendering
784
    is best optimized to the \c Format_RGB32 and \c Format_ARGB32_Premultiplied formats, and secondarily for rendering to the
785
    \c Format_RGB16, \c Format_RGBX8888, \c Format_RGBA8888_Premultiplied, \c Format_RGBX64 and \c Format_RGBA64_Premultiplied formats
786
787
    \sa format(), convertToFormat()
788
*/
789
790
/*****************************************************************************
791
  QImage member functions
792
 *****************************************************************************/
793
794
/*!
795
    Constructs a null image.
796
797
    \sa isNull()
798
*/
799
800
QImage::QImage() noexcept
801
46.5k
    : QPaintDevice()
802
46.5k
{
803
46.5k
    d = nullptr;
804
46.5k
}
805
806
/*!
807
    Constructs an image with the given \a width, \a height and \a
808
    format.
809
810
    A \l{isNull()}{null} image will be returned if memory cannot be allocated.
811
812
    \warning This will create a QImage with uninitialized data. Call
813
    fill() to fill the image with an appropriate pixel value before
814
    drawing onto it with QPainter.
815
*/
816
QImage::QImage(int width, int height, Format format)
817
0
    : QImage(QSize(width, height), format)
818
0
{
819
0
}
820
821
/*!
822
    Constructs an image with the given \a size and \a format.
823
824
    A \l{isNull()}{null} image is returned if memory cannot be allocated.
825
826
    \warning This will create a QImage with uninitialized data. Call
827
    fill() to fill the image with an appropriate pixel value before
828
    drawing onto it with QPainter.
829
*/
830
QImage::QImage(const QSize &size, Format format)
831
0
    : QPaintDevice()
832
0
{
833
0
    d = QImageData::create(size, format);
834
0
}
835
836
837
838
QImageData *QImageData::create(uchar *data, int width, int height,  qsizetype bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
839
0
{
840
0
    if (width <= 0 || height <= 0 || !data || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
841
0
        return nullptr;
842
843
0
    const int depth = qt_depthForFormat(format);
844
0
    auto params = calculateImageParameters(width, height, depth);
845
0
    if (!params.isValid())
846
0
        return nullptr;
847
848
0
    if (bpl > 0) {
849
        // can't overflow, because has calculateImageParameters already done this multiplication
850
0
        const qsizetype min_bytes_per_line = (qsizetype(width) * depth + 7)/8;
851
0
        if (bpl < min_bytes_per_line)
852
0
            return nullptr;
853
854
        // recalculate the total with this value
855
0
        params.bytesPerLine = bpl;
856
0
        if (qMulOverflow<qsizetype>(bpl, height, &params.totalSize))
857
0
            return nullptr;
858
0
    }
859
860
0
    QImageData *d = new QImageData;
861
0
    d->ref.ref();
862
863
0
    d->own_data = false;
864
0
    d->ro_data = readOnly;
865
0
    d->data = data;
866
0
    d->width = width;
867
0
    d->height = height;
868
0
    d->depth = depth;
869
0
    d->format = format;
870
871
0
    d->bytes_per_line = params.bytesPerLine;
872
0
    d->nbytes = params.totalSize;
873
874
0
    d->cleanupFunction = cleanupFunction;
875
0
    d->cleanupInfo = cleanupInfo;
876
877
0
    return d;
878
0
}
879
880
/*!
881
    Constructs an image with the given \a width, \a height and \a
882
    format, that uses an existing memory buffer, \a data. The \a width
883
    and \a height must be specified in pixels, \a data must be 32-bit aligned,
884
    and each scanline of data in the image must also be 32-bit aligned.
885
886
    The buffer must remain valid throughout the life of the QImage and
887
    all copies that have not been modified or otherwise detached from
888
    the original buffer. The image does not delete the buffer at destruction.
889
    You can provide a function pointer \a cleanupFunction along with an
890
    extra pointer \a cleanupInfo that will be called when the last copy
891
    is destroyed.
892
893
    If \a format is an indexed color format, the image color table is
894
    initially empty and must be sufficiently expanded with
895
    setColorCount() or setColorTable() before the image is used.
896
*/
897
QImage::QImage(uchar* data, int width, int height, Format format, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
898
0
    : QPaintDevice()
899
0
{
900
0
    d = QImageData::create(data, width, height, 0, format, false, cleanupFunction, cleanupInfo);
901
0
}
902
903
/*!
904
    Constructs an image with the given \a width, \a height and \a
905
    format, that uses an existing read-only memory buffer, \a
906
    data. The \a width and \a height must be specified in pixels, \a
907
    data must be 32-bit aligned, and each scanline of data in the
908
    image must also be 32-bit aligned.
909
910
    The buffer must remain valid throughout the life of the QImage and
911
    all copies that have not been modified or otherwise detached from
912
    the original buffer. The image does not delete the buffer at destruction.
913
    You can provide a function pointer \a cleanupFunction along with an
914
    extra pointer \a cleanupInfo that will be called when the last copy
915
    is destroyed.
916
917
    If \a format is an indexed color format, the image color table is
918
    initially empty and must be sufficiently expanded with
919
    setColorCount() or setColorTable() before the image is used.
920
921
    Unlike the similar QImage constructor that takes a non-const data buffer,
922
    this version will never alter the contents of the buffer.  For example,
923
    calling QImage::bits() will return a deep copy of the image, rather than
924
    the buffer passed to the constructor.  This allows for the efficiency of
925
    constructing a QImage from raw data, without the possibility of the raw
926
    data being changed.
927
*/
928
QImage::QImage(const uchar* data, int width, int height, Format format, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
929
0
    : QPaintDevice()
930
0
{
931
0
    d = QImageData::create(const_cast<uchar*>(data), width, height, 0, format, true, cleanupFunction, cleanupInfo);
932
0
}
933
934
/*!
935
    Constructs an image with the given \a width, \a height and \a
936
    format, that uses an existing memory buffer, \a data. The \a width
937
    and \a height must be specified in pixels. \a bytesPerLine
938
    specifies the number of bytes per line (stride).
939
940
    The buffer must remain valid throughout the life of the QImage and
941
    all copies that have not been modified or otherwise detached from
942
    the original buffer. The image does not delete the buffer at destruction.
943
    You can provide a function pointer \a cleanupFunction along with an
944
    extra pointer \a cleanupInfo that will be called when the last copy
945
    is destroyed.
946
947
    If \a format is an indexed color format, the image color table is
948
    initially empty and must be sufficiently expanded with
949
    setColorCount() or setColorTable() before the image is used.
950
*/
951
952
QImage::QImage(uchar *data, int width, int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
953
0
    :QPaintDevice()
954
0
{
955
0
    d = QImageData::create(data, width, height, bytesPerLine, format, false, cleanupFunction, cleanupInfo);
956
0
}
957
958
/*!
959
    Constructs an image with the given \a width, \a height and \a
960
    format, that uses an existing memory buffer, \a data. The \a width
961
    and \a height must be specified in pixels. \a bytesPerLine
962
    specifies the number of bytes per line (stride).
963
964
    The buffer must remain valid throughout the life of the QImage and
965
    all copies that have not been modified or otherwise detached from
966
    the original buffer. The image does not delete the buffer at destruction.
967
    You can provide a function pointer \a cleanupFunction along with an
968
    extra pointer \a cleanupInfo that will be called when the last copy
969
    is destroyed.
970
971
    If \a format is an indexed color format, the image color table is
972
    initially empty and must be sufficiently expanded with
973
    setColorCount() or setColorTable() before the image is used.
974
975
    Unlike the similar QImage constructor that takes a non-const data buffer,
976
    this version will never alter the contents of the buffer.  For example,
977
    calling QImage::bits() will return a deep copy of the image, rather than
978
    the buffer passed to the constructor.  This allows for the efficiency of
979
    constructing a QImage from raw data, without the possibility of the raw
980
    data being changed.
981
*/
982
983
QImage::QImage(const uchar *data, int width, int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
984
0
    :QPaintDevice()
985
0
{
986
0
    d = QImageData::create(const_cast<uchar*>(data), width, height, bytesPerLine, format, true, cleanupFunction, cleanupInfo);
987
0
}
988
989
/*!
990
    Constructs an image and tries to load the image from the file with
991
    the given \a fileName.
992
993
    The loader attempts to read the image using the specified \a
994
    format. If the \a format is not specified (which is the default),
995
    it is auto-detected based on the file's suffix and header. For
996
    details, see {QImageReader::setAutoDetectImageFormat()}{QImageReader}.
997
998
    If the loading of the image failed, this object is a null image.
999
1000
    The file name can either refer to an actual file on disk or to one
1001
    of the application's embedded resources. See the
1002
    \l{resources.html}{Resource System} overview for details on how to
1003
    embed images and other resource files in the application's
1004
    executable.
1005
1006
    \sa isNull(), {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
1007
*/
1008
1009
QImage::QImage(const QString &fileName, const char *format)
1010
0
    : QPaintDevice()
1011
0
{
1012
0
    d = nullptr;
1013
0
    load(fileName, format);
1014
0
}
1015
1016
#ifndef QT_NO_IMAGEFORMAT_XPM
1017
extern bool qt_read_xpm_image_or_array(QIODevice *device, const char * const *source, QImage &image);
1018
1019
/*!
1020
    Constructs an image from the given \a xpm image.
1021
1022
    Make sure that the image is a valid XPM image. Errors are silently
1023
    ignored.
1024
1025
    Note that it's possible to squeeze the XPM variable a little bit
1026
    by using an unusual declaration:
1027
1028
    \snippet code/src_gui_image_qimage.cpp 2
1029
1030
    The extra \c const makes the entire definition read-only, which is
1031
    slightly more efficient (e.g., when the code is in a shared
1032
    library) and able to be stored in ROM with the application.
1033
*/
1034
1035
QImage::QImage(const char * const xpm[])
1036
0
    : QPaintDevice()
1037
0
{
1038
0
    d = nullptr;
1039
0
    if (!xpm)
1040
0
        return;
1041
0
    if (!qt_read_xpm_image_or_array(nullptr, xpm, *this))
1042
        // Issue: Warning because the constructor may be ambiguous
1043
0
        qWarning("QImage::QImage(), XPM is not supported");
1044
0
}
1045
#endif // QT_NO_IMAGEFORMAT_XPM
1046
1047
/*!
1048
    Constructs a shallow copy of the given \a image.
1049
1050
    For more information about shallow copies, see the \l {Implicit
1051
    Data Sharing} documentation.
1052
1053
    \sa copy()
1054
*/
1055
1056
QImage::QImage(const QImage &image)
1057
107k
    : QPaintDevice()
1058
107k
{
1059
107k
    if (image.paintingActive()) {
1060
0
        d = nullptr;
1061
0
        image.copy().swap(*this);
1062
107k
    } else {
1063
107k
        d = image.d;
1064
107k
        if (d)
1065
0
            d->ref.ref();
1066
107k
    }
1067
107k
}
1068
1069
/*!
1070
    Destroys the image and cleans up.
1071
*/
1072
1073
QImage::~QImage()
1074
200k
{
1075
200k
    if (d && !d->ref.deref())
1076
0
        delete d;
1077
200k
}
1078
1079
/*!
1080
    Assigns a shallow copy of the given \a image to this image and
1081
    returns a reference to this image.
1082
1083
    For more information about shallow copies, see the \l {Implicit
1084
    Data Sharing} documentation.
1085
1086
    \sa copy(), QImage()
1087
*/
1088
1089
QImage &QImage::operator=(const QImage &image)
1090
0
{
1091
0
    if (image.paintingActive()) {
1092
0
        operator=(image.copy());
1093
0
    } else {
1094
0
        if (image.d)
1095
0
            image.d->ref.ref();
1096
0
        if (d && !d->ref.deref())
1097
0
            delete d;
1098
0
        d = image.d;
1099
0
    }
1100
0
    return *this;
1101
0
}
1102
1103
/*!
1104
    \fn void QImage::swap(QImage &other)
1105
    \memberswap{image}
1106
*/
1107
1108
/*!
1109
  \internal
1110
*/
1111
int QImage::devType() const
1112
0
{
1113
0
    return QInternal::Image;
1114
0
}
1115
1116
/*!
1117
   Returns the image as a QVariant.
1118
*/
1119
QImage::operator QVariant() const
1120
0
{
1121
0
    return QVariant::fromValue(*this);
1122
0
}
1123
1124
/*!
1125
    \internal
1126
1127
    If multiple images share common data, this image makes a copy of
1128
    the data and detaches itself from the sharing mechanism, making
1129
    sure that this image is the only one referring to the data.
1130
1131
    Nothing is done if there is just a single reference.
1132
1133
    \sa copy(), {QImage::isDetached()}{isDetached()}, {Implicit Data Sharing}
1134
*/
1135
void QImage::detach()
1136
0
{
1137
0
    if (d) {
1138
0
        if (d->is_cached && d->ref.loadRelaxed() == 1)
1139
0
            QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1140
1141
0
        if (d->ref.loadRelaxed() != 1 || d->ro_data)
1142
0
            *this = copy();
1143
1144
0
        if (d)
1145
0
            ++d->detach_no;
1146
0
    }
1147
0
}
1148
1149
1150
/*!
1151
    \internal
1152
1153
    A variant for metadata-only detach, which will not detach readonly image data,
1154
    and only invalidate caches of the image data if asked to.
1155
1156
    \sa detach(), isDetached()
1157
*/
1158
void QImage::detachMetadata(bool invalidateCache)
1159
0
{
1160
0
    if (d) {
1161
0
        if (d->is_cached && d->ref.loadRelaxed() == 1)
1162
0
            QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1163
1164
0
        if (d->ref.loadRelaxed() != 1)
1165
0
            *this = copy();
1166
1167
0
        if (d && invalidateCache)
1168
0
            ++d->detach_no;
1169
0
    }
1170
0
}
1171
1172
static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
1173
0
{
1174
0
    dst->dpmx = src->dpmx;
1175
0
    dst->dpmy = src->dpmy;
1176
0
    dst->devicePixelRatio = src->devicePixelRatio;
1177
0
}
1178
1179
static void copyMetadata(QImageData *dst, const QImageData *src)
1180
0
{
1181
    // Doesn't copy colortable and alpha_clut.
1182
0
    copyPhysicalMetadata(dst, src);
1183
0
    dst->text = src->text;
1184
0
    dst->offset = src->offset;
1185
0
    dst->colorSpace = src->colorSpace;
1186
0
}
1187
1188
static void copyMetadata(QImage *dst, const QImage &src)
1189
0
{
1190
0
    dst->setDotsPerMeterX(src.dotsPerMeterX());
1191
0
    dst->setDotsPerMeterY(src.dotsPerMeterY());
1192
0
    dst->setDevicePixelRatio(src.devicePixelRatio());
1193
0
    const auto textKeys = src.textKeys();
1194
0
    for (const auto &key: textKeys)
1195
0
        dst->setText(key, src.text(key));
1196
1197
0
}
1198
1199
/*!
1200
    \fn QImage QImage::copy(int x, int y, int width, int height) const
1201
    \overload
1202
1203
    The returned image is copied from the position (\a x, \a y) in
1204
    this image, and has the given \a width and \a height. In areas
1205
    beyond this image, pixels are set to 0.
1206
1207
    Returns a null image if this image is null, if the rectangle
1208
    described by \a x, \a y, \a width, and \a height is empty but
1209
    not null, or if the image can't be allocated.
1210
*/
1211
1212
/*!
1213
    \fn QImage QImage::copy(const QRect& rectangle) const
1214
1215
    Returns a sub-area of the image as a new image.
1216
1217
    The returned image is copied from the position (\a
1218
    {rectangle}.x(), \a{rectangle}.y()) in this image, and has the
1219
    size of the given \a rectangle.
1220
1221
    In areas beyond this image, pixels are set to 0. For 32-bit RGB
1222
    images, this means black; for 32-bit ARGB images, this means
1223
    transparent black; for 8-bit images, this means the color with
1224
    index 0 in the color table which can be anything; for 1-bit
1225
    images, this means Qt::color0.
1226
1227
    If the given \a rectangle is a null rectangle the entire image is
1228
    copied.
1229
1230
    Returns a null image if this image is null, if \a rectangle is
1231
    empty but not null, or if the image can't be allocated.
1232
1233
    \sa QImage(), QRect::isNull(), QRect::isEmpty()
1234
*/
1235
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(const QRect& r) const
1236
0
{
1237
0
    Q_TRACE_SCOPE(QImage_copy, r);
1238
0
    if (!d)
1239
0
        return QImage();
1240
1241
0
    if (r.isNull()) {
1242
0
        QImage image(d->width, d->height, d->format);
1243
0
        if (image.isNull())
1244
0
            return image;
1245
1246
        // Qt for Embedded Linux can create images with non-default bpl
1247
        // make sure we don't crash.
1248
0
        if (image.d->nbytes != d->nbytes) {
1249
0
            qsizetype bpl = qMin(bytesPerLine(), image.bytesPerLine());
1250
0
            for (int i = 0; i < height(); i++)
1251
0
                memcpy(image.scanLine(i), scanLine(i), bpl);
1252
0
        } else
1253
0
            memcpy(image.bits(), bits(), d->nbytes);
1254
0
        image.d->colortable = d->colortable;
1255
0
        image.d->has_alpha_clut = d->has_alpha_clut;
1256
0
        copyMetadata(image.d, d);
1257
0
        return image;
1258
0
    }
1259
1260
0
    int x = r.x();
1261
0
    int y = r.y();
1262
0
    int w = r.width();
1263
0
    int h = r.height();
1264
1265
0
    int dx = 0;
1266
0
    int dy = 0;
1267
0
    if (w <= 0 || h <= 0)
1268
0
        return QImage();
1269
1270
0
    QImage image(w, h, d->format);
1271
0
    if (image.isNull())
1272
0
        return image;
1273
1274
0
    if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {
1275
        // bitBlt will not cover entire image - clear it.
1276
0
        image.fill(0);
1277
0
        if (x < 0) {
1278
0
            dx = -x;
1279
0
            x = 0;
1280
0
        }
1281
0
        if (y < 0) {
1282
0
            dy = -y;
1283
0
            y = 0;
1284
0
        }
1285
0
    }
1286
1287
0
    image.d->colortable = d->colortable;
1288
1289
0
    int pixels_to_copy = qMax(w - dx, 0);
1290
0
    if (x > d->width)
1291
0
        pixels_to_copy = 0;
1292
0
    else if (pixels_to_copy > d->width - x)
1293
0
        pixels_to_copy = d->width - x;
1294
0
    int lines_to_copy = qMax(h - dy, 0);
1295
0
    if (y > d->height)
1296
0
        lines_to_copy = 0;
1297
0
    else if (lines_to_copy > d->height - y)
1298
0
        lines_to_copy = d->height - y;
1299
1300
0
    bool byteAligned = true;
1301
0
    if (d->format == Format_Mono || d->format == Format_MonoLSB)
1302
0
        byteAligned = !(dx & 7) && !(x & 7) && !(pixels_to_copy & 7);
1303
1304
0
    if (byteAligned) {
1305
0
        const uchar *src = d->data + ((x * d->depth) >> 3) + y * d->bytes_per_line;
1306
0
        uchar *dest = image.d->data + ((dx * d->depth) >> 3) + dy * image.d->bytes_per_line;
1307
0
        const qsizetype bytes_to_copy = (qsizetype(pixels_to_copy) * d->depth) >> 3;
1308
0
        for (int i = 0; i < lines_to_copy; ++i) {
1309
0
            memcpy(dest, src, bytes_to_copy);
1310
0
            src += d->bytes_per_line;
1311
0
            dest += image.d->bytes_per_line;
1312
0
        }
1313
0
    } else if (d->format == Format_Mono) {
1314
0
        const uchar *src = d->data + y * d->bytes_per_line;
1315
0
        uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1316
0
        for (int i = 0; i < lines_to_copy; ++i) {
1317
0
            for (int j = 0; j < pixels_to_copy; ++j) {
1318
0
                if (src[(x + j) >> 3] & (0x80 >> ((x + j) & 7)))
1319
0
                    dest[(dx + j) >> 3] |= (0x80 >> ((dx + j) & 7));
1320
0
                else
1321
0
                    dest[(dx + j) >> 3] &= ~(0x80 >> ((dx + j) & 7));
1322
0
            }
1323
0
            src += d->bytes_per_line;
1324
0
            dest += image.d->bytes_per_line;
1325
0
        }
1326
0
    } else { // Format_MonoLSB
1327
0
        Q_ASSERT(d->format == Format_MonoLSB);
1328
0
        const uchar *src = d->data + y * d->bytes_per_line;
1329
0
        uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1330
0
        for (int i = 0; i < lines_to_copy; ++i) {
1331
0
            for (int j = 0; j < pixels_to_copy; ++j) {
1332
0
                if (src[(x + j) >> 3] & (0x1 << ((x + j) & 7)))
1333
0
                    dest[(dx + j) >> 3] |= (0x1 << ((dx + j) & 7));
1334
0
                else
1335
0
                    dest[(dx + j) >> 3] &= ~(0x1 << ((dx + j) & 7));
1336
0
            }
1337
0
            src += d->bytes_per_line;
1338
0
            dest += image.d->bytes_per_line;
1339
0
        }
1340
0
    }
1341
1342
0
    copyMetadata(image.d, d);
1343
0
    image.d->has_alpha_clut = d->has_alpha_clut;
1344
0
    return image;
1345
0
}
1346
1347
1348
/*!
1349
    \fn bool QImage::isNull() const
1350
1351
    Returns \c true if it is a null image, otherwise returns \c false.
1352
1353
    A null image has all parameters set to zero and no allocated data.
1354
*/
1355
bool QImage::isNull() const
1356
80.3k
{
1357
80.3k
    return !d;
1358
80.3k
}
1359
1360
/*!
1361
    \fn int QImage::width() const
1362
1363
    Returns the width of the image.
1364
1365
    \sa {QImage#Image Information}{Image Information}
1366
*/
1367
int QImage::width() const
1368
0
{
1369
0
    return d ? d->width : 0;
1370
0
}
1371
1372
/*!
1373
    \fn int QImage::height() const
1374
1375
    Returns the height of the image.
1376
1377
    \sa {QImage#Image Information}{Image Information}
1378
*/
1379
int QImage::height() const
1380
0
{
1381
0
    return d ? d->height : 0;
1382
0
}
1383
1384
/*!
1385
    \fn QSize QImage::size() const
1386
1387
    Returns the size of the image, i.e. its width() and height().
1388
1389
    \sa {QImage#Image Information}{Image Information}, deviceIndependentSize()
1390
*/
1391
QSize QImage::size() const
1392
0
{
1393
0
    return d ? QSize(d->width, d->height) : QSize(0, 0);
1394
0
}
1395
1396
/*!
1397
    \fn QRect QImage::rect() const
1398
1399
    Returns the enclosing rectangle (0, 0, width(), height()) of the
1400
    image.
1401
1402
    \sa {QImage#Image Information}{Image Information}
1403
*/
1404
QRect QImage::rect() const
1405
0
{
1406
0
    return d ? QRect(0, 0, d->width, d->height) : QRect();
1407
0
}
1408
1409
/*!
1410
    Returns the depth of the image.
1411
1412
    The image depth is the number of bits used to store a single
1413
    pixel, also called bits per pixel (bpp).
1414
1415
    The supported depths are 1, 8, 16, 24, 32 and 64.
1416
1417
    \sa bitPlaneCount(), convertToFormat(), {QImage#Image Formats}{Image Formats},
1418
    {QImage#Image Information}{Image Information}
1419
1420
*/
1421
int QImage::depth() const
1422
0
{
1423
0
    return d ? d->depth : 0;
1424
0
}
1425
1426
/*!
1427
    \fn int QImage::colorCount() const
1428
1429
    Returns the size of the color table for the image.
1430
1431
    Notice that colorCount() returns 0 for 32-bpp images because these
1432
    images do not use color tables, but instead encode pixel values as
1433
    ARGB quadruplets.
1434
1435
    \sa setColorCount(), {QImage#Image Information}{Image Information}
1436
*/
1437
int QImage::colorCount() const
1438
0
{
1439
0
    return d ? d->colortable.size() : 0;
1440
0
}
1441
1442
/*!
1443
    Sets the color table used to translate color indexes to QRgb
1444
    values, to the specified \a colors.
1445
1446
    When the image is used, the color table must be large enough to
1447
    have entries for all the pixel/index values present in the image,
1448
    otherwise the results are undefined.
1449
1450
    \sa colorTable(), setColor(), {QImage#Image Transformations}{Image
1451
    Transformations}
1452
*/
1453
void QImage::setColorTable(const QList<QRgb> &colors)
1454
0
{
1455
0
    if (!d)
1456
0
        return;
1457
0
    detachMetadata(true);
1458
1459
    // In case detach() ran out of memory
1460
0
    if (!d)
1461
0
        return;
1462
1463
0
    d->colortable = colors;
1464
0
    d->has_alpha_clut = false;
1465
0
    for (int i = 0; i < d->colortable.size(); ++i) {
1466
0
        if (qAlpha(d->colortable.at(i)) != 255) {
1467
0
            d->has_alpha_clut = true;
1468
0
            break;
1469
0
        }
1470
0
    }
1471
0
}
1472
1473
/*!
1474
    Returns a list of the colors contained in the image's color table,
1475
    or an empty list if the image does not have a color table
1476
1477
    \sa setColorTable(), colorCount(), color()
1478
*/
1479
QList<QRgb> QImage::colorTable() const
1480
0
{
1481
0
    return d ? d->colortable : QList<QRgb>();
1482
0
}
1483
1484
/*!
1485
    Returns the device pixel ratio for the image. This is the
1486
    ratio between \e{device pixels} and \e{device independent pixels}.
1487
1488
    Use this function when calculating layout geometry based on
1489
    the image size: QSize layoutSize = image.size() / image.devicePixelRatio()
1490
1491
    The default value is 1.0.
1492
1493
    \sa setDevicePixelRatio(), QImageReader
1494
*/
1495
qreal QImage::devicePixelRatio() const
1496
0
{
1497
0
    if (!d)
1498
0
        return 1.0;
1499
0
    return d->devicePixelRatio;
1500
0
}
1501
1502
/*!
1503
    Sets the device pixel ratio for the image. This is the
1504
    ratio between image pixels and device-independent pixels.
1505
1506
    The default \a scaleFactor is 1.0. Setting it to something else has
1507
    two effects:
1508
1509
    QPainters that are opened on the image will be scaled. For
1510
    example, painting on a 200x200 image if with a ratio of 2.0
1511
    will result in effective (device-independent) painting bounds
1512
    of 100x100.
1513
1514
    Code paths in Qt that calculate layout geometry based on the
1515
    image size will take the ratio into account:
1516
    QSize layoutSize = image.size() / image.devicePixelRatio()
1517
    The net effect of this is that the image is displayed as
1518
    high-DPI image rather than a large image
1519
    (see \l{Drawing High Resolution Versions of Pixmaps and Images}).
1520
1521
    \sa devicePixelRatio(), deviceIndependentSize()
1522
*/
1523
void QImage::setDevicePixelRatio(qreal scaleFactor)
1524
0
{
1525
0
    if (!d)
1526
0
        return;
1527
1528
0
    if (scaleFactor == d->devicePixelRatio)
1529
0
        return;
1530
1531
0
    detachMetadata();
1532
0
    if (d)
1533
0
        d->devicePixelRatio = scaleFactor;
1534
0
}
1535
1536
/*!
1537
    Returns the size of the image in device independent pixels.
1538
1539
    This value should be used when using the image size in user interface
1540
    size calculations.
1541
1542
    The return value is equivalent to image.size() / image.devicePixelRatio().
1543
1544
    \since 6.2
1545
*/
1546
QSizeF QImage::deviceIndependentSize() const
1547
0
{
1548
0
    if (!d)
1549
0
        return QSizeF(0, 0);
1550
0
    return QSizeF(d->width, d->height) / d->devicePixelRatio;
1551
0
}
1552
1553
1554
/*!
1555
    \since 5.10
1556
    Returns the image data size in bytes.
1557
1558
    \sa bytesPerLine(), bits(), {QImage#Image Information}{Image
1559
    Information}
1560
*/
1561
qsizetype QImage::sizeInBytes() const
1562
0
{
1563
0
    return d ? d->nbytes : 0;
1564
0
}
1565
1566
/*!
1567
    Returns the number of bytes per image scanline.
1568
1569
    This is equivalent to sizeInBytes() / height() if height() is non-zero.
1570
1571
    \sa scanLine()
1572
*/
1573
qsizetype QImage::bytesPerLine() const
1574
0
{
1575
0
    return d ? d->bytes_per_line : 0;
1576
0
}
1577
1578
1579
/*!
1580
    Returns the color in the color table at index \a i. The first
1581
    color is at index 0.
1582
1583
    The colors in an image's color table are specified as ARGB
1584
    quadruplets (QRgb). Use the qAlpha(), qRed(), qGreen(), and
1585
    qBlue() functions to get the color value components.
1586
1587
    \sa setColor(), pixelIndex(), {QImage#Pixel Manipulation}{Pixel
1588
    Manipulation}
1589
*/
1590
QRgb QImage::color(int i) const
1591
0
{
1592
0
    Q_ASSERT(i < colorCount());
1593
0
    return d ? d->colortable.at(i) : QRgb(uint(-1));
1594
0
}
1595
1596
/*!
1597
    \fn void QImage::setColor(int index, QRgb colorValue)
1598
1599
    Sets the color at the given \a index in the color table, to the
1600
    given to \a colorValue. The color value is an ARGB quadruplet.
1601
1602
    If \a index is outside the current size of the color table, it is
1603
    expanded with setColorCount().
1604
1605
    \sa color(), colorCount(), setColorTable(), {QImage#Pixel Manipulation}{Pixel
1606
    Manipulation}
1607
*/
1608
void QImage::setColor(int i, QRgb c)
1609
0
{
1610
0
    if (!d)
1611
0
        return;
1612
0
    if (i < 0 || d->depth > 8 || i >= 1<<d->depth) {
1613
0
        qWarning("QImage::setColor: Index out of bound %d", i);
1614
0
        return;
1615
0
    }
1616
0
    detachMetadata(true);
1617
1618
    // In case detach() run out of memory
1619
0
    if (!d)
1620
0
        return;
1621
1622
0
    if (i >= d->colortable.size())
1623
0
        setColorCount(i+1);
1624
0
    d->colortable[i] = c;
1625
0
    d->has_alpha_clut |= (qAlpha(c) != 255);
1626
0
}
1627
1628
/*!
1629
    Returns a pointer to the pixel data at the scanline with index \a
1630
    i. The first scanline is at index 0.
1631
1632
    The scanline data is as minimum 32-bit aligned. For 64-bit formats
1633
    it follows the native alignment of 64-bit integers (64-bit for most
1634
    platforms, but notably 32-bit on i386).
1635
1636
    For example, to remove the green component of each pixel in an image:
1637
1638
    \snippet code/src_gui_image_qimage.cpp scanLine
1639
1640
    \warning If you are accessing 32-bpp image data, cast the returned
1641
    pointer to \c{QRgb*} (QRgb has a 32-bit size) and use it to
1642
    read/write the pixel value. You cannot use the \c{uchar*} pointer
1643
    directly, because the pixel format depends on the byte order on
1644
    the underlying platform. Use qRed(), qGreen(), qBlue(), and
1645
    qAlpha() to access the pixels.
1646
1647
    \sa bytesPerLine(), bits(), {QImage#Pixel Manipulation}{Pixel
1648
    Manipulation}, constScanLine()
1649
*/
1650
uchar *QImage::scanLine(int i)
1651
0
{
1652
0
    if (!d)
1653
0
        return nullptr;
1654
1655
0
    detach();
1656
1657
    // In case detach() ran out of memory
1658
0
    if (!d)
1659
0
        return nullptr;
1660
1661
0
    return d->data + i * d->bytes_per_line;
1662
0
}
1663
1664
/*!
1665
    \overload
1666
*/
1667
const uchar *QImage::scanLine(int i) const
1668
0
{
1669
0
    if (!d)
1670
0
        return nullptr;
1671
1672
0
    Q_ASSERT(i >= 0 && i < height());
1673
0
    return d->data + i * d->bytes_per_line;
1674
0
}
1675
1676
1677
/*!
1678
    Returns a pointer to the pixel data at the scanline with index \a
1679
    i. The first scanline is at index 0.
1680
1681
    The scanline data is as minimum 32-bit aligned. For 64-bit formats
1682
    it follows the native alignment of 64-bit integers (64-bit for most
1683
    platforms, but notably 32-bit on i386).
1684
1685
    Note that QImage uses \l{Implicit Data Sharing} {implicit data
1686
    sharing}, but this function does \e not perform a deep copy of the
1687
    shared pixel data, because the returned data is const.
1688
1689
    \sa scanLine(), constBits()
1690
*/
1691
const uchar *QImage::constScanLine(int i) const
1692
0
{
1693
0
    if (!d)
1694
0
        return nullptr;
1695
1696
0
    Q_ASSERT(i >= 0 && i < height());
1697
0
    return d->data + i * d->bytes_per_line;
1698
0
}
1699
1700
/*!
1701
    Returns a pointer to the first pixel data. This is equivalent to
1702
    scanLine(0).
1703
1704
    Note that QImage uses \l{Implicit Data Sharing} {implicit data
1705
    sharing}. This function performs a deep copy of the shared pixel
1706
    data, thus ensuring that this QImage is the only one using the
1707
    current return value.
1708
1709
    \sa scanLine(), sizeInBytes(), constBits()
1710
*/
1711
uchar *QImage::bits()
1712
0
{
1713
0
    if (!d)
1714
0
        return nullptr;
1715
0
    detach();
1716
1717
    // In case detach ran out of memory...
1718
0
    if (!d)
1719
0
        return nullptr;
1720
1721
0
    return d->data;
1722
0
}
1723
1724
/*!
1725
    \overload
1726
1727
    Note that QImage uses \l{Implicit Data Sharing} {implicit data
1728
    sharing}, but this function does \e not perform a deep copy of the
1729
    shared pixel data, because the returned data is const.
1730
*/
1731
const uchar *QImage::bits() const
1732
0
{
1733
0
    return d ? d->data : nullptr;
1734
0
}
1735
1736
1737
/*!
1738
    Returns a pointer to the first pixel data.
1739
1740
    Note that QImage uses \l{Implicit Data Sharing} {implicit data
1741
    sharing}, but this function does \e not perform a deep copy of the
1742
    shared pixel data, because the returned data is const.
1743
1744
    \sa bits(), constScanLine()
1745
*/
1746
const uchar *QImage::constBits() const
1747
0
{
1748
0
    return d ? d->data : nullptr;
1749
0
}
1750
1751
/*!
1752
    \fn void QImage::fill(uint pixelValue)
1753
1754
    Fills the entire image with the given \a pixelValue.
1755
1756
    If the depth of this image is 1, only the lowest bit is used. If
1757
    you say fill(0), fill(2), etc., the image is filled with 0s. If
1758
    you say fill(1), fill(3), etc., the image is filled with 1s. If
1759
    the depth is 8, the lowest 8 bits are used and if the depth is 16
1760
    the lowest 16 bits are used.
1761
1762
    If the image depth is higher than 32bit the result is undefined.
1763
1764
    \note There are no corresponding value getter, though QImage::pixelIndex()
1765
    will return the same value for indexed formats, and QImage::pixel() for
1766
    RGB32, ARGB32, and ARGB32PM formats.
1767
1768
    \sa depth(), {QImage#Image Transformations}{Image Transformations}
1769
*/
1770
1771
void QImage::fill(uint pixel)
1772
0
{
1773
0
    if (!d)
1774
0
        return;
1775
1776
0
    detach();
1777
1778
    // In case detach() ran out of memory
1779
0
    if (!d)
1780
0
        return;
1781
1782
0
    if (d->depth == 1 || d->depth == 8) {
1783
0
        int w = d->width;
1784
0
        if (d->depth == 1) {
1785
0
            if (pixel & 1)
1786
0
                pixel = 0xffffffff;
1787
0
            else
1788
0
                pixel = 0;
1789
0
            w = (w + 7) / 8;
1790
0
        } else {
1791
0
            pixel &= 0xff;
1792
0
        }
1793
0
        qt_rectfill<quint8>(d->data, pixel, 0, 0,
1794
0
                            w, d->height, d->bytes_per_line);
1795
0
        return;
1796
0
    } else if (d->depth == 16) {
1797
0
        if (d->format == Format_RGB444)
1798
0
            pixel |= 0xf000;
1799
0
        qt_rectfill<quint16>(reinterpret_cast<quint16*>(d->data), pixel,
1800
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1801
0
        return;
1802
0
    } else if (d->depth == 24) {
1803
0
        if (d->format == Format_RGB666)
1804
0
            pixel |= 0xfc0000;
1805
0
        qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
1806
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1807
0
        return;
1808
0
    } else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
1809
0
        qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
1810
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1811
0
        return;
1812
0
    } else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
1813
0
        quint64 cu;
1814
0
        QRgbaFloat16 cf = QRgbaFloat16::fromArgb32(pixel);
1815
0
        ::memcpy(&cu, &cf, sizeof(quint64));
1816
0
        qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), cu,
1817
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1818
0
        return;
1819
0
    } else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
1820
0
        QRgbaFloat32 cf = QRgbaFloat32::fromArgb32(pixel);
1821
0
        uchar *data = d->data;
1822
0
        for (int y = 0; y < d->height; ++y) {
1823
0
            QRgbaFloat32 *line = reinterpret_cast<QRgbaFloat32 *>(data);
1824
0
            for (int x = 0; x < d->width; ++x)
1825
0
                line[x] = cf;
1826
0
            data += d->bytes_per_line;
1827
0
        }
1828
0
        return;
1829
0
    }
1830
0
    Q_ASSERT(d->depth == 32);
1831
1832
0
    if (d->format == Format_RGB32)
1833
0
        pixel |= 0xff000000;
1834
0
    if (d->format == Format_RGBX8888)
1835
0
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1836
0
        pixel |= 0xff000000;
1837
#else
1838
        pixel |= 0x000000ff;
1839
#endif
1840
0
    if (d->format == Format_BGR30 || d->format == Format_RGB30)
1841
0
        pixel |= 0xc0000000;
1842
1843
0
    qt_rectfill<uint>(reinterpret_cast<uint*>(d->data), pixel,
1844
0
                      0, 0, d->width, d->height, d->bytes_per_line);
1845
0
}
1846
1847
1848
/*!
1849
    \fn void QImage::fill(Qt::GlobalColor color)
1850
    \overload
1851
1852
    Fills the image with the given \a color, described as a standard global
1853
    color.
1854
 */
1855
1856
void QImage::fill(Qt::GlobalColor color)
1857
0
{
1858
0
    fill(QColor(color));
1859
0
}
1860
1861
1862
1863
/*!
1864
    \fn void QImage::fill(const QColor &color)
1865
1866
    \overload
1867
1868
    Fills the entire image with the given \a color.
1869
1870
    If the depth of the image is 1, the image will be filled with 1 if
1871
    \a color equals Qt::color1; it will otherwise be filled with 0.
1872
1873
    If the depth of the image is 8, the image will be filled with the
1874
    index corresponding the \a color in the color table if present; it
1875
    will otherwise be filled with 0.
1876
*/
1877
1878
void QImage::fill(const QColor &color)
1879
0
{
1880
0
    if (!d)
1881
0
        return;
1882
0
    detach();
1883
1884
    // In case we run out of memory
1885
0
    if (!d)
1886
0
        return;
1887
1888
0
    QRgba64 opaque = color.rgba64();
1889
0
    opaque.setAlpha(65535);
1890
0
    switch (d->format) {
1891
0
    case QImage::Format_RGB32:
1892
0
    case QImage::Format_ARGB32:
1893
0
        fill(color.rgba());
1894
0
        break;
1895
0
    case QImage::Format_ARGB32_Premultiplied:
1896
0
        fill(qPremultiply(color.rgba()));
1897
0
        break;
1898
0
    case QImage::Format_RGBX8888:
1899
0
        fill(ARGB2RGBA(color.rgba() | 0xff000000));
1900
0
        break;
1901
0
    case QImage::Format_RGBA8888:
1902
0
        fill(ARGB2RGBA(color.rgba()));
1903
0
        break;
1904
0
    case QImage::Format_RGBA8888_Premultiplied:
1905
0
        fill(ARGB2RGBA(qPremultiply(color.rgba())));
1906
0
        break;
1907
0
    case QImage::Format_BGR30:
1908
0
        fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
1909
0
        break;
1910
0
    case QImage::Format_RGB30:
1911
0
        fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
1912
0
        break;
1913
0
    case QImage::Format_RGB16:
1914
0
        fill((uint) qConvertRgb32To16(color.rgba()));
1915
0
        break;
1916
0
    case QImage::Format_Indexed8: {
1917
0
        uint pixel = 0;
1918
0
        for (int i=0; i<d->colortable.size(); ++i) {
1919
0
            if (color.rgba() == d->colortable.at(i)) {
1920
0
                pixel = i;
1921
0
                break;
1922
0
            }
1923
0
        }
1924
0
        fill(pixel);
1925
0
        break;
1926
0
    }
1927
0
    case QImage::Format_Mono:
1928
0
    case QImage::Format_MonoLSB:
1929
0
        if (color == Qt::color1)
1930
0
            fill((uint) 1);
1931
0
        else
1932
0
            fill((uint) 0);
1933
0
        break;
1934
0
    case QImage::Format_RGBX64:
1935
0
        qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), opaque,
1936
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1937
0
        break;
1938
0
    case QImage::Format_RGBA64:
1939
0
        qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
1940
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1941
0
        break;
1942
0
    case QImage::Format_RGBA64_Premultiplied:
1943
0
        qt_rectfill<quint64>(reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
1944
0
                             0, 0, d->width, d->height, d->bytes_per_line);
1945
0
        break;
1946
0
    case QImage::Format_RGBX16FPx4:
1947
0
    case QImage::Format_RGBA16FPx4:
1948
0
    case QImage::Format_RGBA16FPx4_Premultiplied:
1949
0
    case QImage::Format_RGBX32FPx4:
1950
0
    case QImage::Format_RGBA32FPx4:
1951
0
    case QImage::Format_RGBA32FPx4_Premultiplied:{
1952
0
        float r, g, b, a;
1953
0
        color.getRgbF(&r, &g, &b, &a);
1954
0
        if (!hasAlphaChannel())
1955
0
            a = 1.0f;
1956
0
        if (depth() == 64) {
1957
0
            QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
1958
0
            if (d->format == Format_RGBA16FPx4_Premultiplied)
1959
0
                c16 = c16.premultiplied();
1960
0
            qt_rectfill<QRgbaFloat16>(reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
1961
0
                                 0, 0, d->width, d->height, d->bytes_per_line);
1962
0
        } else {
1963
0
            QRgbaFloat32 c32{r, g, b, a};
1964
0
            if (d->format == Format_RGBA32FPx4_Premultiplied)
1965
0
                c32 = c32.premultiplied();
1966
0
            qt_rectfill<QRgbaFloat32>(reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
1967
0
                                 0, 0, d->width, d->height, d->bytes_per_line);
1968
0
        }
1969
0
        break;
1970
0
    }
1971
0
    default: {
1972
0
        QPainter p(this);
1973
0
        p.setCompositionMode(QPainter::CompositionMode_Source);
1974
0
        p.fillRect(rect(), color);
1975
0
    }}
1976
0
}
1977
1978
1979
1980
/*!
1981
    Inverts all pixel values in the image.
1982
1983
    The given invert \a mode only have a meaning when the image's
1984
    depth is 32. The default \a mode is InvertRgb, which leaves the
1985
    alpha channel unchanged. If the \a mode is InvertRgba, the alpha
1986
    bits are also inverted.
1987
1988
    Inverting an 8-bit image means to replace all pixels using color
1989
    index \e i with a pixel using color index 255 minus \e i. The same
1990
    is the case for a 1-bit image. Note that the color table is \e not
1991
    changed.
1992
1993
    If the image has a premultiplied alpha channel, the image is first
1994
    converted to an unpremultiplied image format to be inverted and
1995
    then converted back.
1996
1997
    \sa {QImage#Image Transformations}{Image Transformations}
1998
*/
1999
2000
void QImage::invertPixels(InvertMode mode)
2001
0
{
2002
0
    if (!d)
2003
0
        return;
2004
2005
0
    detach();
2006
2007
    // In case detach() ran out of memory
2008
0
    if (!d)
2009
0
        return;
2010
2011
0
    QImage::Format originalFormat = d->format;
2012
    // Inverting premultiplied pixels would produce invalid image data.
2013
0
    if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
2014
0
        if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
2015
0
            if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
2016
0
                *this = convertToFormat(QImage::Format_RGBA16FPx4);
2017
0
        } else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
2018
0
            if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
2019
0
                *this = convertToFormat(QImage::Format_RGBA32FPx4);
2020
0
        } else if (depth() > 32) {
2021
0
            if (!d->convertInPlace(QImage::Format_RGBA64, { }))
2022
0
                *this = convertToFormat(QImage::Format_RGBA64);
2023
0
        } else {
2024
0
            if (!d->convertInPlace(QImage::Format_ARGB32, { }))
2025
0
                *this = convertToFormat(QImage::Format_ARGB32);
2026
0
        }
2027
0
    }
2028
2029
0
    if (depth() < 32) {
2030
        // This assumes no alpha-channel as the only formats with non-premultipled alpha are 32bit.
2031
0
        qsizetype bpl = (qsizetype(d->width) * d->depth + 7) / 8;
2032
0
        int pad = d->bytes_per_line - bpl;
2033
0
        uchar *sl = d->data;
2034
0
        for (int y=0; y<d->height; ++y) {
2035
0
            for (qsizetype x=0; x<bpl; ++x)
2036
0
                *sl++ ^= 0xff;
2037
0
            sl += pad;
2038
0
        }
2039
0
    } else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
2040
0
        qfloat16 *p = reinterpret_cast<qfloat16 *>(d->data);
2041
0
        qfloat16 *end = reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
2042
0
        while (p < end) {
2043
0
            p[0] = qfloat16(1) - p[0];
2044
0
            p[1] = qfloat16(1) - p[1];
2045
0
            p[2] = qfloat16(1) - p[2];
2046
0
            if (mode == InvertRgba)
2047
0
                p[3] = qfloat16(1) - p[3];
2048
0
            p += 4;
2049
0
        }
2050
0
    } else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
2051
0
        uchar *data = d->data;
2052
0
        for (int y = 0; y < d->height; ++y) {
2053
0
            float *p = reinterpret_cast<float *>(data);
2054
0
            for (int x = 0; x < d->width; ++x) {
2055
0
                p[0] = 1.0f - p[0];
2056
0
                p[1] = 1.0f - p[1];
2057
0
                p[2] = 1.0f - p[2];
2058
0
                if (mode == InvertRgba)
2059
0
                    p[3] = 1.0f - p[3];
2060
0
                p += 4;
2061
0
            }
2062
0
            data += d->bytes_per_line;
2063
0
        }
2064
0
    } else if (depth() == 64) {
2065
0
        quint16 *p = (quint16*)d->data;
2066
0
        quint16 *end = (quint16*)(d->data + d->nbytes);
2067
0
        quint16 xorbits = 0xffff;
2068
0
        while (p < end) {
2069
0
            *p++ ^= xorbits;
2070
0
            *p++ ^= xorbits;
2071
0
            *p++ ^= xorbits;
2072
0
            if (mode == InvertRgba)
2073
0
                *p++ ^= xorbits;
2074
0
            else
2075
0
                p++;
2076
0
        }
2077
0
    } else {
2078
0
        quint32 *p = (quint32*)d->data;
2079
0
        quint32 *end = (quint32*)(d->data + d->nbytes);
2080
0
        quint32 xorbits = 0xffffffff;
2081
0
        switch (d->format) {
2082
0
        case QImage::Format_RGBA8888:
2083
0
            if (mode == InvertRgba)
2084
0
                break;
2085
0
            Q_FALLTHROUGH();
2086
0
        case QImage::Format_RGBX8888:
2087
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
2088
            xorbits = 0xffffff00;
2089
            break;
2090
#else
2091
0
            xorbits = 0x00ffffff;
2092
0
            break;
2093
0
#endif
2094
0
        case QImage::Format_ARGB32:
2095
0
            if (mode == InvertRgba)
2096
0
                break;
2097
0
            Q_FALLTHROUGH();
2098
0
        case QImage::Format_RGB32:
2099
0
            xorbits = 0x00ffffff;
2100
0
            break;
2101
0
        case QImage::Format_BGR30:
2102
0
        case QImage::Format_RGB30:
2103
0
            xorbits = 0x3fffffff;
2104
0
            break;
2105
0
        default:
2106
0
            Q_UNREACHABLE();
2107
0
            xorbits = 0;
2108
0
            break;
2109
0
        }
2110
0
        while (p < end)
2111
0
            *p++ ^= xorbits;
2112
0
    }
2113
2114
0
    if (originalFormat != d->format) {
2115
0
        if (!d->convertInPlace(originalFormat, { }))
2116
0
            *this = convertToFormat(originalFormat);
2117
0
    }
2118
0
}
2119
2120
// Windows defines these
2121
#if defined(write)
2122
# undef write
2123
#endif
2124
#if defined(close)
2125
# undef close
2126
#endif
2127
#if defined(read)
2128
# undef read
2129
#endif
2130
2131
/*!
2132
    Resizes the color table to contain \a colorCount entries.
2133
2134
    If the color table is expanded, all the extra colors will be set to
2135
    transparent (i.e qRgba(0, 0, 0, 0)).
2136
2137
    When the image is used, the color table must be large enough to
2138
    have entries for all the pixel/index values present in the image,
2139
    otherwise the results are undefined.
2140
2141
    \sa colorCount(), colorTable(), setColor(), {QImage#Image
2142
    Transformations}{Image Transformations}
2143
*/
2144
2145
void QImage::setColorCount(int colorCount)
2146
0
{
2147
0
    if (!d) {
2148
0
        qWarning("QImage::setColorCount: null image");
2149
0
        return;
2150
0
    }
2151
2152
0
    detachMetadata(true);
2153
2154
    // In case detach() ran out of memory
2155
0
    if (!d)
2156
0
        return;
2157
2158
0
    if (colorCount == d->colortable.size())
2159
0
        return;
2160
0
    if (colorCount <= 0) {                        // use no color table
2161
0
        d->colortable.clear();
2162
0
        return;
2163
0
    }
2164
0
    int nc = d->colortable.size();
2165
0
    d->colortable.resize(colorCount);
2166
0
    for (int i = nc; i < colorCount; ++i)
2167
0
        d->colortable[i] = 0;
2168
0
}
2169
2170
/*!
2171
    Returns the format of the image.
2172
2173
    \sa {QImage#Image Formats}{Image Formats}
2174
*/
2175
QImage::Format QImage::format() const
2176
0
{
2177
0
    if (d) {
2178
        // Class Invariant Check
2179
0
        Q_ASSERT(d->format < NImageFormats);
2180
0
        Q_ASSERT(d->format > Format_Invalid);
2181
0
    }
2182
0
    return d ? d->format : Format_Invalid;
2183
0
}
2184
2185
/*!
2186
    \fn QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) const &
2187
    \fn QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) &&
2188
2189
    Returns a copy of the image in the given \a format.
2190
2191
    The specified image conversion \a flags control how the image data
2192
    is handled during the conversion process.
2193
2194
    \sa convertTo(), {Image Formats}
2195
*/
2196
2197
/*!
2198
    \fn QImage QImage::convertedTo(Format format, Qt::ImageConversionFlags flags) const &
2199
    \fn QImage QImage::convertedTo(Format format, Qt::ImageConversionFlags flags) &&
2200
    \since 6.0
2201
2202
    Returns a copy of the image in the given \a format.
2203
2204
    The specified image conversion \a flags control how the image data
2205
    is handled during the conversion process.
2206
2207
    \sa convertTo(), {Image Formats}
2208
*/
2209
2210
/*!
2211
    \internal
2212
*/
2213
QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags flags) const
2214
0
{
2215
0
    if (!d || d->format == format)
2216
0
        return *this;
2217
2218
0
    if (d->format == Format_Invalid || format <= Format_Invalid || format >= NImageFormats)
2219
0
        return QImage();
2220
2221
0
    const QPixelLayout *destLayout = &qPixelLayouts[format];
2222
0
    Image_Converter converter = qimage_converter_map[d->format][format];
2223
0
    if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
2224
0
        if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
2225
0
                && qt_highColorPrecision(format, !hasAlphaChannel())) {
2226
0
#if QT_CONFIG(raster_fp)
2227
0
            if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
2228
0
                converter = convert_generic_over_rgba32f;
2229
0
            else
2230
0
#endif
2231
0
                converter = convert_generic_over_rgb64;
2232
0
        } else
2233
0
            converter = convert_generic;
2234
0
    }
2235
0
    if (converter) {
2236
0
        QImage image(d->width, d->height, format);
2237
2238
0
        QIMAGE_SANITYCHECK_MEMORY(image);
2239
2240
0
        copyMetadata(image.d, d);
2241
2242
0
        converter(image.d, d, flags);
2243
0
        return image;
2244
0
    }
2245
2246
    // Convert indexed formats over ARGB32 or RGB32 to the final format.
2247
0
    Q_ASSERT(format != QImage::Format_ARGB32 && format != QImage::Format_RGB32);
2248
0
    Q_ASSERT(d->format != QImage::Format_ARGB32 && d->format != QImage::Format_RGB32);
2249
2250
0
    if (!hasAlphaChannel())
2251
0
        return convertToFormat(Format_RGB32, flags).convertToFormat(format, flags);
2252
2253
0
    return convertToFormat(Format_ARGB32, flags).convertToFormat(format, flags);
2254
0
}
2255
2256
/*!
2257
    \internal
2258
*/
2259
bool QImage::convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags)
2260
0
{
2261
0
    return d && d->convertInPlace(format, flags);
2262
0
}
2263
2264
0
static inline int pixel_distance(QRgb p1, QRgb p2) {
2265
0
    int r1 = qRed(p1);
2266
0
    int g1 = qGreen(p1);
2267
0
    int b1 = qBlue(p1);
2268
0
    int a1 = qAlpha(p1);
2269
2270
0
    int r2 = qRed(p2);
2271
0
    int g2 = qGreen(p2);
2272
0
    int b2 = qBlue(p2);
2273
0
    int a2 = qAlpha(p2);
2274
2275
0
    return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) + abs(a1 - a2);
2276
0
}
2277
2278
0
static inline int closestMatch(QRgb pixel, const QList<QRgb> &clut) {
2279
0
    int idx = 0;
2280
0
    int current_distance = INT_MAX;
2281
0
    for (int i=0; i<clut.size(); ++i) {
2282
0
        int dist = pixel_distance(pixel, clut.at(i));
2283
0
        if (dist < current_distance) {
2284
0
            current_distance = dist;
2285
0
            idx = i;
2286
0
        }
2287
0
    }
2288
0
    return idx;
2289
0
}
2290
2291
static QImage convertWithPalette(const QImage &src, QImage::Format format,
2292
0
                                 const QList<QRgb> &clut) {
2293
0
    QImage dest(src.size(), format);
2294
0
    dest.setColorTable(clut);
2295
2296
0
    copyMetadata(QImageData::get(dest), QImageData::get(src));
2297
2298
0
    int h = src.height();
2299
0
    int w = src.width();
2300
2301
0
    QHash<QRgb, int> cache;
2302
2303
0
    if (format == QImage::Format_Indexed8) {
2304
0
        for (int y=0; y<h; ++y) {
2305
0
            const QRgb *src_pixels = (const QRgb *) src.scanLine(y);
2306
0
            uchar *dest_pixels = (uchar *) dest.scanLine(y);
2307
0
            for (int x=0; x<w; ++x) {
2308
0
                int src_pixel = src_pixels[x];
2309
0
                int value = cache.value(src_pixel, -1);
2310
0
                if (value == -1) {
2311
0
                    value = closestMatch(src_pixel, clut);
2312
0
                    cache.insert(src_pixel, value);
2313
0
                }
2314
0
                dest_pixels[x] = (uchar) value;
2315
0
            }
2316
0
        }
2317
0
    } else {
2318
0
        QList<QRgb> table = clut;
2319
0
        table.resize(2);
2320
0
        for (int y=0; y<h; ++y) {
2321
0
            const QRgb *src_pixels = (const QRgb *) src.scanLine(y);
2322
0
            for (int x=0; x<w; ++x) {
2323
0
                int src_pixel = src_pixels[x];
2324
0
                int value = cache.value(src_pixel, -1);
2325
0
                if (value == -1) {
2326
0
                    value = closestMatch(src_pixel, table);
2327
0
                    cache.insert(src_pixel, value);
2328
0
                }
2329
0
                dest.setPixel(x, y, value);
2330
0
            }
2331
0
        }
2332
0
    }
2333
2334
0
    return dest;
2335
0
}
2336
2337
/*!
2338
    \overload
2339
2340
    Returns a copy of the image converted to the given \a format,
2341
    using the specified \a colorTable.
2342
2343
    Conversion from RGB formats to indexed formats is a slow operation
2344
    and will use a straightforward nearest color approach, with no
2345
    dithering.
2346
*/
2347
QImage QImage::convertToFormat(Format format, const QList<QRgb> &colorTable, Qt::ImageConversionFlags flags) const
2348
0
{
2349
0
    if (!d || d->format == format)
2350
0
        return *this;
2351
2352
0
    if (format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2353
0
        return QImage();
2354
0
    if (format <= QImage::Format_Indexed8)
2355
0
        return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
2356
2357
0
    return convertToFormat(format, flags);
2358
0
}
2359
2360
/*!
2361
    \since 5.9
2362
2363
    Changes the format of the image to \a format without changing the
2364
    data. Only works between formats of the same depth.
2365
2366
    Returns \c true if successful.
2367
2368
    This function can be used to change images with alpha-channels to
2369
    their corresponding opaque formats if the data is known to be opaque-only,
2370
    or to change the format of a given image buffer before overwriting
2371
    it with new data.
2372
2373
    \warning The function does not check if the image data is valid in the
2374
    new format and will still return \c true if the depths are compatible.
2375
    Operations on an image with invalid data are undefined.
2376
2377
    \warning If the image is not detached, this will cause the data to be
2378
    copied.
2379
2380
    \sa hasAlphaChannel(), convertToFormat()
2381
*/
2382
2383
bool QImage::reinterpretAsFormat(Format format)
2384
0
{
2385
0
    if (format <= Format_Invalid || format >= NImageFormats)
2386
0
        return false;
2387
0
    if (!d)
2388
0
        return false;
2389
0
    if (d->format == format)
2390
0
        return true;
2391
0
    if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
2392
0
        return false;
2393
0
    if (!isDetached()) { // Detach only if shared, not for read-only data.
2394
0
        QImageData *oldD = d;
2395
0
        detach();
2396
        // In case detach() ran out of memory
2397
0
        if (!d) {
2398
0
            d = oldD;
2399
0
            d->ref.ref();
2400
0
            return false;
2401
0
        }
2402
0
    }
2403
2404
0
    d->format = format;
2405
0
    return true;
2406
0
}
2407
2408
/*!
2409
    \since 5.13
2410
2411
    Converts the image to the given \a format in place, detaching if necessary.
2412
2413
    The specified image conversion \a flags control how the image data
2414
    is handled during the conversion process.
2415
2416
    \sa convertedTo()
2417
*/
2418
2419
void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
2420
0
{
2421
0
    if (!d || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2422
0
        return;
2423
2424
0
    if (d->format == format)
2425
0
        return;
2426
2427
0
    detach();
2428
0
    if (convertToFormat_inplace(format, flags))
2429
0
        return;
2430
2431
0
    *this = convertToFormat_helper(format, flags);
2432
0
}
2433
2434
/*!
2435
    \fn bool QImage::valid(const QPoint &pos) const
2436
2437
    Returns \c true if \a pos is a valid coordinate pair within the
2438
    image; otherwise returns \c false.
2439
2440
    \sa rect(), QRect::contains()
2441
*/
2442
2443
/*!
2444
    \overload
2445
2446
    Returns \c true if QPoint(\a x, \a y) is a valid coordinate pair
2447
    within the image; otherwise returns \c false.
2448
*/
2449
bool QImage::valid(int x, int y) const
2450
0
{
2451
0
    return d
2452
0
        && x >= 0 && x < d->width
2453
0
        && y >= 0 && y < d->height;
2454
0
}
2455
2456
/*!
2457
    \fn int QImage::pixelIndex(const QPoint &position) const
2458
2459
    Returns the pixel index at the given \a position.
2460
2461
    If \a position is not valid, or if the image is not a paletted
2462
    image (depth() > 8), the results are undefined.
2463
2464
    \sa valid(), depth(), {QImage#Pixel Manipulation}{Pixel Manipulation}
2465
*/
2466
2467
/*!
2468
    \overload
2469
2470
    Returns the pixel index at (\a x, \a y).
2471
*/
2472
int QImage::pixelIndex(int x, int y) const
2473
0
{
2474
0
    if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2475
0
        qWarning("QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
2476
0
        return -12345;
2477
0
    }
2478
0
    const uchar * s = scanLine(y);
2479
0
    switch(d->format) {
2480
0
    case Format_Mono:
2481
0
        return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2482
0
    case Format_MonoLSB:
2483
0
        return (*(s + (x >> 3)) >> (x & 7)) & 1;
2484
0
    case Format_Indexed8:
2485
0
        return (int)s[x];
2486
0
    default:
2487
0
        qWarning("QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
2488
0
    }
2489
0
    return 0;
2490
0
}
2491
2492
2493
/*!
2494
    \fn QRgb QImage::pixel(const QPoint &position) const
2495
2496
    Returns the color of the pixel at the given \a position.
2497
2498
    If the \a position is not valid, the results are undefined.
2499
2500
    \warning This function is expensive when used for massive pixel
2501
    manipulations. Use constBits() or constScanLine() when many
2502
    pixels needs to be read.
2503
2504
    \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel
2505
    Manipulation}
2506
*/
2507
2508
/*!
2509
    \overload
2510
2511
    Returns the color of the pixel at coordinates (\a x, \a y).
2512
*/
2513
QRgb QImage::pixel(int x, int y) const
2514
0
{
2515
0
    if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
2516
0
        qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y);
2517
0
        return 12345;
2518
0
    }
2519
2520
0
    const uchar *s = d->data + y * d->bytes_per_line;
2521
2522
0
    int index = -1;
2523
0
    switch (d->format) {
2524
0
    case Format_Mono:
2525
0
        index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
2526
0
        break;
2527
0
    case Format_MonoLSB:
2528
0
        index = (*(s + (x >> 3)) >> (x & 7)) & 1;
2529
0
        break;
2530
0
    case Format_Indexed8:
2531
0
        index = s[x];
2532
0
        break;
2533
0
    default:
2534
0
        break;
2535
0
    }
2536
0
    if (index >= 0) {    // Indexed format
2537
0
        if (index >= d->colortable.size()) {
2538
0
            qWarning("QImage::pixel: color table index %d out of range.", index);
2539
0
            return 0;
2540
0
        }
2541
0
        return d->colortable.at(index);
2542
0
    }
2543
0
    std::optional<QRgb> out;
2544
0
    switch (d->format) {
2545
0
    case Format_RGB32:
2546
0
    case Format_ARGB32: // Keep old behaviour.
2547
0
    case Format_ARGB32_Premultiplied:
2548
0
        out = reinterpret_cast<const QRgb *>(s)[x];
2549
0
        break;
2550
0
    case Format_RGBX8888:
2551
0
    case Format_RGBA8888: // Match ARGB32 behavior.
2552
0
    case Format_RGBA8888_Premultiplied:
2553
0
        out = RGBA2ARGB(reinterpret_cast<const quint32 *>(s)[x]);
2554
0
        break;
2555
0
    case Format_BGR30:
2556
0
    case Format_A2BGR30_Premultiplied:
2557
0
        out = qConvertA2rgb30ToArgb32<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
2558
0
        break;
2559
0
    case Format_RGB30:
2560
0
    case Format_A2RGB30_Premultiplied:
2561
0
        out = qConvertA2rgb30ToArgb32<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
2562
0
        break;
2563
0
    case Format_RGB16:
2564
0
        return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]);
2565
0
    case Format_RGBX64:
2566
0
    case Format_RGBA64: // Match ARGB32 behavior.
2567
0
    case Format_RGBA64_Premultiplied:
2568
0
        out = reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
2569
0
        break;
2570
0
    case Format_RGBX16FPx4:
2571
0
    case Format_RGBA16FPx4: // Match ARGB32 behavior.
2572
0
    case Format_RGBA16FPx4_Premultiplied:
2573
0
        out = reinterpret_cast<const QRgbaFloat16 *>(s)[x].toArgb32();
2574
0
        break;
2575
0
    case Format_RGBX32FPx4:
2576
0
    case Format_RGBA32FPx4: // Match ARGB32 behavior.
2577
0
    case Format_RGBA32FPx4_Premultiplied:
2578
0
        out = reinterpret_cast<const QRgbaFloat32 *>(s)[x].toArgb32();
2579
0
    default:
2580
0
        break;
2581
0
    }
2582
0
    const QPixelLayout *layout = &qPixelLayouts[d->format];
2583
0
    if (out) {
2584
        // Fix up alpha
2585
0
        if (!layout->hasAlphaChannel)
2586
0
            *out |= 0xff000000;
2587
0
        return *out;
2588
0
    }
2589
0
    uint result;
2590
0
    return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr);
2591
0
}
2592
2593
/*!
2594
    \fn void QImage::setPixel(const QPoint &position, uint index_or_rgb)
2595
2596
    Sets the pixel index or color at the given \a position to \a
2597
    index_or_rgb.
2598
2599
    If the image's format is either monochrome or paletted, the given \a
2600
    index_or_rgb value must be an index in the image's color table,
2601
    otherwise the parameter must be a QRgb value.
2602
2603
    If \a position is not a valid coordinate pair in the image, or if
2604
    \a index_or_rgb >= colorCount() in the case of monochrome and
2605
    paletted images, the result is undefined.
2606
2607
    \warning This function is expensive due to the call of the internal
2608
    \c{detach()} function called within; if performance is a concern, we
2609
    recommend the use of scanLine() or bits() to access pixel data directly.
2610
2611
    \sa pixel(), {QImage#Pixel Manipulation}{Pixel Manipulation}
2612
*/
2613
2614
/*!
2615
    \overload
2616
2617
    Sets the pixel index or color at (\a x, \a y) to \a index_or_rgb.
2618
*/
2619
void QImage::setPixel(int x, int y, uint index_or_rgb)
2620
0
{
2621
0
    if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2622
0
        qWarning("QImage::setPixel: coordinate (%d,%d) out of range", x, y);
2623
0
        return;
2624
0
    }
2625
    // detach is called from within scanLine
2626
0
    uchar * s = scanLine(y);
2627
0
    switch(d->format) {
2628
0
    case Format_Mono:
2629
0
    case Format_MonoLSB:
2630
0
        if (index_or_rgb > 1) {
2631
0
            qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
2632
0
        } else if (format() == Format_MonoLSB) {
2633
0
            if (index_or_rgb==0)
2634
0
                *(s + (x >> 3)) &= ~(1 << (x & 7));
2635
0
            else
2636
0
                *(s + (x >> 3)) |= (1 << (x & 7));
2637
0
        } else {
2638
0
            if (index_or_rgb==0)
2639
0
                *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2640
0
            else
2641
0
                *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2642
0
        }
2643
0
        return;
2644
0
    case Format_Indexed8:
2645
0
        if (index_or_rgb >= (uint)d->colortable.size()) {
2646
0
            qWarning("QImage::setPixel: Index %d out of range", index_or_rgb);
2647
0
            return;
2648
0
        }
2649
0
        s[x] = index_or_rgb;
2650
0
        return;
2651
0
    case Format_RGB32:
2652
        //make sure alpha is 255, we depend on it in qdrawhelper for cases
2653
        // when image is set as a texture pattern on a qbrush
2654
0
        ((uint *)s)[x] = 0xff000000 | index_or_rgb;
2655
0
        return;
2656
0
    case Format_ARGB32:
2657
0
    case Format_ARGB32_Premultiplied:
2658
0
        ((uint *)s)[x] = index_or_rgb;
2659
0
        return;
2660
0
    case Format_RGB16:
2661
0
        ((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
2662
0
        return;
2663
0
    case Format_RGBX8888:
2664
0
        ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
2665
0
        return;
2666
0
    case Format_RGBA8888:
2667
0
    case Format_RGBA8888_Premultiplied:
2668
0
        ((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
2669
0
        return;
2670
0
    case Format_BGR30:
2671
0
        ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
2672
0
        return;
2673
0
    case Format_A2BGR30_Premultiplied:
2674
0
        ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
2675
0
        return;
2676
0
    case Format_RGB30:
2677
0
        ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
2678
0
        return;
2679
0
    case Format_A2RGB30_Premultiplied:
2680
0
        ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
2681
0
        return;
2682
0
    case Format_RGBX64:
2683
0
        ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
2684
0
        return;
2685
0
    case Format_RGBA64:
2686
0
    case Format_RGBA64_Premultiplied:
2687
0
        ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
2688
0
        return;
2689
0
    case Format_RGBX16FPx4:
2690
0
        ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb | 0xff000000);
2691
0
        return;
2692
0
    case Format_RGBA16FPx4:
2693
0
    case Format_RGBA16FPx4_Premultiplied:
2694
0
        ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb);
2695
0
        return;
2696
0
    case Format_RGBX32FPx4:
2697
0
        ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb | 0xff000000);
2698
0
        return;
2699
0
    case Format_RGBA32FPx4:
2700
0
    case Format_RGBA32FPx4_Premultiplied:
2701
0
        ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb);
2702
0
        return;
2703
0
    case Format_Invalid:
2704
0
    case NImageFormats:
2705
0
        Q_ASSERT(false);
2706
0
        return;
2707
0
    default:
2708
0
        break;
2709
0
    }
2710
2711
0
    const QPixelLayout *layout = &qPixelLayouts[d->format];
2712
0
    if (!hasAlphaChannel())
2713
0
        layout->storeFromRGB32(s, &index_or_rgb, x, 1, nullptr, nullptr);
2714
0
    else
2715
0
        layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
2716
0
}
2717
2718
/*!
2719
    \fn QColor QImage::pixelColor(const QPoint &position) const
2720
    \since 5.6
2721
2722
    Returns the color of the pixel at the given \a position as a QColor.
2723
2724
    If the \a position is not valid, an invalid QColor is returned.
2725
2726
    \warning This function is expensive when used for massive pixel
2727
    manipulations. Use constBits() or constScanLine() when many
2728
    pixels needs to be read.
2729
2730
    \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel
2731
    Manipulation}
2732
*/
2733
2734
/*!
2735
    \overload
2736
    \since 5.6
2737
2738
    Returns the color of the pixel at coordinates (\a x, \a y) as a QColor.
2739
*/
2740
QColor QImage::pixelColor(int x, int y) const
2741
0
{
2742
0
    if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2743
0
        qWarning("QImage::pixelColor: coordinate (%d,%d) out of range", x, y);
2744
0
        return QColor();
2745
0
    }
2746
2747
0
    QRgba64 c;
2748
0
    const uchar * s = constScanLine(y);
2749
0
    switch (d->format) {
2750
0
    case Format_BGR30:
2751
0
    case Format_A2BGR30_Premultiplied:
2752
0
        c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
2753
0
        break;
2754
0
    case Format_RGB30:
2755
0
    case Format_A2RGB30_Premultiplied:
2756
0
        c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
2757
0
        break;
2758
0
    case Format_RGBX64:
2759
0
    case Format_RGBA64:
2760
0
    case Format_RGBA64_Premultiplied:
2761
0
        c = reinterpret_cast<const QRgba64 *>(s)[x];
2762
0
        break;
2763
0
    case Format_Grayscale16: {
2764
0
        quint16 v = reinterpret_cast<const quint16 *>(s)[x];
2765
0
        return QColor(qRgba64(v, v, v, 0xffff));
2766
0
    }
2767
0
    case Format_RGBX16FPx4:
2768
0
    case Format_RGBA16FPx4:
2769
0
    case Format_RGBA16FPx4_Premultiplied: {
2770
0
        QRgbaFloat16 p = reinterpret_cast<const QRgbaFloat16 *>(s)[x];
2771
0
        if (d->format == Format_RGBA16FPx4_Premultiplied)
2772
0
            p = p.unpremultiplied();
2773
0
        else if (d->format == Format_RGBX16FPx4)
2774
0
            p.setAlpha(1.0f);
2775
0
        QColor color;
2776
0
        color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2777
0
        return color;
2778
0
    }
2779
0
    case Format_RGBX32FPx4:
2780
0
    case Format_RGBA32FPx4:
2781
0
    case Format_RGBA32FPx4_Premultiplied: {
2782
0
        QRgbaFloat32 p = reinterpret_cast<const QRgbaFloat32 *>(s)[x];
2783
0
        if (d->format == Format_RGBA32FPx4_Premultiplied)
2784
0
            p = p.unpremultiplied();
2785
0
        else if (d->format == Format_RGBX32FPx4)
2786
0
            p.setAlpha(1.0f);
2787
0
        QColor color;
2788
0
        color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2789
0
        return color;
2790
0
    }
2791
0
    default:
2792
0
        c = QRgba64::fromArgb32(pixel(x, y));
2793
0
        break;
2794
0
    }
2795
    // Alpha fix up
2796
0
    switch (d->format) {
2797
0
    case Format_BGR30:
2798
0
    case Format_RGB30:
2799
0
    case Format_RGBX64:
2800
0
        c.setAlpha(65535);
2801
0
        break;
2802
0
    default:
2803
0
        break;
2804
0
    }
2805
    // QColor is always unpremultiplied
2806
0
    if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
2807
0
        c = c.unpremultiplied();
2808
0
    return QColor(c);
2809
0
}
2810
2811
/*!
2812
    \fn void QImage::setPixelColor(const QPoint &position, const QColor &color)
2813
    \since 5.6
2814
2815
    Sets the color at the given \a position to \a color.
2816
2817
    If \a position is not a valid coordinate pair in the image, or
2818
    the image's format is either monochrome or paletted, the result is undefined.
2819
2820
    \warning This function is expensive due to the call of the internal
2821
    \c{detach()} function called within; if performance is a concern, we
2822
    recommend the use of scanLine() or bits() to access pixel data directly.
2823
2824
    \sa pixel(), bits(), scanLine(), {QImage#Pixel Manipulation}{Pixel Manipulation}
2825
*/
2826
2827
/*!
2828
    \overload
2829
    \since 5.6
2830
2831
    Sets the pixel color at (\a x, \a y) to \a color.
2832
*/
2833
void QImage::setPixelColor(int x, int y, const QColor &color)
2834
0
{
2835
0
    if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2836
0
        qWarning("QImage::setPixelColor: coordinate (%d,%d) out of range", x, y);
2837
0
        return;
2838
0
    }
2839
2840
0
    if (!color.isValid()) {
2841
0
        qWarning("QImage::setPixelColor: color is invalid");
2842
0
        return;
2843
0
    }
2844
2845
    // QColor is always unpremultiplied
2846
0
    QRgba64 c = color.rgba64();
2847
0
    if (!hasAlphaChannel())
2848
0
        c.setAlpha(65535);
2849
0
    else if (qPixelLayouts[d->format].premultiplied)
2850
0
        c = c.premultiplied();
2851
    // detach is called from within scanLine
2852
0
    uchar * s = scanLine(y);
2853
0
    switch (d->format) {
2854
0
    case Format_Mono:
2855
0
    case Format_MonoLSB:
2856
0
    case Format_Indexed8:
2857
0
        qWarning("QImage::setPixelColor: called on monochrome or indexed format");
2858
0
        return;
2859
0
    case Format_BGR30:
2860
0
        ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000;
2861
0
        return;
2862
0
    case Format_A2BGR30_Premultiplied:
2863
0
        ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c);
2864
0
        return;
2865
0
    case Format_RGB30:
2866
0
        ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000;
2867
0
        return;
2868
0
    case Format_A2RGB30_Premultiplied:
2869
0
        ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
2870
0
        return;
2871
0
    case Format_RGBX64:
2872
0
    case Format_RGBA64:
2873
0
    case Format_RGBA64_Premultiplied:
2874
0
        ((QRgba64 *)s)[x] = c;
2875
0
        return;
2876
0
    case Format_RGBX16FPx4:
2877
0
    case Format_RGBA16FPx4:
2878
0
    case Format_RGBA16FPx4_Premultiplied: {
2879
0
        float r, g, b, a;
2880
0
        color.getRgbF(&r, &g, &b, &a);
2881
0
        if (d->format == Format_RGBX16FPx4)
2882
0
            a = 1.0f;
2883
0
        QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
2884
0
        if (d->format == Format_RGBA16FPx4_Premultiplied)
2885
0
            c16f = c16f.premultiplied();
2886
0
        ((QRgbaFloat16 *)s)[x] = c16f;
2887
0
        return;
2888
0
    }
2889
0
    case Format_RGBX32FPx4:
2890
0
    case Format_RGBA32FPx4:
2891
0
    case Format_RGBA32FPx4_Premultiplied: {
2892
0
        float r, g, b, a;
2893
0
        color.getRgbF(&r, &g, &b, &a);
2894
0
        if (d->format == Format_RGBX32FPx4)
2895
0
            a = 1.0f;
2896
0
        QRgbaFloat32 c32f{r, g, b, a};
2897
0
        if (d->format == Format_RGBA32FPx4_Premultiplied)
2898
0
            c32f = c32f.premultiplied();
2899
0
        ((QRgbaFloat32 *)s)[x] = c32f;
2900
0
        return;
2901
0
    }
2902
0
    default:
2903
0
        setPixel(x, y, c.toArgb32());
2904
0
        return;
2905
0
    }
2906
0
}
2907
2908
/*!
2909
    Returns \c true if all the colors in the image are shades of gray
2910
    (i.e. their red, green and blue components are equal); otherwise
2911
    false.
2912
2913
    Note that this function is slow for images without color table.
2914
2915
    \sa isGrayscale()
2916
*/
2917
bool QImage::allGray() const
2918
0
{
2919
0
    if (!d)
2920
0
        return true;
2921
2922
0
    switch (d->format) {
2923
0
    case Format_Mono:
2924
0
    case Format_MonoLSB:
2925
0
    case Format_Indexed8:
2926
0
        for (int i = 0; i < d->colortable.size(); ++i) {
2927
0
            if (!qIsGray(d->colortable.at(i)))
2928
0
                return false;
2929
0
        }
2930
0
        return true;
2931
0
    case Format_Alpha8:
2932
0
        return false;
2933
0
    case Format_Grayscale8:
2934
0
    case Format_Grayscale16:
2935
0
        return true;
2936
0
    case Format_RGB32:
2937
0
    case Format_ARGB32:
2938
0
    case Format_ARGB32_Premultiplied:
2939
0
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
2940
0
    case Format_RGBX8888:
2941
0
    case Format_RGBA8888:
2942
0
    case Format_RGBA8888_Premultiplied:
2943
0
#endif
2944
0
        for (int j = 0; j < d->height; ++j) {
2945
0
            const QRgb *b = (const QRgb *)constScanLine(j);
2946
0
            for (int i = 0; i < d->width; ++i) {
2947
0
                if (!qIsGray(b[i]))
2948
0
                    return false;
2949
0
            }
2950
0
        }
2951
0
        return true;
2952
0
    case Format_RGB16:
2953
0
        for (int j = 0; j < d->height; ++j) {
2954
0
            const quint16 *b = (const quint16 *)constScanLine(j);
2955
0
            for (int i = 0; i < d->width; ++i) {
2956
0
                if (!qIsGray(qConvertRgb16To32(b[i])))
2957
0
                    return false;
2958
0
            }
2959
0
        }
2960
0
        return true;
2961
0
    default:
2962
0
        break;
2963
0
    }
2964
2965
0
    Q_DECL_UNINITIALIZED uint buffer[BufferSize];
2966
0
    const QPixelLayout *layout = &qPixelLayouts[d->format];
2967
0
    const auto fetch = layout->fetchToARGB32PM;
2968
0
    for (int j = 0; j < d->height; ++j) {
2969
0
        const uchar *b = constScanLine(j);
2970
0
        int x = 0;
2971
0
        while (x < d->width) {
2972
0
            int l = qMin(d->width - x, BufferSize);
2973
0
            const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr);
2974
0
            for (int i = 0; i < l; ++i) {
2975
0
                if (!qIsGray(ptr[i]))
2976
0
                    return false;
2977
0
            }
2978
0
            x += l;
2979
0
        }
2980
0
    }
2981
0
    return true;
2982
0
}
2983
2984
/*!
2985
    For 32-bit images, this function is equivalent to allGray().
2986
2987
    For color indexed images, this function returns \c true if
2988
    color(i) is QRgb(i, i, i) for all indexes of the color table;
2989
    otherwise returns \c false.
2990
2991
    \sa allGray(), {QImage#Image Formats}{Image Formats}
2992
*/
2993
bool QImage::isGrayscale() const
2994
0
{
2995
0
    if (!d)
2996
0
        return false;
2997
2998
0
    if (d->format == QImage::Format_Alpha8)
2999
0
        return false;
3000
3001
0
    if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
3002
0
        return true;
3003
3004
0
    switch (depth()) {
3005
0
    case 32:
3006
0
    case 24:
3007
0
    case 16:
3008
0
        return allGray();
3009
0
    case 8: {
3010
0
        Q_ASSERT(d->format == QImage::Format_Indexed8);
3011
0
        for (int i = 0; i < colorCount(); i++)
3012
0
            if (d->colortable.at(i) != qRgb(i,i,i))
3013
0
                return false;
3014
0
        return true;
3015
0
        }
3016
0
    }
3017
0
    return false;
3018
0
}
3019
3020
/*!
3021
    \fn QImage QImage::scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode,
3022
                             Qt::TransformationMode transformMode) const
3023
    \overload
3024
3025
    Returns a copy of the image scaled to a rectangle with the given
3026
    \a width and \a height according to the given \a aspectRatioMode
3027
    and \a transformMode.
3028
3029
    If either the \a width or the \a height is zero or negative, this
3030
    function returns a null image.
3031
*/
3032
3033
/*!
3034
    \fn QImage QImage::scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode,
3035
                             Qt::TransformationMode transformMode) const
3036
3037
    Returns a copy of the image scaled to a rectangle defined by the
3038
    given \a size according to the given \a aspectRatioMode and \a
3039
    transformMode.
3040
3041
    \image qimage-scaling.png {Illustration showing three different
3042
           ways to scale images with Aspect Ratio Mode}
3043
3044
    \list
3045
    \li If \a aspectRatioMode is Qt::IgnoreAspectRatio, the image
3046
       is scaled to \a size.
3047
    \li If \a aspectRatioMode is Qt::KeepAspectRatio, the image is
3048
       scaled to a rectangle as large as possible inside \a size, preserving the aspect ratio.
3049
    \li If \a aspectRatioMode is Qt::KeepAspectRatioByExpanding,
3050
       the image is scaled to a rectangle as small as possible
3051
       outside \a size, preserving the aspect ratio.
3052
    \endlist
3053
3054
    If the given \a size is empty, this function returns a null image.
3055
3056
    \sa isNull(), {QImage#Image Transformations}{Image
3057
    Transformations}
3058
*/
3059
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
3060
0
{
3061
0
    if (!d) {
3062
0
        qWarning("QImage::scaled: Image is a null image");
3063
0
        return QImage();
3064
0
    }
3065
0
    if (s.isEmpty())
3066
0
        return QImage();
3067
3068
0
    QSize newSize = size();
3069
0
    newSize.scale(s, aspectMode);
3070
0
    newSize.rwidth() = qMax(newSize.width(), 1);
3071
0
    newSize.rheight() = qMax(newSize.height(), 1);
3072
0
    if (newSize == size())
3073
0
        return *this;
3074
3075
0
    Q_TRACE_SCOPE(QImage_scaled, s, aspectMode, mode);
3076
3077
0
    QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
3078
0
    QImage img = transformed(wm, mode);
3079
0
    return img;
3080
0
}
3081
3082
/*!
3083
    \fn QImage QImage::scaledToWidth(int width, Qt::TransformationMode mode) const
3084
3085
    Returns a scaled copy of the image. The returned image is scaled
3086
    to the given \a width using the specified transformation \a
3087
    mode.
3088
3089
    This function automatically calculates the height of the image so
3090
    that its aspect ratio is preserved.
3091
3092
    If the given \a width is 0 or negative, a null image is returned.
3093
3094
    \sa {QImage#Image Transformations}{Image Transformations}
3095
*/
3096
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
3097
0
{
3098
0
    if (!d) {
3099
0
        qWarning("QImage::scaleWidth: Image is a null image");
3100
0
        return QImage();
3101
0
    }
3102
0
    if (w <= 0)
3103
0
        return QImage();
3104
3105
0
    Q_TRACE_SCOPE(QImage_scaledToWidth, w, mode);
3106
3107
0
    qreal factor = (qreal) w / width();
3108
0
    QTransform wm = QTransform::fromScale(factor, factor);
3109
0
    return transformed(wm, mode);
3110
0
}
3111
3112
/*!
3113
    \fn QImage QImage::scaledToHeight(int height, Qt::TransformationMode mode) const
3114
3115
    Returns a scaled copy of the image. The returned image is scaled
3116
    to the given \a height using the specified transformation \a
3117
    mode.
3118
3119
    This function automatically calculates the width of the image so that
3120
    the ratio of the image is preserved.
3121
3122
    If the given \a height is 0 or negative, a null image is returned.
3123
3124
    \sa {QImage#Image Transformations}{Image Transformations}
3125
*/
3126
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
3127
0
{
3128
0
    if (!d) {
3129
0
        qWarning("QImage::scaleHeight: Image is a null image");
3130
0
        return QImage();
3131
0
    }
3132
0
    if (h <= 0)
3133
0
        return QImage();
3134
3135
0
    Q_TRACE_SCOPE(QImage_scaledToHeight, h, mode);
3136
3137
0
    qreal factor = (qreal) h / height();
3138
0
    QTransform wm = QTransform::fromScale(factor, factor);
3139
0
    return transformed(wm, mode);
3140
0
}
3141
3142
/*!
3143
    Builds and returns a 1-bpp mask from the alpha buffer in this
3144
    image. Returns a null image if the image's format is
3145
    QImage::Format_RGB32.
3146
3147
    The \a flags argument is a bitwise-OR of the
3148
    Qt::ImageConversionFlags, and controls the conversion
3149
    process. Passing 0 for flags sets all the default options.
3150
3151
    The returned image has little-endian bit order (i.e. the image's
3152
    format is QImage::Format_MonoLSB), which you can convert to
3153
    big-endian (QImage::Format_Mono) using the convertToFormat()
3154
    function.
3155
3156
    \sa createHeuristicMask(), {QImage#Image Transformations}{Image
3157
    Transformations}
3158
*/
3159
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
3160
0
{
3161
0
    if (!d || d->format == QImage::Format_RGB32)
3162
0
        return QImage();
3163
3164
0
    if (d->depth == 1) {
3165
        // A monochrome pixmap, with alpha channels on those two colors.
3166
        // Pretty unlikely, so use less efficient solution.
3167
0
        return convertToFormat(Format_Indexed8, flags).createAlphaMask(flags);
3168
0
    }
3169
3170
0
    if (d->format != Format_Indexed8 && d->format != Format_ARGB32
3171
0
        && d->format != Format_ARGB32_Premultiplied) {
3172
        // dither_to_Mono() only reads alpha from a color table or from ARGB32 pixels.
3173
0
        return convertToFormat(Format_ARGB32_Premultiplied, flags).createAlphaMask(flags);
3174
0
    }
3175
3176
0
    QImage mask(d->width, d->height, Format_MonoLSB);
3177
0
    if (!mask.isNull()) {
3178
0
        dither_to_Mono(mask.d, d, flags, true);
3179
0
        copyPhysicalMetadata(mask.d, d);
3180
0
    }
3181
0
    return mask;
3182
0
}
3183
3184
#ifndef QT_NO_IMAGE_HEURISTIC_MASK
3185
/*!
3186
    Creates and returns a 1-bpp heuristic mask for this image.
3187
3188
    The function works by selecting a color from one of the corners,
3189
    then chipping away pixels of that color starting at all the edges.
3190
    The four corners vote for which color is to be masked away. In
3191
    case of a draw (this generally means that this function is not
3192
    applicable to the image), the result is arbitrary.
3193
3194
    The returned image has little-endian bit order (i.e. the image's
3195
    format is QImage::Format_MonoLSB), which you can convert to
3196
    big-endian (QImage::Format_Mono) using the convertToFormat()
3197
    function.
3198
3199
    If \a clipTight is true (the default) the mask is just large
3200
    enough to cover the pixels; otherwise, the mask is larger than the
3201
    data pixels.
3202
3203
    Note that this function disregards the alpha buffer.
3204
3205
    \sa createAlphaMask(), {QImage#Image Transformations}{Image
3206
    Transformations}
3207
*/
3208
3209
QImage QImage::createHeuristicMask(bool clipTight) const
3210
0
{
3211
0
    if (!d)
3212
0
        return QImage();
3213
3214
0
    if (d->depth != 32) {
3215
0
        QImage img32 = convertToFormat(Format_RGB32);
3216
0
        return img32.createHeuristicMask(clipTight);
3217
0
    }
3218
3219
0
#define PIX(x,y)  (*((const QRgb*)scanLine(y)+x) & 0x00ffffff)
3220
3221
0
    int w = width();
3222
0
    int h = height();
3223
0
    QImage m(w, h, Format_MonoLSB);
3224
0
    QIMAGE_SANITYCHECK_MEMORY(m);
3225
0
    m.setColorCount(2);
3226
0
    m.setColor(0, QColor(Qt::color0).rgba());
3227
0
    m.setColor(1, QColor(Qt::color1).rgba());
3228
0
    m.fill(0xff);
3229
3230
0
    QRgb background = PIX(0,0);
3231
0
    if (background != PIX(w-1,0) &&
3232
0
         background != PIX(0,h-1) &&
3233
0
         background != PIX(w-1,h-1)) {
3234
0
        background = PIX(w-1,0);
3235
0
        if (background != PIX(w-1,h-1) &&
3236
0
             background != PIX(0,h-1) &&
3237
0
             PIX(0,h-1) == PIX(w-1,h-1)) {
3238
0
            background = PIX(w-1,h-1);
3239
0
        }
3240
0
    }
3241
3242
0
    int x,y;
3243
0
    bool done = false;
3244
0
    uchar *ypp, *ypc, *ypn;
3245
0
    while(!done) {
3246
0
        done = true;
3247
0
        ypn = m.scanLine(0);
3248
0
        ypc = nullptr;
3249
0
        for (y = 0; y < h; y++) {
3250
0
            ypp = ypc;
3251
0
            ypc = ypn;
3252
0
            ypn = (y == h-1) ? nullptr : m.scanLine(y+1);
3253
0
            const QRgb *p = (const QRgb *)scanLine(y);
3254
0
            for (x = 0; x < w; x++) {
3255
                // slowness here - it's possible to do six of these tests
3256
                // together in one go. oh well.
3257
0
                if ((x == 0 || y == 0 || x == w-1 || y == h-1 ||
3258
0
                       !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3259
0
                       !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3260
0
                       !(*(ypp + (x     >> 3)) & (1 << (x     & 7))) ||
3261
0
                       !(*(ypn + (x     >> 3)) & (1 << (x     & 7)))) &&
3262
0
                     (       (*(ypc + (x     >> 3)) & (1 << (x     & 7)))) &&
3263
0
                     ((*p & 0x00ffffff) == background)) {
3264
0
                    done = false;
3265
0
                    *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3266
0
                }
3267
0
                p++;
3268
0
            }
3269
0
        }
3270
0
    }
3271
3272
0
    if (!clipTight) {
3273
0
        ypn = m.scanLine(0);
3274
0
        ypc = nullptr;
3275
0
        for (y = 0; y < h; y++) {
3276
0
            ypp = ypc;
3277
0
            ypc = ypn;
3278
0
            ypn = (y == h-1) ? nullptr : m.scanLine(y+1);
3279
0
            const QRgb *p = (const QRgb *)scanLine(y);
3280
0
            for (x = 0; x < w; x++) {
3281
0
                if ((*p & 0x00ffffff) != background) {
3282
0
                    if (x > 0)
3283
0
                        *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3284
0
                    if (x < w-1)
3285
0
                        *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3286
0
                    if (y > 0)
3287
0
                        *(ypp + (x >> 3)) |= (1 << (x & 7));
3288
0
                    if (y < h-1)
3289
0
                        *(ypn + (x >> 3)) |= (1 << (x & 7));
3290
0
                }
3291
0
                p++;
3292
0
            }
3293
0
        }
3294
0
    }
3295
3296
0
#undef PIX
3297
3298
0
    copyPhysicalMetadata(m.d, d);
3299
0
    return m;
3300
0
}
3301
#endif //QT_NO_IMAGE_HEURISTIC_MASK
3302
3303
/*!
3304
    Creates and returns a mask for this image based on the given \a
3305
    color value. If the \a mode is MaskInColor (the default value),
3306
    all pixels matching \a color will be opaque pixels in the mask. If
3307
    \a mode is MaskOutColor, all pixels matching the given color will
3308
    be transparent.
3309
3310
    \sa createAlphaMask(), createHeuristicMask()
3311
*/
3312
3313
QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
3314
0
{
3315
0
    if (!d)
3316
0
        return QImage();
3317
0
    QImage maskImage(size(), QImage::Format_MonoLSB);
3318
0
    QIMAGE_SANITYCHECK_MEMORY(maskImage);
3319
0
    maskImage.fill(0);
3320
0
    uchar *s = maskImage.bits();
3321
0
    if (!s)
3322
0
        return QImage();
3323
3324
0
    if (depth() == 32) {
3325
0
        for (int h = 0; h < d->height; h++) {
3326
0
            const uint *sl = (const uint *) scanLine(h);
3327
0
            for (int w = 0; w < d->width; w++) {
3328
0
                if (sl[w] == color)
3329
0
                    *(s + (w >> 3)) |= (1 << (w & 7));
3330
0
            }
3331
0
            s += maskImage.bytesPerLine();
3332
0
        }
3333
0
    } else {
3334
0
        for (int h = 0; h < d->height; h++) {
3335
0
            for (int w = 0; w < d->width; w++) {
3336
0
                if ((uint) pixel(w, h) == color)
3337
0
                    *(s + (w >> 3)) |= (1 << (w & 7));
3338
0
            }
3339
0
            s += maskImage.bytesPerLine();
3340
0
        }
3341
0
    }
3342
0
    if  (mode == Qt::MaskOutColor)
3343
0
        maskImage.invertPixels();
3344
3345
0
    copyPhysicalMetadata(maskImage.d, d);
3346
0
    return maskImage;
3347
0
}
3348
3349
/*!
3350
    \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const &
3351
    \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) &&
3352
    \deprecated [6.13] Use flipped(Qt::Orientations) instead.
3353
3354
    Returns a mirror of the image, mirrored in the horizontal and/or
3355
    the vertical direction depending on whether \a horizontal and \a
3356
    vertical are set to true or false.
3357
3358
    Note that the original image is not changed.
3359
3360
    \sa mirror(), {QImage#Image Transformations}{Image Transformations}
3361
*/
3362
3363
/*!
3364
    \fn void QImage::mirror(bool horizontal = false, bool vertical = true)
3365
    \since 6.0
3366
    \deprecated [6.13] Use flip(Qt::Orientations) instead.
3367
3368
    Mirrors of the image in the horizontal and/or the vertical direction depending
3369
    on whether \a horizontal and \a vertical are set to true or false.
3370
3371
    \sa mirrored(), {QImage#Image Transformations}{Image Transformations}
3372
*/
3373
3374
/*!
3375
    \fn QImage QImage::flipped(Qt::Orientations orient) const &
3376
    \fn QImage QImage::flipped(Qt::Orientations orient) &&
3377
    \since 6.9
3378
3379
    Returns a flipped or mirror version of the image, mirrored in the horizontal and/or
3380
    the vertical direction depending on \a orient.
3381
3382
    Note that the original image is not changed.
3383
3384
    \sa flip(Qt::Orientations), {QImage#Image Transformations}{Image Transformations}
3385
*/
3386
3387
/*!
3388
    \fn void QImage::flip(Qt::Orientations orient)
3389
    \since 6.9
3390
3391
    Flips or mirrors the image in the horizontal and/or the vertical direction depending
3392
    on \a orient.
3393
3394
    \sa flipped(Qt::Orientations), {QImage#Image Transformations}{Image Transformations}
3395
*/
3396
3397
template<class T> inline void do_mirror_data(QImageData *dst, QImageData *src,
3398
                                             int dstX0, int dstY0,
3399
                                             int dstXIncr, int dstYIncr,
3400
                                             int w, int h)
3401
0
{
3402
0
    if (dst == src) {
3403
        // When mirroring in-place, stop in the middle for one of the directions, since we
3404
        // are swapping the bytes instead of merely copying.
3405
0
        const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w;
3406
0
        const int srcYEnd = dstY0 ? h / 2 : h;
3407
0
        for (int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
3408
0
            T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3409
0
            T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3410
0
            for (int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
3411
0
                std::swap(srcPtr[srcX], dstPtr[dstX]);
3412
0
        }
3413
        // If mirroring both ways, the middle line needs to be mirrored horizontally only.
3414
0
        if (dstX0 && dstY0 && (h & 1)) {
3415
0
            int srcY = h / 2;
3416
0
            int srcXEnd2 = w / 2;
3417
0
            T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3418
0
            for (int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr)
3419
0
                std::swap(srcPtr[srcX], srcPtr[dstX]);
3420
0
        }
3421
0
    } else {
3422
0
        for (int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
3423
0
            T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3424
0
            T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3425
0
            for (int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
3426
0
                dstPtr[dstX] = srcPtr[srcX];
3427
0
        }
3428
0
    }
3429
0
}
Unexecuted instantiation: void do_mirror_data<QRgbaFloat<float> >(QImageData*, QImageData*, int, int, int, int, int, int)
Unexecuted instantiation: void do_mirror_data<unsigned long long>(QImageData*, QImageData*, int, int, int, int, int, int)
Unexecuted instantiation: void do_mirror_data<unsigned int>(QImageData*, QImageData*, int, int, int, int, int, int)
Unexecuted instantiation: void do_mirror_data<quint24>(QImageData*, QImageData*, int, int, int, int, int, int)
Unexecuted instantiation: void do_mirror_data<unsigned short>(QImageData*, QImageData*, int, int, int, int, int, int)
Unexecuted instantiation: void do_mirror_data<unsigned char>(QImageData*, QImageData*, int, int, int, int, int, int)
3430
3431
inline void do_flip(QImageData *dst, QImageData *src, int w, int h, int depth)
3432
0
{
3433
0
    const int data_bytes_per_line = w * (depth / 8);
3434
0
    if (dst == src) {
3435
0
        uint *srcPtr = reinterpret_cast<uint *>(src->data);
3436
0
        uint *dstPtr = reinterpret_cast<uint *>(dst->data + (h - 1) * dst->bytes_per_line);
3437
0
        h = h / 2;
3438
0
        const int uint_per_line = (data_bytes_per_line + 3) >> 2; // bytes per line must be a multiple of 4
3439
0
        for (int y = 0; y < h; ++y) {
3440
            // This is auto-vectorized, no need for SSE2 or NEON versions:
3441
0
            for (int x = 0; x < uint_per_line; x++) {
3442
0
                const uint d = dstPtr[x];
3443
0
                const uint s = srcPtr[x];
3444
0
                dstPtr[x] = s;
3445
0
                srcPtr[x] = d;
3446
0
            }
3447
0
            srcPtr += src->bytes_per_line >> 2;
3448
0
            dstPtr -= dst->bytes_per_line >> 2;
3449
0
        }
3450
3451
0
    } else {
3452
0
        const uchar *srcPtr = src->data;
3453
0
        uchar *dstPtr = dst->data + (h - 1) * dst->bytes_per_line;
3454
0
        for (int y = 0; y < h; ++y) {
3455
0
            memcpy(dstPtr, srcPtr, data_bytes_per_line);
3456
0
            srcPtr += src->bytes_per_line;
3457
0
            dstPtr -= dst->bytes_per_line;
3458
0
        }
3459
0
    }
3460
0
}
3461
3462
inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool vertical)
3463
0
{
3464
0
    Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
3465
0
    int w = src->width;
3466
0
    int h = src->height;
3467
0
    int depth = src->depth;
3468
3469
0
    if (src->depth == 1) {
3470
0
        w = (w + 7) / 8; // byte aligned width
3471
0
        depth = 8;
3472
0
    }
3473
3474
0
    if (vertical && !horizontal) {
3475
        // This one is simple and common, so do it a little more optimized
3476
0
        do_flip(dst, src, w, h, depth);
3477
0
        return;
3478
0
    }
3479
3480
0
    int dstX0 = 0, dstXIncr = 1;
3481
0
    int dstY0 = 0, dstYIncr = 1;
3482
0
    if (horizontal) {
3483
        // 0 -> w-1, 1 -> w-2, 2 -> w-3, ...
3484
0
        dstX0 = w - 1;
3485
0
        dstXIncr = -1;
3486
0
    }
3487
0
    if (vertical) {
3488
        // 0 -> h-1, 1 -> h-2, 2 -> h-3, ...
3489
0
        dstY0 = h - 1;
3490
0
        dstYIncr = -1;
3491
0
    }
3492
3493
0
    switch (depth) {
3494
0
    case 128:
3495
0
        do_mirror_data<QRgbaFloat32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3496
0
        break;
3497
0
    case 64:
3498
0
        do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3499
0
        break;
3500
0
    case 32:
3501
0
        do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3502
0
        break;
3503
0
    case 24:
3504
0
        do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3505
0
        break;
3506
0
    case 16:
3507
0
        do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3508
0
        break;
3509
0
    case 8:
3510
0
        do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3511
0
        break;
3512
0
    default:
3513
0
        Q_ASSERT(false);
3514
0
        break;
3515
0
    }
3516
3517
    // The bytes are now all in the correct place. In addition, the bits in the individual
3518
    // bytes have to be flipped too when horizontally mirroring a 1 bit-per-pixel image.
3519
0
    if (horizontal && dst->depth == 1) {
3520
0
        Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
3521
0
        const int shift = 8 - (dst->width % 8);
3522
0
        const uchar *bitflip = qt_get_bitflip_array();
3523
0
        for (int y = 0; y < h; ++y) {
3524
0
            uchar *begin = dst->data + y * dst->bytes_per_line;
3525
0
            uchar *end = begin + dst->bytes_per_line;
3526
0
            for (uchar *p = begin; p < end; ++p) {
3527
0
                *p = bitflip[*p];
3528
                // When the data is non-byte aligned, an extra bit shift (of the number of
3529
                // unused bits at the end) is needed for the entire scanline.
3530
0
                if (shift != 8 && p != begin) {
3531
0
                    if (dst->format == QImage::Format_Mono) {
3532
0
                        for (int i = 0; i < shift; ++i) {
3533
0
                            p[-1] <<= 1;
3534
0
                            p[-1] |= (*p & (128 >> i)) >> (7 - i);
3535
0
                        }
3536
0
                    } else {
3537
0
                        for (int i = 0; i < shift; ++i) {
3538
0
                            p[-1] >>= 1;
3539
0
                            p[-1] |= (*p & (1 << i)) << (7 - i);
3540
0
                        }
3541
0
                    }
3542
0
                }
3543
0
            }
3544
0
            if (shift != 8) {
3545
0
                if (dst->format == QImage::Format_Mono)
3546
0
                    end[-1] <<= shift;
3547
0
                else
3548
0
                    end[-1] >>= shift;
3549
0
            }
3550
0
        }
3551
0
    }
3552
0
}
3553
3554
/*!
3555
    \internal
3556
*/
3557
QImage QImage::mirrored_helper(bool horizontal, bool vertical) const
3558
0
{
3559
0
    if (!d)
3560
0
        return QImage();
3561
3562
0
    if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3563
0
        return *this;
3564
3565
    // Create result image, copy colormap
3566
0
    QImage result(d->width, d->height, d->format);
3567
0
    QIMAGE_SANITYCHECK_MEMORY(result);
3568
3569
    // check if we ran out of of memory..
3570
0
    if (!result.d)
3571
0
        return QImage();
3572
3573
0
    result.d->colortable = d->colortable;
3574
0
    result.d->has_alpha_clut = d->has_alpha_clut;
3575
0
    copyMetadata(result.d, d);
3576
3577
0
    do_mirror(result.d, d, horizontal, vertical);
3578
3579
0
    return result;
3580
0
}
3581
3582
/*!
3583
    \internal
3584
*/
3585
void QImage::mirrored_inplace(bool horizontal, bool vertical)
3586
0
{
3587
0
    if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3588
0
        return;
3589
3590
0
    detach();
3591
0
    if (!d)
3592
0
        return;
3593
0
    if (!d->own_data)
3594
0
        *this = copy();
3595
3596
0
    do_mirror(d, d, horizontal, vertical);
3597
0
}
3598
3599
/*!
3600
    \fn QImage QImage::rgbSwapped() const &
3601
    \fn QImage QImage::rgbSwapped() &&
3602
3603
    Returns a QImage in which the values of the red and blue
3604
    components of all pixels have been swapped, effectively converting
3605
    an RGB image to an BGR image.
3606
3607
    The original QImage is not changed.
3608
3609
    \sa rgbSwap(), {QImage#Image Transformations}{Image Transformations}
3610
*/
3611
3612
/*!
3613
    \fn void QImage::rgbSwap()
3614
    \since 6.0
3615
3616
    Swaps the values of the red and blue components of all pixels, effectively converting
3617
    an RGB image to an BGR image.
3618
3619
    \sa rgbSwapped(), {QImage#Image Transformations}{Image Transformations}
3620
*/
3621
3622
static inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout)
3623
0
{
3624
0
    const RbSwapFunc func = layout->rbSwap;
3625
0
    if (!func) {
3626
0
        qWarning("Trying to rb-swap an image format where it doesn't make sense");
3627
0
        if (src != dst)
3628
0
            *dst = *src;
3629
0
        return;
3630
0
    }
3631
3632
0
    for (int i = 0; i < height; ++i) {
3633
0
        uchar *q = dst->scanLine(i);
3634
0
        const uchar *p = src->constScanLine(i);
3635
0
        func(q, p, width);
3636
0
    }
3637
0
}
3638
3639
/*!
3640
    \internal
3641
*/
3642
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper() const
3643
0
{
3644
0
    if (isNull())
3645
0
        return *this;
3646
3647
0
    Q_TRACE_SCOPE(QImage_rgbSwapped_helper);
3648
3649
0
    QImage res;
3650
3651
0
    switch (d->format) {
3652
0
    case Format_Invalid:
3653
0
    case NImageFormats:
3654
0
        Q_ASSERT(false);
3655
0
        break;
3656
0
    case Format_Alpha8:
3657
0
    case Format_Grayscale8:
3658
0
    case Format_Grayscale16:
3659
0
        return *this;
3660
0
    case Format_Mono:
3661
0
    case Format_MonoLSB:
3662
0
    case Format_Indexed8:
3663
0
        res = copy();
3664
0
        for (int i = 0; i < res.d->colortable.size(); i++) {
3665
0
            QRgb c = res.d->colortable.at(i);
3666
0
            res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3667
0
        }
3668
0
        break;
3669
0
    case Format_RGBX8888:
3670
0
    case Format_RGBA8888:
3671
0
    case Format_RGBA8888_Premultiplied:
3672
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3673
        res = QImage(d->width, d->height, d->format);
3674
        QIMAGE_SANITYCHECK_MEMORY(res);
3675
        for (int i = 0; i < d->height; i++) {
3676
            uint *q = (uint*)res.scanLine(i);
3677
            const uint *p = (const uint*)constScanLine(i);
3678
            const uint *end = p + d->width;
3679
            while (p < end) {
3680
                uint c = *p;
3681
                *q = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3682
                p++;
3683
                q++;
3684
            }
3685
        }
3686
        break;
3687
#else
3688
        // On little-endian rgba8888 is abgr32 and can use same rgb-swap as argb32
3689
0
        Q_FALLTHROUGH();
3690
0
#endif
3691
0
    case Format_RGB32:
3692
0
    case Format_ARGB32:
3693
0
    case Format_ARGB32_Premultiplied:
3694
0
        res = QImage(d->width, d->height, d->format);
3695
0
        QIMAGE_SANITYCHECK_MEMORY(res);
3696
0
        for (int i = 0; i < d->height; i++) {
3697
0
            uint *q = (uint*)res.scanLine(i);
3698
0
            const uint *p = (const uint*)constScanLine(i);
3699
0
            const uint *end = p + d->width;
3700
0
            while (p < end) {
3701
0
                uint c = *p;
3702
0
                *q = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3703
0
                p++;
3704
0
                q++;
3705
0
            }
3706
0
        }
3707
0
        break;
3708
0
    case Format_RGB16:
3709
0
        res = QImage(d->width, d->height, d->format);
3710
0
        QIMAGE_SANITYCHECK_MEMORY(res);
3711
0
        for (int i = 0; i < d->height; i++) {
3712
0
            ushort *q = (ushort*)res.scanLine(i);
3713
0
            const ushort *p = (const ushort*)constScanLine(i);
3714
0
            const ushort *end = p + d->width;
3715
0
            while (p < end) {
3716
0
                ushort c = *p;
3717
0
                *q = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3718
0
                p++;
3719
0
                q++;
3720
0
            }
3721
0
        }
3722
0
        break;
3723
0
    default:
3724
0
        res = QImage(d->width, d->height, d->format);
3725
0
        QIMAGE_SANITYCHECK_MEMORY(res);
3726
0
        rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
3727
0
        break;
3728
0
    }
3729
0
    copyMetadata(res.d, d);
3730
0
    return res;
3731
0
}
3732
3733
/*!
3734
    \internal
3735
*/
3736
void QImage::rgbSwapped_inplace()
3737
0
{
3738
0
    if (isNull())
3739
0
        return;
3740
3741
0
    detach();
3742
0
    if (!d)
3743
0
        return;
3744
0
    if (!d->own_data)
3745
0
        *this = copy();
3746
3747
0
    switch (d->format) {
3748
0
    case Format_Invalid:
3749
0
    case NImageFormats:
3750
0
        Q_ASSERT(false);
3751
0
        break;
3752
0
    case Format_Alpha8:
3753
0
    case Format_Grayscale8:
3754
0
    case Format_Grayscale16:
3755
0
        return;
3756
0
    case Format_Mono:
3757
0
    case Format_MonoLSB:
3758
0
    case Format_Indexed8:
3759
0
        for (int i = 0; i < d->colortable.size(); i++) {
3760
0
            QRgb c = d->colortable.at(i);
3761
0
            d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3762
0
        }
3763
0
        break;
3764
0
    case Format_RGBX8888:
3765
0
    case Format_RGBA8888:
3766
0
    case Format_RGBA8888_Premultiplied:
3767
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3768
        for (int i = 0; i < d->height; i++) {
3769
            uint *p = (uint*)scanLine(i);
3770
            uint *end = p + d->width;
3771
            while (p < end) {
3772
                uint c = *p;
3773
                *p = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3774
                p++;
3775
            }
3776
        }
3777
        break;
3778
#else
3779
        // On little-endian rgba8888 is abgr32 and can use same rgb-swap as argb32
3780
0
        Q_FALLTHROUGH();
3781
0
#endif
3782
0
    case Format_RGB32:
3783
0
    case Format_ARGB32:
3784
0
    case Format_ARGB32_Premultiplied:
3785
0
        for (int i = 0; i < d->height; i++) {
3786
0
            uint *p = (uint*)scanLine(i);
3787
0
            uint *end = p + d->width;
3788
0
            while (p < end) {
3789
0
                uint c = *p;
3790
0
                *p = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3791
0
                p++;
3792
0
            }
3793
0
        }
3794
0
        break;
3795
0
    case Format_RGB16:
3796
0
        for (int i = 0; i < d->height; i++) {
3797
0
            ushort *p = (ushort*)scanLine(i);
3798
0
            ushort *end = p + d->width;
3799
0
            while (p < end) {
3800
0
                ushort c = *p;
3801
0
                *p = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3802
0
                p++;
3803
0
            }
3804
0
        }
3805
0
        break;
3806
0
    case Format_BGR30:
3807
0
    case Format_A2BGR30_Premultiplied:
3808
0
    case Format_RGB30:
3809
0
    case Format_A2RGB30_Premultiplied:
3810
0
        for (int i = 0; i < d->height; i++) {
3811
0
            uint *p = (uint*)scanLine(i);
3812
0
            uint *end = p + d->width;
3813
0
            while (p < end) {
3814
0
                *p = qRgbSwapRgb30(*p);
3815
0
                p++;
3816
0
            }
3817
0
        }
3818
0
        break;
3819
0
    default:
3820
0
        rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
3821
0
        break;
3822
0
    }
3823
0
}
3824
3825
/*!
3826
    Loads an image from the file with the given \a fileName. Returns \c true if
3827
    the image was successfully loaded; otherwise invalidates the image
3828
    and returns \c false.
3829
3830
    The loader attempts to read the image using the specified \a format, e.g.,
3831
    PNG or JPG. If \a format is not specified (which is the default), it is
3832
    auto-detected based on the file's suffix and header. For details, see
3833
    QImageReader::setAutoDetectImageFormat().
3834
3835
    The file name can either refer to an actual file on disk or to one
3836
    of the application's embedded resources. See the
3837
    \l{resources.html}{Resource System} overview for details on how to
3838
    embed images and other resource files in the application's
3839
    executable.
3840
3841
    \sa {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
3842
*/
3843
3844
bool QImage::load(const QString &fileName, const char* format)
3845
0
{
3846
0
    *this = QImageReader(fileName, format).read();
3847
0
    return !isNull();
3848
0
}
3849
3850
/*!
3851
    \overload
3852
3853
    This function reads a QImage from the given \a device. This can,
3854
    for example, be used to load an image directly into a QByteArray.
3855
*/
3856
3857
bool QImage::load(QIODevice* device, const char* format)
3858
0
{
3859
0
    *this = QImageReader(device, format).read();
3860
0
    return !isNull();
3861
0
}
3862
3863
/*!
3864
    \since 6.2
3865
3866
    Loads an image from the given QByteArrayView \a data. Returns \c true if the image was
3867
    successfully loaded; otherwise invalidates the image and returns \c false.
3868
3869
    The loader attempts to read the image using the specified \a format, e.g.,
3870
    PNG or JPG. If \a format is not specified (which is the default), the
3871
    loader probes the file for a header to guess the file format.
3872
3873
    \sa {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
3874
*/
3875
3876
bool QImage::loadFromData(QByteArrayView data, const char *format)
3877
0
{
3878
0
    *this = fromData(data, format);
3879
0
    return !isNull();
3880
0
}
3881
3882
/*!
3883
    \fn bool QImage::loadFromData(const uchar *data, int len, const char *format)
3884
3885
    \overload
3886
3887
    Loads an image from the first \a len bytes of the given binary \a data.
3888
*/
3889
3890
bool QImage::loadFromData(const uchar *buf, int len, const char *format)
3891
0
{
3892
0
    return loadFromData(QByteArrayView(buf, len), format);
3893
0
}
3894
3895
/*!
3896
    \fn bool QImage::loadFromData(const QByteArray &data, const char *format)
3897
3898
    \overload
3899
3900
    Loads an image from the given QByteArray \a data.
3901
*/
3902
3903
/*!
3904
    \since 6.2
3905
3906
    Constructs an image from the given QByteArrayView \a data. The loader attempts to read the image
3907
    using the specified \a format. If \a format is not specified (which is the default), the loader
3908
    probes the data for a header to guess the file format.
3909
3910
    If \a format is specified, it must be one of the values returned by
3911
    QImageReader::supportedImageFormats().
3912
3913
    If the loading of the image fails, the image returned will be a null image.
3914
3915
    \sa load(), save(), {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
3916
 */
3917
3918
QImage QImage::fromData(QByteArrayView data, const char *format)
3919
0
{
3920
0
    QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
3921
0
    QBuffer b;
3922
0
    b.setData(a);
3923
0
    b.open(QIODevice::ReadOnly);
3924
0
    return QImageReader(&b, format).read();
3925
0
}
3926
3927
/*!
3928
    \fn QImage QImage::fromData(const uchar *data, int size, const char *format)
3929
3930
    \overload
3931
3932
    Constructs a QImage from the first \a size bytes of the given binary \a data.
3933
*/
3934
3935
QImage QImage::fromData(const uchar *data, int size, const char *format)
3936
0
{
3937
0
    return fromData(QByteArrayView(data, size), format);
3938
0
}
3939
3940
/*!
3941
    \fn QImage QImage::fromData(const QByteArray &data, const char *format)
3942
3943
    \overload
3944
3945
    Constructs a QImage from the given QByteArray \a data.
3946
3947
*/
3948
3949
/*!
3950
    Saves the image to the file with the given \a fileName, using the
3951
    given image file \a format and \a quality factor. If \a format is
3952
    \nullptr, QImage will attempt to guess the format by looking at
3953
    \a fileName's suffix.
3954
3955
    The \a quality factor must be in the range 0 to 100 or -1. Specify
3956
    0 to obtain small compressed files, 100 for large uncompressed
3957
    files, and -1 (the default) to use the default settings.
3958
3959
    Returns \c true if the image was successfully saved; otherwise
3960
    returns \c false.
3961
3962
    \sa {QImage#Reading and Writing Image Files}{Reading and Writing
3963
    Image Files}
3964
*/
3965
bool QImage::save(const QString &fileName, const char *format, int quality) const
3966
0
{
3967
0
    if (isNull())
3968
0
        return false;
3969
0
    QImageWriter writer(fileName, format);
3970
0
    return d->doImageIO(this, &writer, quality);
3971
0
}
3972
3973
/*!
3974
    \overload
3975
3976
    This function writes a QImage to the given \a device.
3977
3978
    This can, for example, be used to save an image directly into a
3979
    QByteArray:
3980
3981
    \snippet image/image.cpp 0
3982
*/
3983
3984
bool QImage::save(QIODevice* device, const char* format, int quality) const
3985
0
{
3986
0
    if (isNull())
3987
0
        return false;                                // nothing to save
3988
0
    QImageWriter writer(device, format);
3989
0
    return d->doImageIO(this, &writer, quality);
3990
0
}
3991
3992
/* \internal
3993
*/
3994
3995
bool QImageData::doImageIO(const QImage *image, QImageWriter *writer, int quality) const
3996
0
{
3997
0
    if (quality > 100  || quality < -1)
3998
0
        qWarning("QImage::save: Quality out of range [-1, 100]");
3999
0
    if (quality >= 0)
4000
0
        writer->setQuality(qMin(quality,100));
4001
0
    const bool result = writer->write(*image);
4002
0
#ifdef QT_DEBUG
4003
0
    if (!result)
4004
0
        qWarning("QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
4005
0
#endif
4006
0
    return result;
4007
0
}
4008
4009
bool QImageData::isWithinIOAllocationLimit(int width, int height, QImage::Format format,
4010
                                           const char *context)
4011
0
{
4012
0
    if (const int mbLimit = QImageReader::allocationLimit()) {
4013
0
        qsizetype depth = qMax(qt_depthForFormat(format), 32); // Effective gui depth = 32
4014
0
        QImageData::ImageSizeParameters szp =
4015
0
                QImageData::calculateImageParameters(width, height, depth);
4016
0
        if (!szp.isValid())
4017
0
            return false;
4018
0
        const qsizetype mb = szp.totalSize >> 20;
4019
0
        if (mb > mbLimit || (mb == mbLimit && szp.totalSize % (1 << 20))) {
4020
0
            if (context) {
4021
0
                qCWarning(lcImageIo, "%s: Rejecting image as it exceeds the current "
4022
0
                                     "allocation limit of %i megabytes", context, mbLimit);
4023
0
            }
4024
0
            return false;
4025
0
        }
4026
0
    }
4027
0
    return true;
4028
0
}
4029
4030
/*****************************************************************************
4031
  QImage stream functions
4032
 *****************************************************************************/
4033
#if !defined(QT_NO_DATASTREAM)
4034
/*!
4035
    \fn QDataStream &operator<<(QDataStream &stream, const QImage &image)
4036
    \relates QImage
4037
4038
    Writes the given \a image to the given \a stream as a PNG image,
4039
    or as a BMP image if the stream's version is 1. Note that writing
4040
    the stream to a file will not produce a valid image file.
4041
4042
    \sa QImage::save(), {Serializing Qt Data Types}
4043
*/
4044
4045
QDataStream &operator<<(QDataStream &s, const QImage &image)
4046
0
{
4047
0
    if (s.version() >= 5) {
4048
0
        if (image.isNull()) {
4049
0
            s << (qint32) 0; // null image marker
4050
0
            return s;
4051
0
        } else {
4052
0
            s << (qint32) 1;
4053
            // continue ...
4054
0
        }
4055
0
    }
4056
0
    QImageWriter writer(s.device(), s.version() == 1 ? "bmp" : "png");
4057
0
    writer.write(image);
4058
0
    return s;
4059
0
}
4060
4061
/*!
4062
    \fn QDataStream &operator>>(QDataStream &stream, QImage &image)
4063
    \relates QImage
4064
4065
    Reads an image from the given \a stream and stores it in the given
4066
    \a image.
4067
4068
    \sa QImage::load(), {Serializing Qt Data Types}
4069
*/
4070
4071
QDataStream &operator>>(QDataStream &s, QImage &image)
4072
0
{
4073
0
    if (s.version() >= 5) {
4074
0
        qint32 nullMarker;
4075
0
        s >> nullMarker;
4076
0
        if (!nullMarker) {
4077
0
            image = QImage(); // null image
4078
0
            return s;
4079
0
        }
4080
0
    }
4081
0
    image = QImageReader(s.device(), s.version() == 1 ? "bmp" : "png").read();
4082
0
    if (image.isNull() && s.version() >= 5)
4083
0
        s.setStatus(QDataStream::ReadPastEnd);
4084
0
    return s;
4085
0
}
4086
#endif // QT_NO_DATASTREAM
4087
4088
4089
4090
/*!
4091
    \fn bool QImage::operator==(const QImage & image) const
4092
4093
    Returns \c true if this image and the given \a image have the same
4094
    contents; otherwise returns \c false.
4095
4096
    The comparison can be slow, unless there is some obvious
4097
    difference (e.g. different size or format), in which case the
4098
    function will return quickly.
4099
4100
    \sa operator=()
4101
*/
4102
4103
bool QImage::operator==(const QImage & i) const
4104
0
{
4105
    // same object, or shared?
4106
0
    if (i.d == d)
4107
0
        return true;
4108
0
    if (!i.d || !d)
4109
0
        return false;
4110
4111
    // obviously different stuff?
4112
0
    if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
4113
0
        return false;
4114
4115
0
    if (d->format != Format_RGB32) {
4116
0
        if (d->format >= Format_ARGB32) { // all bits defined
4117
0
            const int n = d->width * d->depth / 8;
4118
0
            if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
4119
0
                if (memcmp(bits(), i.bits(), d->nbytes))
4120
0
                    return false;
4121
0
            } else {
4122
0
                for (int y = 0; y < d->height; ++y) {
4123
0
                    if (memcmp(scanLine(y), i.scanLine(y), n))
4124
0
                        return false;
4125
0
                }
4126
0
            }
4127
0
        } else {
4128
0
            const int w = width();
4129
0
            const int h = height();
4130
0
            const QList<QRgb> &colortable = d->colortable;
4131
0
            const QList<QRgb> &icolortable = i.d->colortable;
4132
0
            for (int y=0; y<h; ++y) {
4133
0
                for (int x=0; x<w; ++x) {
4134
0
                    if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
4135
0
                        return false;
4136
0
                }
4137
0
            }
4138
0
        }
4139
0
    } else {
4140
        //alpha channel undefined, so we must mask it out
4141
0
        for(int l = 0; l < d->height; l++) {
4142
0
            int w = d->width;
4143
0
            const uint *p1 = reinterpret_cast<const uint*>(scanLine(l));
4144
0
            const uint *p2 = reinterpret_cast<const uint*>(i.scanLine(l));
4145
0
            while (w--) {
4146
0
                if ((*p1++ & 0x00ffffff) != (*p2++ & 0x00ffffff))
4147
0
                    return false;
4148
0
            }
4149
0
        }
4150
0
    }
4151
0
    return true;
4152
0
}
4153
4154
4155
/*!
4156
    \fn bool QImage::operator!=(const QImage & image) const
4157
4158
    Returns \c true if this image and the given \a image have different
4159
    contents; otherwise returns \c false.
4160
4161
    The comparison can be slow, unless there is some obvious
4162
    difference, such as different widths, in which case the function
4163
    will return quickly.
4164
4165
    \sa operator=()
4166
*/
4167
4168
bool QImage::operator!=(const QImage & i) const
4169
0
{
4170
0
    return !(*this == i);
4171
0
}
4172
4173
4174
4175
4176
/*!
4177
    Returns the number of pixels that fit horizontally in a physical
4178
    meter. Together with dotsPerMeterY(), this number defines the
4179
    intended scale and aspect ratio of the image.
4180
4181
    \sa setDotsPerMeterX(), {QImage#Image Information}{Image
4182
    Information}
4183
*/
4184
int QImage::dotsPerMeterX() const
4185
0
{
4186
0
    return d ? qRound(d->dpmx) : 0;
4187
0
}
4188
4189
/*!
4190
    Returns the number of pixels that fit vertically in a physical
4191
    meter. Together with dotsPerMeterX(), this number defines the
4192
    intended scale and aspect ratio of the image.
4193
4194
    \sa setDotsPerMeterY(), {QImage#Image Information}{Image
4195
    Information}
4196
*/
4197
int QImage::dotsPerMeterY() const
4198
0
{
4199
0
    return d ? qRound(d->dpmy) : 0;
4200
0
}
4201
4202
/*!
4203
    Sets the number of pixels that fit horizontally in a physical
4204
    meter, to \a x.
4205
4206
    Together with dotsPerMeterY(), this number defines the intended
4207
    scale and aspect ratio of the image, and determines the scale
4208
    at which QPainter will draw graphics on the image. It does not
4209
    change the scale or aspect ratio of the image when it is rendered
4210
    on other paint devices.
4211
4212
    \sa dotsPerMeterX(), {QImage#Image Information}{Image Information}
4213
*/
4214
void QImage::setDotsPerMeterX(int x)
4215
0
{
4216
0
    if (!d || !x || d->dpmx == x)
4217
0
        return;
4218
0
    detachMetadata();
4219
4220
0
    if (d)
4221
0
        d->dpmx = x;
4222
0
}
4223
4224
/*!
4225
    Sets the number of pixels that fit vertically in a physical meter,
4226
    to \a y.
4227
4228
    Together with dotsPerMeterX(), this number defines the intended
4229
    scale and aspect ratio of the image, and determines the scale
4230
    at which QPainter will draw graphics on the image. It does not
4231
    change the scale or aspect ratio of the image when it is rendered
4232
    on other paint devices.
4233
4234
    \sa dotsPerMeterY(), {QImage#Image Information}{Image Information}
4235
*/
4236
void QImage::setDotsPerMeterY(int y)
4237
0
{
4238
0
    if (!d || !y || d->dpmy == y)
4239
0
        return;
4240
0
    detachMetadata();
4241
4242
0
    if (d)
4243
0
        d->dpmy = y;
4244
0
}
4245
4246
/*!
4247
    \fn QPoint QImage::offset() const
4248
4249
    Returns the number of pixels by which the image is intended to be
4250
    offset by when positioning relative to other images.
4251
4252
    \sa setOffset(), {QImage#Image Information}{Image Information}
4253
*/
4254
QPoint QImage::offset() const
4255
0
{
4256
0
    return d ? d->offset : QPoint();
4257
0
}
4258
4259
4260
/*!
4261
    \fn void QImage::setOffset(const QPoint& offset)
4262
4263
    Sets the number of pixels by which the image is intended to be
4264
    offset by when positioning relative to other images, to \a offset.
4265
4266
    \sa offset(), {QImage#Image Information}{Image Information}
4267
*/
4268
void QImage::setOffset(const QPoint& p)
4269
0
{
4270
0
    if (!d || d->offset == p)
4271
0
        return;
4272
0
    detachMetadata();
4273
4274
0
    if (d)
4275
0
        d->offset = p;
4276
0
}
4277
4278
/*!
4279
    Returns the text keys for this image.
4280
4281
    You can use these keys with text() to list the image text for a
4282
    certain key.
4283
4284
    \sa text()
4285
*/
4286
QStringList QImage::textKeys() const
4287
0
{
4288
0
    return d ? QStringList(d->text.keys()) : QStringList();
4289
0
}
4290
4291
/*!
4292
    Returns the image text associated with the given \a key. If the
4293
    specified \a key is an empty string, the whole image text is
4294
    returned, with each key-text pair separated by a newline.
4295
4296
    \sa setText(), textKeys()
4297
*/
4298
QString QImage::text(const QString &key) const
4299
0
{
4300
0
    if (!d)
4301
0
        return QString();
4302
4303
0
    if (!key.isEmpty())
4304
0
        return d->text.value(key);
4305
4306
0
    QString tmp;
4307
0
    for (auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
4308
0
        tmp += it.key() + ": "_L1 + it.value().simplified() + "\n\n"_L1;
4309
0
    if (!tmp.isEmpty())
4310
0
        tmp.chop(2); // remove final \n\n
4311
0
    return tmp;
4312
0
}
4313
4314
/*!
4315
    \fn void QImage::setText(const QString &key, const QString &text)
4316
4317
    Sets the image text to the given \a text and associate it with the
4318
    given \a key.
4319
4320
    If you just want to store a single text block (i.e., a "comment"
4321
    or just a description), you can either pass an empty key, or use a
4322
    generic key like "Description".
4323
4324
    The image text is embedded into the image data when you
4325
    call save() or QImageWriter::write().
4326
4327
    Not all image formats support embedded text. You can find out
4328
    if a specific image or format supports embedding text
4329
    by using QImageWriter::supportsOption(). We give an example:
4330
4331
    \snippet image/supportedformat.cpp 0
4332
4333
    You can use QImageWriter::supportedImageFormats() to find out
4334
    which image formats are available to you.
4335
4336
    \sa text(), textKeys()
4337
*/
4338
void QImage::setText(const QString &key, const QString &value)
4339
0
{
4340
0
    if (!d)
4341
0
        return;
4342
0
    detachMetadata();
4343
4344
0
    if (d)
4345
0
        d->text.insert(key, value);
4346
0
}
4347
4348
/*!
4349
    \internal
4350
4351
    Used by QPainter to retrieve a paint engine for the image.
4352
*/
4353
QPaintEngine *QImage::paintEngine() const
4354
0
{
4355
0
    if (!d)
4356
0
        return nullptr;
4357
4358
0
    if (!d->paintEngine) {
4359
0
        QPaintDevice *paintDevice = const_cast<QImage *>(this);
4360
0
        QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
4361
0
        if (platformIntegration)
4362
0
            d->paintEngine = platformIntegration->createImagePaintEngine(paintDevice);
4363
0
       if (!d->paintEngine)
4364
0
            d->paintEngine = new QRasterPaintEngine(paintDevice);
4365
0
    }
4366
4367
0
    return d->paintEngine;
4368
0
}
4369
4370
4371
/*!
4372
    \internal
4373
4374
    Returns the size for the specified \a metric on the device.
4375
*/
4376
int QImage::metric(PaintDeviceMetric metric) const
4377
0
{
4378
0
    if (!d)
4379
0
        return 0;
4380
4381
0
    switch (metric) {
4382
0
    case PdmWidth:
4383
0
        return d->width;
4384
4385
0
    case PdmHeight:
4386
0
        return d->height;
4387
4388
0
    case PdmWidthMM:
4389
0
        return qRound(d->width * 1000 / d->dpmx);
4390
4391
0
    case PdmHeightMM:
4392
0
        return qRound(d->height * 1000 / d->dpmy);
4393
4394
0
    case PdmNumColors:
4395
0
        return d->colortable.size();
4396
4397
0
    case PdmDepth:
4398
0
        return d->depth;
4399
4400
0
    case PdmDpiX:
4401
0
        return qRound(d->dpmx * 0.0254);
4402
0
        break;
4403
4404
0
    case PdmDpiY:
4405
0
        return qRound(d->dpmy * 0.0254);
4406
0
        break;
4407
4408
0
    case PdmPhysicalDpiX:
4409
0
        return qRound(d->dpmx * 0.0254);
4410
0
        break;
4411
4412
0
    case PdmPhysicalDpiY:
4413
0
        return qRound(d->dpmy * 0.0254);
4414
0
        break;
4415
4416
0
    case PdmDevicePixelRatio:
4417
0
        return d->devicePixelRatio;
4418
0
        break;
4419
4420
0
    case PdmDevicePixelRatioScaled:
4421
0
        return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
4422
0
        break;
4423
4424
0
    case PdmDevicePixelRatioF_EncodedA:
4425
0
        Q_FALLTHROUGH();
4426
0
    case PdmDevicePixelRatioF_EncodedB:
4427
0
        return QPaintDevice::encodeMetricF(metric, d->devicePixelRatio);
4428
0
        break;
4429
4430
0
    default:
4431
0
        qWarning("QImage::metric(): Unhandled metric type %d", metric);
4432
0
        break;
4433
0
    }
4434
0
    return 0;
4435
0
}
4436
4437
4438
4439
/*****************************************************************************
4440
  QPixmap (and QImage) helper functions
4441
 *****************************************************************************/
4442
/*
4443
  This internal function contains the common (i.e. platform independent) code
4444
  to do a transformation of pixel data. It is used by QPixmap::transform() and by
4445
  QImage::transform().
4446
4447
  \a trueMat is the true transformation matrix (see QPixmap::trueMatrix()) and
4448
  \a xoffset is an offset to the matrix.
4449
4450
  \a msbfirst specifies for 1bpp images, if the MSB or LSB comes first and \a
4451
  depth specifies the colordepth of the data.
4452
4453
  \a dptr is a pointer to the destination data, \a dbpl specifies the bits per
4454
  line for the destination data, \a p_inc is the offset that we advance for
4455
  every scanline and \a dHeight is the height of the destination image.
4456
4457
  \a sprt is the pointer to the source data, \a sbpl specifies the bits per
4458
  line of the source data, \a sWidth and \a sHeight are the width and height of
4459
  the source data.
4460
*/
4461
4462
#undef IWX_MSB
4463
0
#define IWX_MSB(b)        if (trigx < maxws && trigy < maxhs) {                              \
4464
0
                            if (*(sptr+sbpl*(trigy>>12)+(trigx>>15)) &                      \
4465
0
                                 (1 << (7-((trigx>>12)&7))))                              \
4466
0
                                *dptr |= b;                                              \
4467
0
                        }                                                              \
4468
0
                        trigx += m11;                                                      \
4469
0
                        trigy += m12;
4470
        // END OF MACRO
4471
#undef IWX_LSB
4472
0
#define IWX_LSB(b)        if (trigx < maxws && trigy < maxhs) {                              \
4473
0
                            if (*(sptr+sbpl*(trigy>>12)+(trigx>>15)) &                      \
4474
0
                                 (1 << ((trigx>>12)&7)))                              \
4475
0
                                *dptr |= b;                                              \
4476
0
                        }                                                              \
4477
0
                        trigx += m11;                                                      \
4478
0
                        trigy += m12;
4479
        // END OF MACRO
4480
#undef IWX_PIX
4481
#define IWX_PIX(b)        if (trigx < maxws && trigy < maxhs) {                              \
4482
                            if ((*(sptr+sbpl*(trigy>>12)+(trigx>>15)) &              \
4483
                                 (1 << (7-((trigx>>12)&7)))) == 0)                      \
4484
                                *dptr &= ~b;                                              \
4485
                        }                                                              \
4486
                        trigx += m11;                                                      \
4487
                        trigy += m12;
4488
        // END OF MACRO
4489
4490
bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth,
4491
                     uchar *dptr, qsizetype dbpl, int p_inc, int dHeight,
4492
                     const uchar *sptr, qsizetype sbpl, int sWidth, int sHeight)
4493
0
{
4494
0
    int m11 = int(trueMat.m11()*4096.0);
4495
0
    int m12 = int(trueMat.m12()*4096.0);
4496
0
    int m21 = int(trueMat.m21()*4096.0);
4497
0
    int m22 = int(trueMat.m22()*4096.0);
4498
0
    int dx  = qRound(trueMat.dx()*4096.0);
4499
0
    int dy  = qRound(trueMat.dy()*4096.0);
4500
4501
0
    int m21ydx = dx + (xoffset<<16) + (m11 + m21) / 2;
4502
0
    int m22ydy = dy + (m12 + m22) / 2;
4503
0
    uint trigx;
4504
0
    uint trigy;
4505
0
    uint maxws = sWidth<<12;
4506
0
    uint maxhs = sHeight<<12;
4507
4508
0
    for (int y=0; y<dHeight; y++) {                // for each target scanline
4509
0
        trigx = m21ydx;
4510
0
        trigy = m22ydy;
4511
0
        uchar *maxp = dptr + dbpl;
4512
0
        if (depth != 1) {
4513
0
            switch (depth) {
4514
0
                case 8:                                // 8 bpp transform
4515
0
                while (dptr < maxp) {
4516
0
                    if (trigx < maxws && trigy < maxhs)
4517
0
                        *dptr = *(sptr+sbpl*(trigy>>12)+(trigx>>12));
4518
0
                    trigx += m11;
4519
0
                    trigy += m12;
4520
0
                    dptr++;
4521
0
                }
4522
0
                break;
4523
4524
0
                case 16:                        // 16 bpp transform
4525
0
                while (dptr < maxp) {
4526
0
                    if (trigx < maxws && trigy < maxhs)
4527
0
                        *((ushort*)dptr) = *((const ushort *)(sptr+sbpl*(trigy>>12) +
4528
0
                                                     ((trigx>>12)<<1)));
4529
0
                    trigx += m11;
4530
0
                    trigy += m12;
4531
0
                    dptr++;
4532
0
                    dptr++;
4533
0
                }
4534
0
                break;
4535
4536
0
                case 24:                        // 24 bpp transform
4537
0
                while (dptr < maxp) {
4538
0
                    if (trigx < maxws && trigy < maxhs) {
4539
0
                        const uchar *p2 = sptr+sbpl*(trigy>>12) + ((trigx>>12)*3);
4540
0
                        dptr[0] = p2[0];
4541
0
                        dptr[1] = p2[1];
4542
0
                        dptr[2] = p2[2];
4543
0
                    }
4544
0
                    trigx += m11;
4545
0
                    trigy += m12;
4546
0
                    dptr += 3;
4547
0
                }
4548
0
                break;
4549
4550
0
                case 32:                        // 32 bpp transform
4551
0
                while (dptr < maxp) {
4552
0
                    if (trigx < maxws && trigy < maxhs)
4553
0
                        *((uint*)dptr) = *((const uint *)(sptr+sbpl*(trigy>>12) +
4554
0
                                                   ((trigx>>12)<<2)));
4555
0
                    trigx += m11;
4556
0
                    trigy += m12;
4557
0
                    dptr += 4;
4558
0
                }
4559
0
                break;
4560
4561
0
                default: {
4562
0
                return false;
4563
0
                }
4564
0
            }
4565
0
        } else  {
4566
0
            switch (type) {
4567
0
                case QT_XFORM_TYPE_MSBFIRST:
4568
0
                    while (dptr < maxp) {
4569
0
                        IWX_MSB(128);
4570
0
                        IWX_MSB(64);
4571
0
                        IWX_MSB(32);
4572
0
                        IWX_MSB(16);
4573
0
                        IWX_MSB(8);
4574
0
                        IWX_MSB(4);
4575
0
                        IWX_MSB(2);
4576
0
                        IWX_MSB(1);
4577
0
                        dptr++;
4578
0
                    }
4579
0
                    break;
4580
0
                case QT_XFORM_TYPE_LSBFIRST:
4581
0
                    while (dptr < maxp) {
4582
0
                        IWX_LSB(1);
4583
0
                        IWX_LSB(2);
4584
0
                        IWX_LSB(4);
4585
0
                        IWX_LSB(8);
4586
0
                        IWX_LSB(16);
4587
0
                        IWX_LSB(32);
4588
0
                        IWX_LSB(64);
4589
0
                        IWX_LSB(128);
4590
0
                        dptr++;
4591
0
                    }
4592
0
                    break;
4593
0
            }
4594
0
        }
4595
0
        m21ydx += m21;
4596
0
        m22ydy += m22;
4597
0
        dptr += p_inc;
4598
0
    }
4599
0
    return true;
4600
0
}
4601
#undef IWX_MSB
4602
#undef IWX_LSB
4603
#undef IWX_PIX
4604
4605
/*!
4606
    Returns a number that identifies the contents of this QImage
4607
    object. Distinct QImage objects can only have the same key if they
4608
    refer to the same contents.
4609
4610
    The key will change when the image is altered.
4611
*/
4612
qint64 QImage::cacheKey() const
4613
0
{
4614
0
    if (!d)
4615
0
        return 0;
4616
0
    else
4617
0
        return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
4618
0
}
4619
4620
/*!
4621
    \internal
4622
4623
    Returns \c true if the image is detached; otherwise returns \c false.
4624
4625
    \sa detach(), {Implicit Data Sharing}
4626
*/
4627
4628
bool QImage::isDetached() const
4629
0
{
4630
0
    return d && d->ref.loadRelaxed() == 1;
4631
0
}
4632
4633
4634
/*!
4635
    Sets the alpha channel of this image to the given \a alphaChannel.
4636
4637
    If \a alphaChannel is an 8 bit alpha image, the alpha values are
4638
    used directly. Otherwise, \a alphaChannel is converted to 8 bit
4639
    grayscale and the intensity of the pixel values is used.
4640
4641
    If the image already has an alpha channel, the existing alpha channel
4642
    is multiplied with the new one. If the image doesn't have an alpha
4643
    channel it will be converted to a format that does.
4644
4645
    The operation is similar to painting \a alphaChannel as an alpha image
4646
    over this image using \c QPainter::CompositionMode_DestinationIn.
4647
4648
    \sa hasAlphaChannel(),
4649
        {QImage#Image Transformations}{Image Transformations},
4650
        {QImage#Image Formats}{Image Formats}
4651
*/
4652
4653
void QImage::setAlphaChannel(const QImage &alphaChannel)
4654
0
{
4655
0
    if (!d || alphaChannel.isNull())
4656
0
        return;
4657
4658
0
    if (d->paintEngine && d->paintEngine->isActive()) {
4659
0
        qWarning("QImage::setAlphaChannel: "
4660
0
                 "Unable to set alpha channel while image is being painted on");
4661
0
        return;
4662
0
    }
4663
4664
0
    const Format alphaFormat = qt_alphaVersionForPainting(d->format);
4665
0
    if (d->format == alphaFormat)
4666
0
        detach();
4667
0
    else
4668
0
        convertTo(alphaFormat);
4669
4670
0
    if (isNull())
4671
0
        return;
4672
4673
0
    QImage sourceImage;
4674
0
    if (alphaChannel.format() == QImage::Format_Alpha8 || (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()))
4675
0
        sourceImage = alphaChannel;
4676
0
    else
4677
0
        sourceImage = alphaChannel.convertToFormat(QImage::Format_Grayscale8);
4678
0
    if (!sourceImage.reinterpretAsFormat(QImage::Format_Alpha8))
4679
0
        return;
4680
4681
0
    QPainter painter(this);
4682
0
    if (sourceImage.size() != size())
4683
0
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
4684
0
    painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
4685
0
    painter.drawImage(rect(), sourceImage);
4686
0
}
4687
4688
/*!
4689
    Returns \c true if the image has a format that respects the alpha
4690
    channel, otherwise returns \c false.
4691
4692
    \sa {QImage#Image Information}{Image Information}
4693
*/
4694
bool QImage::hasAlphaChannel() const
4695
0
{
4696
0
    if (!d)
4697
0
        return false;
4698
0
    const QPixelFormat format = pixelFormat();
4699
0
    if (format.alphaUsage() == QPixelFormat::UsesAlpha)
4700
0
        return true;
4701
0
    if (format.colorModel() == QPixelFormat::Indexed)
4702
0
        return d->has_alpha_clut;
4703
0
    return false;
4704
0
}
4705
4706
/*!
4707
    Returns the number of bit planes in the image.
4708
4709
    The number of bit planes is the number of bits of color and
4710
    transparency information for each pixel. This is different from
4711
    (i.e. smaller than) the depth when the image format contains
4712
    unused bits.
4713
4714
    \sa depth(), format(), {QImage#Image Formats}{Image Formats}
4715
*/
4716
int QImage::bitPlaneCount() const
4717
0
{
4718
0
    if (!d)
4719
0
        return 0;
4720
0
    int bpc = 0;
4721
0
    switch (d->format) {
4722
0
    case QImage::Format_Invalid:
4723
0
        break;
4724
0
    case QImage::Format_BGR30:
4725
0
    case QImage::Format_RGB30:
4726
0
        bpc = 30;
4727
0
        break;
4728
0
    case QImage::Format_RGB32:
4729
0
    case QImage::Format_RGBX8888:
4730
0
        bpc = 24;
4731
0
        break;
4732
0
    case QImage::Format_RGB666:
4733
0
        bpc = 18;
4734
0
        break;
4735
0
    case QImage::Format_RGB555:
4736
0
        bpc = 15;
4737
0
        break;
4738
0
    case QImage::Format_ARGB8555_Premultiplied:
4739
0
        bpc = 23;
4740
0
        break;
4741
0
    case QImage::Format_RGB444:
4742
0
        bpc = 12;
4743
0
        break;
4744
0
    case QImage::Format_RGBX64:
4745
0
    case QImage::Format_RGBX16FPx4:
4746
0
        bpc = 48;
4747
0
        break;
4748
0
    case QImage::Format_RGBX32FPx4:
4749
0
        bpc = 96;
4750
0
        break;
4751
0
    default:
4752
0
        bpc = qt_depthForFormat(d->format);
4753
0
        break;
4754
0
    }
4755
0
    return bpc;
4756
0
}
4757
4758
/*!
4759
   \internal
4760
   Returns a smoothly scaled copy of the image. The returned image has a size
4761
   of width \a w by height \a h pixels.
4762
4763
   The function operates internally on \c Format_RGB32, \c Format_ARGB32_Premultiplied,
4764
   \c Format_RGBX8888, \c Format_RGBA8888_Premultiplied, \c Format_RGBX64,
4765
   or \c Format_RGBA64_Premultiplied and will convert to those formats
4766
   if necessary. To avoid unnecessary conversion the result is returned in the format
4767
   internally used, and not in the original format.
4768
*/
4769
QImage QImage::smoothScaled(int w, int h) const
4770
0
{
4771
0
    QImage src = *this;
4772
0
    switch (src.format()) {
4773
0
    case QImage::Format_RGB32:
4774
0
    case QImage::Format_ARGB32_Premultiplied:
4775
0
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4776
0
    case QImage::Format_RGBX8888:
4777
0
#endif
4778
0
    case QImage::Format_RGBA8888_Premultiplied:
4779
0
#if QT_CONFIG(raster_64bit)
4780
0
    case QImage::Format_RGBX64:
4781
0
    case QImage::Format_RGBA64_Premultiplied:
4782
0
        break;
4783
0
    case QImage::Format_RGBA64:
4784
0
    case QImage::Format_Grayscale16:
4785
0
        src.convertTo(QImage::Format_RGBA64_Premultiplied);
4786
0
        break;
4787
0
#endif
4788
0
#if QT_CONFIG(raster_fp)
4789
0
    case QImage::Format_RGBX32FPx4:
4790
0
    case QImage::Format_RGBA32FPx4_Premultiplied:
4791
0
        break;
4792
0
    case QImage::Format_RGBX16FPx4:
4793
0
        src.convertTo(QImage::Format_RGBX32FPx4);
4794
0
        break;
4795
0
    case QImage::Format_RGBA16FPx4:
4796
0
    case QImage::Format_RGBA16FPx4_Premultiplied:
4797
0
    case QImage::Format_RGBA32FPx4:
4798
0
        src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
4799
0
        break;
4800
0
#endif
4801
0
    case QImage::Format_CMYK8888:
4802
0
        break;
4803
0
    default:
4804
0
        if (src.hasAlphaChannel())
4805
0
            src.convertTo(QImage::Format_ARGB32_Premultiplied);
4806
0
        else
4807
0
            src.convertTo(QImage::Format_RGB32);
4808
0
    }
4809
0
    src = qSmoothScaleImage(src, w, h);
4810
0
    if (!src.isNull())
4811
0
        copyMetadata(src.d, d);
4812
0
    return src;
4813
0
}
4814
4815
static QImage rotated90(const QImage &image)
4816
0
{
4817
0
    QImage out(image.height(), image.width(), image.format());
4818
0
    if (out.isNull())
4819
0
        return out;
4820
0
    copyMetadata(QImageData::get(out), QImageData::get(image));
4821
0
    if (image.colorCount() > 0)
4822
0
        out.setColorTable(image.colorTable());
4823
0
    int w = image.width();
4824
0
    int h = image.height();
4825
0
    const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][2];
4826
0
    if (memrotate) {
4827
0
        memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4828
0
    } else {
4829
0
        for (int y=0; y<h; ++y) {
4830
0
            if (image.colorCount())
4831
0
                for (int x=0; x<w; ++x)
4832
0
                    out.setPixel(h-y-1, x, image.pixelIndex(x, y));
4833
0
            else
4834
0
                for (int x=0; x<w; ++x)
4835
0
                    out.setPixel(h-y-1, x, image.pixel(x, y));
4836
0
        }
4837
0
    }
4838
0
    return out;
4839
0
}
4840
4841
static QImage rotated180(const QImage &image)
4842
0
{
4843
0
    const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][1];
4844
0
    if (!memrotate)
4845
0
        return image.flipped(Qt::Horizontal | Qt::Vertical);
4846
4847
0
    QImage out(image.width(), image.height(), image.format());
4848
0
    if (out.isNull())
4849
0
        return out;
4850
0
    copyMetadata(QImageData::get(out), QImageData::get(image));
4851
0
    if (image.colorCount() > 0)
4852
0
        out.setColorTable(image.colorTable());
4853
0
    int w = image.width();
4854
0
    int h = image.height();
4855
0
    memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4856
0
    return out;
4857
0
}
4858
4859
static QImage rotated270(const QImage &image)
4860
0
{
4861
0
    QImage out(image.height(), image.width(), image.format());
4862
0
    if (out.isNull())
4863
0
        return out;
4864
0
    copyMetadata(QImageData::get(out), QImageData::get(image));
4865
0
    if (image.colorCount() > 0)
4866
0
        out.setColorTable(image.colorTable());
4867
0
    int w = image.width();
4868
0
    int h = image.height();
4869
0
    const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][0];
4870
0
    if (memrotate) {
4871
0
        memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4872
0
    } else {
4873
0
        for (int y=0; y<h; ++y) {
4874
0
            if (image.colorCount())
4875
0
                for (int x=0; x<w; ++x)
4876
0
                    out.setPixel(y, w-x-1, image.pixelIndex(x, y));
4877
0
            else
4878
0
                for (int x=0; x<w; ++x)
4879
0
                    out.setPixel(y, w-x-1, image.pixel(x, y));
4880
0
        }
4881
0
    }
4882
0
    return out;
4883
0
}
4884
4885
/*!
4886
    Returns a copy of the image that is transformed using the given
4887
    transformation \a matrix and transformation \a mode.
4888
4889
    The returned image will normally have the same {Image Formats}{format} as
4890
    the original image. However, a complex transformation may result in an
4891
    image where not all pixels are covered by the transformed pixels of the
4892
    original image. In such cases, those background pixels will be assigned a
4893
    transparent color value, and the transformed image will be given a format
4894
    with an alpha channel, even if the original image did not have that.
4895
4896
    The transformation \a matrix is internally adjusted to compensate
4897
    for unwanted translation; i.e. the image produced is the smallest
4898
    image that contains all the transformed points of the original
4899
    image. Use the trueMatrix() function to retrieve the actual matrix
4900
    used for transforming an image.
4901
4902
    Unlike the other overload, this function can be used to perform perspective
4903
    transformations on images.
4904
4905
    \sa trueMatrix(), {QImage#Image Transformations}{Image
4906
    Transformations}
4907
*/
4908
4909
QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
4910
0
{
4911
0
    if (!d)
4912
0
        return QImage();
4913
4914
0
    Q_TRACE_PARAM_REPLACE(const QTransform &, double[9]);
4915
0
    Q_TRACE_SCOPE(QImage_transformed, QList<double>({matrix.m11(), matrix.m12(), matrix.m13(),
4916
0
                                                  matrix.m21(), matrix.m22(), matrix.m23(),
4917
0
                                                  matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
4918
4919
    // source image data
4920
0
    const int ws = width();
4921
0
    const int hs = height();
4922
4923
    // target image data
4924
0
    qreal wdf;
4925
0
    qreal hdf;
4926
4927
    // compute size of target image
4928
0
    QTransform mat = trueMatrix(matrix, ws, hs);
4929
0
    bool complex_xform = false;
4930
0
    bool scale_xform = false;
4931
0
    bool nonpaintable_scale_xform = false;
4932
0
    if (mat.type() <= QTransform::TxScale) {
4933
0
        if (mat.type() == QTransform::TxNone) // identity matrix
4934
0
            return *this;
4935
0
        else if (mat.m11() == -1. && mat.m22() == -1.)
4936
0
            return rotated180(*this);
4937
4938
0
        hdf = qAbs(mat.m22()) * hs;
4939
0
        wdf = qAbs(mat.m11()) * ws;
4940
0
        scale_xform = true;
4941
0
    } else {
4942
0
        if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
4943
0
            if (mat.m12() == 1. && mat.m21() == -1.)
4944
0
                return rotated90(*this);
4945
0
            else if (mat.m12() == -1. && mat.m21() == 1.)
4946
0
                return rotated270(*this);
4947
0
        }
4948
4949
0
        QPolygonF a(QRectF(0, 0, ws, hs));
4950
0
        a = mat.map(a);
4951
0
        const QRectF r = a.boundingRect();
4952
0
        wdf = std::ceil(r.right()) - std::floor(r.left());
4953
0
        hdf = std::ceil(r.bottom()) - std::floor(r.top());
4954
0
        complex_xform = true;
4955
0
    }
4956
4957
0
    if (!(wdf < INT_MAX && hdf < INT_MAX)) // also rejects NaN
4958
0
        return QImage();
4959
0
    const int wd = qRound(wdf);
4960
0
    const int hd = qRound(hdf);
4961
4962
0
    if (scale_xform) {
4963
        // The paint-based scaling is only bilinear, and has problems
4964
        // with scaling smoothly more than 2x down.
4965
0
        if (qint64(hd) * 2 < hs || qint64(wd) * 2 < ws)
4966
0
            nonpaintable_scale_xform = true;
4967
        // We cannot paint on a CMYK image, so don't try to do so
4968
0
        if (format() == QImage::Format_CMYK8888)
4969
0
            nonpaintable_scale_xform = true;
4970
0
    }
4971
4972
0
    if (wd == 0 || hd == 0)
4973
0
        return QImage();
4974
4975
0
    if (scale_xform && mode == Qt::SmoothTransformation) {
4976
0
        switch (format()) {
4977
0
        case QImage::Format_RGB32:
4978
0
        case QImage::Format_ARGB32_Premultiplied:
4979
0
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4980
0
        case QImage::Format_RGBX8888:
4981
0
#endif
4982
0
        case QImage::Format_RGBA8888_Premultiplied:
4983
0
#if QT_CONFIG(raster_64bit)
4984
0
        case QImage::Format_RGBX64:
4985
0
        case QImage::Format_RGBA64_Premultiplied:
4986
0
#endif
4987
0
        case QImage::Format_CMYK8888:
4988
            // Use smoothScaled for scaling when we can do so without conversion.
4989
0
            if (mat.m11() > 0.0F && mat.m22() > 0.0F)
4990
0
                return smoothScaled(wd, hd);
4991
0
            break;
4992
0
        default:
4993
0
            break;
4994
0
        }
4995
        // Otherwise only use it when the scaling factor demands it, or the image is large enough to scale multi-threaded
4996
0
        if (nonpaintable_scale_xform
4997
0
#if QT_CONFIG(qtgui_threadpool)
4998
0
            || qint64(ws) * hs >= (1 << 20)
4999
0
#endif
5000
0
            ) {
5001
0
            QImage scaledImage;
5002
0
            if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
5003
0
                scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal | Qt::Vertical);
5004
0
            } else if (mat.m11() < 0.0F) { // horizontal flip
5005
0
                scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal);
5006
0
            } else if (mat.m22() < 0.0F) { // vertical flip
5007
0
                scaledImage = smoothScaled(wd, hd).flipped(Qt::Vertical);
5008
0
            } else { // no flipping
5009
0
                scaledImage = smoothScaled(wd, hd);
5010
0
            }
5011
5012
0
            switch (format()) {
5013
0
            case QImage::Format_Mono:
5014
0
            case QImage::Format_MonoLSB:
5015
0
            case QImage::Format_Indexed8:
5016
0
                return scaledImage;
5017
0
            default:
5018
0
                return scaledImage.convertToFormat(format());
5019
0
            }
5020
0
        }
5021
0
    }
5022
5023
0
    int bpp = depth();
5024
5025
0
    qsizetype sbpl = bytesPerLine();
5026
0
    const uchar *sptr = bits();
5027
5028
0
    QImage::Format target_format = d->format;
5029
5030
0
    if (complex_xform || mode == Qt::SmoothTransformation) {
5031
0
        if (d->format < QImage::Format_RGB32 || (!hasAlphaChannel() && complex_xform)) {
5032
0
            target_format = qt_alphaVersion(d->format);
5033
0
        }
5034
0
    }
5035
5036
0
    QImage dImage(wd, hd, target_format);
5037
0
    QIMAGE_SANITYCHECK_MEMORY(dImage);
5038
5039
0
    if (target_format == QImage::Format_MonoLSB
5040
0
        || target_format == QImage::Format_Mono
5041
0
        || target_format == QImage::Format_Indexed8) {
5042
0
        dImage.d->colortable = d->colortable;
5043
0
        dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
5044
0
    }
5045
5046
    // initizialize the data
5047
0
    if (target_format == QImage::Format_Indexed8) {
5048
0
        if (dImage.d->colortable.size() < 256) {
5049
            // colors are left in the color table, so pick that one as transparent
5050
0
            dImage.d->colortable.append(0x0);
5051
0
            memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
5052
0
        } else {
5053
0
            memset(dImage.bits(), 0, dImage.d->nbytes);
5054
0
        }
5055
0
    } else
5056
0
        memset(dImage.bits(), 0x00, dImage.d->nbytes);
5057
5058
0
    if (target_format >= QImage::Format_RGB32 && target_format != QImage::Format_CMYK8888) {
5059
        // Prevent QPainter from applying devicePixelRatio corrections
5060
0
        QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
5061
0
        if (sImage.d != d
5062
0
            && (d->format == QImage::Format_MonoLSB
5063
0
             || d->format == QImage::Format_Mono
5064
0
             || d->format == QImage::Format_Indexed8)) {
5065
0
            sImage.d->colortable = d->colortable;
5066
0
            sImage.d->has_alpha_clut = d->has_alpha_clut;
5067
0
        }
5068
5069
0
        Q_ASSERT(sImage.devicePixelRatio() == 1);
5070
0
        Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
5071
5072
0
        QPainter p(&dImage);
5073
0
        if (mode == Qt::SmoothTransformation) {
5074
0
            p.setRenderHint(QPainter::Antialiasing);
5075
0
            p.setRenderHint(QPainter::SmoothPixmapTransform);
5076
0
        }
5077
0
        p.setTransform(mat);
5078
0
        p.drawImage(QPoint(0, 0), sImage);
5079
0
    } else {
5080
0
        bool invertible;
5081
0
        mat = mat.inverted(&invertible);                // invert matrix
5082
0
        if (!invertible)        // error, return null image
5083
0
            return QImage();
5084
5085
        // create target image (some of the code is from QImage::copy())
5086
0
        int type = format() == Format_Mono ? QT_XFORM_TYPE_MSBFIRST : QT_XFORM_TYPE_LSBFIRST;
5087
0
        qsizetype dbpl = dImage.bytesPerLine();
5088
0
        qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
5089
0
    }
5090
0
    copyMetadata(dImage.d, d);
5091
5092
0
    return dImage;
5093
0
}
5094
5095
/*!
5096
    \fn QTransform QImage::trueMatrix(const QTransform &matrix, int width, int height)
5097
5098
    Returns the actual matrix used for transforming an image with the
5099
    given \a width, \a height and \a matrix.
5100
5101
    When transforming an image using the transformed() function, the
5102
    transformation matrix is internally adjusted to compensate for
5103
    unwanted translation, i.e. transformed() returns the smallest
5104
    image containing all transformed points of the original image.
5105
    This function returns the modified matrix, which maps points
5106
    correctly from the original image into the new image.
5107
5108
    Unlike the other overload, this function creates transformation
5109
    matrices that can be used to perform perspective
5110
    transformations on images.
5111
5112
    \sa transformed(), {QImage#Image Transformations}{Image
5113
    Transformations}
5114
*/
5115
5116
QTransform QImage::trueMatrix(const QTransform &matrix, int w, int h)
5117
0
{
5118
0
    const QRectF mapped = matrix.mapRect(QRectF(0, 0, w, h));
5119
    // Same as toAlignedRect().topLeft(), but safe from int overflow:
5120
0
    return matrix * QTransform().translate(-std::floor(mapped.left()), -std::floor(mapped.top()));
5121
0
}
5122
5123
/*!
5124
    \since 5.14
5125
5126
    Sets the image color space to \a colorSpace without performing any conversions on image data.
5127
5128
    \sa colorSpace()
5129
*/
5130
void QImage::setColorSpace(const QColorSpace &colorSpace)
5131
0
{
5132
0
    if (!d)
5133
0
        return;
5134
0
    if (d->colorSpace == colorSpace)
5135
0
        return;
5136
0
    if (colorSpace.isValid() && !qt_compatibleColorModelSource(pixelFormat().colorModel(), colorSpace.colorModel()))
5137
0
        return;
5138
5139
0
    detachMetadata(false);
5140
0
    if (d)
5141
0
        d->colorSpace = colorSpace;
5142
0
}
5143
5144
/*!
5145
    \since 5.14
5146
5147
    Converts the image to \a colorSpace.
5148
5149
    If the image has no valid color space, the method does nothing.
5150
5151
    \note If \a colorSpace is not compatible with the current format, the image
5152
    will be converted to one that is.
5153
5154
    \sa convertedToColorSpace(), setColorSpace()
5155
*/
5156
void QImage::convertToColorSpace(const QColorSpace &colorSpace)
5157
0
{
5158
0
    if (!d || !d->colorSpace.isValid())
5159
0
        return;
5160
0
    if (!colorSpace.isValidTarget()) {
5161
0
        qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
5162
0
        return;
5163
0
    }
5164
0
    if (d->colorSpace == colorSpace)
5165
0
        return;
5166
0
    if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(),
5167
0
                                       colorSpace.colorModel(), colorSpace.transformModel())) {
5168
0
        *this = convertedToColorSpace(colorSpace);
5169
0
        return;
5170
0
    }
5171
0
    applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
5172
0
    if (d->ref.loadRelaxed() != 1)
5173
0
        detachMetadata(false);
5174
0
    d->colorSpace = colorSpace;
5175
0
}
5176
5177
/*!
5178
    \since 6.8
5179
5180
    Converts the image to \a colorSpace and \a format.
5181
5182
    If the image has no valid color space, the method does nothing,
5183
    nor if the color space is not compatible with with the format.
5184
5185
    The specified image conversion \a flags control how the image data
5186
    is handled during the format conversion process.
5187
5188
    \sa convertedToColorSpace(), setColorSpace()
5189
*/
5190
void QImage::convertToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
5191
0
{
5192
0
    if (!d || !d->colorSpace.isValid())
5193
0
        return;
5194
0
    if (!colorSpace.isValidTarget()) {
5195
0
        qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
5196
0
        return;
5197
0
    }
5198
0
    if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5199
0
                                       colorSpace.colorModel(), colorSpace.transformModel())) {
5200
0
        qWarning() << "QImage::convertToColorSpace: Color space is not compatible with format";
5201
0
        return;
5202
0
    }
5203
5204
0
    if (d->colorSpace == colorSpace)
5205
0
        return convertTo(format, flags);
5206
0
    applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5207
0
    d->colorSpace = colorSpace;
5208
0
}
5209
5210
/*!
5211
    \since 5.14
5212
5213
    Returns the image converted to \a colorSpace.
5214
5215
    If the image has no valid color space, a null QImage is returned.
5216
5217
    \note If \a colorSpace is not compatible with the current format,
5218
    the returned image will also be converted to a format this is.
5219
    For more control over returned image format, see the three argument
5220
    overload of this method.
5221
5222
    \sa convertToColorSpace(), colorTransformed()
5223
*/
5224
QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace) const
5225
0
{
5226
0
    if (!d || !d->colorSpace.isValid())
5227
0
        return QImage();
5228
0
    if (!colorSpace.isValidTarget()) {
5229
0
        qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
5230
0
        return QImage();
5231
0
    }
5232
0
    if (d->colorSpace == colorSpace)
5233
0
        return *this;
5234
0
    QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
5235
0
    image.setColorSpace(colorSpace);
5236
0
    return image;
5237
0
}
5238
5239
/*!
5240
    \fn QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) const &
5241
    \fn QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) &&
5242
    \since 6.8
5243
5244
    Returns the image converted to \a colorSpace and \a format.
5245
5246
    If the image has no valid color space, a null QImage is returned.
5247
5248
    The specified image conversion \a flags control how the image data
5249
    is handled during the format conversion process.
5250
5251
    \sa colorTransformed()
5252
*/
5253
QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) const &
5254
0
{
5255
0
    if (!d || !d->colorSpace.isValid())
5256
0
        return QImage();
5257
0
    if (!colorSpace.isValidTarget()) {
5258
0
        qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
5259
0
        return QImage();
5260
0
    }
5261
0
    if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5262
0
                                       colorSpace.colorModel(), colorSpace.transformModel())) {
5263
0
        qWarning() << "QImage::convertedToColorSpace: Color space is not compatible with format";
5264
0
        return QImage();
5265
0
    }
5266
0
    if (d->colorSpace == colorSpace)
5267
0
        return convertedTo(format, flags);
5268
0
    QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5269
0
    image.setColorSpace(colorSpace);
5270
0
    return image;
5271
0
}
5272
5273
QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) &&
5274
0
{
5275
0
    if (!d || !d->colorSpace.isValid())
5276
0
        return QImage();
5277
0
    if (!colorSpace.isValidTarget()) {
5278
0
        qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
5279
0
        return QImage();
5280
0
    }
5281
0
    if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5282
0
                                       colorSpace.colorModel(), colorSpace.transformModel())) {
5283
0
        qWarning() << "QImage::convertedToColorSpace: Color space is not compatible with format";
5284
0
        return QImage();
5285
0
    }
5286
0
    if (d->colorSpace == colorSpace)
5287
0
        return convertedTo(format, flags);
5288
0
    applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5289
0
    return std::move(*this);
5290
0
}
5291
5292
/*!
5293
    \since 5.14
5294
5295
    Returns the color space of the image if a color space is defined.
5296
*/
5297
QColorSpace QImage::colorSpace() const
5298
0
{
5299
0
    if (!d)
5300
0
        return QColorSpace();
5301
0
    return d->colorSpace;
5302
0
}
5303
5304
/*!
5305
    \since 5.14
5306
5307
    Applies the color transformation \a transform to all pixels in the image.
5308
*/
5309
void QImage::applyColorTransform(const QColorTransform &transform)
5310
0
{
5311
0
    if (transform.isIdentity())
5312
0
        return;
5313
5314
0
    if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
5315
0
        !qt_compatibleColorModelTarget(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel,
5316
0
                                       QColorTransformPrivate::get(transform)->colorSpaceOut->transformModel)) {
5317
0
        qWarning() << "QImage::applyColorTransform can not apply format switching transform without switching format";
5318
0
        return;
5319
0
    }
5320
5321
0
    detach();
5322
0
    if (!d)
5323
0
        return;
5324
0
    if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5325
0
        for (int i = 0; i < d->colortable.size(); ++i)
5326
0
            d->colortable[i] = transform.map(d->colortable[i]);
5327
0
        return;
5328
0
    }
5329
0
    QImage::Format oldFormat = format();
5330
0
    if (qt_fpColorPrecision(oldFormat)) {
5331
0
        if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5332
0
                && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5333
0
            convertTo(QImage::Format_RGBA32FPx4);
5334
0
    } else if (depth() > 32) {
5335
0
        if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5336
0
                && oldFormat != QImage::Format_RGBA64_Premultiplied)
5337
0
            convertTo(QImage::Format_RGBA64);
5338
0
    } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5339
0
                && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5340
0
                && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5341
0
        if (hasAlphaChannel())
5342
0
            convertTo(QImage::Format_ARGB32);
5343
0
        else
5344
0
            convertTo(QImage::Format_RGB32);
5345
0
    }
5346
5347
0
    QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
5348
0
    switch (format()) {
5349
0
    case Format_ARGB32_Premultiplied:
5350
0
    case Format_RGBA64_Premultiplied:
5351
0
    case Format_RGBA32FPx4_Premultiplied:
5352
0
        flags = QColorTransformPrivate::Premultiplied;
5353
0
        break;
5354
0
    case Format_Grayscale8:
5355
0
    case Format_Grayscale16:
5356
0
    case Format_RGB32:
5357
0
    case Format_CMYK8888:
5358
0
    case Format_RGBX64:
5359
0
    case Format_RGBX32FPx4:
5360
0
        flags = QColorTransformPrivate::InputOpaque;
5361
0
        break;
5362
0
    case Format_ARGB32:
5363
0
    case Format_RGBA64:
5364
0
    case Format_RGBA32FPx4:
5365
0
        break;
5366
0
    default:
5367
0
        Q_UNREACHABLE();
5368
0
    }
5369
5370
0
    std::function<void(int,int)> transformSegment;
5371
5372
0
    if (format() == Format_Grayscale8) {
5373
0
        transformSegment = [&](int yStart, int yEnd) {
5374
0
            for (int y = yStart; y < yEnd; ++y) {
5375
0
                uint8_t *scanline = reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
5376
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5377
0
            }
5378
0
        };
5379
0
    } else if (format() == Format_Grayscale16) {
5380
0
        transformSegment = [&](int yStart, int yEnd) {
5381
0
            for (int y = yStart; y < yEnd; ++y) {
5382
0
                uint16_t *scanline = reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
5383
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5384
0
            }
5385
0
        };
5386
0
    } else if (qt_fpColorPrecision(format())) {
5387
0
        transformSegment = [&](int yStart, int yEnd) {
5388
0
            for (int y = yStart; y < yEnd; ++y) {
5389
0
                QRgbaFloat32 *scanline = reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
5390
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5391
0
            }
5392
0
        };
5393
0
    } else  if (depth() > 32) {
5394
0
        transformSegment = [&](int yStart, int yEnd) {
5395
0
            for (int y = yStart; y < yEnd; ++y) {
5396
0
                QRgba64 *scanline = reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
5397
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5398
0
            }
5399
0
        };
5400
0
    } else if (oldFormat == QImage::Format_CMYK8888) {
5401
0
        transformSegment = [&](int yStart, int yEnd) {
5402
0
            for (int y = yStart; y < yEnd; ++y) {
5403
0
                QCmyk32 *scanline = reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
5404
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5405
0
            }
5406
0
        };
5407
0
    } else {
5408
0
        transformSegment = [&](int yStart, int yEnd) {
5409
0
            for (int y = yStart; y < yEnd; ++y) {
5410
0
                QRgb *scanline = reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
5411
0
                QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5412
0
            }
5413
0
        };
5414
0
    }
5415
5416
0
#if QT_CONFIG(qtgui_threadpool)
5417
0
    int segments = (qsizetype(width()) * height()) >> 16;
5418
0
    segments = std::min(segments, height());
5419
0
    QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5420
0
    if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5421
0
        QLatch latch(segments);
5422
0
        int y = 0;
5423
0
        for (int i = 0; i < segments; ++i) {
5424
0
            int yn = (height() - y) / (segments - i);
5425
0
            threadPool->start([&, y, yn]() {
5426
0
                transformSegment(y, y + yn);
5427
0
                latch.countDown();
5428
0
            });
5429
0
            y += yn;
5430
0
        }
5431
0
        latch.wait();
5432
0
    } else
5433
0
#endif
5434
0
        transformSegment(0, height());
5435
5436
0
    if (oldFormat != format())
5437
0
        *this = std::move(*this).convertToFormat(oldFormat);
5438
0
}
5439
5440
/*!
5441
    \since 6.8
5442
5443
    Applies the color transformation \a transform to all pixels in the image, and converts the format of the image to \a toFormat.
5444
5445
    The specified image conversion \a flags control how the image data
5446
    is handled during the format conversion process.
5447
*/
5448
void QImage::applyColorTransform(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
5449
0
{
5450
0
    if (!d)
5451
0
        return;
5452
0
    if (transform.isIdentity())
5453
0
        return convertTo(toFormat, flags);
5454
5455
0
    *this = colorTransformed(transform, toFormat, flags);
5456
0
}
5457
5458
/*!
5459
    \since 6.4
5460
5461
    Returns the image color transformed using \a transform on all pixels in the image.
5462
5463
    \note If \a transform has a source color space which is incompatible with the format of this image,
5464
    returns a null QImage. If \a transform has a target color space which is incompatible with the format
5465
    of this image, the image will also be converted to a compatible format. For more control about the
5466
    choice of the target pixel format, see the three argument overload of this method.
5467
5468
    \sa applyColorTransform()
5469
*/
5470
QImage QImage::colorTransformed(const QColorTransform &transform) const &
5471
0
{
5472
0
    if (!d)
5473
0
        return QImage();
5474
0
    if (transform.isIdentity())
5475
0
        return *this;
5476
5477
0
    const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5478
0
    const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5479
0
    if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5480
0
        qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
5481
0
        return QImage();
5482
0
    }
5483
0
    if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5484
        // All model switching transforms are opaque in at least one end.
5485
0
        switch (outColorSpace->colorModel) {
5486
0
        case QColorSpace::ColorModel::Rgb:
5487
0
            return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5488
0
        case QColorSpace::ColorModel::Gray:
5489
0
            return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5490
0
        case QColorSpace::ColorModel::Cmyk:
5491
0
            return colorTransformed(transform, QImage::Format_CMYK8888);
5492
0
        case QColorSpace::ColorModel::Undefined:
5493
0
            break;
5494
0
        }
5495
0
        return QImage();
5496
0
    }
5497
5498
0
    QImage image = copy();
5499
0
    image.applyColorTransform(transform);
5500
0
    return image;
5501
0
}
5502
5503
static bool isRgb32Data(QImage::Format f)
5504
0
{
5505
0
    switch (f) {
5506
0
    case QImage::Format_RGB32:
5507
0
    case QImage::Format_ARGB32:
5508
0
    case QImage::Format_ARGB32_Premultiplied:
5509
0
        return true;
5510
0
    default:
5511
0
        break;
5512
0
    }
5513
0
    return false;
5514
0
}
5515
5516
static bool isRgb64Data(QImage::Format f)
5517
0
{
5518
0
    switch (f) {
5519
0
    case QImage::Format_RGBX64:
5520
0
    case QImage::Format_RGBA64:
5521
0
    case QImage::Format_RGBA64_Premultiplied:
5522
0
        return true;
5523
0
    default:
5524
0
        break;
5525
0
    }
5526
0
    return false;
5527
0
}
5528
5529
static bool isRgb32fpx4Data(QImage::Format f)
5530
0
{
5531
0
    switch (f) {
5532
0
    case QImage::Format_RGBX32FPx4:
5533
0
    case QImage::Format_RGBA32FPx4:
5534
0
    case QImage::Format_RGBA32FPx4_Premultiplied:
5535
0
        return true;
5536
0
    default:
5537
0
        break;
5538
0
    }
5539
0
    return false;
5540
0
}
5541
5542
/*!
5543
    \since 6.8
5544
5545
    Returns the image color transformed using \a transform on all pixels in the image, returning an image of format \a toFormat.
5546
5547
    The specified image conversion \a flags control how the image data
5548
    is handled during the format conversion process.
5549
5550
    \note If \a transform has a source color space which is incompatible with the format of this image,
5551
    or a target color space that is incompatible with \a toFormat, returns a null QImage.
5552
5553
    \sa applyColorTransform()
5554
*/
5555
QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags) const &
5556
0
{
5557
0
    if (!d)
5558
0
        return QImage();
5559
0
    if (toFormat == QImage::Format_Invalid)
5560
0
        toFormat = format();
5561
0
    if (transform.isIdentity())
5562
0
        return convertedTo(toFormat, flags);
5563
5564
0
    const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5565
0
    const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5566
0
    if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5567
0
        qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
5568
0
        return QImage();
5569
0
    }
5570
0
    if (!qt_compatibleColorModelTarget(toPixelFormat(toFormat).colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5571
0
        qWarning() << "QImage::colorTransformed: Invalid output color space for transform";
5572
0
        return QImage();
5573
0
    }
5574
5575
0
    QImage fromImage = *this;
5576
5577
0
    QImage::Format tmpFormat = toFormat;
5578
0
    switch (toFormat) {
5579
0
    case QImage::Format_RGB32:
5580
0
    case QImage::Format_ARGB32:
5581
0
    case QImage::Format_ARGB32_Premultiplied:
5582
0
    case QImage::Format_RGBX32FPx4:
5583
0
    case QImage::Format_RGBA32FPx4:
5584
0
    case QImage::Format_RGBA32FPx4_Premultiplied:
5585
0
    case QImage::Format_RGBX64:
5586
0
    case QImage::Format_RGBA64:
5587
0
    case QImage::Format_RGBA64_Premultiplied:
5588
0
    case QImage::Format_Grayscale8:
5589
0
    case QImage::Format_Grayscale16:
5590
0
    case QImage::Format_CMYK8888:
5591
        // can be output natively
5592
0
        break;
5593
0
    case QImage::Format_RGB16:
5594
0
    case QImage::Format_RGB444:
5595
0
    case QImage::Format_RGB555:
5596
0
    case QImage::Format_RGB666:
5597
0
    case QImage::Format_RGB888:
5598
0
    case QImage::Format_BGR888:
5599
0
    case QImage::Format_RGBX8888:
5600
0
        tmpFormat = QImage::Format_RGB32;
5601
0
        break;
5602
0
    case QImage::Format_Mono:
5603
0
    case QImage::Format_MonoLSB:
5604
0
    case QImage::Format_Indexed8:
5605
0
    case QImage::Format_ARGB8565_Premultiplied:
5606
0
    case QImage::Format_ARGB6666_Premultiplied:
5607
0
    case QImage::Format_ARGB8555_Premultiplied:
5608
0
    case QImage::Format_ARGB4444_Premultiplied:
5609
0
    case QImage::Format_RGBA8888:
5610
0
    case QImage::Format_RGBA8888_Premultiplied:
5611
0
        tmpFormat = QImage::Format_ARGB32;
5612
0
        break;
5613
0
    case QImage::Format_BGR30:
5614
0
    case QImage::Format_RGB30:
5615
0
        tmpFormat = QImage::Format_RGBX64;
5616
0
        break;
5617
0
    case QImage::Format_A2BGR30_Premultiplied:
5618
0
    case QImage::Format_A2RGB30_Premultiplied:
5619
0
        tmpFormat = QImage::Format_RGBA64;
5620
0
        break;
5621
0
    case QImage::Format_RGBX16FPx4:
5622
0
    case QImage::Format_RGBA16FPx4:
5623
0
    case QImage::Format_RGBA16FPx4_Premultiplied:
5624
0
        tmpFormat = QImage::Format_RGBA32FPx4;
5625
0
        break;
5626
0
    case QImage::Format_Alpha8:
5627
0
        return convertedTo(QImage::Format_Alpha8);
5628
0
    case QImage::Format_Invalid:
5629
0
    case QImage::NImageFormats:
5630
0
        Q_UNREACHABLE();
5631
0
        break;
5632
0
    }
5633
0
    QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
5634
0
    QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
5635
    // Ensure only precision increasing transforms
5636
0
    if (inColorData != outColorData) {
5637
0
        if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
5638
0
            tmpFormat = QImage::Format_RGB32;
5639
0
        else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
5640
0
            tmpFormat = QImage::Format_Grayscale16;
5641
0
        else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
5642
0
            tmpFormat = QImage::Format_RGBX64;
5643
0
    } else {
5644
0
        if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
5645
0
            tmpFormat = QImage::Format_Grayscale16;
5646
0
        else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
5647
0
            tmpFormat = QImage::Format_RGBA32FPx4;
5648
0
        else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(), true))
5649
0
            tmpFormat = QImage::Format_RGBA64;
5650
0
    }
5651
5652
0
    QImage toImage(size(), tmpFormat);
5653
0
    copyMetadata(&toImage, *this);
5654
5655
0
    std::function<void(int, int)> transformSegment;
5656
0
    QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
5657
5658
0
    if (inColorData != outColorData) {
5659
        // Needs color model switching transform
5660
0
        if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
5661
            // Gray -> RGB
5662
0
            if (format() == QImage::Format_Grayscale8) {
5663
0
                transformSegment = [&](int yStart, int yEnd) {
5664
0
                    for (int y = yStart; y < yEnd; ++y) {
5665
0
                        const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
5666
0
                        QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5667
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5668
0
                    }
5669
0
                };
5670
0
            } else {
5671
0
                transformSegment = [&](int yStart, int yEnd) {
5672
0
                    for (int y = yStart; y < yEnd; ++y) {
5673
0
                        const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
5674
0
                        QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5675
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5676
0
                    }
5677
0
                };
5678
0
            }
5679
0
        } else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
5680
            // Gray -> CMYK
5681
0
            if (format() == QImage::Format_Grayscale8) {
5682
0
                transformSegment = [&](int yStart, int yEnd) {
5683
0
                    for (int y = yStart; y < yEnd; ++y) {
5684
0
                        const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
5685
0
                        QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5686
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5687
0
                    }
5688
0
                };
5689
0
            } else {
5690
0
                transformSegment = [&](int yStart, int yEnd) {
5691
0
                    for (int y = yStart; y < yEnd; ++y) {
5692
0
                        const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
5693
0
                        QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5694
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5695
0
                    }
5696
0
                };
5697
0
            }
5698
0
        } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
5699
            // RGB -> Gray
5700
0
            if (tmpFormat == QImage::Format_Grayscale8) {
5701
0
                fromImage.convertTo(QImage::Format_RGB32);
5702
0
                transformSegment = [&](int yStart, int yEnd) {
5703
0
                    for (int y = yStart; y < yEnd; ++y) {
5704
0
                        const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5705
0
                        quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5706
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5707
0
                    }
5708
0
                };
5709
0
            } else {
5710
0
                fromImage.convertTo(QImage::Format_RGBX64);
5711
0
                transformSegment = [&](int yStart, int yEnd) {
5712
0
                    for (int y = yStart; y < yEnd; ++y) {
5713
0
                        const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5714
0
                        quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5715
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5716
0
                    }
5717
0
                };
5718
0
            }
5719
0
        } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
5720
             // CMYK -> Gray
5721
0
            if (tmpFormat == QImage::Format_Grayscale8) {
5722
0
                transformSegment = [&](int yStart, int yEnd) {
5723
0
                    for (int y = yStart; y < yEnd; ++y) {
5724
0
                        const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5725
0
                        quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5726
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5727
0
                    }
5728
0
                };
5729
0
            } else {
5730
0
                transformSegment = [&](int yStart, int yEnd) {
5731
0
                    for (int y = yStart; y < yEnd; ++y) {
5732
0
                        const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5733
0
                        quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5734
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5735
0
                    }
5736
0
                };
5737
0
            }
5738
0
        } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
5739
             // CMYK -> RGB
5740
0
            if (isRgb32Data(tmpFormat) ) {
5741
0
                transformSegment = [&](int yStart, int yEnd) {
5742
0
                    for (int y = yStart; y < yEnd; ++y) {
5743
0
                        const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5744
0
                        QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5745
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5746
0
                    }
5747
0
                };
5748
0
            } else if (isRgb64Data(tmpFormat)) {
5749
0
                transformSegment = [&](int yStart, int yEnd) {
5750
0
                    for (int y = yStart; y < yEnd; ++y) {
5751
0
                        const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5752
0
                        QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5753
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5754
0
                    }
5755
0
                };
5756
0
            } else {
5757
0
                Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5758
0
                transformSegment = [&](int yStart, int yEnd) {
5759
0
                    for (int y = yStart; y < yEnd; ++y) {
5760
0
                        const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5761
0
                        QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5762
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5763
0
                    }
5764
0
                };
5765
0
            }
5766
0
        } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
5767
            // RGB -> CMYK
5768
0
            if (!fromImage.hasAlphaChannel())
5769
0
                transFlags = QColorTransformPrivate::InputOpaque;
5770
0
            else if (qPixelLayouts[fromImage.format()].premultiplied)
5771
0
                transFlags = QColorTransformPrivate::Premultiplied;
5772
0
            if (isRgb32Data(fromImage.format()) ) {
5773
0
                transformSegment = [&](int yStart, int yEnd) {
5774
0
                    for (int y = yStart; y < yEnd; ++y) {
5775
0
                        const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5776
0
                        QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5777
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5778
0
                    }
5779
0
                };
5780
0
            } else if (isRgb64Data(fromImage.format())) {
5781
0
                transformSegment = [&](int yStart, int yEnd) {
5782
0
                    for (int y = yStart; y < yEnd; ++y) {
5783
0
                        const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5784
0
                        QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5785
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5786
0
                    }
5787
0
                };
5788
0
            } else {
5789
0
                Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
5790
0
                transformSegment = [&](int yStart, int yEnd) {
5791
0
                    for (int y = yStart; y < yEnd; ++y) {
5792
0
                        const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5793
0
                        QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5794
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5795
0
                    }
5796
0
                };
5797
0
            }
5798
0
        } else {
5799
0
            Q_UNREACHABLE();
5800
0
        }
5801
0
    } else {
5802
        // Conversion on same color model
5803
0
        if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5804
0
            for (int i = 0; i < d->colortable.size(); ++i)
5805
0
                fromImage.d->colortable[i] = transform.map(d->colortable[i]);
5806
0
            return fromImage.convertedTo(toFormat, flags);
5807
0
        }
5808
5809
0
        QImage::Format oldFormat = format();
5810
0
        if (qt_fpColorPrecision(oldFormat)) {
5811
0
            if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5812
0
                && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5813
0
                fromImage.convertTo(QImage::Format_RGBA32FPx4);
5814
0
        } else if (qt_highColorPrecision(oldFormat, true)) {
5815
0
            if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5816
0
                && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
5817
0
                fromImage.convertTo(QImage::Format_RGBA64);
5818
0
        } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5819
0
                   && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5820
0
                   && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5821
0
            if (hasAlphaChannel())
5822
0
                fromImage.convertTo(QImage::Format_ARGB32);
5823
0
            else
5824
0
                fromImage.convertTo(QImage::Format_RGB32);
5825
0
        }
5826
5827
0
        if (!fromImage.hasAlphaChannel())
5828
0
            transFlags = QColorTransformPrivate::InputOpaque;
5829
0
        else if (qPixelLayouts[fromImage.format()].premultiplied)
5830
0
            transFlags = QColorTransformPrivate::Premultiplied;
5831
5832
0
        if (fromImage.format() == Format_Grayscale8) {
5833
0
            transformSegment = [&](int yStart, int yEnd) {
5834
0
                for (int y = yStart; y < yEnd; ++y) {
5835
0
                    const quint8 *in_scanline = reinterpret_cast<const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5836
0
                    if (tmpFormat == Format_Grayscale8) {
5837
0
                        quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5838
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5839
0
                    } else {
5840
0
                        Q_ASSERT(tmpFormat == Format_Grayscale16);
5841
0
                        quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5842
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5843
0
                    }
5844
0
                }
5845
0
            };
5846
0
        } else if (fromImage.format() == Format_Grayscale16) {
5847
0
            transformSegment = [&](int yStart, int yEnd) {
5848
0
                for (int y = yStart; y < yEnd; ++y) {
5849
0
                    const quint16 *in_scanline = reinterpret_cast<const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5850
0
                    quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5851
0
                    QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5852
0
                }
5853
0
            };
5854
0
        } else if (fromImage.format() == Format_CMYK8888) {
5855
0
            Q_ASSERT(tmpFormat == Format_CMYK8888);
5856
0
            transformSegment = [&](int yStart, int yEnd) {
5857
0
                for (int y = yStart; y < yEnd; ++y) {
5858
0
                    const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5859
0
                    QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5860
0
                    QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5861
0
                }
5862
0
            };
5863
0
        } else if (isRgb32fpx4Data(fromImage.format())) {
5864
0
            Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5865
0
            transformSegment = [&](int yStart, int yEnd) {
5866
0
                for (int y = yStart; y < yEnd; ++y) {
5867
0
                    const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5868
0
                    QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5869
0
                    QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5870
0
                }
5871
0
            };
5872
0
        } else if (isRgb64Data(fromImage.format())) {
5873
0
            transformSegment = [&](int yStart, int yEnd) {
5874
0
                for (int y = yStart; y < yEnd; ++y) {
5875
0
                    const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5876
0
                    if (isRgb32fpx4Data(tmpFormat)) {
5877
0
                        QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5878
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5879
0
                    } else {
5880
0
                        Q_ASSERT(isRgb64Data(tmpFormat));
5881
0
                        QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5882
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5883
0
                    }
5884
0
                }
5885
0
            };
5886
0
        } else {
5887
0
            transformSegment = [&](int yStart, int yEnd) {
5888
0
                for (int y = yStart; y < yEnd; ++y) {
5889
0
                    const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5890
0
                    if (isRgb32fpx4Data(tmpFormat)) {
5891
0
                        QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5892
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5893
0
                    } else if (isRgb64Data(tmpFormat)) {
5894
0
                        QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5895
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5896
0
                    } else {
5897
0
                        Q_ASSERT(isRgb32Data(tmpFormat));
5898
0
                        QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5899
0
                        QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5900
0
                    }
5901
0
                }
5902
0
            };
5903
0
        }
5904
0
    }
5905
5906
0
#if QT_CONFIG(qtgui_threadpool)
5907
0
    int segments = (qsizetype(width()) * height()) >> 16;
5908
0
    segments = std::min(segments, height());
5909
0
    QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5910
0
    if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5911
0
        QLatch latch(segments);
5912
0
        int y = 0;
5913
0
        for (int i = 0; i < segments; ++i) {
5914
0
            int yn = (height() - y) / (segments - i);
5915
0
            threadPool->start([&, y, yn]() {
5916
0
                transformSegment(y, y + yn);
5917
0
                latch.countDown();
5918
0
            });
5919
0
            y += yn;
5920
0
        }
5921
0
        latch.wait();
5922
0
    } else
5923
0
#endif
5924
0
        transformSegment(0, height());
5925
5926
0
    if (tmpFormat != toFormat)
5927
0
        toImage.convertTo(toFormat);
5928
5929
0
    return toImage;
5930
0
}
5931
5932
/*!
5933
    \since 6.4
5934
    \overload
5935
5936
    Returns the image color transformed using \a transform on all pixels in the image.
5937
5938
    \sa applyColorTransform()
5939
*/
5940
QImage QImage::colorTransformed(const QColorTransform &transform) &&
5941
0
{
5942
0
    if (!d)
5943
0
        return QImage();
5944
5945
0
    const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5946
0
    const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5947
0
    if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5948
0
        qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
5949
0
        return QImage();
5950
0
    }
5951
0
    if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5952
        // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
5953
0
        switch (outColorSpace->colorModel) {
5954
0
        case QColorSpace::ColorModel::Rgb:
5955
0
            return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5956
0
        case QColorSpace::ColorModel::Gray:
5957
0
            return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5958
0
        case QColorSpace::ColorModel::Cmyk:
5959
0
            return colorTransformed(transform, QImage::Format_CMYK8888);
5960
0
        case QColorSpace::ColorModel::Undefined:
5961
0
            break;
5962
0
        }
5963
0
        return QImage();
5964
0
    }
5965
5966
0
    applyColorTransform(transform);
5967
0
    return std::move(*this);
5968
0
}
5969
5970
/*!
5971
    \since 6.8
5972
    \overload
5973
5974
    Returns the image color transformed using \a transform on all pixels in the image.
5975
5976
    \sa applyColorTransform()
5977
*/
5978
QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
5979
0
{
5980
    // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
5981
0
    return colorTransformed(transform, format, flags);
5982
0
}
5983
5984
bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
5985
0
{
5986
0
    if (format == newFormat)
5987
0
        return true;
5988
5989
    // No in-place conversion if we have to detach
5990
0
    if (ref.loadRelaxed() > 1 || !own_data)
5991
0
        return false;
5992
5993
0
    InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat];
5994
0
    if (converter)
5995
0
        return converter(this, flags);
5996
0
    if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8 && !qimage_converter_map[format][newFormat]) {
5997
        // Convert inplace generic, but only if there are no direct converters,
5998
        // any direct ones are probably better even if not inplace.
5999
0
        if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
6000
0
                && qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
6001
0
#if QT_CONFIG(raster_fp)
6002
0
            if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
6003
0
                return convert_generic_inplace_over_rgba32f(this, newFormat, flags);
6004
0
#endif
6005
0
            return convert_generic_inplace_over_rgb64(this, newFormat, flags);
6006
0
        }
6007
0
        return convert_generic_inplace(this, newFormat, flags);
6008
0
    }
6009
0
    return false;
6010
0
}
6011
6012
/*!
6013
    \typedef QImage::DataPtr
6014
    \internal
6015
*/
6016
6017
/*!
6018
    \fn DataPtr & QImage::data_ptr()
6019
    \internal
6020
*/
6021
6022
#ifndef QT_NO_DEBUG_STREAM
6023
QDebug operator<<(QDebug dbg, const QImage &i)
6024
0
{
6025
0
    QDebugStateSaver saver(dbg);
6026
0
    dbg.nospace();
6027
0
    dbg.noquote();
6028
0
    dbg << "QImage(";
6029
0
    if (i.isNull()) {
6030
0
        dbg << "null";
6031
0
    } else {
6032
0
        dbg << i.size() << ",format=" << i.format() << ",depth=" << i.depth();
6033
0
        if (i.colorCount())
6034
0
            dbg << ",colorCount=" << i.colorCount();
6035
0
        const int bytesPerLine = i.bytesPerLine();
6036
0
        dbg << ",devicePixelRatio=" << i.devicePixelRatio()
6037
0
            << ",bytesPerLine=" << bytesPerLine << ",sizeInBytes=" << i.sizeInBytes();
6038
0
        if (dbg.verbosity() > 2 && i.height() > 0) {
6039
0
            const int outputLength = qMin(bytesPerLine, 24);
6040
0
            dbg << ",line0="
6041
0
                << QByteArray(reinterpret_cast<const char *>(i.scanLine(0)), outputLength).toHex()
6042
0
                << "...";
6043
0
        }
6044
0
    }
6045
0
    dbg << ')';
6046
0
    return dbg;
6047
0
}
6048
#endif
6049
6050
static constexpr QPixelFormat pixelformats[] = {
6051
        //QImage::Format_Invalid:
6052
        QPixelFormat(),
6053
        //QImage::Format_Mono:
6054
        QPixelFormat(QPixelFormat::Indexed,
6055
                        /*RED*/            1,
6056
                        /*GREEN*/          0,
6057
                        /*BLUE*/           0,
6058
                        /*FOURTH*/         0,
6059
                        /*FIFTH*/          0,
6060
                        /*ALPHA*/          0,
6061
                        /*ALPHA USAGE*/    QPixelFormat::IgnoresAlpha,
6062
                        /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
6063
                        /*PREMULTIPLIED*/  QPixelFormat::NotPremultiplied,
6064
                        /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
6065
                        /*BYTE ORDER*/     QPixelFormat::BigEndian),
6066
        //QImage::Format_MonoLSB:
6067
        QPixelFormat(QPixelFormat::Indexed,
6068
                        /*RED*/            1,
6069
                        /*GREEN*/          0,
6070
                        /*BLUE*/           0,
6071
                        /*FOURTH*/         0,
6072
                        /*FIFTH*/          0,
6073
                        /*ALPHA*/          0,
6074
                        /*ALPHA USAGE*/    QPixelFormat::IgnoresAlpha,
6075
                        /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
6076
                        /*PREMULTIPLIED*/  QPixelFormat::NotPremultiplied,
6077
                        /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
6078
                        /*BYTE ORDER*/     QPixelFormat::BigEndian),
6079
        //QImage::Format_Indexed8:
6080
         QPixelFormat(QPixelFormat::Indexed,
6081
                        /*RED*/            8,
6082
                        /*GREEN*/          0,
6083
                        /*BLUE*/           0,
6084
                        /*FOURTH*/         0,
6085
                        /*FIFTH*/          0,
6086
                        /*ALPHA*/          0,
6087
                        /*ALPHA USAGE*/    QPixelFormat::IgnoresAlpha,
6088
                        /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
6089
                        /*PREMULTIPLIED*/  QPixelFormat::NotPremultiplied,
6090
                        /*INTERPRETATION*/ QPixelFormat::UnsignedByte,
6091
                        /*BYTE ORDER*/     QPixelFormat::BigEndian),
6092
        //QImage::Format_RGB32:
6093
         QPixelFormat(QPixelFormat::RGB,
6094
                     /*RED*/                8,
6095
                     /*GREEN*/              8,
6096
                     /*BLUE*/               8,
6097
                     /*FOURTH*/             0,
6098
                     /*FIFTH*/              0,
6099
                     /*ALPHA*/              8,
6100
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6101
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6102
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6103
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6104
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6105
        //QImage::Format_ARGB32:
6106
         QPixelFormat(QPixelFormat::RGB,
6107
                     /*RED*/                8,
6108
                     /*GREEN*/              8,
6109
                     /*BLUE*/               8,
6110
                     /*FOURTH*/             0,
6111
                     /*FIFTH*/              0,
6112
                     /*ALPHA*/              8,
6113
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6114
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6115
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6116
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6117
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6118
        //QImage::Format_ARGB32_Premultiplied:
6119
         QPixelFormat(QPixelFormat::RGB,
6120
                     /*RED*/                8,
6121
                     /*GREEN*/              8,
6122
                     /*BLUE*/               8,
6123
                     /*FOURTH*/             0,
6124
                     /*FIFTH*/              0,
6125
                     /*ALPHA*/              8,
6126
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6127
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6128
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6129
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6130
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6131
        //QImage::Format_RGB16:
6132
         QPixelFormat(QPixelFormat::RGB,
6133
                     /*RED*/                5,
6134
                     /*GREEN*/              6,
6135
                     /*BLUE*/               5,
6136
                     /*FOURTH*/             0,
6137
                     /*FIFTH*/              0,
6138
                     /*ALPHA*/              0,
6139
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6140
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6141
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6142
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6143
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6144
        //QImage::Format_ARGB8565_Premultiplied:
6145
         QPixelFormat(QPixelFormat::RGB,
6146
                     /*RED*/                5,
6147
                     /*GREEN*/              6,
6148
                     /*BLUE*/               5,
6149
                     /*FOURTH*/             0,
6150
                     /*FIFTH*/              0,
6151
                     /*ALPHA*/              8,
6152
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6153
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6154
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6155
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6156
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6157
        //QImage::Format_RGB666:
6158
         QPixelFormat(QPixelFormat::RGB,
6159
                     /*RED*/                6,
6160
                     /*GREEN*/              6,
6161
                     /*BLUE*/               6,
6162
                     /*FOURTH*/             0,
6163
                     /*FIFTH*/              0,
6164
                     /*ALPHA*/              0,
6165
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6166
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6167
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6168
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6169
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6170
        //QImage::Format_ARGB6666_Premultiplied:
6171
         QPixelFormat(QPixelFormat::RGB,
6172
                     /*RED*/                6,
6173
                     /*GREEN*/              6,
6174
                     /*BLUE*/               6,
6175
                     /*FOURTH*/             0,
6176
                     /*FIFTH*/              0,
6177
                     /*ALPHA*/              6,
6178
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6179
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6180
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6181
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6182
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6183
        //QImage::Format_RGB555:
6184
         QPixelFormat(QPixelFormat::RGB,
6185
                     /*RED*/                5,
6186
                     /*GREEN*/              5,
6187
                     /*BLUE*/               5,
6188
                     /*FOURTH*/             0,
6189
                     /*FIFTH*/              0,
6190
                     /*ALPHA*/              0,
6191
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6192
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6193
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6194
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6195
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6196
        //QImage::Format_ARGB8555_Premultiplied:
6197
         QPixelFormat(QPixelFormat::RGB,
6198
                     /*RED*/                5,
6199
                     /*GREEN*/              5,
6200
                     /*BLUE*/               5,
6201
                     /*FOURTH*/             0,
6202
                     /*FIFTH*/              0,
6203
                     /*ALPHA*/              8,
6204
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6205
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6206
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6207
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6208
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6209
        //QImage::Format_RGB888:
6210
         QPixelFormat(QPixelFormat::RGB,
6211
                     /*RED*/                8,
6212
                     /*GREEN*/              8,
6213
                     /*BLUE*/               8,
6214
                     /*FOURTH*/             0,
6215
                     /*FIFTH*/              0,
6216
                     /*ALPHA*/              0,
6217
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6218
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6219
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6220
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6221
                     /*BYTE ORDER*/        QPixelFormat::BigEndian),
6222
        //QImage::Format_RGB444:
6223
         QPixelFormat(QPixelFormat::RGB,
6224
                     /*RED*/                4,
6225
                     /*GREEN*/              4,
6226
                     /*BLUE*/               4,
6227
                     /*FOURTH*/             0,
6228
                     /*FIFTH*/              0,
6229
                     /*ALPHA*/              0,
6230
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6231
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6232
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6233
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6234
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6235
        //QImage::Format_ARGB4444_Premultiplied:
6236
         QPixelFormat(QPixelFormat::RGB,
6237
                     /*RED*/                4,
6238
                     /*GREEN*/              4,
6239
                     /*BLUE*/               4,
6240
                     /*FOURTH*/             0,
6241
                     /*FIFTH*/              0,
6242
                     /*ALPHA*/              4,
6243
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6244
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6245
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6246
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6247
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6248
        //QImage::Format_RGBX8888:
6249
         QPixelFormat(QPixelFormat::RGB,
6250
                     /*RED*/                8,
6251
                     /*GREEN*/              8,
6252
                     /*BLUE*/               8,
6253
                     /*FOURTH*/             0,
6254
                     /*FIFTH*/              0,
6255
                     /*ALPHA*/              8,
6256
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6257
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6258
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6259
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6260
                     /*BYTE ORDER*/        QPixelFormat::BigEndian),
6261
        //QImage::Format_RGBA8888:
6262
         QPixelFormat(QPixelFormat::RGB,
6263
                     /*RED*/                8,
6264
                     /*GREEN*/              8,
6265
                     /*BLUE*/               8,
6266
                     /*FOURTH*/             0,
6267
                     /*FIFTH*/              0,
6268
                     /*ALPHA*/              8,
6269
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6270
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6271
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6272
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6273
                     /*BYTE ORDER*/        QPixelFormat::BigEndian),
6274
        //QImage::Format_RGBA8888_Premultiplied:
6275
         QPixelFormat(QPixelFormat::RGB,
6276
                     /*RED*/                8,
6277
                     /*GREEN*/              8,
6278
                     /*BLUE*/               8,
6279
                     /*FOURTH*/             0,
6280
                     /*FIFTH*/              0,
6281
                     /*ALPHA*/              8,
6282
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6283
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6284
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6285
                     /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6286
                     /*BYTE ORDER*/        QPixelFormat::BigEndian),
6287
        //QImage::Format_BGR30:
6288
         QPixelFormat(QPixelFormat::BGR,
6289
                     /*RED*/                10,
6290
                     /*GREEN*/              10,
6291
                     /*BLUE*/               10,
6292
                     /*FOURTH*/             0,
6293
                     /*FIFTH*/              0,
6294
                     /*ALPHA*/              2,
6295
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6296
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6297
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6298
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6299
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6300
        //QImage::Format_A2BGR30_Premultiplied:
6301
         QPixelFormat(QPixelFormat::BGR,
6302
                     /*RED*/                10,
6303
                     /*GREEN*/              10,
6304
                     /*BLUE*/               10,
6305
                     /*FOURTH*/             0,
6306
                     /*FIFTH*/              0,
6307
                     /*ALPHA*/              2,
6308
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6309
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6310
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6311
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6312
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6313
        //QImage::Format_RGB30:
6314
         QPixelFormat(QPixelFormat::RGB,
6315
                     /*RED*/                10,
6316
                     /*GREEN*/              10,
6317
                     /*BLUE*/               10,
6318
                     /*FOURTH*/             0,
6319
                     /*FIFTH*/              0,
6320
                     /*ALPHA*/              2,
6321
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6322
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6323
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6324
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6325
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6326
        //QImage::Format_A2RGB30_Premultiplied:
6327
         QPixelFormat(QPixelFormat::RGB,
6328
                     /*RED*/                10,
6329
                     /*GREEN*/              10,
6330
                     /*BLUE*/               10,
6331
                     /*FOURTH*/             0,
6332
                     /*FIFTH*/              0,
6333
                     /*ALPHA*/              2,
6334
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6335
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6336
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6337
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6338
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6339
        //QImage::Format_Alpha8:
6340
        QPixelFormat(QPixelFormat::Alpha,
6341
                    /*First*/              0,
6342
                    /*SECOND*/             0,
6343
                    /*THIRD*/              0,
6344
                    /*FOURTH*/             0,
6345
                    /*FIFTH*/              0,
6346
                    /*ALPHA*/              8,
6347
                    /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6348
                    /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6349
                    /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6350
                    /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6351
                    /*BYTE ORDER*/        QPixelFormat::BigEndian),
6352
        //QImage::Format_Grayscale8:
6353
        QPixelFormat(QPixelFormat::Grayscale,
6354
                    /*GRAY*/               8,
6355
                    /*SECOND*/             0,
6356
                    /*THIRD*/              0,
6357
                    /*FOURTH*/             0,
6358
                    /*FIFTH*/              0,
6359
                    /*ALPHA*/              0,
6360
                    /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6361
                    /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6362
                    /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6363
                    /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6364
                    /*BYTE ORDER*/        QPixelFormat::BigEndian),
6365
        //QImage::Format_RGBX64:
6366
        QPixelFormat(QPixelFormat::RGB,
6367
                     /*RED*/                16,
6368
                     /*GREEN*/              16,
6369
                     /*BLUE*/               16,
6370
                     /*FOURTH*/             0,
6371
                     /*FIFTH*/              0,
6372
                     /*ALPHA*/              16,
6373
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6374
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6375
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6376
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6377
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6378
        //QImage::Format_RGBA64:
6379
        QPixelFormat(QPixelFormat::RGB,
6380
                     /*RED*/                16,
6381
                     /*GREEN*/              16,
6382
                     /*BLUE*/               16,
6383
                     /*FOURTH*/             0,
6384
                     /*FIFTH*/              0,
6385
                     /*ALPHA*/              16,
6386
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6387
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6388
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6389
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6390
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6391
         //QImage::Format_RGBA64_Premultiplied:
6392
         QPixelFormat(QPixelFormat::RGB,
6393
                     /*RED*/                16,
6394
                     /*GREEN*/              16,
6395
                     /*BLUE*/               16,
6396
                     /*FOURTH*/             0,
6397
                     /*FIFTH*/              0,
6398
                     /*ALPHA*/              16,
6399
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6400
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6401
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6402
                     /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6403
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6404
        //QImage::Format_Grayscale16:
6405
        QPixelFormat(QPixelFormat::Grayscale,
6406
                    /*GRAY*/               16,
6407
                    /*SECOND*/             0,
6408
                    /*THIRD*/              0,
6409
                    /*FOURTH*/             0,
6410
                    /*FIFTH*/              0,
6411
                    /*ALPHA*/              0,
6412
                    /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6413
                    /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6414
                    /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6415
                    /*INTERPRETATION*/    QPixelFormat::UnsignedShort,
6416
                    /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6417
        //QImage::Format_BGR888:
6418
        QPixelFormat(QPixelFormat::BGR,
6419
                    /*RED*/                8,
6420
                    /*GREEN*/              8,
6421
                    /*BLUE*/               8,
6422
                    /*FOURTH*/             0,
6423
                    /*FIFTH*/              0,
6424
                    /*ALPHA*/              0,
6425
                    /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6426
                    /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6427
                    /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6428
                    /*INTERPRETATION*/    QPixelFormat::UnsignedByte,
6429
                    /*BYTE ORDER*/        QPixelFormat::BigEndian),
6430
        //QImage::Format_RGBX16FPx4:
6431
        QPixelFormat(QPixelFormat::RGB,
6432
                     /*RED*/                16,
6433
                     /*GREEN*/              16,
6434
                     /*BLUE*/               16,
6435
                     /*FOURTH*/             0,
6436
                     /*FIFTH*/              0,
6437
                     /*ALPHA*/              16,
6438
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6439
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6440
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6441
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6442
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6443
        //QImage::Format_RGBA16FPx4:
6444
        QPixelFormat(QPixelFormat::RGB,
6445
                     /*RED*/                16,
6446
                     /*GREEN*/              16,
6447
                     /*BLUE*/               16,
6448
                     /*FOURTH*/             0,
6449
                     /*FIFTH*/              0,
6450
                     /*ALPHA*/              16,
6451
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6452
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6453
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6454
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6455
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6456
         //QImage::Format_RGBA16FPx4_Premultiplied:
6457
         QPixelFormat(QPixelFormat::RGB,
6458
                     /*RED*/                16,
6459
                     /*GREEN*/              16,
6460
                     /*BLUE*/               16,
6461
                     /*FOURTH*/             0,
6462
                     /*FIFTH*/              0,
6463
                     /*ALPHA*/              16,
6464
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6465
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6466
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6467
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6468
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6469
        //QImage::Format_RGBX32FPx4:
6470
        QPixelFormat(QPixelFormat::RGB,
6471
                     /*RED*/                32,
6472
                     /*GREEN*/              32,
6473
                     /*BLUE*/               32,
6474
                     /*FOURTH*/             0,
6475
                     /*FIFTH*/              0,
6476
                     /*ALPHA*/              32,
6477
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6478
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6479
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6480
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6481
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6482
        //QImage::Format_RGBA32FPx4:
6483
        QPixelFormat(QPixelFormat::RGB,
6484
                     /*RED*/                32,
6485
                     /*GREEN*/              32,
6486
                     /*BLUE*/               32,
6487
                     /*FOURTH*/             0,
6488
                     /*FIFTH*/              0,
6489
                     /*ALPHA*/              32,
6490
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6491
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6492
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6493
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6494
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6495
         //QImage::Format_RGBA32FPx4_Premultiplied:
6496
         QPixelFormat(QPixelFormat::RGB,
6497
                     /*RED*/                32,
6498
                     /*GREEN*/              32,
6499
                     /*BLUE*/               32,
6500
                     /*FOURTH*/             0,
6501
                     /*FIFTH*/              0,
6502
                     /*ALPHA*/              32,
6503
                     /*ALPHA USAGE*/       QPixelFormat::UsesAlpha,
6504
                     /*ALPHA POSITION*/    QPixelFormat::AtEnd,
6505
                     /*PREMULTIPLIED*/     QPixelFormat::Premultiplied,
6506
                     /*INTERPRETATION*/    QPixelFormat::FloatingPoint,
6507
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6508
        //QImage::Format_CMYK8888:
6509
        QPixelFormat(QPixelFormat::CMYK,
6510
                     /*RED*/                8,
6511
                     /*GREEN*/              8,
6512
                     /*BLUE*/               8,
6513
                     /*FOURTH*/             8,
6514
                     /*FIFTH*/              0,
6515
                     /*ALPHA*/              0,
6516
                     /*ALPHA USAGE*/       QPixelFormat::IgnoresAlpha,
6517
                     /*ALPHA POSITION*/    QPixelFormat::AtBeginning,
6518
                     /*PREMULTIPLIED*/     QPixelFormat::NotPremultiplied,
6519
                     /*INTERPRETATION*/    QPixelFormat::UnsignedInteger,
6520
                     /*BYTE ORDER*/        QPixelFormat::CurrentSystemEndian),
6521
};
6522
static_assert(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
6523
6524
/*!
6525
    Returns the QImage::Format as a QPixelFormat
6526
*/
6527
QPixelFormat QImage::pixelFormat() const noexcept
6528
0
{
6529
0
    return toPixelFormat(format());
6530
0
}
6531
6532
/*!
6533
    Converts \a format into a QPixelFormat
6534
*/
6535
QPixelFormat QImage::toPixelFormat(QImage::Format format) noexcept
6536
0
{
6537
0
    Q_ASSERT(static_cast<int>(format) < NImageFormats && static_cast<int>(format) >= 0);
6538
0
    return pixelformats[format];
6539
0
}
6540
6541
/*!
6542
    Converts \a format into a QImage::Format
6543
*/
6544
QImage::Format QImage::toImageFormat(QPixelFormat format) noexcept
6545
0
{
6546
0
    for (int i = 0; i < NImageFormats; i++) {
6547
0
        if (format == pixelformats[i])
6548
0
            return Format(i);
6549
0
    }
6550
0
    return Format_Invalid;
6551
0
}
6552
6553
static inline Qt::Orientations toOrientations(QImageIOHandler::Transformations orient)
6554
0
{
6555
0
    Qt::Orientations orients = {};
6556
0
    if (orient.testFlag(QImageIOHandler::TransformationMirror))
6557
0
        orients |= Qt::Horizontal;
6558
0
    if (orient.testFlag(QImageIOHandler::TransformationFlip))
6559
0
        orients |= Qt::Vertical;
6560
0
    return orients;
6561
0
}
6562
6563
Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
6564
0
{
6565
0
    if (orient == QImageIOHandler::TransformationNone)
6566
0
        return;
6567
0
    if (orient == QImageIOHandler::TransformationRotate270) {
6568
0
        src = rotated270(src);
6569
0
    } else {
6570
0
        src.flip(toOrientations(orient));
6571
0
        if (orient & QImageIOHandler::TransformationRotate90)
6572
0
            src = rotated90(src);
6573
0
    }
6574
0
}
6575
6576
QMap<QString, QString> qt_getImageText(const QImage &image, const QString &description)
6577
0
{
6578
0
    QMap<QString, QString> text = qt_getImageTextFromDescription(description);
6579
0
    const auto textKeys = image.textKeys();
6580
0
    for (const QString &key : textKeys) {
6581
0
        if (!key.isEmpty() && !text.contains(key))
6582
0
            text.insert(key, image.text(key));
6583
0
    }
6584
0
    return text;
6585
0
}
6586
6587
QMap<QString, QString> qt_getImageTextFromDescription(const QString &description)
6588
0
{
6589
0
    QMap<QString, QString> text;
6590
0
    for (const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
6591
0
        int index = pair.indexOf(u':');
6592
0
        if (index >= 0 && pair.indexOf(u' ') < index) {
6593
0
            if (!pair.trimmed().isEmpty())
6594
0
                text.insert("Description"_L1, pair.toString().simplified());
6595
0
        } else {
6596
0
            const auto key = pair.left(index);
6597
0
            if (!key.trimmed().isEmpty())
6598
0
                text.insert(key.toString(), pair.mid(index + 2).toString().simplified());
6599
0
        }
6600
0
    }
6601
0
    return text;
6602
0
}
6603
6604
QT_END_NAMESPACE
6605
6606
#include "moc_qimage.cpp"