19#include <qpa/qplatformintegration.h>
20#include <private/qguiapplication_p.h>
24#include <qpa/qplatformpixmap.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>
35#include <private/qpaintengine_raster_p.h>
37#include <private/qimage_p.h>
38#include <private/qfont_p.h>
40#if QT_CONFIG(qtgui_threadpool)
41#include <private/qlatch_p.h>
42#include <qthreadpool.h>
43#include <private/qthreadpool_p.h>
46#include <qtgui_tracepoints_p.h>
50#define QT_XFORM_TYPE_MSBFIRST 0
51#define QT_XFORM_TYPE_LSBFIRST 1
56using namespace Qt::StringLiterals;
61QT_WARNING_DISABLE_MSVC(4723)
63#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0
>= 50190001
)
64#pragma message disable narrowptr
68#define QIMAGE_SANITYCHECK_MEMORY(image)
69 if ((image).isNull()) {
70 qWarning("QImage: out of memory, returning null image");
75 "#include <qimagereader.h>"
79"ENUM { } QImage::Format;" \
80"FLAGS { } Qt::ImageConversionFlags;"
83Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode,
int);
84Q_TRACE_PARAM_REPLACE(Qt::TransformationMode,
int);
86static QImage
rotated90(
const QImage &src);
92 Q_CONSTINIT
static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
93 return 1 + serial.fetchAndAddRelaxed(1);
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()),
101 offset(0, 0), own_data(
true), ro_data(
false), has_alpha_clut(
false),
102 is_cached(
false), cleanupFunction(
nullptr), cleanupInfo(
nullptr),
105 QPoint dpis = qt_defaultDpis();
106 dpmx = dpis.x() * 100 / qreal(2.54);
107 dpmy = dpis.y() * 100 / qreal(2.54);
111
112
113
114
115
116
117QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(
const QSize &size, QImage::Format format)
119 if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
122 Q_TRACE_SCOPE(QImageData_create, size, format);
124 int width = size.width();
125 int height = size.height();
126 int depth = qt_depthForFormat(format);
127 auto params = calculateImageParameters(width, height, depth);
128 if (!params.isValid())
131 auto d = std::make_unique<QImageData>();
134 case QImage::Format_Mono:
135 case QImage::Format_MonoLSB:
136 d->colortable.resize(2);
137 d->colortable[0] = QColor(Qt::black).rgba();
138 d->colortable[1] = QColor(Qt::white).rgba();
148 d->has_alpha_clut =
false;
149 d->is_cached =
false;
151 d->bytes_per_line = params.bytesPerLine;
152 d->nbytes = params.totalSize;
153 d->data = (uchar *)malloc(d->nbytes);
162QImageData::~QImageData()
165 cleanupFunction(cleanupInfo);
167 QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
169 if (data && own_data)
170 QtPrivate::sizedFree(data, nbytes);
174#if defined(_M_ARM) && defined(_MSC_VER)
175#pragma optimize("", off)
178bool QImageData::checkForAlphaPixels()
const
180 bool has_alpha_pixels =
false;
184 case QImage::Format_Mono:
185 case QImage::Format_MonoLSB:
186 case QImage::Format_Indexed8:
187 has_alpha_pixels = has_alpha_clut;
189 case QImage::Format_Alpha8:
190 has_alpha_pixels =
true;
192 case QImage::Format_ARGB32:
193 case QImage::Format_ARGB32_Premultiplied: {
194 const uchar *bits = data;
195 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
196 uint alphaAnd = 0xff000000;
197 for (
int x=0; x<width; ++x)
198 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
199 has_alpha_pixels = (alphaAnd != 0xff000000);
200 bits += bytes_per_line;
204 case QImage::Format_RGBA8888:
205 case QImage::Format_RGBA8888_Premultiplied: {
206 const uchar *bits = data;
207 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
208 uchar alphaAnd = 0xff;
209 for (
int x=0; x<width; ++x)
210 alphaAnd &= bits[x * 4+ 3];
211 has_alpha_pixels = (alphaAnd != 0xff);
212 bits += bytes_per_line;
216 case QImage::Format_A2BGR30_Premultiplied:
217 case QImage::Format_A2RGB30_Premultiplied: {
218 const uchar *bits = data;
219 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
220 uint alphaAnd = 0xc0000000;
221 for (
int x=0; x<width; ++x)
222 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
223 has_alpha_pixels = (alphaAnd != 0xc0000000);
224 bits += bytes_per_line;
228 case QImage::Format_ARGB8555_Premultiplied:
229 case QImage::Format_ARGB8565_Premultiplied: {
230 const uchar *bits = data;
231 const uchar *end_bits = data + bytes_per_line;
233 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
234 uchar alphaAnd = 0xff;
235 while (bits < end_bits) {
239 has_alpha_pixels = (alphaAnd != 0xff);
241 end_bits += bytes_per_line;
245 case QImage::Format_ARGB6666_Premultiplied: {
246 const uchar *bits = data;
247 const uchar *end_bits = data + bytes_per_line;
249 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
250 uchar alphaAnd = 0xfc;
251 while (bits < end_bits) {
255 has_alpha_pixels = (alphaAnd != 0xfc);
257 end_bits += bytes_per_line;
261 case QImage::Format_ARGB4444_Premultiplied: {
262 const uchar *bits = data;
263 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
264 ushort alphaAnd = 0xf000;
265 for (
int x=0; x<width; ++x)
266 alphaAnd &=
reinterpret_cast<
const ushort*>(bits)[x];
267 has_alpha_pixels = (alphaAnd != 0xf000);
268 bits += bytes_per_line;
271 case QImage::Format_RGBA64:
272 case QImage::Format_RGBA64_Premultiplied: {
274 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
275 for (
int x=0; x<width; ++x) {
276 has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
278 bits += bytes_per_line;
281 case QImage::Format_RGBA16FPx4:
282 case QImage::Format_RGBA16FPx4_Premultiplied: {
284 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
285 for (
int x = 0; x < width; ++x)
286 has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
287 bits += bytes_per_line;
290 case QImage::Format_RGBA32FPx4:
291 case QImage::Format_RGBA32FPx4_Premultiplied: {
293 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
294 for (
int x = 0; x < width; ++x)
295 has_alpha_pixels |= ((
float *)bits)[x * 4 + 3] < 1.0f;
296 bits += bytes_per_line;
300 case QImage::Format_RGB32:
301 case QImage::Format_RGB16:
302 case QImage::Format_RGB444:
303 case QImage::Format_RGB555:
304 case QImage::Format_RGB666:
305 case QImage::Format_RGB888:
306 case QImage::Format_BGR888:
307 case QImage::Format_RGBX8888:
308 case QImage::Format_BGR30:
309 case QImage::Format_RGB30:
310 case QImage::Format_Grayscale8:
311 case QImage::Format_Grayscale16:
312 case QImage::Format_RGBX64:
313 case QImage::Format_RGBX16FPx4:
314 case QImage::Format_RGBX32FPx4:
315 case QImage::Format_CMYK8888:
317 case QImage::Format_Invalid:
318 case QImage::NImageFormats:
323 return has_alpha_pixels;
325#if defined(_M_ARM) && defined(_MSC_VER)
326#pragma optimize("", on)
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
633
634
635
636
637
638
639
642
643
644
645
646
647
651
652
653
654
655
656
657
658
659
660
663
664
665
666
667
668
669
670
671
672
673
674
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
791
792
795
796
797
798
800QImage::QImage()
noexcept
807
808
809
810
811
812
813
814
815
816QImage::QImage(
int width,
int height, Format format)
817 : QImage(QSize(width, height), format)
822
823
824
825
826
827
828
829
830QImage::QImage(
const QSize &size, Format format)
833 d = QImageData::create(size, format);
838QImageData *QImageData::create(uchar *data,
int width,
int height, qsizetype bpl, QImage::Format format,
bool readOnly, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
840 if (width <= 0 || height <= 0 || !data || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
843 const int depth = qt_depthForFormat(format);
844 auto params = calculateImageParameters(width, height, depth);
845 if (!params.isValid())
850 const qsizetype min_bytes_per_line = (qsizetype(width) * depth + 7)/8;
851 if (bpl < min_bytes_per_line)
855 params.bytesPerLine = bpl;
856 if (qMulOverflow<qsizetype>(bpl, height, ¶ms.totalSize))
860 QImageData *d =
new QImageData;
864 d->ro_data = readOnly;
871 d->bytes_per_line = params.bytesPerLine;
872 d->nbytes = params.totalSize;
874 d->cleanupFunction = cleanupFunction;
875 d->cleanupInfo = cleanupInfo;
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897QImage::QImage(uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
900 d = QImageData::create(data, width, height, 0, format,
false, cleanupFunction, cleanupInfo);
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928QImage::QImage(
const uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
931 d = QImageData::create(
const_cast<uchar*>(data), width, height, 0, format,
true, cleanupFunction, cleanupInfo);
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
952QImage::QImage(uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
955 d = QImageData::create(data, width, height, bytesPerLine, format,
false, cleanupFunction, cleanupInfo);
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
983QImage::QImage(
const uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
986 d = QImageData::create(
const_cast<uchar*>(data), width, height, bytesPerLine, format,
true, cleanupFunction, cleanupInfo);
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1009QImage::QImage(
const QString &fileName,
const char *format)
1013 load(fileName, format);
1016#ifndef QT_NO_IMAGEFORMAT_XPM
1017extern bool qt_read_xpm_image_or_array(QIODevice *device,
const char *
const *source, QImage &image);
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1035QImage::QImage(
const char *
const xpm[])
1041 if (!qt_read_xpm_image_or_array(
nullptr, xpm, *
this))
1043 qWarning(
"QImage::QImage(), XPM is not supported");
1048
1049
1050
1051
1052
1053
1054
1056QImage::QImage(
const QImage &image)
1059 if (image.paintingActive()) {
1061 image.copy().swap(*
this);
1070
1071
1075 if (d && !d->ref.deref())
1080
1081
1082
1083
1084
1085
1086
1087
1089QImage &QImage::operator=(
const QImage &image)
1091 if (image.paintingActive()) {
1092 operator=(image.copy());
1096 if (d && !d->ref.deref())
1104
1105
1106
1109
1110
1111int QImage::devType()
const
1113 return QInternal::Image;
1117
1118
1119QImage::operator QVariant()
const
1121 return QVariant::fromValue(*
this);
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135void QImage::detach()
1138 if (d->is_cached && d->ref.loadRelaxed() == 1)
1139 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1141 if (d->ref.loadRelaxed() != 1 || d->ro_data)
1151
1152
1153
1154
1155
1156
1157
1158void QImage::detachMetadata(
bool invalidateCache)
1161 if (d->is_cached && d->ref.loadRelaxed() == 1)
1162 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1164 if (d->ref.loadRelaxed() != 1)
1167 if (d && invalidateCache)
1174 dst->dpmx = src->dpmx;
1175 dst->dpmy = src->dpmy;
1176 dst->devicePixelRatio = src->devicePixelRatio;
1183 dst->text = src->text;
1184 dst->offset = src->offset;
1185 dst->colorSpace = src->colorSpace;
1190 dst->setDotsPerMeterX(src.dotsPerMeterX());
1191 dst->setDotsPerMeterY(src.dotsPerMeterY());
1192 dst->setDevicePixelRatio(src.devicePixelRatio());
1193 const auto textKeys = src.textKeys();
1194 for (
const auto &key: textKeys)
1195 dst->setText(key, src.text(key));
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(
const QRect& r)
const
1237 Q_TRACE_SCOPE(QImage_copy, r);
1242 QImage image(d->width, d->height, d->format);
1248 if (image.d->nbytes != d->nbytes) {
1249 qsizetype bpl = qMin(bytesPerLine(), image.bytesPerLine());
1250 for (
int i = 0; i < height(); i++)
1251 memcpy(image.scanLine(i), scanLine(i), bpl);
1253 memcpy(image.bits(), bits(), d->nbytes);
1254 image.d->colortable = d->colortable;
1255 image.d->has_alpha_clut = d->has_alpha_clut;
1256 copyMetadata(image.d, d);
1267 if (w <= 0 || h <= 0)
1270 QImage image(w, h, d->format);
1274 if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {
1287 image.d->colortable = d->colortable;
1289 int pixels_to_copy = qMax(w - dx, 0);
1292 else if (pixels_to_copy > d->width - x)
1293 pixels_to_copy = d->width - x;
1294 int lines_to_copy = qMax(h - dy, 0);
1297 else if (lines_to_copy > d->height - y)
1298 lines_to_copy = d->height - y;
1300 bool byteAligned =
true;
1301 if (d->format == Format_Mono || d->format == Format_MonoLSB)
1302 byteAligned = !(dx & 7) && !(x & 7) && !(pixels_to_copy & 7);
1305 const uchar *src = d->data + ((x * d->depth) >> 3) + y * d->bytes_per_line;
1306 uchar *dest = image.d->data + ((dx * d->depth) >> 3) + dy * image.d->bytes_per_line;
1307 const qsizetype bytes_to_copy = (qsizetype(pixels_to_copy) * d->depth) >> 3;
1308 for (
int i = 0; i < lines_to_copy; ++i) {
1309 memcpy(dest, src, bytes_to_copy);
1310 src += d->bytes_per_line;
1311 dest += image.d->bytes_per_line;
1313 }
else if (d->format == Format_Mono) {
1314 const uchar *src = d->data + y * d->bytes_per_line;
1315 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1316 for (
int i = 0; i < lines_to_copy; ++i) {
1317 for (
int j = 0; j < pixels_to_copy; ++j) {
1318 if (src[(x + j) >> 3] & (0x80 >> ((x + j) & 7)))
1319 dest[(dx + j) >> 3] |= (0x80 >> ((dx + j) & 7));
1321 dest[(dx + j) >> 3] &= ~(0x80 >> ((dx + j) & 7));
1323 src += d->bytes_per_line;
1324 dest += image.d->bytes_per_line;
1327 Q_ASSERT(d->format == Format_MonoLSB);
1328 const uchar *src = d->data + y * d->bytes_per_line;
1329 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1330 for (
int i = 0; i < lines_to_copy; ++i) {
1331 for (
int j = 0; j < pixels_to_copy; ++j) {
1332 if (src[(x + j) >> 3] & (0x1 << ((x + j) & 7)))
1333 dest[(dx + j) >> 3] |= (0x1 << ((dx + j) & 7));
1335 dest[(dx + j) >> 3] &= ~(0x1 << ((dx + j) & 7));
1337 src += d->bytes_per_line;
1338 dest += image.d->bytes_per_line;
1342 copyMetadata(image.d, d);
1343 image.d->has_alpha_clut = d->has_alpha_clut;
1350
1351
1352
1353
1354
1355bool QImage::isNull()
const
1361
1362
1363
1364
1365
1366
1367int QImage::width()
const
1369 return d ? d->width : 0;
1373
1374
1375
1376
1377
1378
1379int QImage::height()
const
1381 return d ? d->height : 0;
1385
1386
1387
1388
1389
1390
1391QSize QImage::size()
const
1393 return d ? QSize(d->width, d->height) : QSize(0, 0);
1397
1398
1399
1400
1401
1402
1403
1404QRect QImage::rect()
const
1406 return d ? QRect(0, 0, d->width, d->height) : QRect();
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421int QImage::depth()
const
1423 return d ? d->depth : 0;
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437int QImage::colorCount()
const
1439 return d ? d->colortable.size() : 0;
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453void QImage::setColorTable(
const QList<QRgb> &colors)
1457 detachMetadata(
true);
1463 d->colortable = colors;
1464 d->has_alpha_clut =
false;
1465 for (
int i = 0; i < d->colortable.size(); ++i) {
1466 if (qAlpha(d->colortable.at(i)) != 255) {
1467 d->has_alpha_clut =
true;
1474
1475
1476
1477
1478
1479QList<QRgb> QImage::colorTable()
const
1481 return d ? d->colortable : QList<QRgb>();
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495qreal QImage::devicePixelRatio()
const
1499 return d->devicePixelRatio;
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523void QImage::setDevicePixelRatio(qreal scaleFactor)
1528 if (scaleFactor == d->devicePixelRatio)
1533 d->devicePixelRatio = scaleFactor;
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546QSizeF QImage::deviceIndependentSize()
const
1549 return QSizeF(0, 0);
1550 return QSizeF(d->width, d->height) / d->devicePixelRatio;
1555
1556
1557
1558
1559
1560
1561qsizetype QImage::sizeInBytes()
const
1563 return d ? d->nbytes : 0;
1567
1568
1569
1570
1571
1572
1573qsizetype QImage::bytesPerLine()
const
1575 return d ? d->bytes_per_line : 0;
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590QRgb QImage::color(
int i)
const
1592 Q_ASSERT(i < colorCount());
1593 return d ? d->colortable.at(i) : QRgb(uint(-1));
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608void QImage::setColor(
int i, QRgb c)
1612 if (i < 0 || d->depth > 8 || i >= 1<<d->depth) {
1613 qWarning(
"QImage::setColor: Index out of bound %d", i);
1616 detachMetadata(
true);
1622 if (i >= d->colortable.size())
1624 d->colortable[i] = c;
1625 d->has_alpha_clut |= (qAlpha(c) != 255);
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650uchar *QImage::scanLine(
int i)
1661 return d->data + i * d->bytes_per_line;
1665
1666
1667const uchar *QImage::scanLine(
int i)
const
1672 Q_ASSERT(i >= 0 && i < height());
1673 return d->data + i * d->bytes_per_line;
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691const uchar *QImage::constScanLine(
int i)
const
1696 Q_ASSERT(i >= 0 && i < height());
1697 return d->data + i * d->bytes_per_line;
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711uchar *QImage::bits()
1725
1726
1727
1728
1729
1730
1731const uchar *QImage::bits()
const
1733 return d ? d->data :
nullptr;
1738
1739
1740
1741
1742
1743
1744
1745
1746const uchar *QImage::constBits()
const
1748 return d ? d->data :
nullptr;
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1771void QImage::fill(uint pixel)
1782 if (d->depth == 1 || d->depth == 8) {
1784 if (d->depth == 1) {
1793 qt_rectfill<quint8>(d->data, pixel, 0, 0,
1794 w, d->height, d->bytes_per_line);
1796 }
else if (d->depth == 16) {
1797 if (d->format == Format_RGB444)
1799 qt_rectfill<quint16>(
reinterpret_cast<quint16*>(d->data), pixel,
1800 0, 0, d->width, d->height, d->bytes_per_line);
1802 }
else if (d->depth == 24) {
1803 if (d->format == Format_RGB666)
1805 qt_rectfill<quint24>(
reinterpret_cast<quint24*>(d->data), pixel,
1806 0, 0, d->width, d->height, d->bytes_per_line);
1808 }
else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
1809 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
1810 0, 0, d->width, d->height, d->bytes_per_line);
1812 }
else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
1814 QRgbaFloat16 cf = QRgbaFloat16::fromArgb32(pixel);
1815 ::memcpy(&cu, &cf,
sizeof(quint64));
1816 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), cu,
1817 0, 0, d->width, d->height, d->bytes_per_line);
1819 }
else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
1820 QRgbaFloat32 cf = QRgbaFloat32::fromArgb32(pixel);
1821 uchar *data = d->data;
1822 for (
int y = 0; y < d->height; ++y) {
1823 QRgbaFloat32 *line =
reinterpret_cast<QRgbaFloat32 *>(data);
1824 for (
int x = 0; x < d->width; ++x)
1826 data += d->bytes_per_line;
1830 Q_ASSERT(d->depth == 32);
1832 if (d->format == Format_RGB32)
1833 pixel |= 0xff000000;
1834 if (d->format == Format_RGBX8888)
1835#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1836 pixel |= 0xff000000;
1838 pixel |= 0x000000ff;
1840 if (d->format == Format_BGR30 || d->format == Format_RGB30)
1841 pixel |= 0xc0000000;
1843 qt_rectfill<uint>(
reinterpret_cast<uint*>(d->data), pixel,
1844 0, 0, d->width, d->height, d->bytes_per_line);
1849
1850
1851
1852
1853
1854
1856void QImage::fill(Qt::GlobalColor color)
1858 fill(QColor(color));
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1878void QImage::fill(
const QColor &color)
1888 QRgba64 opaque = color.rgba64();
1889 opaque.setAlpha(65535);
1890 switch (d->format) {
1891 case QImage::Format_RGB32:
1892 case QImage::Format_ARGB32:
1895 case QImage::Format_ARGB32_Premultiplied:
1896 fill(qPremultiply(color.rgba()));
1898 case QImage::Format_RGBX8888:
1899 fill(ARGB2RGBA(color.rgba() | 0xff000000));
1901 case QImage::Format_RGBA8888:
1902 fill(ARGB2RGBA(color.rgba()));
1904 case QImage::Format_RGBA8888_Premultiplied:
1905 fill(ARGB2RGBA(qPremultiply(color.rgba())));
1907 case QImage::Format_BGR30:
1908 fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
1910 case QImage::Format_RGB30:
1911 fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
1913 case QImage::Format_RGB16:
1914 fill((uint) qConvertRgb32To16(color.rgba()));
1916 case QImage::Format_Indexed8: {
1918 for (
int i=0; i<d->colortable.size(); ++i) {
1919 if (color.rgba() == d->colortable.at(i)) {
1927 case QImage::Format_Mono:
1928 case QImage::Format_MonoLSB:
1929 if (color == Qt::color1)
1934 case QImage::Format_RGBX64:
1935 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), opaque,
1936 0, 0, d->width, d->height, d->bytes_per_line);
1938 case QImage::Format_RGBA64:
1939 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), color.rgba64(),
1940 0, 0, d->width, d->height, d->bytes_per_line);
1942 case QImage::Format_RGBA64_Premultiplied:
1943 qt_rectfill<quint64>(
reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
1944 0, 0, d->width, d->height, d->bytes_per_line);
1946 case QImage::Format_RGBX16FPx4:
1947 case QImage::Format_RGBA16FPx4:
1948 case QImage::Format_RGBA16FPx4_Premultiplied:
1949 case QImage::Format_RGBX32FPx4:
1950 case QImage::Format_RGBA32FPx4:
1951 case QImage::Format_RGBA32FPx4_Premultiplied:{
1953 color.getRgbF(&r, &g, &b, &a);
1954 if (!hasAlphaChannel())
1956 if (depth() == 64) {
1957 QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
1958 if (d->format == Format_RGBA16FPx4_Premultiplied)
1959 c16 = c16.premultiplied();
1960 qt_rectfill<QRgbaFloat16>(
reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
1961 0, 0, d->width, d->height, d->bytes_per_line);
1963 QRgbaFloat32 c32{r, g, b, a};
1964 if (d->format == Format_RGBA32FPx4_Premultiplied)
1965 c32 = c32.premultiplied();
1966 qt_rectfill<QRgbaFloat32>(
reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
1967 0, 0, d->width, d->height, d->bytes_per_line);
1973 p.setCompositionMode(QPainter::CompositionMode_Source);
1974 p.fillRect(rect(), color);
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
2000void QImage::invertPixels(InvertMode mode)
2011 QImage::Format originalFormat = d->format;
2013 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
2014 if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
2015 if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
2016 *
this = convertToFormat(QImage::Format_RGBA16FPx4);
2017 }
else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
2018 if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
2019 *
this = convertToFormat(QImage::Format_RGBA32FPx4);
2020 }
else if (depth() > 32) {
2021 if (!d->convertInPlace(QImage::Format_RGBA64, { }))
2022 *
this = convertToFormat(QImage::Format_RGBA64);
2024 if (!d->convertInPlace(QImage::Format_ARGB32, { }))
2025 *
this = convertToFormat(QImage::Format_ARGB32);
2031 qsizetype bpl = (qsizetype(d->width) * d->depth + 7) / 8;
2032 int pad = d->bytes_per_line - bpl;
2033 uchar *sl = d->data;
2034 for (
int y=0; y<d->height; ++y) {
2035 for (qsizetype x=0; x<bpl; ++x)
2039 }
else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
2040 qfloat16 *p =
reinterpret_cast<qfloat16 *>(d->data);
2041 qfloat16 *end =
reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
2043 p[0] = qfloat16(1) - p[0];
2044 p[1] = qfloat16(1) - p[1];
2045 p[2] = qfloat16(1) - p[2];
2046 if (mode == InvertRgba)
2047 p[3] = qfloat16(1) - p[3];
2050 }
else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
2051 uchar *data = d->data;
2052 for (
int y = 0; y < d->height; ++y) {
2053 float *p =
reinterpret_cast<
float *>(data);
2054 for (
int x = 0; x < d->width; ++x) {
2058 if (mode == InvertRgba)
2062 data += d->bytes_per_line;
2064 }
else if (depth() == 64) {
2065 quint16 *p = (quint16*)d->data;
2066 quint16 *end = (quint16*)(d->data + d->nbytes);
2067 quint16 xorbits = 0xffff;
2072 if (mode == InvertRgba)
2078 quint32 *p = (quint32*)d->data;
2079 quint32 *end = (quint32*)(d->data + d->nbytes);
2080 quint32 xorbits = 0xffffffff;
2081 switch (d->format) {
2082 case QImage::Format_RGBA8888:
2083 if (mode == InvertRgba)
2086 case QImage::Format_RGBX8888:
2087#if Q_BYTE_ORDER == Q_BIG_ENDIAN
2088 xorbits = 0xffffff00;
2091 xorbits = 0x00ffffff;
2094 case QImage::Format_ARGB32:
2095 if (mode == InvertRgba)
2098 case QImage::Format_RGB32:
2099 xorbits = 0x00ffffff;
2101 case QImage::Format_BGR30:
2102 case QImage::Format_RGB30:
2103 xorbits = 0x3fffffff;
2114 if (originalFormat != d->format) {
2115 if (!d->convertInPlace(originalFormat, { }))
2116 *
this = convertToFormat(originalFormat);
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2145void QImage::setColorCount(
int colorCount)
2148 qWarning(
"QImage::setColorCount: null image");
2152 detachMetadata(
true);
2158 if (colorCount == d->colortable.size())
2160 if (colorCount <= 0) {
2161 d->colortable.clear();
2164 int nc = d->colortable.size();
2165 d->colortable.resize(colorCount);
2166 for (
int i = nc; i < colorCount; ++i)
2167 d->colortable[i] = 0;
2171
2172
2173
2174
2175QImage::Format QImage::format()
const
2179 Q_ASSERT(d->format < NImageFormats);
2180 Q_ASSERT(d->format > Format_Invalid);
2182 return d ? d->format : Format_Invalid;
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2211
2212
2213QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags flags)
const
2215 if (!d || d->format == format)
2218 if (d->format == Format_Invalid || format <= Format_Invalid || format >= NImageFormats)
2221 const QPixelLayout *destLayout = &qPixelLayouts[format];
2222 Image_Converter converter = qimage_converter_map[d->format][format];
2223 if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
2224 if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
2225 && qt_highColorPrecision(format, !hasAlphaChannel())) {
2226#if QT_CONFIG(raster_fp)
2227 if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
2228 converter = convert_generic_over_rgba32f;
2231 converter = convert_generic_over_rgb64;
2233 converter = convert_generic;
2236 QImage image(d->width, d->height, format);
2240 copyMetadata(image.d, d);
2242 converter(image.d, d, flags);
2247 Q_ASSERT(format != QImage::Format_ARGB32 && format != QImage::Format_RGB32);
2248 Q_ASSERT(d->format != QImage::Format_ARGB32 && d->format != QImage::Format_RGB32);
2250 if (!hasAlphaChannel())
2251 return convertToFormat(Format_RGB32, flags).convertToFormat(format, flags);
2253 return convertToFormat(Format_ARGB32, flags).convertToFormat(format, flags);
2257
2258
2259bool QImage::convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags)
2261 return d && d->convertInPlace(format, flags);
2264static inline int pixel_distance(QRgb p1, QRgb p2) {
2266 int g1 = qGreen(p1);
2268 int a1 = qAlpha(p1);
2271 int g2 = qGreen(p2);
2273 int a2 = qAlpha(p2);
2275 return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) + abs(a1 - a2);
2278static inline int closestMatch(QRgb pixel,
const QList<QRgb> &clut) {
2280 int current_distance = INT_MAX;
2281 for (
int i=0; i<clut.size(); ++i) {
2282 int dist = pixel_distance(pixel, clut.at(i));
2283 if (dist < current_distance) {
2284 current_distance = dist;
2291static QImage convertWithPalette(
const QImage &src, QImage::Format format,
2292 const QList<QRgb> &clut) {
2293 QImage dest(src.size(), format);
2294 dest.setColorTable(clut);
2296 copyMetadata(QImageData::get(dest), QImageData::get(src));
2298 int h = src.height();
2299 int w = src.width();
2301 QHash<QRgb,
int> cache;
2303 if (format == QImage::Format_Indexed8) {
2304 for (
int y=0; y<h; ++y) {
2305 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2306 uchar *dest_pixels = (uchar *) dest.scanLine(y);
2307 for (
int x=0; x<w; ++x) {
2308 int src_pixel = src_pixels[x];
2309 int value = cache.value(src_pixel, -1);
2311 value = closestMatch(src_pixel, clut);
2312 cache.insert(src_pixel, value);
2314 dest_pixels[x] = (uchar) value;
2318 QList<QRgb> table = clut;
2320 for (
int y=0; y<h; ++y) {
2321 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2322 for (
int x=0; x<w; ++x) {
2323 int src_pixel = src_pixels[x];
2324 int value = cache.value(src_pixel, -1);
2326 value = closestMatch(src_pixel, table);
2327 cache.insert(src_pixel, value);
2329 dest.setPixel(x, y, value);
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347QImage QImage::convertToFormat(Format format,
const QList<QRgb> &colorTable, Qt::ImageConversionFlags flags)
const
2349 if (!d || d->format == format)
2352 if (format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2354 if (format <= QImage::Format_Indexed8)
2355 return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
2357 return convertToFormat(format, flags);
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2383bool QImage::reinterpretAsFormat(Format format)
2385 if (format <= Format_Invalid || format >= NImageFormats)
2389 if (d->format == format)
2391 if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
2393 if (!isDetached()) {
2394 QImageData *oldD = d;
2409
2410
2411
2412
2413
2414
2415
2416
2417
2419void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
2421 if (!d || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2424 if (d->format == format)
2428 if (convertToFormat_inplace(format, flags))
2431 *
this = convertToFormat_helper(format, flags);
2435
2436
2437
2438
2439
2440
2441
2444
2445
2446
2447
2448
2449bool QImage::valid(
int x,
int y)
const
2452 && x >= 0 && x < d->width
2453 && y >= 0 && y < d->height;
2457
2458
2459
2460
2461
2462
2463
2464
2465
2468
2469
2470
2471
2472int QImage::pixelIndex(
int x,
int y)
const
2474 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2475 qWarning(
"QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
2478 const uchar * s = scanLine(y);
2481 return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2482 case Format_MonoLSB:
2483 return (*(s + (x >> 3)) >> (x & 7)) & 1;
2484 case Format_Indexed8:
2487 qWarning(
"QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2509
2510
2511
2512
2513QRgb QImage::pixel(
int x,
int y)
const
2515 if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
2516 qWarning(
"QImage::pixel: coordinate (%d,%d) out of range", x, y);
2520 const uchar *s = d->data + y * d->bytes_per_line;
2523 switch (d->format) {
2525 index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
2527 case Format_MonoLSB:
2528 index = (*(s + (x >> 3)) >> (x & 7)) & 1;
2530 case Format_Indexed8:
2537 if (index >= d->colortable.size()) {
2538 qWarning(
"QImage::pixel: color table index %d out of range.", index);
2541 return d->colortable.at(index);
2543 std::optional<QRgb> out;
2544 switch (d->format) {
2547 case Format_ARGB32_Premultiplied:
2548 out =
reinterpret_cast<
const QRgb *>(s)[x];
2550 case Format_RGBX8888:
2551 case Format_RGBA8888:
2552 case Format_RGBA8888_Premultiplied:
2553 out = RGBA2ARGB(
reinterpret_cast<
const quint32 *>(s)[x]);
2556 case Format_A2BGR30_Premultiplied:
2557 out = qConvertA2rgb30ToArgb32<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2560 case Format_A2RGB30_Premultiplied:
2561 out = qConvertA2rgb30ToArgb32<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2564 return qConvertRgb16To32(
reinterpret_cast<
const quint16 *>(s)[x]);
2567 case Format_RGBA64_Premultiplied:
2568 out =
reinterpret_cast<
const QRgba64 *>(s)[x].toArgb32();
2570 case Format_RGBX16FPx4:
2571 case Format_RGBA16FPx4:
2572 case Format_RGBA16FPx4_Premultiplied:
2573 out =
reinterpret_cast<
const QRgbaFloat16 *>(s)[x].toArgb32();
2575 case Format_RGBX32FPx4:
2576 case Format_RGBA32FPx4:
2577 case Format_RGBA32FPx4_Premultiplied:
2578 out =
reinterpret_cast<
const QRgbaFloat32 *>(s)[x].toArgb32();
2582 const QPixelLayout *layout = &qPixelLayouts[d->format];
2585 if (!layout->hasAlphaChannel)
2590 return *layout->fetchToARGB32PM(&result, s, x, 1,
nullptr,
nullptr);
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2615
2616
2617
2618
2619void QImage::setPixel(
int x,
int y, uint index_or_rgb)
2621 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2622 qWarning(
"QImage::setPixel: coordinate (%d,%d) out of range", x, y);
2626 uchar * s = scanLine(y);
2629 case Format_MonoLSB:
2630 if (index_or_rgb > 1) {
2631 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2632 }
else if (format() == Format_MonoLSB) {
2633 if (index_or_rgb==0)
2634 *(s + (x >> 3)) &= ~(1 << (x & 7));
2636 *(s + (x >> 3)) |= (1 << (x & 7));
2638 if (index_or_rgb==0)
2639 *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2641 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2644 case Format_Indexed8:
2645 if (index_or_rgb >= (uint)d->colortable.size()) {
2646 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2649 s[x] = index_or_rgb;
2654 ((uint *)s)[x] = 0xff000000 | index_or_rgb;
2657 case Format_ARGB32_Premultiplied:
2658 ((uint *)s)[x] = index_or_rgb;
2661 ((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
2663 case Format_RGBX8888:
2664 ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
2666 case Format_RGBA8888:
2667 case Format_RGBA8888_Premultiplied:
2668 ((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
2671 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
2673 case Format_A2BGR30_Premultiplied:
2674 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
2677 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
2679 case Format_A2RGB30_Premultiplied:
2680 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
2683 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
2686 case Format_RGBA64_Premultiplied:
2687 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
2689 case Format_RGBX16FPx4:
2690 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb | 0xff000000);
2692 case Format_RGBA16FPx4:
2693 case Format_RGBA16FPx4_Premultiplied:
2694 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb);
2696 case Format_RGBX32FPx4:
2697 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb | 0xff000000);
2699 case Format_RGBA32FPx4:
2700 case Format_RGBA32FPx4_Premultiplied:
2701 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb);
2703 case Format_Invalid:
2711 const QPixelLayout *layout = &qPixelLayouts[d->format];
2712 if (!hasAlphaChannel())
2713 layout->storeFromRGB32(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2715 layout->storeFromARGB32PM(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2735
2736
2737
2738
2739
2740QColor QImage::pixelColor(
int x,
int y)
const
2742 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2743 qWarning(
"QImage::pixelColor: coordinate (%d,%d) out of range", x, y);
2748 const uchar * s = constScanLine(y);
2749 switch (d->format) {
2751 case Format_A2BGR30_Premultiplied:
2752 c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2755 case Format_A2RGB30_Premultiplied:
2756 c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2760 case Format_RGBA64_Premultiplied:
2761 c =
reinterpret_cast<
const QRgba64 *>(s)[x];
2763 case Format_Grayscale16: {
2764 quint16 v =
reinterpret_cast<
const quint16 *>(s)[x];
2765 return QColor(qRgba64(v, v, v, 0xffff));
2767 case Format_RGBX16FPx4:
2768 case Format_RGBA16FPx4:
2769 case Format_RGBA16FPx4_Premultiplied: {
2770 QRgbaFloat16 p =
reinterpret_cast<
const QRgbaFloat16 *>(s)[x];
2771 if (d->format == Format_RGBA16FPx4_Premultiplied)
2772 p = p.unpremultiplied();
2773 else if (d->format == Format_RGBX16FPx4)
2776 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2779 case Format_RGBX32FPx4:
2780 case Format_RGBA32FPx4:
2781 case Format_RGBA32FPx4_Premultiplied: {
2782 QRgbaFloat32 p =
reinterpret_cast<
const QRgbaFloat32 *>(s)[x];
2783 if (d->format == Format_RGBA32FPx4_Premultiplied)
2784 p = p.unpremultiplied();
2785 else if (d->format == Format_RGBX32FPx4)
2788 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2792 c = QRgba64::fromArgb32(pixel(x, y));
2796 switch (d->format) {
2806 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
2807 c = c.unpremultiplied();
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2828
2829
2830
2831
2832
2833void QImage::setPixelColor(
int x,
int y,
const QColor &color)
2835 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2836 qWarning(
"QImage::setPixelColor: coordinate (%d,%d) out of range", x, y);
2840 if (!color.isValid()) {
2841 qWarning(
"QImage::setPixelColor: color is invalid");
2846 QRgba64 c = color.rgba64();
2847 if (!hasAlphaChannel())
2849 else if (qPixelLayouts[d->format].premultiplied)
2850 c = c.premultiplied();
2852 uchar * s = scanLine(y);
2853 switch (d->format) {
2855 case Format_MonoLSB:
2856 case Format_Indexed8:
2857 qWarning(
"QImage::setPixelColor: called on monochrome or indexed format");
2860 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000;
2862 case Format_A2BGR30_Premultiplied:
2863 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c);
2866 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000;
2868 case Format_A2RGB30_Premultiplied:
2869 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
2873 case Format_RGBA64_Premultiplied:
2874 ((QRgba64 *)s)[x] = c;
2876 case Format_RGBX16FPx4:
2877 case Format_RGBA16FPx4:
2878 case Format_RGBA16FPx4_Premultiplied: {
2880 color.getRgbF(&r, &g, &b, &a);
2881 if (d->format == Format_RGBX16FPx4)
2883 QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
2884 if (d->format == Format_RGBA16FPx4_Premultiplied)
2885 c16f = c16f.premultiplied();
2886 ((QRgbaFloat16 *)s)[x] = c16f;
2889 case Format_RGBX32FPx4:
2890 case Format_RGBA32FPx4:
2891 case Format_RGBA32FPx4_Premultiplied: {
2893 color.getRgbF(&r, &g, &b, &a);
2894 if (d->format == Format_RGBX32FPx4)
2896 QRgbaFloat32 c32f{r, g, b, a};
2897 if (d->format == Format_RGBA32FPx4_Premultiplied)
2898 c32f = c32f.premultiplied();
2899 ((QRgbaFloat32 *)s)[x] = c32f;
2903 setPixel(x, y, c.toArgb32());
2909
2910
2911
2912
2913
2914
2915
2916
2917bool QImage::allGray()
const
2922 switch (d->format) {
2924 case Format_MonoLSB:
2925 case Format_Indexed8:
2926 for (
int i = 0; i < d->colortable.size(); ++i) {
2927 if (!qIsGray(d->colortable.at(i)))
2933 case Format_Grayscale8:
2934 case Format_Grayscale16:
2938 case Format_ARGB32_Premultiplied:
2939#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
2940 case Format_RGBX8888:
2941 case Format_RGBA8888:
2942 case Format_RGBA8888_Premultiplied:
2944 for (
int j = 0; j < d->height; ++j) {
2945 const QRgb *b = (
const QRgb *)constScanLine(j);
2946 for (
int i = 0; i < d->width; ++i) {
2953 for (
int j = 0; j < d->height; ++j) {
2954 const quint16 *b = (
const quint16 *)constScanLine(j);
2955 for (
int i = 0; i < d->width; ++i) {
2956 if (!qIsGray(qConvertRgb16To32(b[i])))
2965 Q_DECL_UNINITIALIZED uint buffer[BufferSize];
2966 const QPixelLayout *layout = &qPixelLayouts[d->format];
2967 const auto fetch = layout->fetchToARGB32PM;
2968 for (
int j = 0; j < d->height; ++j) {
2969 const uchar *b = constScanLine(j);
2971 while (x < d->width) {
2972 int l = qMin(d->width - x, BufferSize);
2973 const uint *ptr = fetch(buffer, b, x, l,
nullptr,
nullptr);
2974 for (
int i = 0; i < l; ++i) {
2975 if (!qIsGray(ptr[i]))
2985
2986
2987
2988
2989
2990
2991
2992
2993bool QImage::isGrayscale()
const
2998 if (d->format == QImage::Format_Alpha8)
3001 if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
3010 Q_ASSERT(d->format == QImage::Format_Indexed8);
3011 for (
int i = 0; i < colorCount(); i++)
3012 if (d->colortable.at(i) != qRgb(i,i,i))
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(
const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
const
3062 qWarning(
"QImage::scaled: Image is a null image");
3068 QSize newSize = size();
3069 newSize.scale(s, aspectMode);
3070 newSize.rwidth() = qMax(newSize.width(), 1);
3071 newSize.rheight() = qMax(newSize.height(), 1);
3072 if (newSize == size())
3075 Q_TRACE_SCOPE(QImage_scaled, s, aspectMode, mode);
3077 QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
3078 QImage img = transformed(wm, mode);
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(
int w, Qt::TransformationMode mode)
const
3099 qWarning(
"QImage::scaleWidth: Image is a null image");
3105 Q_TRACE_SCOPE(QImage_scaledToWidth, w, mode);
3107 qreal factor = (qreal) w / width();
3108 QTransform wm = QTransform::fromScale(factor, factor);
3109 return transformed(wm, mode);
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(
int h, Qt::TransformationMode mode)
const
3129 qWarning(
"QImage::scaleHeight: Image is a null image");
3135 Q_TRACE_SCOPE(QImage_scaledToHeight, h, mode);
3137 qreal factor = (qreal) h / height();
3138 QTransform wm = QTransform::fromScale(factor, factor);
3139 return transformed(wm, mode);
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags)
const
3161 if (!d || d->format == QImage::Format_RGB32)
3164 if (d->depth == 1) {
3167 return convertToFormat(Format_Indexed8, flags).createAlphaMask(flags);
3170 QImage mask(d->width, d->height, Format_MonoLSB);
3171 if (!mask.isNull()) {
3172 dither_to_Mono(mask.d, d, flags,
true);
3173 copyPhysicalMetadata(mask.d, d);
3178#ifndef QT_NO_IMAGE_HEURISTIC_MASK
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3203QImage QImage::createHeuristicMask(
bool clipTight)
const
3208 if (d->depth != 32) {
3209 QImage img32 = convertToFormat(Format_RGB32);
3210 return img32.createHeuristicMask(clipTight);
3213#define PIX(x,y) (*((const QRgb*)scanLine(y)+x) & 0x00ffffff
)
3217 QImage m(w, h, Format_MonoLSB);
3220 m.setColor(0, QColor(Qt::color0).rgba());
3221 m.setColor(1, QColor(Qt::color1).rgba());
3224 QRgb background =
PIX(0,0);
3225 if (background !=
PIX(w-1,0) &&
3226 background !=
PIX(0,h-1) &&
3227 background !=
PIX(w-1,h-1)) {
3228 background =
PIX(w-1,0);
3229 if (background !=
PIX(w-1,h-1) &&
3230 background !=
PIX(0,h-1) &&
3231 PIX(0,h-1) ==
PIX(w-1,h-1)) {
3232 background =
PIX(w-1,h-1);
3238 uchar *ypp, *ypc, *ypn;
3241 ypn = m.scanLine(0);
3243 for (y = 0; y < h; y++) {
3246 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3247 const QRgb *p = (
const QRgb *)scanLine(y);
3248 for (x = 0; x < w; x++) {
3251 if ((x == 0 || y == 0 || x == w-1 || y == h-1 ||
3252 !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3253 !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3254 !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
3255 !(*(ypn + (x >> 3)) & (1 << (x & 7)))) &&
3256 ( (*(ypc + (x >> 3)) & (1 << (x & 7)))) &&
3257 ((*p & 0x00ffffff) == background)) {
3259 *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3267 ypn = m.scanLine(0);
3269 for (y = 0; y < h; y++) {
3272 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3273 const QRgb *p = (
const QRgb *)scanLine(y);
3274 for (x = 0; x < w; x++) {
3275 if ((*p & 0x00ffffff) != background) {
3277 *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3279 *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3281 *(ypp + (x >> 3)) |= (1 << (x & 7));
3283 *(ypn + (x >> 3)) |= (1 << (x & 7));
3292 copyPhysicalMetadata(m.d, d);
3298
3299
3300
3301
3302
3303
3304
3305
3307QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode)
const
3311 QImage maskImage(size(), QImage::Format_MonoLSB);
3314 uchar *s = maskImage.bits();
3318 if (depth() == 32) {
3319 for (
int h = 0; h < d->height; h++) {
3320 const uint *sl = (
const uint *) scanLine(h);
3321 for (
int w = 0; w < d->width; w++) {
3323 *(s + (w >> 3)) |= (1 << (w & 7));
3325 s += maskImage.bytesPerLine();
3328 for (
int h = 0; h < d->height; h++) {
3329 for (
int w = 0; w < d->width; w++) {
3330 if ((uint) pixel(w, h) == color)
3331 *(s + (w >> 3)) |= (1 << (w & 7));
3333 s += maskImage.bytesPerLine();
3336 if (mode == Qt::MaskOutColor)
3337 maskImage.invertPixels();
3339 copyPhysicalMetadata(maskImage.d, d);
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3358
3359
3360
3361
3362
3363
3364
3365
3366
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3382
3383
3384
3385
3386
3387
3388
3389
3391template<
class T>
inline void do_mirror_data(QImageData *dst, QImageData *src,
3392 int dstX0,
int dstY0,
3393 int dstXIncr,
int dstYIncr,
3399 const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w;
3400 const int srcYEnd = dstY0 ? h / 2 : h;
3401 for (
int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
3402 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3403 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3404 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
3405 std::swap(srcPtr[srcX], dstPtr[dstX]);
3408 if (dstX0 && dstY0 && (h & 1)) {
3410 int srcXEnd2 = w / 2;
3411 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3412 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr)
3413 std::swap(srcPtr[srcX], srcPtr[dstX]);
3416 for (
int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
3417 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3418 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3419 for (
int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
3420 dstPtr[dstX] = srcPtr[srcX];
3425inline void do_flip(QImageData *dst, QImageData *src,
int w,
int h,
int depth)
3427 const int data_bytes_per_line = w * (depth / 8);
3429 uint *srcPtr =
reinterpret_cast<uint *>(src->data);
3430 uint *dstPtr =
reinterpret_cast<uint *>(dst->data + (h - 1) * dst->bytes_per_line);
3432 const int uint_per_line = (data_bytes_per_line + 3) >> 2;
3433 for (
int y = 0; y < h; ++y) {
3435 for (
int x = 0; x < uint_per_line; x++) {
3436 const uint d = dstPtr[x];
3437 const uint s = srcPtr[x];
3441 srcPtr += src->bytes_per_line >> 2;
3442 dstPtr -= dst->bytes_per_line >> 2;
3446 const uchar *srcPtr = src->data;
3447 uchar *dstPtr = dst->data + (h - 1) * dst->bytes_per_line;
3448 for (
int y = 0; y < h; ++y) {
3449 memcpy(dstPtr, srcPtr, data_bytes_per_line);
3450 srcPtr += src->bytes_per_line;
3451 dstPtr -= dst->bytes_per_line;
3456inline void do_mirror(QImageData *dst, QImageData *src,
bool horizontal,
bool vertical)
3458 Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
3460 int h = src->height;
3461 int depth = src->depth;
3463 if (src->depth == 1) {
3468 if (vertical && !horizontal) {
3470 do_flip(dst, src, w, h, depth);
3474 int dstX0 = 0, dstXIncr = 1;
3475 int dstY0 = 0, dstYIncr = 1;
3489 do_mirror_data<QRgbaFloat32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3492 do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3495 do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3498 do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3501 do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3504 do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3513 if (horizontal && dst->depth == 1) {
3514 Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
3515 const int shift = 8 - (dst->width % 8);
3516 const uchar *bitflip = qt_get_bitflip_array();
3517 for (
int y = 0; y < h; ++y) {
3518 uchar *begin = dst->data + y * dst->bytes_per_line;
3519 uchar *end = begin + dst->bytes_per_line;
3520 for (uchar *p = begin; p < end; ++p) {
3524 if (shift != 8 && p != begin) {
3525 if (dst->format == QImage::Format_Mono) {
3526 for (
int i = 0; i < shift; ++i) {
3528 p[-1] |= (*p & (128 >> i)) >> (7 - i);
3531 for (
int i = 0; i < shift; ++i) {
3533 p[-1] |= (*p & (1 << i)) << (7 - i);
3539 if (dst->format == QImage::Format_Mono)
3549
3550
3551QImage QImage::mirrored_helper(
bool horizontal,
bool vertical)
const
3556 if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3560 QImage result(d->width, d->height, d->format);
3567 result.d->colortable = d->colortable;
3568 result.d->has_alpha_clut = d->has_alpha_clut;
3569 copyMetadata(result.d, d);
3571 do_mirror(result.d, d, horizontal, vertical);
3577
3578
3579void QImage::mirrored_inplace(
bool horizontal,
bool vertical)
3581 if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3590 do_mirror(d, d, horizontal, vertical);
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3607
3608
3609
3610
3611
3612
3613
3614
3616static inline void rgbSwapped_generic(
int width,
int height,
const QImage *src, QImage *dst,
const QPixelLayout* layout)
3618 const RbSwapFunc func = layout->rbSwap;
3620 qWarning(
"Trying to rb-swap an image format where it doesn't make sense");
3626 for (
int i = 0; i < height; ++i) {
3627 uchar *q = dst->scanLine(i);
3628 const uchar *p = src->constScanLine(i);
3634
3635
3636QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper()
const
3641 Q_TRACE_SCOPE(QImage_rgbSwapped_helper);
3645 switch (d->format) {
3646 case Format_Invalid:
3651 case Format_Grayscale8:
3652 case Format_Grayscale16:
3655 case Format_MonoLSB:
3656 case Format_Indexed8:
3658 for (
int i = 0; i < res.d->colortable.size(); i++) {
3659 QRgb c = res.d->colortable.at(i);
3660 res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3663 case Format_RGBX8888:
3664 case Format_RGBA8888:
3665 case Format_RGBA8888_Premultiplied:
3666#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3667 res = QImage(d->width, d->height, d->format);
3669 for (
int i = 0; i < d->height; i++) {
3670 uint *q = (uint*)res.scanLine(i);
3671 const uint *p = (
const uint*)constScanLine(i);
3672 const uint *end = p + d->width;
3675 *q = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3687 case Format_ARGB32_Premultiplied:
3688 res = QImage(d->width, d->height, d->format);
3690 for (
int i = 0; i < d->height; i++) {
3691 uint *q = (uint*)res.scanLine(i);
3692 const uint *p = (
const uint*)constScanLine(i);
3693 const uint *end = p + d->width;
3696 *q = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3703 res = QImage(d->width, d->height, d->format);
3705 for (
int i = 0; i < d->height; i++) {
3706 ushort *q = (ushort*)res.scanLine(i);
3707 const ushort *p = (
const ushort*)constScanLine(i);
3708 const ushort *end = p + d->width;
3711 *q = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3718 res = QImage(d->width, d->height, d->format);
3720 rgbSwapped_generic(d->width, d->height,
this, &res, &qPixelLayouts[d->format]);
3723 copyMetadata(res.d, d);
3728
3729
3730void QImage::rgbSwapped_inplace()
3741 switch (d->format) {
3742 case Format_Invalid:
3747 case Format_Grayscale8:
3748 case Format_Grayscale16:
3751 case Format_MonoLSB:
3752 case Format_Indexed8:
3753 for (
int i = 0; i < d->colortable.size(); i++) {
3754 QRgb c = d->colortable.at(i);
3755 d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3758 case Format_RGBX8888:
3759 case Format_RGBA8888:
3760 case Format_RGBA8888_Premultiplied:
3761#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3762 for (
int i = 0; i < d->height; i++) {
3763 uint *p = (uint*)scanLine(i);
3764 uint *end = p + d->width;
3767 *p = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3778 case Format_ARGB32_Premultiplied:
3779 for (
int i = 0; i < d->height; i++) {
3780 uint *p = (uint*)scanLine(i);
3781 uint *end = p + d->width;
3784 *p = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3790 for (
int i = 0; i < d->height; i++) {
3791 ushort *p = (ushort*)scanLine(i);
3792 ushort *end = p + d->width;
3795 *p = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3801 case Format_A2BGR30_Premultiplied:
3803 case Format_A2RGB30_Premultiplied:
3804 for (
int i = 0; i < d->height; i++) {
3805 uint *p = (uint*)scanLine(i);
3806 uint *end = p + d->width;
3808 *p = qRgbSwapRgb30(*p);
3814 rgbSwapped_generic(d->width, d->height,
this,
this, &qPixelLayouts[d->format]);
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3838bool QImage::load(
const QString &fileName,
const char* format)
3840 *
this = QImageReader(fileName, format).read();
3845
3846
3847
3848
3849
3851bool QImage::load(QIODevice* device,
const char* format)
3853 *
this = QImageReader(device, format).read();
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3870bool QImage::loadFromData(QByteArrayView data,
const char *format)
3872 *
this = fromData(data, format);
3877
3878
3879
3880
3881
3882
3884bool QImage::loadFromData(
const uchar *buf,
int len,
const char *format)
3886 return loadFromData(QByteArrayView(buf, len), format);
3890
3891
3892
3893
3894
3895
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3912QImage QImage::fromData(QByteArrayView data,
const char *format)
3914 QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
3917 b.open(QIODevice::ReadOnly);
3918 return QImageReader(&b, format).read();
3922
3923
3924
3925
3926
3927
3929QImage QImage::fromData(
const uchar *data,
int size,
const char *format)
3931 return fromData(QByteArrayView(data, size), format);
3935
3936
3937
3938
3939
3940
3941
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959bool QImage::save(
const QString &fileName,
const char *format,
int quality)
const
3963 QImageWriter writer(fileName, format);
3964 return d->doImageIO(
this, &writer, quality);
3968
3969
3970
3971
3972
3973
3974
3975
3976
3978bool QImage::save(QIODevice* device,
const char* format,
int quality)
const
3982 QImageWriter writer(device, format);
3983 return d->doImageIO(
this, &writer, quality);
3987
3989bool QImageData::doImageIO(
const QImage *image, QImageWriter *writer,
int quality)
const
3991 if (quality > 100 || quality < -1)
3992 qWarning(
"QImage::save: Quality out of range [-1, 100]");
3994 writer->setQuality(qMin(quality,100));
3995 const bool result = writer->write(*image);
3998 qWarning(
"QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
4004
4005
4006#if !defined(QT_NO_DATASTREAM)
4008
4009
4010
4011
4012
4013
4014
4015
4016
4018QDataStream &operator<<(QDataStream &s,
const QImage &image)
4020 if (s.version() >= 5) {
4021 if (image.isNull()) {
4029 QImageWriter writer(s.device(), s.version() == 1 ?
"bmp" :
"png");
4030 writer.write(image);
4035
4036
4037
4038
4039
4040
4041
4042
4044QDataStream &operator>>(QDataStream &s, QImage &image)
4046 if (s.version() >= 5) {
4054 image = QImageReader(s.device(), s.version() == 1 ?
"bmp" :
"png").read();
4055 if (image.isNull() && s.version() >= 5)
4056 s.setStatus(QDataStream::ReadPastEnd);
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4076bool QImage::operator==(
const QImage & i)
const
4085 if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
4088 if (d->format != Format_RGB32) {
4089 if (d->format >= Format_ARGB32) {
4090 const int n = d->width * d->depth / 8;
4091 if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
4092 if (memcmp(bits(), i.bits(), d->nbytes))
4095 for (
int y = 0; y < d->height; ++y) {
4096 if (memcmp(scanLine(y), i.scanLine(y), n))
4101 const int w = width();
4102 const int h = height();
4103 const QList<QRgb> &colortable = d->colortable;
4104 const QList<QRgb> &icolortable = i.d->colortable;
4105 for (
int y=0; y<h; ++y) {
4106 for (
int x=0; x<w; ++x) {
4107 if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
4114 for(
int l = 0; l < d->height; l++) {
4116 const uint *p1 =
reinterpret_cast<
const uint*>(scanLine(l));
4117 const uint *p2 =
reinterpret_cast<
const uint*>(i.scanLine(l));
4119 if ((*p1++ & 0x00ffffff) != (*p2++ & 0x00ffffff))
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4141bool QImage::operator!=(
const QImage & i)
const
4143 return !(*
this == i);
4150
4151
4152
4153
4154
4155
4156
4157int QImage::dotsPerMeterX()
const
4159 return d ? qRound(d->dpmx) : 0;
4163
4164
4165
4166
4167
4168
4169
4170int QImage::dotsPerMeterY()
const
4172 return d ? qRound(d->dpmy) : 0;
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187void QImage::setDotsPerMeterX(
int x)
4189 if (!d || !x || d->dpmx == x)
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209void QImage::setDotsPerMeterY(
int y)
4211 if (!d || !y || d->dpmy == y)
4220
4221
4222
4223
4224
4225
4226
4227QPoint QImage::offset()
const
4229 return d ? d->offset : QPoint();
4234
4235
4236
4237
4238
4239
4240
4241void QImage::setOffset(
const QPoint& p)
4243 if (!d || d->offset == p)
4252
4253
4254
4255
4256
4257
4258
4259QStringList QImage::textKeys()
const
4261 return d ? QStringList(d->text.keys()) : QStringList();
4265
4266
4267
4268
4269
4270
4271QString QImage::text(
const QString &key)
const
4277 return d->text.value(key);
4280 for (
auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
4281 tmp += it.key() +
": "_L1 + it.value().simplified() +
"\n\n"_L1;
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311void QImage::setText(
const QString &key,
const QString &value)
4318 d->text.insert(key, value);
4322
4323
4324
4325
4326QPaintEngine *QImage::paintEngine()
const
4331 if (!d->paintEngine) {
4332 QPaintDevice *paintDevice =
const_cast<QImage *>(
this);
4333 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
4334 if (platformIntegration)
4335 d->paintEngine = platformIntegration->createImagePaintEngine(paintDevice);
4336 if (!d->paintEngine)
4337 d->paintEngine =
new QRasterPaintEngine(paintDevice);
4340 return d->paintEngine;
4345
4346
4347
4348
4349int QImage::metric(PaintDeviceMetric metric)
const
4362 return qRound(d->width * 1000 / d->dpmx);
4365 return qRound(d->height * 1000 / d->dpmy);
4368 return d->colortable.size();
4374 return qRound(d->dpmx * 0.0254);
4378 return qRound(d->dpmy * 0.0254);
4381 case PdmPhysicalDpiX:
4382 return qRound(d->dpmx * 0.0254);
4385 case PdmPhysicalDpiY:
4386 return qRound(d->dpmy * 0.0254);
4389 case PdmDevicePixelRatio:
4390 return d->devicePixelRatio;
4393 case PdmDevicePixelRatioScaled:
4394 return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
4397 case PdmDevicePixelRatioF_EncodedA:
4399 case PdmDevicePixelRatioF_EncodedB:
4400 return QPaintDevice::encodeMetricF(metric, d->devicePixelRatio);
4404 qWarning(
"QImage::metric(): Unhandled metric type %d", metric);
4413
4414
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4436#define IWX_MSB(b) if (trigx < maxws && trigy < maxhs) {
4437 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4438 (1
<< (7
-((trigx>>12
)&7
))))
4445#define IWX_LSB(b) if (trigx < maxws && trigy < maxhs) {
4446 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4447 (1
<< ((trigx>>12
)&7
)))
4454#define IWX_PIX(b) if (trigx < maxws && trigy < maxhs) {
4455 if ((*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4456 (1
<< (7
-((trigx>>12
)&7
)))) == 0
)
4463bool qt_xForm_helper(
const QTransform &trueMat,
int xoffset,
int type,
int depth,
4464 uchar *dptr, qsizetype dbpl,
int p_inc,
int dHeight,
4465 const uchar *sptr, qsizetype sbpl,
int sWidth,
int sHeight)
4467 int m11 =
int(trueMat.m11()*4096.0);
4468 int m12 =
int(trueMat.m12()*4096.0);
4469 int m21 =
int(trueMat.m21()*4096.0);
4470 int m22 =
int(trueMat.m22()*4096.0);
4471 int dx = qRound(trueMat.dx()*4096.0);
4472 int dy = qRound(trueMat.dy()*4096.0);
4474 int m21ydx = dx + (xoffset<<16) + (m11 + m21) / 2;
4475 int m22ydy = dy + (m12 + m22) / 2;
4478 uint maxws = sWidth<<12;
4479 uint maxhs = sHeight<<12;
4481 for (
int y=0; y<dHeight; y++) {
4484 uchar *maxp = dptr + dbpl;
4488 while (dptr < maxp) {
4489 if (trigx < maxws && trigy < maxhs)
4490 *dptr = *(sptr+sbpl*(trigy>>12)+(trigx>>12));
4498 while (dptr < maxp) {
4499 if (trigx < maxws && trigy < maxhs)
4500 *((ushort*)dptr) = *((
const ushort *)(sptr+sbpl*(trigy>>12) +
4510 while (dptr < maxp) {
4511 if (trigx < maxws && trigy < maxhs) {
4512 const uchar *p2 = sptr+sbpl*(trigy>>12) + ((trigx>>12)*3);
4524 while (dptr < maxp) {
4525 if (trigx < maxws && trigy < maxhs)
4526 *((uint*)dptr) = *((
const uint *)(sptr+sbpl*(trigy>>12) +
4541 while (dptr < maxp) {
4554 while (dptr < maxp) {
4579
4580
4581
4582
4583
4584
4585qint64 QImage::cacheKey()
const
4590 return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
4594
4595
4596
4597
4598
4599
4601bool QImage::isDetached()
const
4603 return d && d->ref.loadRelaxed() == 1;
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4626void QImage::setAlphaChannel(
const QImage &alphaChannel)
4628 if (!d || alphaChannel.isNull())
4631 if (d->paintEngine && d->paintEngine->isActive()) {
4632 qWarning(
"QImage::setAlphaChannel: "
4633 "Unable to set alpha channel while image is being painted on");
4637 const Format alphaFormat = qt_alphaVersionForPainting(d->format);
4638 if (d->format == alphaFormat)
4641 convertTo(alphaFormat);
4647 if (alphaChannel.format() == QImage::Format_Alpha8 || (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()))
4648 sourceImage = alphaChannel;
4650 sourceImage = alphaChannel.convertToFormat(QImage::Format_Grayscale8);
4651 if (!sourceImage.reinterpretAsFormat(QImage::Format_Alpha8))
4654 QPainter painter(
this);
4655 if (sourceImage.size() != size())
4656 painter.setRenderHint(QPainter::SmoothPixmapTransform);
4657 painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
4658 painter.drawImage(rect(), sourceImage);
4662
4663
4664
4665
4666
4667bool QImage::hasAlphaChannel()
const
4671 const QPixelFormat format = pixelFormat();
4672 if (format.alphaUsage() == QPixelFormat::UsesAlpha)
4674 if (format.colorModel() == QPixelFormat::Indexed)
4675 return d->has_alpha_clut;
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689int QImage::bitPlaneCount()
const
4694 switch (d->format) {
4695 case QImage::Format_Invalid:
4697 case QImage::Format_BGR30:
4698 case QImage::Format_RGB30:
4701 case QImage::Format_RGB32:
4702 case QImage::Format_RGBX8888:
4705 case QImage::Format_RGB666:
4708 case QImage::Format_RGB555:
4711 case QImage::Format_ARGB8555_Premultiplied:
4714 case QImage::Format_RGB444:
4717 case QImage::Format_RGBX64:
4718 case QImage::Format_RGBX16FPx4:
4721 case QImage::Format_RGBX32FPx4:
4725 bpc = qt_depthForFormat(d->format);
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742QImage QImage::smoothScaled(
int w,
int h)
const
4745 switch (src.format()) {
4746 case QImage::Format_RGB32:
4747 case QImage::Format_ARGB32_Premultiplied:
4748#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4749 case QImage::Format_RGBX8888:
4751 case QImage::Format_RGBA8888_Premultiplied:
4752#if QT_CONFIG(raster_64bit)
4753 case QImage::Format_RGBX64:
4754 case QImage::Format_RGBA64_Premultiplied:
4756 case QImage::Format_RGBA64:
4757 case QImage::Format_Grayscale16:
4758 src.convertTo(QImage::Format_RGBA64_Premultiplied);
4761#if QT_CONFIG(raster_fp)
4762 case QImage::Format_RGBX32FPx4:
4763 case QImage::Format_RGBA32FPx4_Premultiplied:
4765 case QImage::Format_RGBX16FPx4:
4766 src.convertTo(QImage::Format_RGBX32FPx4);
4768 case QImage::Format_RGBA16FPx4:
4769 case QImage::Format_RGBA16FPx4_Premultiplied:
4770 case QImage::Format_RGBA32FPx4:
4771 src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
4774 case QImage::Format_CMYK8888:
4777 if (src.hasAlphaChannel())
4778 src.convertTo(QImage::Format_ARGB32_Premultiplied);
4780 src.convertTo(QImage::Format_RGB32);
4782 src = qSmoothScaleImage(src, w, h);
4784 copyMetadata(src.d, d);
4788static QImage rotated90(
const QImage &image)
4790 QImage out(image.height(), image.width(), image.format());
4793 copyMetadata(QImageData::get(out), QImageData::get(image));
4794 if (image.colorCount() > 0)
4795 out.setColorTable(image.colorTable());
4796 int w = image.width();
4797 int h = image.height();
4798 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][2];
4800 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4802 for (
int y=0; y<h; ++y) {
4803 if (image.colorCount())
4804 for (
int x=0; x<w; ++x)
4805 out.setPixel(h-y-1, x, image.pixelIndex(x, y));
4807 for (
int x=0; x<w; ++x)
4808 out.setPixel(h-y-1, x, image.pixel(x, y));
4814static QImage rotated180(
const QImage &image)
4816 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][1];
4818 return image.flipped(Qt::Horizontal | Qt::Vertical);
4820 QImage out(image.width(), image.height(), image.format());
4823 copyMetadata(QImageData::get(out), QImageData::get(image));
4824 if (image.colorCount() > 0)
4825 out.setColorTable(image.colorTable());
4826 int w = image.width();
4827 int h = image.height();
4828 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4832static QImage rotated270(
const QImage &image)
4834 QImage out(image.height(), image.width(), image.format());
4837 copyMetadata(QImageData::get(out), QImageData::get(image));
4838 if (image.colorCount() > 0)
4839 out.setColorTable(image.colorTable());
4840 int w = image.width();
4841 int h = image.height();
4842 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][0];
4844 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4846 for (
int y=0; y<h; ++y) {
4847 if (image.colorCount())
4848 for (
int x=0; x<w; ++x)
4849 out.setPixel(y, w-x-1, image.pixelIndex(x, y));
4851 for (
int x=0; x<w; ++x)
4852 out.setPixel(y, w-x-1, image.pixel(x, y));
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4882QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(
const QTransform &matrix, Qt::TransformationMode mode )
const
4887 Q_TRACE_PARAM_REPLACE(
const QTransform &,
double[9]);
4888 Q_TRACE_SCOPE(QImage_transformed, QList<
double>({matrix.m11(), matrix.m12(), matrix.m13(),
4889 matrix.m21(), matrix.m22(), matrix.m23(),
4890 matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
4893 const int ws = width();
4894 const int hs = height();
4901 QTransform mat = trueMatrix(matrix, ws, hs);
4902 bool complex_xform =
false;
4903 bool scale_xform =
false;
4904 bool nonpaintable_scale_xform =
false;
4905 if (mat.type() <= QTransform::TxScale) {
4906 if (mat.type() == QTransform::TxNone)
4908 else if (mat.m11() == -1. && mat.m22() == -1.)
4909 return rotated180(*
this);
4911 hd = qRound(qAbs(mat.m22()) * hs);
4912 wd = qRound(qAbs(mat.m11()) * ws);
4916 if (hd * 2 < hs || wd * 2 < ws)
4917 nonpaintable_scale_xform =
true;
4919 if (format() == QImage::Format_CMYK8888)
4920 nonpaintable_scale_xform =
true;
4922 if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
4923 if (mat.m12() == 1. && mat.m21() == -1.)
4924 return rotated90(*
this);
4925 else if (mat.m12() == -1. && mat.m21() == 1.)
4926 return rotated270(*
this);
4929 QPolygonF a(QRectF(0, 0, ws, hs));
4931 QRect r = a.boundingRect().toAlignedRect();
4934 complex_xform =
true;
4937 if (wd == 0 || hd == 0)
4940 if (scale_xform && mode == Qt::SmoothTransformation) {
4942 case QImage::Format_RGB32:
4943 case QImage::Format_ARGB32_Premultiplied:
4944#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4945 case QImage::Format_RGBX8888:
4947 case QImage::Format_RGBA8888_Premultiplied:
4948#if QT_CONFIG(raster_64bit)
4949 case QImage::Format_RGBX64:
4950 case QImage::Format_RGBA64_Premultiplied:
4952 case QImage::Format_CMYK8888:
4954 if (mat.m11() > 0.0F && mat.m22() > 0.0F)
4955 return smoothScaled(wd, hd);
4961 if (nonpaintable_scale_xform
4962#if QT_CONFIG(qtgui_threadpool)
4963 || (ws * hs) >= (1<<20)
4967 if (mat.m11() < 0.0F && mat.m22() < 0.0F) {
4968 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal | Qt::Vertical);
4969 }
else if (mat.m11() < 0.0F) {
4970 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal);
4971 }
else if (mat.m22() < 0.0F) {
4972 scaledImage = smoothScaled(wd, hd).flipped(Qt::Vertical);
4974 scaledImage = smoothScaled(wd, hd);
4978 case QImage::Format_Mono:
4979 case QImage::Format_MonoLSB:
4980 case QImage::Format_Indexed8:
4983 return scaledImage.convertToFormat(format());
4990 qsizetype sbpl = bytesPerLine();
4991 const uchar *sptr = bits();
4993 QImage::Format target_format = d->format;
4995 if (complex_xform || mode == Qt::SmoothTransformation) {
4996 if (d->format < QImage::Format_RGB32 || (!hasAlphaChannel() && complex_xform)) {
4997 target_format = qt_alphaVersion(d->format);
5001 QImage dImage(wd, hd, target_format);
5004 if (target_format == QImage::Format_MonoLSB
5005 || target_format == QImage::Format_Mono
5006 || target_format == QImage::Format_Indexed8) {
5007 dImage.d->colortable = d->colortable;
5008 dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
5012 if (target_format == QImage::Format_Indexed8) {
5013 if (dImage.d->colortable.size() < 256) {
5015 dImage.d->colortable.append(0x0);
5016 memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
5018 memset(dImage.bits(), 0, dImage.d->nbytes);
5021 memset(dImage.bits(), 0x00, dImage.d->nbytes);
5023 if (target_format >= QImage::Format_RGB32 && target_format != QImage::Format_CMYK8888) {
5025 QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *
this;
5027 && (d->format == QImage::Format_MonoLSB
5028 || d->format == QImage::Format_Mono
5029 || d->format == QImage::Format_Indexed8)) {
5030 sImage.d->colortable = d->colortable;
5031 sImage.d->has_alpha_clut = d->has_alpha_clut;
5034 Q_ASSERT(sImage.devicePixelRatio() == 1);
5035 Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
5037 QPainter p(&dImage);
5038 if (mode == Qt::SmoothTransformation) {
5039 p.setRenderHint(QPainter::Antialiasing);
5040 p.setRenderHint(QPainter::SmoothPixmapTransform);
5042 p.setTransform(mat);
5043 p.drawImage(QPoint(0, 0), sImage);
5046 mat = mat.inverted(&invertible);
5052 qsizetype dbpl = dImage.bytesPerLine();
5053 qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
5055 copyMetadata(dImage.d, d);
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5081QTransform QImage::trueMatrix(
const QTransform &matrix,
int w,
int h)
5083 const QRectF rect(0, 0, w, h);
5084 const QRect mapped = matrix.mapRect(rect).toAlignedRect();
5085 const QPoint delta = mapped.topLeft();
5086 return matrix * QTransform().translate(-delta.x(), -delta.y());
5090
5091
5092
5093
5094
5095
5096void QImage::setColorSpace(
const QColorSpace &colorSpace)
5100 if (d->colorSpace == colorSpace)
5102 if (colorSpace.isValid() && !qt_compatibleColorModelSource(pixelFormat().colorModel(), colorSpace.colorModel()))
5105 detachMetadata(
false);
5107 d->colorSpace = colorSpace;
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122void QImage::convertToColorSpace(
const QColorSpace &colorSpace)
5124 if (!d || !d->colorSpace.isValid())
5126 if (!colorSpace.isValidTarget()) {
5127 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5130 if (d->colorSpace == colorSpace)
5132 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(),
5133 colorSpace.colorModel(), colorSpace.transformModel())) {
5134 *
this = convertedToColorSpace(colorSpace);
5137 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
5138 if (d->ref.loadRelaxed() != 1)
5139 detachMetadata(
false);
5140 d->colorSpace = colorSpace;
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156void QImage::convertToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
5158 if (!d || !d->colorSpace.isValid())
5160 if (!colorSpace.isValidTarget()) {
5161 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5164 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5165 colorSpace.colorModel(), colorSpace.transformModel())) {
5166 qWarning() <<
"QImage::convertToColorSpace: Color space is not compatible with format";
5170 if (d->colorSpace == colorSpace)
5171 return convertTo(format, flags);
5172 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5173 d->colorSpace = colorSpace;
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace)
const
5192 if (!d || !d->colorSpace.isValid())
5194 if (!colorSpace.isValidTarget()) {
5195 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5198 if (d->colorSpace == colorSpace)
5200 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
5201 image.setColorSpace(colorSpace);
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
const &
5221 if (!d || !d->colorSpace.isValid())
5223 if (!colorSpace.isValidTarget()) {
5224 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5227 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5228 colorSpace.colorModel(), colorSpace.transformModel())) {
5229 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5232 if (d->colorSpace == colorSpace)
5233 return convertedTo(format, flags);
5234 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5235 image.setColorSpace(colorSpace);
5239QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) &&
5241 if (!d || !d->colorSpace.isValid())
5243 if (!colorSpace.isValidTarget()) {
5244 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5247 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5248 colorSpace.colorModel(), colorSpace.transformModel())) {
5249 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5252 if (d->colorSpace == colorSpace)
5253 return convertedTo(format, flags);
5254 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5255 return std::move(*
this);
5259
5260
5261
5262
5263QColorSpace QImage::colorSpace()
const
5266 return QColorSpace();
5267 return d->colorSpace;
5271
5272
5273
5274
5275void QImage::applyColorTransform(
const QColorTransform &transform)
5277 if (transform.isIdentity())
5280 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
5281 !qt_compatibleColorModelTarget(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel,
5282 QColorTransformPrivate::get(transform)->colorSpaceOut->transformModel)) {
5283 qWarning() <<
"QImage::applyColorTransform can not apply format switching transform without switching format";
5290 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5291 for (
int i = 0; i < d->colortable.size(); ++i)
5292 d->colortable[i] = transform.map(d->colortable[i]);
5295 QImage::Format oldFormat = format();
5296 if (qt_fpColorPrecision(oldFormat)) {
5297 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5298 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5299 convertTo(QImage::Format_RGBA32FPx4);
5300 }
else if (depth() > 32) {
5301 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5302 && oldFormat != QImage::Format_RGBA64_Premultiplied)
5303 convertTo(QImage::Format_RGBA64);
5304 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5305 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5306 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5307 if (hasAlphaChannel())
5308 convertTo(QImage::Format_ARGB32);
5310 convertTo(QImage::Format_RGB32);
5313 QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
5315 case Format_ARGB32_Premultiplied:
5316 case Format_RGBA64_Premultiplied:
5317 case Format_RGBA32FPx4_Premultiplied:
5318 flags = QColorTransformPrivate::Premultiplied;
5320 case Format_Grayscale8:
5321 case Format_Grayscale16:
5323 case Format_CMYK8888:
5325 case Format_RGBX32FPx4:
5326 flags = QColorTransformPrivate::InputOpaque;
5330 case Format_RGBA32FPx4:
5336 std::function<
void(
int,
int)> transformSegment;
5338 if (format() == Format_Grayscale8) {
5339 transformSegment = [&](
int yStart,
int yEnd) {
5340 for (
int y = yStart; y < yEnd; ++y) {
5341 uint8_t *scanline =
reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
5342 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5345 }
else if (format() == Format_Grayscale16) {
5346 transformSegment = [&](
int yStart,
int yEnd) {
5347 for (
int y = yStart; y < yEnd; ++y) {
5348 uint16_t *scanline =
reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
5349 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5352 }
else if (qt_fpColorPrecision(format())) {
5353 transformSegment = [&](
int yStart,
int yEnd) {
5354 for (
int y = yStart; y < yEnd; ++y) {
5355 QRgbaFloat32 *scanline =
reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
5356 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5359 }
else if (depth() > 32) {
5360 transformSegment = [&](
int yStart,
int yEnd) {
5361 for (
int y = yStart; y < yEnd; ++y) {
5362 QRgba64 *scanline =
reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
5363 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5366 }
else if (oldFormat == QImage::Format_CMYK8888) {
5367 transformSegment = [&](
int yStart,
int yEnd) {
5368 for (
int y = yStart; y < yEnd; ++y) {
5369 QCmyk32 *scanline =
reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
5370 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5374 transformSegment = [&](
int yStart,
int yEnd) {
5375 for (
int y = yStart; y < yEnd; ++y) {
5376 QRgb *scanline =
reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
5377 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5382#if QT_CONFIG(qtgui_threadpool)
5383 int segments = (qsizetype(width()) * height()) >> 16;
5384 segments = std::min(segments, height());
5385 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5386 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5387 QLatch latch(segments);
5389 for (
int i = 0; i < segments; ++i) {
5390 int yn = (height() - y) / (segments - i);
5391 threadPool->start([&, y, yn]() {
5392 transformSegment(y, y + yn);
5400 transformSegment(0, height());
5402 if (oldFormat != format())
5403 *
this = std::move(*
this).convertToFormat(oldFormat);
5407
5408
5409
5410
5411
5412
5413
5414void QImage::applyColorTransform(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
5418 if (transform.isIdentity())
5419 return convertTo(toFormat, flags);
5421 *
this = colorTransformed(transform, toFormat, flags);
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436QImage QImage::colorTransformed(
const QColorTransform &transform)
const &
5440 if (transform.isIdentity())
5443 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5444 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5445 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5446 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5449 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5451 switch (outColorSpace->colorModel) {
5452 case QColorSpace::ColorModel::Rgb:
5453 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5454 case QColorSpace::ColorModel::Gray:
5455 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5456 case QColorSpace::ColorModel::Cmyk:
5457 return colorTransformed(transform, QImage::Format_CMYK8888);
5458 case QColorSpace::ColorModel::Undefined:
5464 QImage image = copy();
5465 image.applyColorTransform(transform);
5469static bool isRgb32Data(QImage::Format f)
5472 case QImage::Format_RGB32:
5473 case QImage::Format_ARGB32:
5474 case QImage::Format_ARGB32_Premultiplied:
5482static bool isRgb64Data(QImage::Format f)
5485 case QImage::Format_RGBX64:
5486 case QImage::Format_RGBA64:
5487 case QImage::Format_RGBA64_Premultiplied:
5495static bool isRgb32fpx4Data(QImage::Format f)
5498 case QImage::Format_RGBX32FPx4:
5499 case QImage::Format_RGBA32FPx4:
5500 case QImage::Format_RGBA32FPx4_Premultiplied:
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
const &
5525 if (toFormat == QImage::Format_Invalid)
5526 toFormat = format();
5527 if (transform.isIdentity())
5528 return convertedTo(toFormat, flags);
5530 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5531 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5532 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5533 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5536 if (!qt_compatibleColorModelTarget(toPixelFormat(toFormat).colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5537 qWarning() <<
"QImage::colorTransformed: Invalid output color space for transform";
5541 QImage fromImage = *
this;
5543 QImage::Format tmpFormat = toFormat;
5545 case QImage::Format_RGB32:
5546 case QImage::Format_ARGB32:
5547 case QImage::Format_ARGB32_Premultiplied:
5548 case QImage::Format_RGBX32FPx4:
5549 case QImage::Format_RGBA32FPx4:
5550 case QImage::Format_RGBA32FPx4_Premultiplied:
5551 case QImage::Format_RGBX64:
5552 case QImage::Format_RGBA64:
5553 case QImage::Format_RGBA64_Premultiplied:
5554 case QImage::Format_Grayscale8:
5555 case QImage::Format_Grayscale16:
5556 case QImage::Format_CMYK8888:
5559 case QImage::Format_RGB16:
5560 case QImage::Format_RGB444:
5561 case QImage::Format_RGB555:
5562 case QImage::Format_RGB666:
5563 case QImage::Format_RGB888:
5564 case QImage::Format_BGR888:
5565 case QImage::Format_RGBX8888:
5566 tmpFormat = QImage::Format_RGB32;
5568 case QImage::Format_Mono:
5569 case QImage::Format_MonoLSB:
5570 case QImage::Format_Indexed8:
5571 case QImage::Format_ARGB8565_Premultiplied:
5572 case QImage::Format_ARGB6666_Premultiplied:
5573 case QImage::Format_ARGB8555_Premultiplied:
5574 case QImage::Format_ARGB4444_Premultiplied:
5575 case QImage::Format_RGBA8888:
5576 case QImage::Format_RGBA8888_Premultiplied:
5577 tmpFormat = QImage::Format_ARGB32;
5579 case QImage::Format_BGR30:
5580 case QImage::Format_RGB30:
5581 tmpFormat = QImage::Format_RGBX64;
5583 case QImage::Format_A2BGR30_Premultiplied:
5584 case QImage::Format_A2RGB30_Premultiplied:
5585 tmpFormat = QImage::Format_RGBA64;
5587 case QImage::Format_RGBX16FPx4:
5588 case QImage::Format_RGBA16FPx4:
5589 case QImage::Format_RGBA16FPx4_Premultiplied:
5590 tmpFormat = QImage::Format_RGBA32FPx4;
5592 case QImage::Format_Alpha8:
5593 return convertedTo(QImage::Format_Alpha8);
5594 case QImage::Format_Invalid:
5595 case QImage::NImageFormats:
5599 QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
5600 QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
5602 if (inColorData != outColorData) {
5603 if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
5604 tmpFormat = QImage::Format_RGB32;
5605 else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
5606 tmpFormat = QImage::Format_Grayscale16;
5607 else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
5608 tmpFormat = QImage::Format_RGBX64;
5610 if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
5611 tmpFormat = QImage::Format_Grayscale16;
5612 else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
5613 tmpFormat = QImage::Format_RGBA32FPx4;
5614 else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(),
true))
5615 tmpFormat = QImage::Format_RGBA64;
5618 QImage toImage(size(), tmpFormat);
5619 copyMetadata(&toImage, *
this);
5621 std::function<
void(
int,
int)> transformSegment;
5622 QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
5624 if (inColorData != outColorData) {
5626 if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
5628 if (format() == QImage::Format_Grayscale8) {
5629 transformSegment = [&](
int yStart,
int yEnd) {
5630 for (
int y = yStart; y < yEnd; ++y) {
5631 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5632 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5633 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5637 transformSegment = [&](
int yStart,
int yEnd) {
5638 for (
int y = yStart; y < yEnd; ++y) {
5639 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5640 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5641 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5645 }
else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
5647 if (format() == QImage::Format_Grayscale8) {
5648 transformSegment = [&](
int yStart,
int yEnd) {
5649 for (
int y = yStart; y < yEnd; ++y) {
5650 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5651 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5652 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5656 transformSegment = [&](
int yStart,
int yEnd) {
5657 for (
int y = yStart; y < yEnd; ++y) {
5658 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5659 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5660 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5664 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
5666 if (tmpFormat == QImage::Format_Grayscale8) {
5667 fromImage.convertTo(QImage::Format_RGB32);
5668 transformSegment = [&](
int yStart,
int yEnd) {
5669 for (
int y = yStart; y < yEnd; ++y) {
5670 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5671 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5672 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5676 fromImage.convertTo(QImage::Format_RGBX64);
5677 transformSegment = [&](
int yStart,
int yEnd) {
5678 for (
int y = yStart; y < yEnd; ++y) {
5679 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5680 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5681 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5685 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
5687 if (tmpFormat == QImage::Format_Grayscale8) {
5688 transformSegment = [&](
int yStart,
int yEnd) {
5689 for (
int y = yStart; y < yEnd; ++y) {
5690 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5691 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5692 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5696 transformSegment = [&](
int yStart,
int yEnd) {
5697 for (
int y = yStart; y < yEnd; ++y) {
5698 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5699 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5700 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5704 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
5706 if (isRgb32Data(tmpFormat) ) {
5707 transformSegment = [&](
int yStart,
int yEnd) {
5708 for (
int y = yStart; y < yEnd; ++y) {
5709 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5710 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5711 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5714 }
else if (isRgb64Data(tmpFormat)) {
5715 transformSegment = [&](
int yStart,
int yEnd) {
5716 for (
int y = yStart; y < yEnd; ++y) {
5717 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5718 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5719 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5723 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5724 transformSegment = [&](
int yStart,
int yEnd) {
5725 for (
int y = yStart; y < yEnd; ++y) {
5726 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5727 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5728 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5732 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
5734 if (!fromImage.hasAlphaChannel())
5735 transFlags = QColorTransformPrivate::InputOpaque;
5736 else if (qPixelLayouts[fromImage.format()].premultiplied)
5737 transFlags = QColorTransformPrivate::Premultiplied;
5738 if (isRgb32Data(fromImage.format()) ) {
5739 transformSegment = [&](
int yStart,
int yEnd) {
5740 for (
int y = yStart; y < yEnd; ++y) {
5741 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5742 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5743 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5746 }
else if (isRgb64Data(fromImage.format())) {
5747 transformSegment = [&](
int yStart,
int yEnd) {
5748 for (
int y = yStart; y < yEnd; ++y) {
5749 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5750 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5751 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5755 Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
5756 transformSegment = [&](
int yStart,
int yEnd) {
5757 for (
int y = yStart; y < yEnd; ++y) {
5758 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5759 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5760 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5769 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5770 for (
int i = 0; i < d->colortable.size(); ++i)
5771 fromImage.d->colortable[i] = transform.map(d->colortable[i]);
5772 return fromImage.convertedTo(toFormat, flags);
5775 QImage::Format oldFormat = format();
5776 if (qt_fpColorPrecision(oldFormat)) {
5777 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5778 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5779 fromImage.convertTo(QImage::Format_RGBA32FPx4);
5780 }
else if (qt_highColorPrecision(oldFormat,
true)) {
5781 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5782 && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
5783 fromImage.convertTo(QImage::Format_RGBA64);
5784 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5785 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5786 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5787 if (hasAlphaChannel())
5788 fromImage.convertTo(QImage::Format_ARGB32);
5790 fromImage.convertTo(QImage::Format_RGB32);
5793 if (!fromImage.hasAlphaChannel())
5794 transFlags = QColorTransformPrivate::InputOpaque;
5795 else if (qPixelLayouts[fromImage.format()].premultiplied)
5796 transFlags = QColorTransformPrivate::Premultiplied;
5798 if (fromImage.format() == Format_Grayscale8) {
5799 transformSegment = [&](
int yStart,
int yEnd) {
5800 for (
int y = yStart; y < yEnd; ++y) {
5801 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5802 if (tmpFormat == Format_Grayscale8) {
5803 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5804 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5806 Q_ASSERT(tmpFormat == Format_Grayscale16);
5807 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5808 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5812 }
else if (fromImage.format() == Format_Grayscale16) {
5813 transformSegment = [&](
int yStart,
int yEnd) {
5814 for (
int y = yStart; y < yEnd; ++y) {
5815 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5816 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5817 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5820 }
else if (fromImage.format() == Format_CMYK8888) {
5821 Q_ASSERT(tmpFormat == Format_CMYK8888);
5822 transformSegment = [&](
int yStart,
int yEnd) {
5823 for (
int y = yStart; y < yEnd; ++y) {
5824 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5825 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5826 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5829 }
else if (isRgb32fpx4Data(fromImage.format())) {
5830 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5831 transformSegment = [&](
int yStart,
int yEnd) {
5832 for (
int y = yStart; y < yEnd; ++y) {
5833 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5834 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5835 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5838 }
else if (isRgb64Data(fromImage.format())) {
5839 transformSegment = [&](
int yStart,
int yEnd) {
5840 for (
int y = yStart; y < yEnd; ++y) {
5841 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5842 if (isRgb32fpx4Data(tmpFormat)) {
5843 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5844 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5846 Q_ASSERT(isRgb64Data(tmpFormat));
5847 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5848 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5853 transformSegment = [&](
int yStart,
int yEnd) {
5854 for (
int y = yStart; y < yEnd; ++y) {
5855 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5856 if (isRgb32fpx4Data(tmpFormat)) {
5857 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5858 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5859 }
else if (isRgb64Data(tmpFormat)) {
5860 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5861 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5863 Q_ASSERT(isRgb32Data(tmpFormat));
5864 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5865 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5872#if QT_CONFIG(qtgui_threadpool)
5873 int segments = (qsizetype(width()) * height()) >> 16;
5874 segments = std::min(segments, height());
5875 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5876 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5877 QLatch latch(segments);
5879 for (
int i = 0; i < segments; ++i) {
5880 int yn = (height() - y) / (segments - i);
5881 threadPool->start([&, y, yn]() {
5882 transformSegment(y, y + yn);
5890 transformSegment(0, height());
5892 if (tmpFormat != toFormat)
5893 toImage.convertTo(toFormat);
5899
5900
5901
5902
5903
5904
5905
5906QImage QImage::colorTransformed(
const QColorTransform &transform) &&
5911 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5912 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5913 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5914 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5917 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5919 switch (outColorSpace->colorModel) {
5920 case QColorSpace::ColorModel::Rgb:
5921 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5922 case QColorSpace::ColorModel::Gray:
5923 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5924 case QColorSpace::ColorModel::Cmyk:
5925 return colorTransformed(transform, QImage::Format_CMYK8888);
5926 case QColorSpace::ColorModel::Undefined:
5932 applyColorTransform(transform);
5933 return std::move(*
this);
5937
5938
5939
5940
5941
5942
5943
5944QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
5947 return colorTransformed(transform, format, flags);
5950bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
5952 if (format == newFormat)
5956 if (ref.loadRelaxed() > 1 || !own_data)
5959 InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat];
5961 return converter(
this, flags);
5962 if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8 && !qimage_converter_map[format][newFormat]) {
5965 if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
5966 && qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
5967#if QT_CONFIG(raster_fp)
5968 if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
5969 return convert_generic_inplace_over_rgba32f(
this, newFormat, flags);
5971 return convert_generic_inplace_over_rgb64(
this, newFormat, flags);
5973 return convert_generic_inplace(
this, newFormat, flags);
5979
5980
5981
5984
5985
5986
5988#ifndef QT_NO_DEBUG_STREAM
5989QDebug operator<<(QDebug dbg,
const QImage &i)
5991 QDebugStateSaver saver(dbg);
5998 dbg << i.size() <<
",format=" << i.format() <<
",depth=" << i.depth();
6000 dbg <<
",colorCount=" << i.colorCount();
6001 const int bytesPerLine = i.bytesPerLine();
6002 dbg <<
",devicePixelRatio=" << i.devicePixelRatio()
6003 <<
",bytesPerLine=" << bytesPerLine <<
",sizeInBytes=" << i.sizeInBytes();
6004 if (dbg.verbosity() > 2 && i.height() > 0) {
6005 const int outputLength = qMin(bytesPerLine, 24);
6007 << QByteArray(
reinterpret_cast<
const char *>(i.scanLine(0)), outputLength).toHex()
6016static constexpr QPixelFormat pixelformats[] = {
6020 QPixelFormat(QPixelFormat::Indexed,
6027 QPixelFormat::IgnoresAlpha,
6028 QPixelFormat::AtBeginning,
6029 QPixelFormat::NotPremultiplied,
6030 QPixelFormat::UnsignedByte,
6031 QPixelFormat::BigEndian),
6033 QPixelFormat(QPixelFormat::Indexed,
6040 QPixelFormat::IgnoresAlpha,
6041 QPixelFormat::AtBeginning,
6042 QPixelFormat::NotPremultiplied,
6043 QPixelFormat::UnsignedByte,
6044 QPixelFormat::BigEndian),
6046 QPixelFormat(QPixelFormat::Indexed,
6053 QPixelFormat::IgnoresAlpha,
6054 QPixelFormat::AtBeginning,
6055 QPixelFormat::NotPremultiplied,
6056 QPixelFormat::UnsignedByte,
6057 QPixelFormat::BigEndian),
6059 QPixelFormat(QPixelFormat::RGB,
6066 QPixelFormat::IgnoresAlpha,
6067 QPixelFormat::AtBeginning,
6068 QPixelFormat::NotPremultiplied,
6069 QPixelFormat::UnsignedInteger,
6070 QPixelFormat::CurrentSystemEndian),
6072 QPixelFormat(QPixelFormat::RGB,
6079 QPixelFormat::UsesAlpha,
6080 QPixelFormat::AtBeginning,
6081 QPixelFormat::NotPremultiplied,
6082 QPixelFormat::UnsignedInteger,
6083 QPixelFormat::CurrentSystemEndian),
6085 QPixelFormat(QPixelFormat::RGB,
6092 QPixelFormat::UsesAlpha,
6093 QPixelFormat::AtBeginning,
6094 QPixelFormat::Premultiplied,
6095 QPixelFormat::UnsignedInteger,
6096 QPixelFormat::CurrentSystemEndian),
6098 QPixelFormat(QPixelFormat::RGB,
6105 QPixelFormat::IgnoresAlpha,
6106 QPixelFormat::AtBeginning,
6107 QPixelFormat::NotPremultiplied,
6108 QPixelFormat::UnsignedShort,
6109 QPixelFormat::CurrentSystemEndian),
6111 QPixelFormat(QPixelFormat::RGB,
6118 QPixelFormat::UsesAlpha,
6119 QPixelFormat::AtBeginning,
6120 QPixelFormat::Premultiplied,
6121 QPixelFormat::UnsignedInteger,
6122 QPixelFormat::CurrentSystemEndian),
6124 QPixelFormat(QPixelFormat::RGB,
6131 QPixelFormat::IgnoresAlpha,
6132 QPixelFormat::AtBeginning,
6133 QPixelFormat::NotPremultiplied,
6134 QPixelFormat::UnsignedInteger,
6135 QPixelFormat::CurrentSystemEndian),
6137 QPixelFormat(QPixelFormat::RGB,
6144 QPixelFormat::UsesAlpha,
6145 QPixelFormat::AtEnd,
6146 QPixelFormat::Premultiplied,
6147 QPixelFormat::UnsignedInteger,
6148 QPixelFormat::CurrentSystemEndian),
6150 QPixelFormat(QPixelFormat::RGB,
6157 QPixelFormat::IgnoresAlpha,
6158 QPixelFormat::AtBeginning,
6159 QPixelFormat::NotPremultiplied,
6160 QPixelFormat::UnsignedShort,
6161 QPixelFormat::CurrentSystemEndian),
6163 QPixelFormat(QPixelFormat::RGB,
6170 QPixelFormat::UsesAlpha,
6171 QPixelFormat::AtBeginning,
6172 QPixelFormat::Premultiplied,
6173 QPixelFormat::UnsignedInteger,
6174 QPixelFormat::CurrentSystemEndian),
6176 QPixelFormat(QPixelFormat::RGB,
6183 QPixelFormat::IgnoresAlpha,
6184 QPixelFormat::AtBeginning,
6185 QPixelFormat::NotPremultiplied,
6186 QPixelFormat::UnsignedByte,
6187 QPixelFormat::BigEndian),
6189 QPixelFormat(QPixelFormat::RGB,
6196 QPixelFormat::IgnoresAlpha,
6197 QPixelFormat::AtBeginning,
6198 QPixelFormat::NotPremultiplied,
6199 QPixelFormat::UnsignedShort,
6200 QPixelFormat::CurrentSystemEndian),
6202 QPixelFormat(QPixelFormat::RGB,
6209 QPixelFormat::UsesAlpha,
6210 QPixelFormat::AtBeginning,
6211 QPixelFormat::Premultiplied,
6212 QPixelFormat::UnsignedShort,
6213 QPixelFormat::CurrentSystemEndian),
6215 QPixelFormat(QPixelFormat::RGB,
6222 QPixelFormat::IgnoresAlpha,
6223 QPixelFormat::AtEnd,
6224 QPixelFormat::NotPremultiplied,
6225 QPixelFormat::UnsignedByte,
6226 QPixelFormat::BigEndian),
6228 QPixelFormat(QPixelFormat::RGB,
6235 QPixelFormat::UsesAlpha,
6236 QPixelFormat::AtEnd,
6237 QPixelFormat::NotPremultiplied,
6238 QPixelFormat::UnsignedByte,
6239 QPixelFormat::BigEndian),
6241 QPixelFormat(QPixelFormat::RGB,
6248 QPixelFormat::UsesAlpha,
6249 QPixelFormat::AtEnd,
6250 QPixelFormat::Premultiplied,
6251 QPixelFormat::UnsignedByte,
6252 QPixelFormat::BigEndian),
6254 QPixelFormat(QPixelFormat::BGR,
6261 QPixelFormat::IgnoresAlpha,
6262 QPixelFormat::AtBeginning,
6263 QPixelFormat::NotPremultiplied,
6264 QPixelFormat::UnsignedInteger,
6265 QPixelFormat::CurrentSystemEndian),
6267 QPixelFormat(QPixelFormat::BGR,
6274 QPixelFormat::UsesAlpha,
6275 QPixelFormat::AtBeginning,
6276 QPixelFormat::Premultiplied,
6277 QPixelFormat::UnsignedInteger,
6278 QPixelFormat::CurrentSystemEndian),
6280 QPixelFormat(QPixelFormat::RGB,
6287 QPixelFormat::IgnoresAlpha,
6288 QPixelFormat::AtBeginning,
6289 QPixelFormat::NotPremultiplied,
6290 QPixelFormat::UnsignedInteger,
6291 QPixelFormat::CurrentSystemEndian),
6293 QPixelFormat(QPixelFormat::RGB,
6300 QPixelFormat::UsesAlpha,
6301 QPixelFormat::AtBeginning,
6302 QPixelFormat::Premultiplied,
6303 QPixelFormat::UnsignedInteger,
6304 QPixelFormat::CurrentSystemEndian),
6306 QPixelFormat(QPixelFormat::Alpha,
6313 QPixelFormat::UsesAlpha,
6314 QPixelFormat::AtBeginning,
6315 QPixelFormat::Premultiplied,
6316 QPixelFormat::UnsignedByte,
6317 QPixelFormat::BigEndian),
6319 QPixelFormat(QPixelFormat::Grayscale,
6326 QPixelFormat::IgnoresAlpha,
6327 QPixelFormat::AtBeginning,
6328 QPixelFormat::NotPremultiplied,
6329 QPixelFormat::UnsignedByte,
6330 QPixelFormat::BigEndian),
6332 QPixelFormat(QPixelFormat::RGB,
6339 QPixelFormat::IgnoresAlpha,
6340 QPixelFormat::AtEnd,
6341 QPixelFormat::NotPremultiplied,
6342 QPixelFormat::UnsignedShort,
6343 QPixelFormat::CurrentSystemEndian),
6345 QPixelFormat(QPixelFormat::RGB,
6352 QPixelFormat::UsesAlpha,
6353 QPixelFormat::AtEnd,
6354 QPixelFormat::NotPremultiplied,
6355 QPixelFormat::UnsignedShort,
6356 QPixelFormat::CurrentSystemEndian),
6358 QPixelFormat(QPixelFormat::RGB,
6365 QPixelFormat::UsesAlpha,
6366 QPixelFormat::AtEnd,
6367 QPixelFormat::Premultiplied,
6368 QPixelFormat::UnsignedShort,
6369 QPixelFormat::CurrentSystemEndian),
6371 QPixelFormat(QPixelFormat::Grayscale,
6378 QPixelFormat::IgnoresAlpha,
6379 QPixelFormat::AtBeginning,
6380 QPixelFormat::NotPremultiplied,
6381 QPixelFormat::UnsignedShort,
6382 QPixelFormat::CurrentSystemEndian),
6384 QPixelFormat(QPixelFormat::BGR,
6391 QPixelFormat::IgnoresAlpha,
6392 QPixelFormat::AtBeginning,
6393 QPixelFormat::NotPremultiplied,
6394 QPixelFormat::UnsignedByte,
6395 QPixelFormat::BigEndian),
6397 QPixelFormat(QPixelFormat::RGB,
6404 QPixelFormat::IgnoresAlpha,
6405 QPixelFormat::AtEnd,
6406 QPixelFormat::NotPremultiplied,
6407 QPixelFormat::FloatingPoint,
6408 QPixelFormat::CurrentSystemEndian),
6410 QPixelFormat(QPixelFormat::RGB,
6417 QPixelFormat::UsesAlpha,
6418 QPixelFormat::AtEnd,
6419 QPixelFormat::NotPremultiplied,
6420 QPixelFormat::FloatingPoint,
6421 QPixelFormat::CurrentSystemEndian),
6423 QPixelFormat(QPixelFormat::RGB,
6430 QPixelFormat::UsesAlpha,
6431 QPixelFormat::AtEnd,
6432 QPixelFormat::Premultiplied,
6433 QPixelFormat::FloatingPoint,
6434 QPixelFormat::CurrentSystemEndian),
6436 QPixelFormat(QPixelFormat::RGB,
6443 QPixelFormat::IgnoresAlpha,
6444 QPixelFormat::AtEnd,
6445 QPixelFormat::NotPremultiplied,
6446 QPixelFormat::FloatingPoint,
6447 QPixelFormat::CurrentSystemEndian),
6449 QPixelFormat(QPixelFormat::RGB,
6456 QPixelFormat::UsesAlpha,
6457 QPixelFormat::AtEnd,
6458 QPixelFormat::NotPremultiplied,
6459 QPixelFormat::FloatingPoint,
6460 QPixelFormat::CurrentSystemEndian),
6462 QPixelFormat(QPixelFormat::RGB,
6469 QPixelFormat::UsesAlpha,
6470 QPixelFormat::AtEnd,
6471 QPixelFormat::Premultiplied,
6472 QPixelFormat::FloatingPoint,
6473 QPixelFormat::CurrentSystemEndian),
6475 QPixelFormat(QPixelFormat::CMYK,
6482 QPixelFormat::IgnoresAlpha,
6483 QPixelFormat::AtBeginning,
6484 QPixelFormat::NotPremultiplied,
6485 QPixelFormat::UnsignedInteger,
6486 QPixelFormat::CurrentSystemEndian),
6488static_assert(
sizeof(pixelformats) /
sizeof(*pixelformats) == QImage::NImageFormats);
6491
6492
6493QPixelFormat QImage::pixelFormat()
const noexcept
6495 return toPixelFormat(format());
6499
6500
6501QPixelFormat QImage::toPixelFormat(QImage::Format format)
noexcept
6503 Q_ASSERT(
static_cast<
int>(format) < NImageFormats &&
static_cast<
int>(format) >= 0);
6504 return pixelformats[format];
6508
6509
6510QImage::Format QImage::toImageFormat(QPixelFormat format)
noexcept
6512 for (
int i = 0; i < NImageFormats; i++) {
6513 if (format == pixelformats[i])
6516 return Format_Invalid;
6521 Qt::Orientations orients = {};
6522 if (orient.testFlag(QImageIOHandler::TransformationMirror))
6523 orients |= Qt::Horizontal;
6524 if (orient.testFlag(QImageIOHandler::TransformationFlip))
6525 orients |= Qt::Vertical;
6531 if (orient == QImageIOHandler::TransformationNone)
6533 if (orient == QImageIOHandler::TransformationRotate270) {
6534 src = rotated270(src);
6536 src.flip(toOrientations(orient));
6537 if (orient & QImageIOHandler::TransformationRotate90)
6538 src = rotated90(src);
6544 QMap<QString, QString> text = qt_getImageTextFromDescription(description);
6545 const auto textKeys = image.textKeys();
6546 for (
const QString &key : textKeys) {
6547 if (!key.isEmpty() && !text.contains(key))
6548 text.insert(key, image.text(key));
6555 QMap<QString, QString> text;
6556 for (
const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
6557 int index = pair.indexOf(u':');
6558 if (index >= 0 && pair.indexOf(u' ') < index) {
6559 if (!pair.trimmed().isEmpty())
6560 text.insert(
"Description"_L1, pair.toString().simplified());
6562 const auto key = pair.left(index);
6563 if (!key.trimmed().isEmpty())
6564 text.insert(key.toString(), pair.mid(index + 2).toString().simplified());
6572#include "moc_qimage.cpp"
Combined button and popup list for selecting options.
Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;")
static QImage rotated90(const QImage &src)
static void copyMetadata(QImage *dst, const QImage &src)
#define QT_XFORM_TYPE_LSBFIRST
static void copyMetadata(QImageData *dst, const QImageData *src)
#define QT_XFORM_TYPE_MSBFIRST
static int next_qimage_serial_number()
#define QIMAGE_SANITYCHECK_MEMORY(image)
static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
static QImage rotated270(const QImage &src)
QMap< QString, QString > qt_getImageText(const QImage &image, const QString &description)
Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
static QImage rotated180(const QImage &src)
static Qt::Orientations toOrientations(QImageIOHandler::Transformations orient)
QMap< QString, QString > qt_getImageTextFromDescription(const QString &description)