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