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