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