18#include <qpa/qplatformintegration.h>
19#include <private/qguiapplication_p.h>
23#include <qpa/qplatformpixmap.h>
24#include <private/qcolorspace_p.h>
25#include <private/qcolortransform_p.h>
26#include <private/qmemrotate_p.h>
27#include <private/qimagescale_p.h>
28#include <private/qpixellayout_p.h>
29#include <private/qsimd_p.h>
33#include <private/qpaintengine_raster_p.h>
35#include <private/qimage_p.h>
36#include <private/qfont_p.h>
38#if QT_CONFIG(qtgui_threadpool)
39#include <qsemaphore.h>
40#include <qthreadpool.h>
41#include <private/qthreadpool_p.h>
44#include <qtgui_tracepoints_p.h>
51using namespace Qt::StringLiterals;
56QT_WARNING_DISABLE_MSVC(4723)
58#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0
>= 50190001
)
59#pragma message disable narrowptr
63#define QIMAGE_SANITYCHECK_MEMORY(image)
64 if ((image).isNull()) {
65 qWarning("QImage: out of memory, returning null image");
70 "#include <qimagereader.h>"
74"ENUM { } QImage::Format;" \
75"FLAGS { } Qt::ImageConversionFlags;"
78Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode,
int);
79Q_TRACE_PARAM_REPLACE(Qt::TransformationMode,
int);
81static QImage
rotated90(
const QImage &src);
87 Q_CONSTINIT
static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
88 return 1 + serial.fetchAndAddRelaxed(1);
91QImageData::QImageData()
92 : ref(0), width(0), height(0), depth(0), nbytes(0), devicePixelRatio(1.0), data(
nullptr),
93 format(QImage::Format_ARGB32), bytes_per_line(0),
94 ser_no(next_qimage_serial_number()),
96 dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
97 dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
98 offset(0, 0), own_data(
true), ro_data(
false), has_alpha_clut(
false),
99 is_cached(
false), cleanupFunction(
nullptr), cleanupInfo(
nullptr),
105
106
107
108
109
110
111QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(
const QSize &size, QImage::Format format)
113 if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
116 Q_TRACE_SCOPE(QImageData_create, size, format);
118 int width = size.width();
119 int height = size.height();
120 int depth = qt_depthForFormat(format);
121 auto params = calculateImageParameters(width, height, depth);
122 if (!params.isValid())
125 auto d = std::make_unique<QImageData>();
128 case QImage::Format_Mono:
129 case QImage::Format_MonoLSB:
130 d->colortable.resize(2);
131 d->colortable[0] = QColor(Qt::black).rgba();
132 d->colortable[1] = QColor(Qt::white).rgba();
142 d->has_alpha_clut =
false;
143 d->is_cached =
false;
145 d->bytes_per_line = params.bytesPerLine;
146 d->nbytes = params.totalSize;
147 d->data = (uchar *)malloc(d->nbytes);
156QImageData::~QImageData()
159 cleanupFunction(cleanupInfo);
161 QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
163 if (data && own_data)
168#if defined(_M_ARM) && defined(_MSC_VER)
169#pragma optimize("", off)
172bool QImageData::checkForAlphaPixels()
const
174 bool has_alpha_pixels =
false;
178 case QImage::Format_Mono:
179 case QImage::Format_MonoLSB:
180 case QImage::Format_Indexed8:
181 has_alpha_pixels = has_alpha_clut;
183 case QImage::Format_Alpha8:
184 has_alpha_pixels =
true;
186 case QImage::Format_ARGB32:
187 case QImage::Format_ARGB32_Premultiplied: {
188 const uchar *bits = data;
189 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
190 uint alphaAnd = 0xff000000;
191 for (
int x=0; x<width; ++x)
192 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
193 has_alpha_pixels = (alphaAnd != 0xff000000);
194 bits += bytes_per_line;
198 case QImage::Format_RGBA8888:
199 case QImage::Format_RGBA8888_Premultiplied: {
200 const uchar *bits = data;
201 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
202 uchar alphaAnd = 0xff;
203 for (
int x=0; x<width; ++x)
204 alphaAnd &= bits[x * 4+ 3];
205 has_alpha_pixels = (alphaAnd != 0xff);
206 bits += bytes_per_line;
210 case QImage::Format_A2BGR30_Premultiplied:
211 case QImage::Format_A2RGB30_Premultiplied: {
212 const uchar *bits = data;
213 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
214 uint alphaAnd = 0xc0000000;
215 for (
int x=0; x<width; ++x)
216 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
217 has_alpha_pixels = (alphaAnd != 0xc0000000);
218 bits += bytes_per_line;
222 case QImage::Format_ARGB8555_Premultiplied:
223 case QImage::Format_ARGB8565_Premultiplied: {
224 const uchar *bits = data;
225 const uchar *end_bits = data + bytes_per_line;
227 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
228 uchar alphaAnd = 0xff;
229 while (bits < end_bits) {
233 has_alpha_pixels = (alphaAnd != 0xff);
235 end_bits += bytes_per_line;
239 case QImage::Format_ARGB6666_Premultiplied: {
240 const uchar *bits = data;
241 const uchar *end_bits = data + bytes_per_line;
243 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
244 uchar alphaAnd = 0xfc;
245 while (bits < end_bits) {
249 has_alpha_pixels = (alphaAnd != 0xfc);
251 end_bits += bytes_per_line;
255 case QImage::Format_ARGB4444_Premultiplied: {
256 const uchar *bits = data;
257 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
258 ushort alphaAnd = 0xf000;
259 for (
int x=0; x<width; ++x)
260 alphaAnd &=
reinterpret_cast<
const ushort*>(bits)[x];
261 has_alpha_pixels = (alphaAnd != 0xf000);
262 bits += bytes_per_line;
265 case QImage::Format_RGBA64:
266 case QImage::Format_RGBA64_Premultiplied: {
268 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
269 for (
int x=0; x<width; ++x) {
270 has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
272 bits += bytes_per_line;
275 case QImage::Format_RGBA16FPx4:
276 case QImage::Format_RGBA16FPx4_Premultiplied: {
278 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
279 for (
int x = 0; x < width; ++x)
280 has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
281 bits += bytes_per_line;
284 case QImage::Format_RGBA32FPx4:
285 case QImage::Format_RGBA32FPx4_Premultiplied: {
287 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
288 for (
int x = 0; x < width; ++x)
289 has_alpha_pixels |= ((
float *)bits)[x * 4 + 3] < 1.0f;
290 bits += bytes_per_line;
294 case QImage::Format_RGB32:
295 case QImage::Format_RGB16:
296 case QImage::Format_RGB444:
297 case QImage::Format_RGB555:
298 case QImage::Format_RGB666:
299 case QImage::Format_RGB888:
300 case QImage::Format_BGR888:
301 case QImage::Format_RGBX8888:
302 case QImage::Format_BGR30:
303 case QImage::Format_RGB30:
304 case QImage::Format_Grayscale8:
305 case QImage::Format_Grayscale16:
306 case QImage::Format_RGBX64:
307 case QImage::Format_RGBX16FPx4:
308 case QImage::Format_RGBX32FPx4:
309 case QImage::Format_CMYK8888:
311 case QImage::Format_Invalid:
312 case QImage::NImageFormats:
317 return has_alpha_pixels;
319#if defined(_M_ARM) && defined(_MSC_VER)
320#pragma optimize("", on)
324
325
326
327
328
329
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
625
626
627
628
629
630
631
634
635
636
637
638
639
643
644
645
646
647
648
649
650
651
652
655
656
657
658
659
660
661
662
663
664
665
666
669
670
671
672
673
674
675
676
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
780
781
784
785
786
787
789QImage::QImage()
noexcept
796
797
798
799
800
801
802
803
804
805QImage::QImage(
int width,
int height, Format format)
806 : QImage(QSize(width, height), format)
811
812
813
814
815
816
817
818
819QImage::QImage(
const QSize &size, Format format)
822 d = QImageData::create(size, format);
827QImageData *QImageData::create(uchar *data,
int width,
int height, qsizetype bpl, QImage::Format format,
bool readOnly, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
829 if (width <= 0 || height <= 0 || !data || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
832 const int depth = qt_depthForFormat(format);
833 auto params = calculateImageParameters(width, height, depth);
834 if (!params.isValid())
839 const qsizetype min_bytes_per_line = (qsizetype(width) * depth + 7)/8;
840 if (bpl < min_bytes_per_line)
844 params.bytesPerLine = bpl;
845 if (qMulOverflow<qsizetype>(bpl, height, ¶ms.totalSize))
849 QImageData *d =
new QImageData;
853 d->ro_data = readOnly;
860 d->bytes_per_line = params.bytesPerLine;
861 d->nbytes = params.totalSize;
863 d->cleanupFunction = cleanupFunction;
864 d->cleanupInfo = cleanupInfo;
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886QImage::QImage(uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
889 d = QImageData::create(data, width, height, 0, format,
false, cleanupFunction, cleanupInfo);
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917QImage::QImage(
const uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
920 d = QImageData::create(
const_cast<uchar*>(data), width, height, 0, format,
true, cleanupFunction, cleanupInfo);
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
941QImage::QImage(uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
944 d = QImageData::create(data, width, height, bytesPerLine, format,
false, cleanupFunction, cleanupInfo);
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
972QImage::QImage(
const uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
975 d = QImageData::create(
const_cast<uchar*>(data), width, height, bytesPerLine, format,
true, cleanupFunction, cleanupInfo);
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
998QImage::QImage(
const QString &fileName,
const char *format)
1002 load(fileName, format);
1005#ifndef QT_NO_IMAGEFORMAT_XPM
1006extern bool qt_read_xpm_image_or_array(QIODevice *device,
const char *
const *source, QImage &image);
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1024QImage::QImage(
const char *
const xpm[])
1030 if (!qt_read_xpm_image_or_array(
nullptr, xpm, *
this))
1032 qWarning(
"QImage::QImage(), XPM is not supported");
1037
1038
1039
1040
1041
1042
1043
1045QImage::QImage(
const QImage &image)
1048 if (image.paintingActive()) {
1050 image.copy().swap(*
this);
1059
1060
1064 if (d && !d->ref.deref())
1069
1070
1071
1072
1073
1074
1075
1076
1078QImage &QImage::operator=(
const QImage &image)
1080 if (image.paintingActive()) {
1081 operator=(image.copy());
1085 if (d && !d->ref.deref())
1093
1094
1095
1098
1099
1100int QImage::devType()
const
1102 return QInternal::Image;
1106
1107
1108QImage::operator QVariant()
const
1110 return QVariant::fromValue(*
this);
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124void QImage::detach()
1127 if (d->is_cached && d->ref.loadRelaxed() == 1)
1128 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1130 if (d->ref.loadRelaxed() != 1 || d->ro_data)
1140
1141
1142
1143
1144
1145
1146
1147void QImage::detachMetadata(
bool invalidateCache)
1150 if (d->is_cached && d->ref.loadRelaxed() == 1)
1151 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1153 if (d->ref.loadRelaxed() != 1)
1156 if (d && invalidateCache)
1163 dst->dpmx = src->dpmx;
1164 dst->dpmy = src->dpmy;
1165 dst->devicePixelRatio = src->devicePixelRatio;
1172 dst->text = src->text;
1173 dst->offset = src->offset;
1174 dst->colorSpace = src->colorSpace;
1179 dst->setDotsPerMeterX(src.dotsPerMeterX());
1180 dst->setDotsPerMeterY(src.dotsPerMeterY());
1181 dst->setDevicePixelRatio(src.devicePixelRatio());
1182 const auto textKeys = src.textKeys();
1183 for (
const auto &key: textKeys)
1184 dst->setText(key, src.text(key));
1189
1190
1191
1192
1193
1194
1195
1196
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(
const QRect& r)
const
1220 Q_TRACE_SCOPE(QImage_copy, r);
1225 QImage image(d->width, d->height, d->format);
1231 if (image.d->nbytes != d->nbytes) {
1232 qsizetype bpl = qMin(bytesPerLine(), image.bytesPerLine());
1233 for (
int i = 0; i < height(); i++)
1234 memcpy(image.scanLine(i), scanLine(i), bpl);
1236 memcpy(image.bits(), bits(), d->nbytes);
1237 image.d->colortable = d->colortable;
1238 image.d->has_alpha_clut = d->has_alpha_clut;
1239 copyMetadata(image.d, d);
1250 if (w <= 0 || h <= 0)
1253 QImage image(w, h, d->format);
1257 if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {
1270 image.d->colortable = d->colortable;
1272 int pixels_to_copy = qMax(w - dx, 0);
1275 else if (pixels_to_copy > d->width - x)
1276 pixels_to_copy = d->width - x;
1277 int lines_to_copy = qMax(h - dy, 0);
1280 else if (lines_to_copy > d->height - y)
1281 lines_to_copy = d->height - y;
1283 bool byteAligned =
true;
1284 if (d->format == Format_Mono || d->format == Format_MonoLSB)
1285 byteAligned = !(dx & 7) && !(x & 7) && !(pixels_to_copy & 7);
1288 const uchar *src = d->data + ((x * d->depth) >> 3) + y * d->bytes_per_line;
1289 uchar *dest = image.d->data + ((dx * d->depth) >> 3) + dy * image.d->bytes_per_line;
1290 const qsizetype bytes_to_copy = (qsizetype(pixels_to_copy) * d->depth) >> 3;
1291 for (
int i = 0; i < lines_to_copy; ++i) {
1292 memcpy(dest, src, bytes_to_copy);
1293 src += d->bytes_per_line;
1294 dest += image.d->bytes_per_line;
1296 }
else if (d->format == Format_Mono) {
1297 const uchar *src = d->data + y * d->bytes_per_line;
1298 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1299 for (
int i = 0; i < lines_to_copy; ++i) {
1300 for (
int j = 0; j < pixels_to_copy; ++j) {
1301 if (src[(x + j) >> 3] & (0x80 >> ((x + j) & 7)))
1302 dest[(dx + j) >> 3] |= (0x80 >> ((dx + j) & 7));
1304 dest[(dx + j) >> 3] &= ~(0x80 >> ((dx + j) & 7));
1306 src += d->bytes_per_line;
1307 dest += image.d->bytes_per_line;
1310 Q_ASSERT(d->format == Format_MonoLSB);
1311 const uchar *src = d->data + y * d->bytes_per_line;
1312 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1313 for (
int i = 0; i < lines_to_copy; ++i) {
1314 for (
int j = 0; j < pixels_to_copy; ++j) {
1315 if (src[(x + j) >> 3] & (0x1 << ((x + j) & 7)))
1316 dest[(dx + j) >> 3] |= (0x1 << ((dx + j) & 7));
1318 dest[(dx + j) >> 3] &= ~(0x1 << ((dx + j) & 7));
1320 src += d->bytes_per_line;
1321 dest += image.d->bytes_per_line;
1325 copyMetadata(image.d, d);
1326 image.d->has_alpha_clut = d->has_alpha_clut;
1333
1334
1335
1336
1337
1338bool QImage::isNull()
const
1344
1345
1346
1347
1348
1349
1350int QImage::width()
const
1352 return d ? d->width : 0;
1356
1357
1358
1359
1360
1361
1362int QImage::height()
const
1364 return d ? d->height : 0;
1368
1369
1370
1371
1372
1373
1374QSize QImage::size()
const
1376 return d ? QSize(d->width, d->height) : QSize(0, 0);
1380
1381
1382
1383
1384
1385
1386
1387QRect QImage::rect()
const
1389 return d ? QRect(0, 0, d->width, d->height) : QRect();
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404int QImage::depth()
const
1406 return d ? d->depth : 0;
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420int QImage::colorCount()
const
1422 return d ? d->colortable.size() : 0;
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436void QImage::setColorTable(
const QList<QRgb> &colors)
1440 detachMetadata(
true);
1446 d->colortable = colors;
1447 d->has_alpha_clut =
false;
1448 for (
int i = 0; i < d->colortable.size(); ++i) {
1449 if (qAlpha(d->colortable.at(i)) != 255) {
1450 d->has_alpha_clut =
true;
1457
1458
1459
1460
1461
1462QList<QRgb> QImage::colorTable()
const
1464 return d ? d->colortable : QList<QRgb>();
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478qreal QImage::devicePixelRatio()
const
1482 return d->devicePixelRatio;
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506void QImage::setDevicePixelRatio(qreal scaleFactor)
1511 if (scaleFactor == d->devicePixelRatio)
1516 d->devicePixelRatio = scaleFactor;
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529QSizeF QImage::deviceIndependentSize()
const
1532 return QSizeF(0, 0);
1533 return QSizeF(d->width, d->height) / d->devicePixelRatio;
1538
1539
1540
1541
1542
1543
1544qsizetype QImage::sizeInBytes()
const
1546 return d ? d->nbytes : 0;
1550
1551
1552
1553
1554
1555
1556qsizetype QImage::bytesPerLine()
const
1558 return d ? d->bytes_per_line : 0;
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573QRgb QImage::color(
int i)
const
1575 Q_ASSERT(i < colorCount());
1576 return d ? d->colortable.at(i) : QRgb(uint(-1));
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591void QImage::setColor(
int i, QRgb c)
1595 if (i < 0 || d->depth > 8 || i >= 1<<d->depth) {
1596 qWarning(
"QImage::setColor: Index out of bound %d", i);
1599 detachMetadata(
true);
1605 if (i >= d->colortable.size())
1607 d->colortable[i] = c;
1608 d->has_alpha_clut |= (qAlpha(c) != 255);
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633uchar *QImage::scanLine(
int i)
1644 return d->data + i * d->bytes_per_line;
1648
1649
1650const uchar *QImage::scanLine(
int i)
const
1655 Q_ASSERT(i >= 0 && i < height());
1656 return d->data + i * d->bytes_per_line;
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674const uchar *QImage::constScanLine(
int i)
const
1679 Q_ASSERT(i >= 0 && i < height());
1680 return d->data + i * d->bytes_per_line;
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694uchar *QImage::bits()
1708
1709
1710
1711
1712
1713
1714const uchar *QImage::bits()
const
1716 return d ? d->data :
nullptr;
1721
1722
1723
1724
1725
1726
1727
1728
1729const uchar *QImage::constBits()
const
1731 return d ? d->data :
nullptr;
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1754void QImage::fill(uint pixel)
1765 if (d->depth == 1 || d->depth == 8) {
1767 if (d->depth == 1) {
1776 qt_rectfill<quint8>(d->data, pixel, 0, 0,
1777 w, d->height, d->bytes_per_line);
1779 }
else if (d->depth == 16) {
1780 if (d->format == Format_RGB444)
1782 qt_rectfill<quint16>(
reinterpret_cast<quint16*>(d->data), pixel,
1783 0, 0, d->width, d->height, d->bytes_per_line);
1785 }
else if (d->depth == 24) {
1786 if (d->format == Format_RGB666)
1788 qt_rectfill<quint24>(
reinterpret_cast<quint24*>(d->data), pixel,
1789 0, 0, d->width, d->height, d->bytes_per_line);
1791 }
else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
1792 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
1793 0, 0, d->width, d->height, d->bytes_per_line);
1795 }
else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
1797 QRgbaFloat16 cf = QRgbaFloat16::fromArgb32(pixel);
1798 ::memcpy(&cu, &cf,
sizeof(quint64));
1799 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), cu,
1800 0, 0, d->width, d->height, d->bytes_per_line);
1802 }
else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
1803 QRgbaFloat32 cf = QRgbaFloat32::fromArgb32(pixel);
1804 uchar *data = d->data;
1805 for (
int y = 0; y < d->height; ++y) {
1806 QRgbaFloat32 *line =
reinterpret_cast<QRgbaFloat32 *>(data);
1807 for (
int x = 0; x < d->width; ++x)
1809 data += d->bytes_per_line;
1813 Q_ASSERT(d->depth == 32);
1815 if (d->format == Format_RGB32)
1816 pixel |= 0xff000000;
1817 if (d->format == Format_RGBX8888)
1818#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1819 pixel |= 0xff000000;
1821 pixel |= 0x000000ff;
1823 if (d->format == Format_BGR30 || d->format == Format_RGB30)
1824 pixel |= 0xc0000000;
1826 qt_rectfill<uint>(
reinterpret_cast<uint*>(d->data), pixel,
1827 0, 0, d->width, d->height, d->bytes_per_line);
1832
1833
1834
1835
1836
1837
1839void QImage::fill(Qt::GlobalColor color)
1841 fill(QColor(color));
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1861void QImage::fill(
const QColor &color)
1871 QRgba64 opaque = color.rgba64();
1872 opaque.setAlpha(65535);
1873 switch (d->format) {
1874 case QImage::Format_RGB32:
1875 case QImage::Format_ARGB32:
1878 case QImage::Format_ARGB32_Premultiplied:
1879 fill(qPremultiply(color.rgba()));
1881 case QImage::Format_RGBX8888:
1882 fill(ARGB2RGBA(color.rgba() | 0xff000000));
1884 case QImage::Format_RGBA8888:
1885 fill(ARGB2RGBA(color.rgba()));
1887 case QImage::Format_RGBA8888_Premultiplied:
1888 fill(ARGB2RGBA(qPremultiply(color.rgba())));
1890 case QImage::Format_BGR30:
1891 fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
1893 case QImage::Format_RGB30:
1894 fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
1896 case QImage::Format_RGB16:
1897 fill((uint) qConvertRgb32To16(color.rgba()));
1899 case QImage::Format_Indexed8: {
1901 for (
int i=0; i<d->colortable.size(); ++i) {
1902 if (color.rgba() == d->colortable.at(i)) {
1910 case QImage::Format_Mono:
1911 case QImage::Format_MonoLSB:
1912 if (color == Qt::color1)
1917 case QImage::Format_RGBX64:
1918 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), opaque,
1919 0, 0, d->width, d->height, d->bytes_per_line);
1921 case QImage::Format_RGBA64:
1922 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), color.rgba64(),
1923 0, 0, d->width, d->height, d->bytes_per_line);
1925 case QImage::Format_RGBA64_Premultiplied:
1926 qt_rectfill<quint64>(
reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
1927 0, 0, d->width, d->height, d->bytes_per_line);
1929 case QImage::Format_RGBX16FPx4:
1930 case QImage::Format_RGBA16FPx4:
1931 case QImage::Format_RGBA16FPx4_Premultiplied:
1932 case QImage::Format_RGBX32FPx4:
1933 case QImage::Format_RGBA32FPx4:
1934 case QImage::Format_RGBA32FPx4_Premultiplied:{
1936 color.getRgbF(&r, &g, &b, &a);
1937 if (!hasAlphaChannel())
1939 if (depth() == 64) {
1940 QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
1941 if (d->format == Format_RGBA16FPx4_Premultiplied)
1942 c16 = c16.premultiplied();
1943 qt_rectfill<QRgbaFloat16>(
reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
1944 0, 0, d->width, d->height, d->bytes_per_line);
1946 QRgbaFloat32 c32{r, g, b, a};
1947 if (d->format == Format_RGBA32FPx4_Premultiplied)
1948 c32 = c32.premultiplied();
1949 qt_rectfill<QRgbaFloat32>(
reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
1950 0, 0, d->width, d->height, d->bytes_per_line);
1956 p.setCompositionMode(QPainter::CompositionMode_Source);
1957 p.fillRect(rect(), color);
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1983void QImage::invertPixels(InvertMode mode)
1994 QImage::Format originalFormat = d->format;
1996 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
1997 if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
1998 if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
1999 *
this = convertToFormat(QImage::Format_RGBA16FPx4);
2000 }
else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
2001 if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
2002 *
this = convertToFormat(QImage::Format_RGBA32FPx4);
2003 }
else if (depth() > 32) {
2004 if (!d->convertInPlace(QImage::Format_RGBA64, { }))
2005 *
this = convertToFormat(QImage::Format_RGBA64);
2007 if (!d->convertInPlace(QImage::Format_ARGB32, { }))
2008 *
this = convertToFormat(QImage::Format_ARGB32);
2014 qsizetype bpl = (qsizetype(d->width) * d->depth + 7) / 8;
2015 int pad = d->bytes_per_line - bpl;
2016 uchar *sl = d->data;
2017 for (
int y=0; y<d->height; ++y) {
2018 for (qsizetype x=0; x<bpl; ++x)
2022 }
else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
2023 qfloat16 *p =
reinterpret_cast<qfloat16 *>(d->data);
2024 qfloat16 *end =
reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
2026 p[0] = qfloat16(1) - p[0];
2027 p[1] = qfloat16(1) - p[1];
2028 p[2] = qfloat16(1) - p[2];
2029 if (mode == InvertRgba)
2030 p[3] = qfloat16(1) - p[3];
2033 }
else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
2034 uchar *data = d->data;
2035 for (
int y = 0; y < d->height; ++y) {
2036 float *p =
reinterpret_cast<
float *>(data);
2037 for (
int x = 0; x < d->width; ++x) {
2041 if (mode == InvertRgba)
2045 data += d->bytes_per_line;
2047 }
else if (depth() == 64) {
2048 quint16 *p = (quint16*)d->data;
2049 quint16 *end = (quint16*)(d->data + d->nbytes);
2050 quint16 xorbits = 0xffff;
2055 if (mode == InvertRgba)
2061 quint32 *p = (quint32*)d->data;
2062 quint32 *end = (quint32*)(d->data + d->nbytes);
2063 quint32 xorbits = 0xffffffff;
2064 switch (d->format) {
2065 case QImage::Format_RGBA8888:
2066 if (mode == InvertRgba)
2069 case QImage::Format_RGBX8888:
2070#if Q_BYTE_ORDER == Q_BIG_ENDIAN
2071 xorbits = 0xffffff00;
2074 xorbits = 0x00ffffff;
2077 case QImage::Format_ARGB32:
2078 if (mode == InvertRgba)
2081 case QImage::Format_RGB32:
2082 xorbits = 0x00ffffff;
2084 case QImage::Format_BGR30:
2085 case QImage::Format_RGB30:
2086 xorbits = 0x3fffffff;
2097 if (originalFormat != d->format) {
2098 if (!d->convertInPlace(originalFormat, { }))
2099 *
this = convertToFormat(originalFormat);
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2128void QImage::setColorCount(
int colorCount)
2131 qWarning(
"QImage::setColorCount: null image");
2135 detachMetadata(
true);
2141 if (colorCount == d->colortable.size())
2143 if (colorCount <= 0) {
2144 d->colortable.clear();
2147 int nc = d->colortable.size();
2148 d->colortable.resize(colorCount);
2149 for (
int i = nc; i < colorCount; ++i)
2150 d->colortable[i] = 0;
2154
2155
2156
2157
2158QImage::Format QImage::format()
const
2160 return d ? d->format : Format_Invalid;
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2189
2190
2191QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags flags)
const
2193 if (!d || d->format == format)
2196 if (d->format == Format_Invalid || format <= Format_Invalid || format >= NImageFormats)
2199 const QPixelLayout *destLayout = &qPixelLayouts[format];
2200 Image_Converter converter = qimage_converter_map[d->format][format];
2201 if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
2202 if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
2203 && qt_highColorPrecision(format, !hasAlphaChannel())) {
2204#if QT_CONFIG(raster_fp)
2205 if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
2206 converter = convert_generic_over_rgba32f;
2209 converter = convert_generic_over_rgb64;
2211 converter = convert_generic;
2214 QImage image(d->width, d->height, format);
2218 copyMetadata(image.d, d);
2220 converter(image.d, d, flags);
2225 Q_ASSERT(format != QImage::Format_ARGB32 && format != QImage::Format_RGB32);
2226 Q_ASSERT(d->format != QImage::Format_ARGB32 && d->format != QImage::Format_RGB32);
2228 if (!hasAlphaChannel())
2229 return convertToFormat(Format_RGB32, flags).convertToFormat(format, flags);
2231 return convertToFormat(Format_ARGB32, flags).convertToFormat(format, flags);
2235
2236
2237bool QImage::convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags)
2239 return d && d->convertInPlace(format, flags);
2242static inline int pixel_distance(QRgb p1, QRgb p2) {
2244 int g1 = qGreen(p1);
2246 int a1 = qAlpha(p1);
2249 int g2 = qGreen(p2);
2251 int a2 = qAlpha(p2);
2253 return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) + abs(a1 - a2);
2256static inline int closestMatch(QRgb pixel,
const QList<QRgb> &clut) {
2258 int current_distance = INT_MAX;
2259 for (
int i=0; i<clut.size(); ++i) {
2260 int dist = pixel_distance(pixel, clut.at(i));
2261 if (dist < current_distance) {
2262 current_distance = dist;
2269static QImage convertWithPalette(
const QImage &src, QImage::Format format,
2270 const QList<QRgb> &clut) {
2271 QImage dest(src.size(), format);
2272 dest.setColorTable(clut);
2274 copyMetadata(QImageData::get(dest), QImageData::get(src));
2276 int h = src.height();
2277 int w = src.width();
2279 QHash<QRgb,
int> cache;
2281 if (format == QImage::Format_Indexed8) {
2282 for (
int y=0; y<h; ++y) {
2283 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2284 uchar *dest_pixels = (uchar *) dest.scanLine(y);
2285 for (
int x=0; x<w; ++x) {
2286 int src_pixel = src_pixels[x];
2287 int value = cache.value(src_pixel, -1);
2289 value = closestMatch(src_pixel, clut);
2290 cache.insert(src_pixel, value);
2292 dest_pixels[x] = (uchar) value;
2296 QList<QRgb> table = clut;
2298 for (
int y=0; y<h; ++y) {
2299 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2300 for (
int x=0; x<w; ++x) {
2301 int src_pixel = src_pixels[x];
2302 int value = cache.value(src_pixel, -1);
2304 value = closestMatch(src_pixel, table);
2305 cache.insert(src_pixel, value);
2307 dest.setPixel(x, y, value);
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325QImage QImage::convertToFormat(Format format,
const QList<QRgb> &colorTable, Qt::ImageConversionFlags flags)
const
2327 if (!d || d->format == format)
2330 if (format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2332 if (format <= QImage::Format_Indexed8)
2333 return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
2335 return convertToFormat(format, flags);
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2361bool QImage::reinterpretAsFormat(Format format)
2365 if (d->format == format)
2367 if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
2369 if (!isDetached()) {
2370 QImageData *oldD = d;
2385
2386
2387
2388
2389
2390
2391
2392
2393
2395void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
2397 if (!d || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2400 if (d->format == format)
2404 if (convertToFormat_inplace(format, flags))
2407 *
this = convertToFormat_helper(format, flags);
2411
2412
2413
2414
2415
2416
2417
2420
2421
2422
2423
2424
2425bool QImage::valid(
int x,
int y)
const
2428 && x >= 0 && x < d->width
2429 && y >= 0 && y < d->height;
2433
2434
2435
2436
2437
2438
2439
2440
2441
2444
2445
2446
2447
2448int QImage::pixelIndex(
int x,
int y)
const
2450 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2451 qWarning(
"QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
2454 const uchar * s = scanLine(y);
2457 return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2458 case Format_MonoLSB:
2459 return (*(s + (x >> 3)) >> (x & 7)) & 1;
2460 case Format_Indexed8:
2463 qWarning(
"QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2485
2486
2487
2488
2489QRgb QImage::pixel(
int x,
int y)
const
2491 if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
2492 qWarning(
"QImage::pixel: coordinate (%d,%d) out of range", x, y);
2496 const uchar *s = d->data + y * d->bytes_per_line;
2499 switch (d->format) {
2501 index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
2503 case Format_MonoLSB:
2504 index = (*(s + (x >> 3)) >> (x & 7)) & 1;
2506 case Format_Indexed8:
2513 if (index >= d->colortable.size()) {
2514 qWarning(
"QImage::pixel: color table index %d out of range.", index);
2517 return d->colortable.at(index);
2520 switch (d->format) {
2522 return 0xff000000 |
reinterpret_cast<
const QRgb *>(s)[x];
2524 case Format_ARGB32_Premultiplied:
2525 return reinterpret_cast<
const QRgb *>(s)[x];
2526 case Format_RGBX8888:
2527 case Format_RGBA8888:
2528 case Format_RGBA8888_Premultiplied:
2529 return RGBA2ARGB(
reinterpret_cast<
const quint32 *>(s)[x]);
2531 case Format_A2BGR30_Premultiplied:
2532 return qConvertA2rgb30ToArgb32<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2534 case Format_A2RGB30_Premultiplied:
2535 return qConvertA2rgb30ToArgb32<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2537 return qConvertRgb16To32(
reinterpret_cast<
const quint16 *>(s)[x]);
2540 case Format_RGBA64_Premultiplied:
2541 return reinterpret_cast<
const QRgba64 *>(s)[x].toArgb32();
2542 case Format_RGBX16FPx4:
2543 case Format_RGBA16FPx4:
2544 case Format_RGBA16FPx4_Premultiplied:
2545 return reinterpret_cast<
const QRgbaFloat16 *>(s)[x].toArgb32();
2546 case Format_RGBX32FPx4:
2547 case Format_RGBA32FPx4:
2548 case Format_RGBA32FPx4_Premultiplied:
2549 return reinterpret_cast<
const QRgbaFloat32 *>(s)[x].toArgb32();
2553 const QPixelLayout *layout = &qPixelLayouts[d->format];
2555 return *layout->fetchToARGB32PM(&result, s, x, 1,
nullptr,
nullptr);
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2580
2581
2582
2583
2584void QImage::setPixel(
int x,
int y, uint index_or_rgb)
2586 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2587 qWarning(
"QImage::setPixel: coordinate (%d,%d) out of range", x, y);
2591 uchar * s = scanLine(y);
2594 case Format_MonoLSB:
2595 if (index_or_rgb > 1) {
2596 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2597 }
else if (format() == Format_MonoLSB) {
2598 if (index_or_rgb==0)
2599 *(s + (x >> 3)) &= ~(1 << (x & 7));
2601 *(s + (x >> 3)) |= (1 << (x & 7));
2603 if (index_or_rgb==0)
2604 *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2606 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2609 case Format_Indexed8:
2610 if (index_or_rgb >= (uint)d->colortable.size()) {
2611 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2614 s[x] = index_or_rgb;
2619 ((uint *)s)[x] = 0xff000000 | index_or_rgb;
2622 case Format_ARGB32_Premultiplied:
2623 ((uint *)s)[x] = index_or_rgb;
2626 ((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
2628 case Format_RGBX8888:
2629 ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
2631 case Format_RGBA8888:
2632 case Format_RGBA8888_Premultiplied:
2633 ((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
2636 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
2638 case Format_A2BGR30_Premultiplied:
2639 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
2642 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
2644 case Format_A2RGB30_Premultiplied:
2645 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
2648 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
2651 case Format_RGBA64_Premultiplied:
2652 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
2654 case Format_RGBX16FPx4:
2655 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb | 0xff000000);
2657 case Format_RGBA16FPx4:
2658 case Format_RGBA16FPx4_Premultiplied:
2659 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb);
2661 case Format_RGBX32FPx4:
2662 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb | 0xff000000);
2664 case Format_RGBA32FPx4:
2665 case Format_RGBA32FPx4_Premultiplied:
2666 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb);
2668 case Format_Invalid:
2676 const QPixelLayout *layout = &qPixelLayouts[d->format];
2677 if (!hasAlphaChannel())
2678 layout->storeFromRGB32(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2680 layout->storeFromARGB32PM(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2700
2701
2702
2703
2704
2705QColor QImage::pixelColor(
int x,
int y)
const
2707 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2708 qWarning(
"QImage::pixelColor: coordinate (%d,%d) out of range", x, y);
2713 const uchar * s = constScanLine(y);
2714 switch (d->format) {
2716 case Format_A2BGR30_Premultiplied:
2717 c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2720 case Format_A2RGB30_Premultiplied:
2721 c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2725 case Format_RGBA64_Premultiplied:
2726 c =
reinterpret_cast<
const QRgba64 *>(s)[x];
2728 case Format_Grayscale16: {
2729 quint16 v =
reinterpret_cast<
const quint16 *>(s)[x];
2730 return QColor(qRgba64(v, v, v, 0xffff));
2732 case Format_RGBX16FPx4:
2733 case Format_RGBA16FPx4:
2734 case Format_RGBA16FPx4_Premultiplied: {
2735 QRgbaFloat16 p =
reinterpret_cast<
const QRgbaFloat16 *>(s)[x];
2736 if (d->format == Format_RGBA16FPx4_Premultiplied)
2737 p = p.unpremultiplied();
2739 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2742 case Format_RGBX32FPx4:
2743 case Format_RGBA32FPx4:
2744 case Format_RGBA32FPx4_Premultiplied: {
2745 QRgbaFloat32 p =
reinterpret_cast<
const QRgbaFloat32 *>(s)[x];
2746 if (d->format == Format_RGBA32FPx4_Premultiplied)
2747 p = p.unpremultiplied();
2749 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2753 c = QRgba64::fromArgb32(pixel(x, y));
2757 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
2758 c = c.unpremultiplied();
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2779
2780
2781
2782
2783
2784void QImage::setPixelColor(
int x,
int y,
const QColor &color)
2786 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2787 qWarning(
"QImage::setPixelColor: coordinate (%d,%d) out of range", x, y);
2791 if (!color.isValid()) {
2792 qWarning(
"QImage::setPixelColor: color is invalid");
2797 QRgba64 c = color.rgba64();
2798 if (!hasAlphaChannel())
2800 else if (qPixelLayouts[d->format].premultiplied)
2801 c = c.premultiplied();
2803 uchar * s = scanLine(y);
2804 switch (d->format) {
2806 case Format_MonoLSB:
2807 case Format_Indexed8:
2808 qWarning(
"QImage::setPixelColor: called on monochrome or indexed format");
2811 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000;
2813 case Format_A2BGR30_Premultiplied:
2814 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c);
2817 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000;
2819 case Format_A2RGB30_Premultiplied:
2820 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
2824 case Format_RGBA64_Premultiplied:
2825 ((QRgba64 *)s)[x] = c;
2827 case Format_RGBX16FPx4:
2828 case Format_RGBA16FPx4:
2829 case Format_RGBA16FPx4_Premultiplied: {
2831 color.getRgbF(&r, &g, &b, &a);
2832 if (d->format == Format_RGBX16FPx4)
2834 QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
2835 if (d->format == Format_RGBA16FPx4_Premultiplied)
2836 c16f = c16f.premultiplied();
2837 ((QRgbaFloat16 *)s)[x] = c16f;
2840 case Format_RGBX32FPx4:
2841 case Format_RGBA32FPx4:
2842 case Format_RGBA32FPx4_Premultiplied: {
2844 color.getRgbF(&r, &g, &b, &a);
2845 if (d->format == Format_RGBX32FPx4)
2847 QRgbaFloat32 c32f{r, g, b, a};
2848 if (d->format == Format_RGBA32FPx4_Premultiplied)
2849 c32f = c32f.premultiplied();
2850 ((QRgbaFloat32 *)s)[x] = c32f;
2854 setPixel(x, y, c.toArgb32());
2860
2861
2862
2863
2864
2865
2866
2867
2868bool QImage::allGray()
const
2873 switch (d->format) {
2875 case Format_MonoLSB:
2876 case Format_Indexed8:
2877 for (
int i = 0; i < d->colortable.size(); ++i) {
2878 if (!qIsGray(d->colortable.at(i)))
2884 case Format_Grayscale8:
2885 case Format_Grayscale16:
2889 case Format_ARGB32_Premultiplied:
2890#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
2891 case Format_RGBX8888:
2892 case Format_RGBA8888:
2893 case Format_RGBA8888_Premultiplied:
2895 for (
int j = 0; j < d->height; ++j) {
2896 const QRgb *b = (
const QRgb *)constScanLine(j);
2897 for (
int i = 0; i < d->width; ++i) {
2904 for (
int j = 0; j < d->height; ++j) {
2905 const quint16 *b = (
const quint16 *)constScanLine(j);
2906 for (
int i = 0; i < d->width; ++i) {
2907 if (!qIsGray(qConvertRgb16To32(b[i])))
2916 Q_DECL_UNINITIALIZED uint buffer[BufferSize];
2917 const QPixelLayout *layout = &qPixelLayouts[d->format];
2918 const auto fetch = layout->fetchToARGB32PM;
2919 for (
int j = 0; j < d->height; ++j) {
2920 const uchar *b = constScanLine(j);
2922 while (x < d->width) {
2923 int l = qMin(d->width - x, BufferSize);
2924 const uint *ptr = fetch(buffer, b, x, l,
nullptr,
nullptr);
2925 for (
int i = 0; i < l; ++i) {
2926 if (!qIsGray(ptr[i]))
2936
2937
2938
2939
2940
2941
2942
2943
2944bool QImage::isGrayscale()
const
2949 if (d->format == QImage::Format_Alpha8)
2952 if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
2961 Q_ASSERT(d->format == QImage::Format_Indexed8);
2962 for (
int i = 0; i < colorCount(); i++)
2963 if (d->colortable.at(i) != qRgb(i,i,i))
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(
const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
const
3012 qWarning(
"QImage::scaled: Image is a null image");
3018 QSize newSize = size();
3019 newSize.scale(s, aspectMode);
3020 newSize.rwidth() = qMax(newSize.width(), 1);
3021 newSize.rheight() = qMax(newSize.height(), 1);
3022 if (newSize == size())
3025 Q_TRACE_SCOPE(QImage_scaled, s, aspectMode, mode);
3027 QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
3028 QImage img = transformed(wm, mode);
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(
int w, Qt::TransformationMode mode)
const
3049 qWarning(
"QImage::scaleWidth: Image is a null image");
3055 Q_TRACE_SCOPE(QImage_scaledToWidth, w, mode);
3057 qreal factor = (qreal) w / width();
3058 QTransform wm = QTransform::fromScale(factor, factor);
3059 return transformed(wm, mode);
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(
int h, Qt::TransformationMode mode)
const
3079 qWarning(
"QImage::scaleHeight: Image is a null image");
3085 Q_TRACE_SCOPE(QImage_scaledToHeight, h, mode);
3087 qreal factor = (qreal) h / height();
3088 QTransform wm = QTransform::fromScale(factor, factor);
3089 return transformed(wm, mode);
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags)
const
3111 if (!d || d->format == QImage::Format_RGB32)
3114 if (d->depth == 1) {
3117 return convertToFormat(Format_Indexed8, flags).createAlphaMask(flags);
3120 QImage mask(d->width, d->height, Format_MonoLSB);
3121 if (!mask.isNull()) {
3122 dither_to_Mono(mask.d, d, flags,
true);
3123 copyPhysicalMetadata(mask.d, d);
3128#ifndef QT_NO_IMAGE_HEURISTIC_MASK
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3153QImage QImage::createHeuristicMask(
bool clipTight)
const
3158 if (d->depth != 32) {
3159 QImage img32 = convertToFormat(Format_RGB32);
3160 return img32.createHeuristicMask(clipTight);
3163#define PIX(x,y) (*((const QRgb*)scanLine(y)+x) & 0x00ffffff
)
3167 QImage m(w, h, Format_MonoLSB);
3170 m.setColor(0, QColor(Qt::color0).rgba());
3171 m.setColor(1, QColor(Qt::color1).rgba());
3174 QRgb background =
PIX(0,0);
3175 if (background !=
PIX(w-1,0) &&
3176 background !=
PIX(0,h-1) &&
3177 background !=
PIX(w-1,h-1)) {
3178 background =
PIX(w-1,0);
3179 if (background !=
PIX(w-1,h-1) &&
3180 background !=
PIX(0,h-1) &&
3181 PIX(0,h-1) ==
PIX(w-1,h-1)) {
3182 background =
PIX(w-1,h-1);
3188 uchar *ypp, *ypc, *ypn;
3191 ypn = m.scanLine(0);
3193 for (y = 0; y < h; y++) {
3196 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3197 const QRgb *p = (
const QRgb *)scanLine(y);
3198 for (x = 0; x < w; x++) {
3201 if ((x == 0 || y == 0 || x == w-1 || y == h-1 ||
3202 !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3203 !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3204 !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
3205 !(*(ypn + (x >> 3)) & (1 << (x & 7)))) &&
3206 ( (*(ypc + (x >> 3)) & (1 << (x & 7)))) &&
3207 ((*p & 0x00ffffff) == background)) {
3209 *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3217 ypn = m.scanLine(0);
3219 for (y = 0; y < h; y++) {
3222 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3223 const QRgb *p = (
const QRgb *)scanLine(y);
3224 for (x = 0; x < w; x++) {
3225 if ((*p & 0x00ffffff) != background) {
3227 *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3229 *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3231 *(ypp + (x >> 3)) |= (1 << (x & 7));
3233 *(ypn + (x >> 3)) |= (1 << (x & 7));
3242 copyPhysicalMetadata(m.d, d);
3248
3249
3250
3251
3252
3253
3254
3255
3257QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode)
const
3261 QImage maskImage(size(), QImage::Format_MonoLSB);
3264 uchar *s = maskImage.bits();
3268 if (depth() == 32) {
3269 for (
int h = 0; h < d->height; h++) {
3270 const uint *sl = (
const uint *) scanLine(h);
3271 for (
int w = 0; w < d->width; w++) {
3273 *(s + (w >> 3)) |= (1 << (w & 7));
3275 s += maskImage.bytesPerLine();
3278 for (
int h = 0; h < d->height; h++) {
3279 for (
int w = 0; w < d->width; w++) {
3280 if ((uint) pixel(w, h) == color)
3281 *(s + (w >> 3)) |= (1 << (w & 7));
3283 s += maskImage.bytesPerLine();
3286 if (mode == Qt::MaskOutColor)
3287 maskImage.invertPixels();
3289 copyPhysicalMetadata(maskImage.d, d);
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3308
3309
3310
3311
3312
3313
3314
3315
3316
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3332
3333
3334
3335
3336
3337
3338
3339
3341template<
class T>
inline void do_mirror_data(QImageData *dst, QImageData *src,
3342 int dstX0,
int dstY0,
3343 int dstXIncr,
int dstYIncr,
3349 const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w;
3350 const int srcYEnd = dstY0 ? h / 2 : h;
3351 for (
int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
3352 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3353 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3354 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
3355 std::swap(srcPtr[srcX], dstPtr[dstX]);
3358 if (dstX0 && dstY0 && (h & 1)) {
3360 int srcXEnd2 = w / 2;
3361 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3362 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr)
3363 std::swap(srcPtr[srcX], srcPtr[dstX]);
3366 for (
int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
3367 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3368 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3369 for (
int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
3370 dstPtr[dstX] = srcPtr[srcX];
3375inline void do_flip(QImageData *dst, QImageData *src,
int w,
int h,
int depth)
3377 const int data_bytes_per_line = w * (depth / 8);
3379 uint *srcPtr =
reinterpret_cast<uint *>(src->data);
3380 uint *dstPtr =
reinterpret_cast<uint *>(dst->data + (h - 1) * dst->bytes_per_line);
3382 const int uint_per_line = (data_bytes_per_line + 3) >> 2;
3383 for (
int y = 0; y < h; ++y) {
3385 for (
int x = 0; x < uint_per_line; x++) {
3386 const uint d = dstPtr[x];
3387 const uint s = srcPtr[x];
3391 srcPtr += src->bytes_per_line >> 2;
3392 dstPtr -= dst->bytes_per_line >> 2;
3396 const uchar *srcPtr = src->data;
3397 uchar *dstPtr = dst->data + (h - 1) * dst->bytes_per_line;
3398 for (
int y = 0; y < h; ++y) {
3399 memcpy(dstPtr, srcPtr, data_bytes_per_line);
3400 srcPtr += src->bytes_per_line;
3401 dstPtr -= dst->bytes_per_line;
3406inline void do_mirror(QImageData *dst, QImageData *src,
bool horizontal,
bool vertical)
3408 Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
3410 int h = src->height;
3411 int depth = src->depth;
3413 if (src->depth == 1) {
3418 if (vertical && !horizontal) {
3420 do_flip(dst, src, w, h, depth);
3424 int dstX0 = 0, dstXIncr = 1;
3425 int dstY0 = 0, dstYIncr = 1;
3439 do_mirror_data<QRgbaFloat32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3442 do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3445 do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3448 do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3451 do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3454 do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3463 if (horizontal && dst->depth == 1) {
3464 Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
3465 const int shift = 8 - (dst->width % 8);
3466 const uchar *bitflip = qt_get_bitflip_array();
3467 for (
int y = 0; y < h; ++y) {
3468 uchar *begin = dst->data + y * dst->bytes_per_line;
3469 uchar *end = begin + dst->bytes_per_line;
3470 for (uchar *p = begin; p < end; ++p) {
3474 if (shift != 8 && p != begin) {
3475 if (dst->format == QImage::Format_Mono) {
3476 for (
int i = 0; i < shift; ++i) {
3478 p[-1] |= (*p & (128 >> i)) >> (7 - i);
3481 for (
int i = 0; i < shift; ++i) {
3483 p[-1] |= (*p & (1 << i)) << (7 - i);
3489 if (dst->format == QImage::Format_Mono)
3499
3500
3501QImage QImage::mirrored_helper(
bool horizontal,
bool vertical)
const
3506 if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3510 QImage result(d->width, d->height, d->format);
3517 result.d->colortable = d->colortable;
3518 result.d->has_alpha_clut = d->has_alpha_clut;
3519 copyMetadata(result.d, d);
3521 do_mirror(result.d, d, horizontal, vertical);
3527
3528
3529void QImage::mirrored_inplace(
bool horizontal,
bool vertical)
3531 if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3540 do_mirror(d, d, horizontal, vertical);
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3557
3558
3559
3560
3561
3562
3563
3564
3566static inline void rgbSwapped_generic(
int width,
int height,
const QImage *src, QImage *dst,
const QPixelLayout* layout)
3568 const RbSwapFunc func = layout->rbSwap;
3570 qWarning(
"Trying to rb-swap an image format where it doesn't make sense");
3576 for (
int i = 0; i < height; ++i) {
3577 uchar *q = dst->scanLine(i);
3578 const uchar *p = src->constScanLine(i);
3584
3585
3586QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper()
const
3591 Q_TRACE_SCOPE(QImage_rgbSwapped_helper);
3595 switch (d->format) {
3596 case Format_Invalid:
3601 case Format_Grayscale8:
3602 case Format_Grayscale16:
3605 case Format_MonoLSB:
3606 case Format_Indexed8:
3608 for (
int i = 0; i < res.d->colortable.size(); i++) {
3609 QRgb c = res.d->colortable.at(i);
3610 res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3613 case Format_RGBX8888:
3614 case Format_RGBA8888:
3615 case Format_RGBA8888_Premultiplied:
3616#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3617 res = QImage(d->width, d->height, d->format);
3619 for (
int i = 0; i < d->height; i++) {
3620 uint *q = (uint*)res.scanLine(i);
3621 const uint *p = (
const uint*)constScanLine(i);
3622 const uint *end = p + d->width;
3625 *q = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3637 case Format_ARGB32_Premultiplied:
3638 res = QImage(d->width, d->height, d->format);
3640 for (
int i = 0; i < d->height; i++) {
3641 uint *q = (uint*)res.scanLine(i);
3642 const uint *p = (
const uint*)constScanLine(i);
3643 const uint *end = p + d->width;
3646 *q = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3653 res = QImage(d->width, d->height, d->format);
3655 for (
int i = 0; i < d->height; i++) {
3656 ushort *q = (ushort*)res.scanLine(i);
3657 const ushort *p = (
const ushort*)constScanLine(i);
3658 const ushort *end = p + d->width;
3661 *q = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3668 res = QImage(d->width, d->height, d->format);
3670 rgbSwapped_generic(d->width, d->height,
this, &res, &qPixelLayouts[d->format]);
3673 copyMetadata(res.d, d);
3678
3679
3680void QImage::rgbSwapped_inplace()
3691 switch (d->format) {
3692 case Format_Invalid:
3697 case Format_Grayscale8:
3698 case Format_Grayscale16:
3701 case Format_MonoLSB:
3702 case Format_Indexed8:
3703 for (
int i = 0; i < d->colortable.size(); i++) {
3704 QRgb c = d->colortable.at(i);
3705 d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3708 case Format_RGBX8888:
3709 case Format_RGBA8888:
3710 case Format_RGBA8888_Premultiplied:
3711#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3712 for (
int i = 0; i < d->height; i++) {
3713 uint *p = (uint*)scanLine(i);
3714 uint *end = p + d->width;
3717 *p = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3728 case Format_ARGB32_Premultiplied:
3729 for (
int i = 0; i < d->height; i++) {
3730 uint *p = (uint*)scanLine(i);
3731 uint *end = p + d->width;
3734 *p = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3740 for (
int i = 0; i < d->height; i++) {
3741 ushort *p = (ushort*)scanLine(i);
3742 ushort *end = p + d->width;
3745 *p = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3751 case Format_A2BGR30_Premultiplied:
3753 case Format_A2RGB30_Premultiplied:
3754 for (
int i = 0; i < d->height; i++) {
3755 uint *p = (uint*)scanLine(i);
3756 uint *end = p + d->width;
3758 *p = qRgbSwapRgb30(*p);
3764 rgbSwapped_generic(d->width, d->height,
this,
this, &qPixelLayouts[d->format]);
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3788bool QImage::load(
const QString &fileName,
const char* format)
3790 *
this = QImageReader(fileName, format).read();
3795
3796
3797
3798
3799
3801bool QImage::load(QIODevice* device,
const char* format)
3803 *
this = QImageReader(device, format).read();
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3820bool QImage::loadFromData(QByteArrayView data,
const char *format)
3822 *
this = fromData(data, format);
3827
3828
3829
3830
3831
3832
3834bool QImage::loadFromData(
const uchar *buf,
int len,
const char *format)
3836 return loadFromData(QByteArrayView(buf, len), format);
3840
3841
3842
3843
3844
3845
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3862QImage QImage::fromData(QByteArrayView data,
const char *format)
3864 QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
3867 b.open(QIODevice::ReadOnly);
3868 return QImageReader(&b, format).read();
3872
3873
3874
3875
3876
3877
3879QImage QImage::fromData(
const uchar *data,
int size,
const char *format)
3881 return fromData(QByteArrayView(data, size), format);
3885
3886
3887
3888
3889
3890
3891
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909bool QImage::save(
const QString &fileName,
const char *format,
int quality)
const
3913 QImageWriter writer(fileName, format);
3914 return d->doImageIO(
this, &writer, quality);
3918
3919
3920
3921
3922
3923
3924
3925
3926
3928bool QImage::save(QIODevice* device,
const char* format,
int quality)
const
3932 QImageWriter writer(device, format);
3933 return d->doImageIO(
this, &writer, quality);
3937
3939bool QImageData::doImageIO(
const QImage *image, QImageWriter *writer,
int quality)
const
3941 if (quality > 100 || quality < -1)
3942 qWarning(
"QImage::save: Quality out of range [-1, 100]");
3944 writer->setQuality(qMin(quality,100));
3945 const bool result = writer->write(*image);
3948 qWarning(
"QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
3954
3955
3956#if !defined(QT_NO_DATASTREAM)
3958
3959
3960
3961
3962
3963
3964
3965
3966
3968QDataStream &operator<<(QDataStream &s,
const QImage &image)
3970 if (s.version() >= 5) {
3971 if (image.isNull()) {
3979 QImageWriter writer(s.device(), s.version() == 1 ?
"bmp" :
"png");
3980 writer.write(image);
3985
3986
3987
3988
3989
3990
3991
3992
3994QDataStream &operator>>(QDataStream &s, QImage &image)
3996 if (s.version() >= 5) {
4004 image = QImageReader(s.device(), s.version() == 1 ?
"bmp" :
"png").read();
4005 if (image.isNull() && s.version() >= 5)
4006 s.setStatus(QDataStream::ReadPastEnd);
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4026bool QImage::operator==(
const QImage & i)
const
4035 if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
4038 if (d->format != Format_RGB32) {
4039 if (d->format >= Format_ARGB32) {
4040 const int n = d->width * d->depth / 8;
4041 if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
4042 if (memcmp(bits(), i.bits(), d->nbytes))
4045 for (
int y = 0; y < d->height; ++y) {
4046 if (memcmp(scanLine(y), i.scanLine(y), n))
4051 const int w = width();
4052 const int h = height();
4053 const QList<QRgb> &colortable = d->colortable;
4054 const QList<QRgb> &icolortable = i.d->colortable;
4055 for (
int y=0; y<h; ++y) {
4056 for (
int x=0; x<w; ++x) {
4057 if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
4064 for(
int l = 0; l < d->height; l++) {
4066 const uint *p1 =
reinterpret_cast<
const uint*>(scanLine(l));
4067 const uint *p2 =
reinterpret_cast<
const uint*>(i.scanLine(l));
4069 if ((*p1++ & 0x00ffffff) != (*p2++ & 0x00ffffff))
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4091bool QImage::operator!=(
const QImage & i)
const
4093 return !(*
this == i);
4100
4101
4102
4103
4104
4105
4106
4107int QImage::dotsPerMeterX()
const
4109 return d ? qRound(d->dpmx) : 0;
4113
4114
4115
4116
4117
4118
4119
4120int QImage::dotsPerMeterY()
const
4122 return d ? qRound(d->dpmy) : 0;
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137void QImage::setDotsPerMeterX(
int x)
4139 if (!d || !x || d->dpmx == x)
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159void QImage::setDotsPerMeterY(
int y)
4161 if (!d || !y || d->dpmy == y)
4170
4171
4172
4173
4174
4175
4176
4177QPoint QImage::offset()
const
4179 return d ? d->offset : QPoint();
4184
4185
4186
4187
4188
4189
4190
4191void QImage::setOffset(
const QPoint& p)
4193 if (!d || d->offset == p)
4202
4203
4204
4205
4206
4207
4208
4209QStringList QImage::textKeys()
const
4211 return d ? QStringList(d->text.keys()) : QStringList();
4215
4216
4217
4218
4219
4220
4221QString QImage::text(
const QString &key)
const
4227 return d->text.value(key);
4230 for (
auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
4231 tmp += it.key() +
": "_L1 + it.value().simplified() +
"\n\n"_L1;
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261void QImage::setText(
const QString &key,
const QString &value)
4268 d->text.insert(key, value);
4272
4273
4274
4275
4276QPaintEngine *QImage::paintEngine()
const
4281 if (!d->paintEngine) {
4282 QPaintDevice *paintDevice =
const_cast<QImage *>(
this);
4283 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
4284 if (platformIntegration)
4285 d->paintEngine = platformIntegration->createImagePaintEngine(paintDevice);
4286 if (!d->paintEngine)
4287 d->paintEngine =
new QRasterPaintEngine(paintDevice);
4290 return d->paintEngine;
4295
4296
4297
4298
4299int QImage::metric(PaintDeviceMetric metric)
const
4312 return qRound(d->width * 1000 / d->dpmx);
4315 return qRound(d->height * 1000 / d->dpmy);
4318 return d->colortable.size();
4324 return qRound(d->dpmx * 0.0254);
4328 return qRound(d->dpmy * 0.0254);
4331 case PdmPhysicalDpiX:
4332 return qRound(d->dpmx * 0.0254);
4335 case PdmPhysicalDpiY:
4336 return qRound(d->dpmy * 0.0254);
4339 case PdmDevicePixelRatio:
4340 return d->devicePixelRatio;
4343 case PdmDevicePixelRatioScaled:
4344 return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
4347 case PdmDevicePixelRatioF_EncodedA:
4349 case PdmDevicePixelRatioF_EncodedB:
4350 return QPaintDevice::encodeMetricF(metric, d->devicePixelRatio);
4354 qWarning(
"QImage::metric(): Unhandled metric type %d", metric);
4363
4364
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4386#define IWX_MSB(b) if (trigx < maxws && trigy < maxhs) {
4387 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4388 (1
<< (7
-((trigx>>12
)&7
))))
4395#define IWX_LSB(b) if (trigx < maxws && trigy < maxhs) {
4396 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4397 (1
<< ((trigx>>12
)&7
)))
4404#define IWX_PIX(b) if (trigx < maxws && trigy < maxhs) {
4405 if ((*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4406 (1
<< (7
-((trigx>>12
)&7
)))) == 0
)
4412bool qt_xForm_helper(
const QTransform &trueMat,
int xoffset,
int type,
int depth,
4413 uchar *dptr, qsizetype dbpl,
int p_inc,
int dHeight,
4414 const uchar *sptr, qsizetype sbpl,
int sWidth,
int sHeight)
4416 int m11 =
int(trueMat.m11()*4096.0);
4417 int m12 =
int(trueMat.m12()*4096.0);
4418 int m21 =
int(trueMat.m21()*4096.0);
4419 int m22 =
int(trueMat.m22()*4096.0);
4420 int dx = qRound(trueMat.dx()*4096.0);
4421 int dy = qRound(trueMat.dy()*4096.0);
4423 int m21ydx = dx + (xoffset<<16) + (m11 + m21) / 2;
4424 int m22ydy = dy + (m12 + m22) / 2;
4427 uint maxws = sWidth<<12;
4428 uint maxhs = sHeight<<12;
4430 for (
int y=0; y<dHeight; y++) {
4433 uchar *maxp = dptr + dbpl;
4437 while (dptr < maxp) {
4438 if (trigx < maxws && trigy < maxhs)
4439 *dptr = *(sptr+sbpl*(trigy>>12)+(trigx>>12));
4447 while (dptr < maxp) {
4448 if (trigx < maxws && trigy < maxhs)
4449 *((ushort*)dptr) = *((
const ushort *)(sptr+sbpl*(trigy>>12) +
4459 while (dptr < maxp) {
4460 if (trigx < maxws && trigy < maxhs) {
4461 const uchar *p2 = sptr+sbpl*(trigy>>12) + ((trigx>>12)*3);
4473 while (dptr < maxp) {
4474 if (trigx < maxws && trigy < maxhs)
4475 *((uint*)dptr) = *((
const uint *)(sptr+sbpl*(trigy>>12) +
4489 case QT_XFORM_TYPE_MSBFIRST:
4490 while (dptr < maxp) {
4502 case QT_XFORM_TYPE_LSBFIRST:
4503 while (dptr < maxp) {
4528
4529
4530
4531
4532
4533
4534qint64 QImage::cacheKey()
const
4539 return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
4543
4544
4545
4546
4547
4548
4550bool QImage::isDetached()
const
4552 return d && d->ref.loadRelaxed() == 1;
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4575void QImage::setAlphaChannel(
const QImage &alphaChannel)
4577 if (!d || alphaChannel.isNull())
4580 if (d->paintEngine && d->paintEngine->isActive()) {
4581 qWarning(
"QImage::setAlphaChannel: "
4582 "Unable to set alpha channel while image is being painted on");
4586 const Format alphaFormat = qt_alphaVersionForPainting(d->format);
4587 if (d->format == alphaFormat)
4590 convertTo(alphaFormat);
4596 if (alphaChannel.format() == QImage::Format_Alpha8 || (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()))
4597 sourceImage = alphaChannel;
4599 sourceImage = alphaChannel.convertToFormat(QImage::Format_Grayscale8);
4600 if (!sourceImage.reinterpretAsFormat(QImage::Format_Alpha8))
4603 QPainter painter(
this);
4604 if (sourceImage.size() != size())
4605 painter.setRenderHint(QPainter::SmoothPixmapTransform);
4606 painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
4607 painter.drawImage(rect(), sourceImage);
4611
4612
4613
4614
4615
4616bool QImage::hasAlphaChannel()
const
4620 const QPixelFormat format = pixelFormat();
4621 if (format.alphaUsage() == QPixelFormat::UsesAlpha)
4623 if (format.colorModel() == QPixelFormat::Indexed)
4624 return d->has_alpha_clut;
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638int QImage::bitPlaneCount()
const
4643 switch (d->format) {
4644 case QImage::Format_Invalid:
4646 case QImage::Format_BGR30:
4647 case QImage::Format_RGB30:
4650 case QImage::Format_RGB32:
4651 case QImage::Format_RGBX8888:
4654 case QImage::Format_RGB666:
4657 case QImage::Format_RGB555:
4660 case QImage::Format_ARGB8555_Premultiplied:
4663 case QImage::Format_RGB444:
4666 case QImage::Format_RGBX64:
4667 case QImage::Format_RGBX16FPx4:
4670 case QImage::Format_RGBX32FPx4:
4674 bpc = qt_depthForFormat(d->format);
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691QImage QImage::smoothScaled(
int w,
int h)
const
4694 switch (src.format()) {
4695 case QImage::Format_RGB32:
4696 case QImage::Format_ARGB32_Premultiplied:
4697#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4698 case QImage::Format_RGBX8888:
4700 case QImage::Format_RGBA8888_Premultiplied:
4701#if QT_CONFIG(raster_64bit)
4702 case QImage::Format_RGBX64:
4703 case QImage::Format_RGBA64_Premultiplied:
4705 case QImage::Format_RGBA64:
4706 case QImage::Format_Grayscale16:
4707 src.convertTo(QImage::Format_RGBA64_Premultiplied);
4710#if QT_CONFIG(raster_fp)
4711 case QImage::Format_RGBX32FPx4:
4712 case QImage::Format_RGBA32FPx4_Premultiplied:
4714 case QImage::Format_RGBX16FPx4:
4715 src.convertTo(QImage::Format_RGBX32FPx4);
4717 case QImage::Format_RGBA16FPx4:
4718 case QImage::Format_RGBA16FPx4_Premultiplied:
4719 case QImage::Format_RGBA32FPx4:
4720 src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
4723 case QImage::Format_CMYK8888:
4726 if (src.hasAlphaChannel())
4727 src.convertTo(QImage::Format_ARGB32_Premultiplied);
4729 src.convertTo(QImage::Format_RGB32);
4731 src = qSmoothScaleImage(src, w, h);
4733 copyMetadata(src.d, d);
4737static QImage rotated90(
const QImage &image)
4739 QImage out(image.height(), image.width(), image.format());
4742 copyMetadata(QImageData::get(out), QImageData::get(image));
4743 if (image.colorCount() > 0)
4744 out.setColorTable(image.colorTable());
4745 int w = image.width();
4746 int h = image.height();
4747 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][2];
4749 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4751 for (
int y=0; y<h; ++y) {
4752 if (image.colorCount())
4753 for (
int x=0; x<w; ++x)
4754 out.setPixel(h-y-1, x, image.pixelIndex(x, y));
4756 for (
int x=0; x<w; ++x)
4757 out.setPixel(h-y-1, x, image.pixel(x, y));
4763static QImage rotated180(
const QImage &image)
4765 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][1];
4767 return image.flipped(Qt::Horizontal | Qt::Vertical);
4769 QImage out(image.width(), image.height(), image.format());
4772 copyMetadata(QImageData::get(out), QImageData::get(image));
4773 if (image.colorCount() > 0)
4774 out.setColorTable(image.colorTable());
4775 int w = image.width();
4776 int h = image.height();
4777 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4781static QImage rotated270(
const QImage &image)
4783 QImage out(image.height(), image.width(), image.format());
4786 copyMetadata(QImageData::get(out), QImageData::get(image));
4787 if (image.colorCount() > 0)
4788 out.setColorTable(image.colorTable());
4789 int w = image.width();
4790 int h = image.height();
4791 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][0];
4793 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4795 for (
int y=0; y<h; ++y) {
4796 if (image.colorCount())
4797 for (
int x=0; x<w; ++x)
4798 out.setPixel(y, w-x-1, image.pixelIndex(x, y));
4800 for (
int x=0; x<w; ++x)
4801 out.setPixel(y, w-x-1, image.pixel(x, y));
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4831QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(
const QTransform &matrix, Qt::TransformationMode mode )
const
4836 Q_TRACE_PARAM_REPLACE(
const QTransform &,
double[9]);
4837 Q_TRACE_SCOPE(QImage_transformed, QList<
double>({matrix.m11(), matrix.m12(), matrix.m13(),
4838 matrix.m21(), matrix.m22(), matrix.m23(),
4839 matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
4842 const int ws = width();
4843 const int hs = height();
4850 QTransform mat = trueMatrix(matrix, ws, hs);
4851 bool complex_xform =
false;
4852 bool scale_xform =
false;
4853 bool nonpaintable_scale_xform =
false;
4854 if (mat.type() <= QTransform::TxScale) {
4855 if (mat.type() == QTransform::TxNone)
4857 else if (mat.m11() == -1. && mat.m22() == -1.)
4858 return rotated180(*
this);
4860 hd = qRound(qAbs(mat.m22()) * hs);
4861 wd = qRound(qAbs(mat.m11()) * ws);
4865 if (hd * 2 < hs || wd * 2 < ws)
4866 nonpaintable_scale_xform =
true;
4868 if (format() == QImage::Format_CMYK8888)
4869 nonpaintable_scale_xform =
true;
4871 if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
4872 if (mat.m12() == 1. && mat.m21() == -1.)
4873 return rotated90(*
this);
4874 else if (mat.m12() == -1. && mat.m21() == 1.)
4875 return rotated270(*
this);
4878 QPolygonF a(QRectF(0, 0, ws, hs));
4880 QRect r = a.boundingRect().toAlignedRect();
4883 complex_xform =
true;
4886 if (wd == 0 || hd == 0)
4889 if (scale_xform && mode == Qt::SmoothTransformation) {
4891 case QImage::Format_RGB32:
4892 case QImage::Format_ARGB32_Premultiplied:
4893#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4894 case QImage::Format_RGBX8888:
4896 case QImage::Format_RGBA8888_Premultiplied:
4897#if QT_CONFIG(raster_64bit)
4898 case QImage::Format_RGBX64:
4899 case QImage::Format_RGBA64_Premultiplied:
4901 case QImage::Format_CMYK8888:
4903 if (mat.m11() > 0.0F && mat.m22() > 0.0F)
4904 return smoothScaled(wd, hd);
4910 if (nonpaintable_scale_xform
4911#if QT_CONFIG(qtgui_threadpool)
4912 || (ws * hs) >= (1<<20)
4916 if (mat.m11() < 0.0F && mat.m22() < 0.0F) {
4917 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal | Qt::Vertical);
4918 }
else if (mat.m11() < 0.0F) {
4919 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal);
4920 }
else if (mat.m22() < 0.0F) {
4921 scaledImage = smoothScaled(wd, hd).flipped(Qt::Vertical);
4923 scaledImage = smoothScaled(wd, hd);
4927 case QImage::Format_Mono:
4928 case QImage::Format_MonoLSB:
4929 case QImage::Format_Indexed8:
4932 return scaledImage.convertToFormat(format());
4939 qsizetype sbpl = bytesPerLine();
4940 const uchar *sptr = bits();
4942 QImage::Format target_format = d->format;
4944 if (complex_xform || mode == Qt::SmoothTransformation) {
4945 if (d->format < QImage::Format_RGB32 || (!hasAlphaChannel() && complex_xform)) {
4946 target_format = qt_alphaVersion(d->format);
4950 QImage dImage(wd, hd, target_format);
4953 if (target_format == QImage::Format_MonoLSB
4954 || target_format == QImage::Format_Mono
4955 || target_format == QImage::Format_Indexed8) {
4956 dImage.d->colortable = d->colortable;
4957 dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
4961 if (target_format == QImage::Format_Indexed8) {
4962 if (dImage.d->colortable.size() < 256) {
4964 dImage.d->colortable.append(0x0);
4965 memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
4967 memset(dImage.bits(), 0, dImage.d->nbytes);
4970 memset(dImage.bits(), 0x00, dImage.d->nbytes);
4972 if (target_format >= QImage::Format_RGB32 && target_format != QImage::Format_CMYK8888) {
4974 QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *
this;
4976 && (d->format == QImage::Format_MonoLSB
4977 || d->format == QImage::Format_Mono
4978 || d->format == QImage::Format_Indexed8)) {
4979 sImage.d->colortable = d->colortable;
4980 sImage.d->has_alpha_clut = d->has_alpha_clut;
4983 Q_ASSERT(sImage.devicePixelRatio() == 1);
4984 Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
4986 QPainter p(&dImage);
4987 if (mode == Qt::SmoothTransformation) {
4988 p.setRenderHint(QPainter::Antialiasing);
4989 p.setRenderHint(QPainter::SmoothPixmapTransform);
4991 p.setTransform(mat);
4992 p.drawImage(QPoint(0, 0), sImage);
4995 mat = mat.inverted(&invertible);
5000 int type = format() == Format_Mono ? QT_XFORM_TYPE_MSBFIRST : QT_XFORM_TYPE_LSBFIRST;
5001 qsizetype dbpl = dImage.bytesPerLine();
5002 qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
5004 copyMetadata(dImage.d, d);
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5030QTransform QImage::trueMatrix(
const QTransform &matrix,
int w,
int h)
5032 const QRectF rect(0, 0, w, h);
5033 const QRect mapped = matrix.mapRect(rect).toAlignedRect();
5034 const QPoint delta = mapped.topLeft();
5035 return matrix * QTransform().translate(-delta.x(), -delta.y());
5039
5040
5041
5042
5043
5044
5045void QImage::setColorSpace(
const QColorSpace &colorSpace)
5049 if (d->colorSpace == colorSpace)
5051 if (colorSpace.isValid() && !qt_compatibleColorModelSource(pixelFormat().colorModel(), colorSpace.colorModel()))
5054 detachMetadata(
false);
5056 d->colorSpace = colorSpace;
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071void QImage::convertToColorSpace(
const QColorSpace &colorSpace)
5073 if (!d || !d->colorSpace.isValid())
5075 if (!colorSpace.isValidTarget()) {
5076 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5079 if (d->colorSpace == colorSpace)
5081 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(),
5082 colorSpace.colorModel(), colorSpace.transformModel())) {
5083 *
this = convertedToColorSpace(colorSpace);
5086 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
5087 if (d->ref.loadRelaxed() != 1)
5088 detachMetadata(
false);
5089 d->colorSpace = colorSpace;
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105void QImage::convertToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
5107 if (!d || !d->colorSpace.isValid())
5109 if (!colorSpace.isValidTarget()) {
5110 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5113 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5114 colorSpace.colorModel(), colorSpace.transformModel())) {
5115 qWarning() <<
"QImage::convertToColorSpace: Color space is not compatible with format";
5119 if (d->colorSpace == colorSpace)
5120 return convertTo(format, flags);
5121 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5122 d->colorSpace = colorSpace;
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace)
const
5141 if (!d || !d->colorSpace.isValid())
5143 if (!colorSpace.isValidTarget()) {
5144 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5147 if (d->colorSpace == colorSpace)
5149 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
5150 image.setColorSpace(colorSpace);
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
const &
5170 if (!d || !d->colorSpace.isValid())
5172 if (!colorSpace.isValidTarget()) {
5173 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5176 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5177 colorSpace.colorModel(), colorSpace.transformModel())) {
5178 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5181 if (d->colorSpace == colorSpace)
5182 return convertedTo(format, flags);
5183 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5184 image.setColorSpace(colorSpace);
5188QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) &&
5190 if (!d || !d->colorSpace.isValid())
5192 if (!colorSpace.isValidTarget()) {
5193 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5196 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5197 colorSpace.colorModel(), colorSpace.transformModel())) {
5198 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5201 if (d->colorSpace == colorSpace)
5202 return convertedTo(format, flags);
5203 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5204 return std::move(*
this);
5208
5209
5210
5211
5212QColorSpace QImage::colorSpace()
const
5215 return QColorSpace();
5216 return d->colorSpace;
5220
5221
5222
5223
5224void QImage::applyColorTransform(
const QColorTransform &transform)
5226 if (transform.isIdentity())
5229 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
5230 !qt_compatibleColorModelTarget(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel,
5231 QColorTransformPrivate::get(transform)->colorSpaceOut->transformModel)) {
5232 qWarning() <<
"QImage::applyColorTransform can not apply format switching transform without switching format";
5239 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5240 for (
int i = 0; i < d->colortable.size(); ++i)
5241 d->colortable[i] = transform.map(d->colortable[i]);
5244 QImage::Format oldFormat = format();
5245 if (qt_fpColorPrecision(oldFormat)) {
5246 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5247 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5248 convertTo(QImage::Format_RGBA32FPx4);
5249 }
else if (depth() > 32) {
5250 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5251 && oldFormat != QImage::Format_RGBA64_Premultiplied)
5252 convertTo(QImage::Format_RGBA64);
5253 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5254 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5255 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5256 if (hasAlphaChannel())
5257 convertTo(QImage::Format_ARGB32);
5259 convertTo(QImage::Format_RGB32);
5262 QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
5264 case Format_ARGB32_Premultiplied:
5265 case Format_RGBA64_Premultiplied:
5266 case Format_RGBA32FPx4_Premultiplied:
5267 flags = QColorTransformPrivate::Premultiplied;
5269 case Format_Grayscale8:
5270 case Format_Grayscale16:
5272 case Format_CMYK8888:
5274 case Format_RGBX32FPx4:
5275 flags = QColorTransformPrivate::InputOpaque;
5279 case Format_RGBA32FPx4:
5285 std::function<
void(
int,
int)> transformSegment;
5287 if (format() == Format_Grayscale8) {
5288 transformSegment = [&](
int yStart,
int yEnd) {
5289 for (
int y = yStart; y < yEnd; ++y) {
5290 uint8_t *scanline =
reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
5291 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5294 }
else if (format() == Format_Grayscale16) {
5295 transformSegment = [&](
int yStart,
int yEnd) {
5296 for (
int y = yStart; y < yEnd; ++y) {
5297 uint16_t *scanline =
reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
5298 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5301 }
else if (qt_fpColorPrecision(format())) {
5302 transformSegment = [&](
int yStart,
int yEnd) {
5303 for (
int y = yStart; y < yEnd; ++y) {
5304 QRgbaFloat32 *scanline =
reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
5305 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5308 }
else if (depth() > 32) {
5309 transformSegment = [&](
int yStart,
int yEnd) {
5310 for (
int y = yStart; y < yEnd; ++y) {
5311 QRgba64 *scanline =
reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
5312 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5315 }
else if (oldFormat == QImage::Format_CMYK8888) {
5316 transformSegment = [&](
int yStart,
int yEnd) {
5317 for (
int y = yStart; y < yEnd; ++y) {
5318 QCmyk32 *scanline =
reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
5319 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5323 transformSegment = [&](
int yStart,
int yEnd) {
5324 for (
int y = yStart; y < yEnd; ++y) {
5325 QRgb *scanline =
reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
5326 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5331#if QT_CONFIG(qtgui_threadpool)
5332 int segments = (qsizetype(width()) * height()) >> 16;
5333 segments = std::min(segments, height());
5334 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5335 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5336 QSemaphore semaphore;
5338 for (
int i = 0; i < segments; ++i) {
5339 int yn = (height() - y) / (segments - i);
5340 threadPool->start([&, y, yn]() {
5341 transformSegment(y, y + yn);
5342 semaphore.release(1);
5346 semaphore.acquire(segments);
5349 transformSegment(0, height());
5351 if (oldFormat != format())
5352 *
this = std::move(*
this).convertToFormat(oldFormat);
5356
5357
5358
5359
5360
5361
5362
5363void QImage::applyColorTransform(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
5367 if (transform.isIdentity())
5368 return convertTo(toFormat, flags);
5370 *
this = colorTransformed(transform, toFormat, flags);
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385QImage QImage::colorTransformed(
const QColorTransform &transform)
const &
5389 if (transform.isIdentity())
5392 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5393 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5394 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5395 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5398 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5400 switch (outColorSpace->colorModel) {
5401 case QColorSpace::ColorModel::Rgb:
5402 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5403 case QColorSpace::ColorModel::Gray:
5404 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5405 case QColorSpace::ColorModel::Cmyk:
5406 return colorTransformed(transform, QImage::Format_CMYK8888);
5407 case QColorSpace::ColorModel::Undefined:
5413 QImage image = copy();
5414 image.applyColorTransform(transform);
5418static bool isRgb32Data(QImage::Format f)
5421 case QImage::Format_RGB32:
5422 case QImage::Format_ARGB32:
5423 case QImage::Format_ARGB32_Premultiplied:
5431static bool isRgb64Data(QImage::Format f)
5434 case QImage::Format_RGBX64:
5435 case QImage::Format_RGBA64:
5436 case QImage::Format_RGBA64_Premultiplied:
5444static bool isRgb32fpx4Data(QImage::Format f)
5447 case QImage::Format_RGBX32FPx4:
5448 case QImage::Format_RGBA32FPx4:
5449 case QImage::Format_RGBA32FPx4_Premultiplied:
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
const &
5474 if (toFormat == QImage::Format_Invalid)
5475 toFormat = format();
5476 if (transform.isIdentity())
5477 return convertedTo(toFormat, flags);
5479 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5480 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5481 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5482 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5485 if (!qt_compatibleColorModelTarget(toPixelFormat(toFormat).colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5486 qWarning() <<
"QImage::colorTransformed: Invalid output color space for transform";
5490 QImage fromImage = *
this;
5492 QImage::Format tmpFormat = toFormat;
5494 case QImage::Format_RGB32:
5495 case QImage::Format_ARGB32:
5496 case QImage::Format_ARGB32_Premultiplied:
5497 case QImage::Format_RGBX32FPx4:
5498 case QImage::Format_RGBA32FPx4:
5499 case QImage::Format_RGBA32FPx4_Premultiplied:
5500 case QImage::Format_RGBX64:
5501 case QImage::Format_RGBA64:
5502 case QImage::Format_RGBA64_Premultiplied:
5503 case QImage::Format_Grayscale8:
5504 case QImage::Format_Grayscale16:
5505 case QImage::Format_CMYK8888:
5508 case QImage::Format_RGB16:
5509 case QImage::Format_RGB444:
5510 case QImage::Format_RGB555:
5511 case QImage::Format_RGB666:
5512 case QImage::Format_RGB888:
5513 case QImage::Format_BGR888:
5514 case QImage::Format_RGBX8888:
5515 tmpFormat = QImage::Format_RGB32;
5517 case QImage::Format_Mono:
5518 case QImage::Format_MonoLSB:
5519 case QImage::Format_Indexed8:
5520 case QImage::Format_ARGB8565_Premultiplied:
5521 case QImage::Format_ARGB6666_Premultiplied:
5522 case QImage::Format_ARGB8555_Premultiplied:
5523 case QImage::Format_ARGB4444_Premultiplied:
5524 case QImage::Format_RGBA8888:
5525 case QImage::Format_RGBA8888_Premultiplied:
5526 tmpFormat = QImage::Format_ARGB32;
5528 case QImage::Format_BGR30:
5529 case QImage::Format_RGB30:
5530 tmpFormat = QImage::Format_RGBX64;
5532 case QImage::Format_A2BGR30_Premultiplied:
5533 case QImage::Format_A2RGB30_Premultiplied:
5534 tmpFormat = QImage::Format_RGBA64;
5536 case QImage::Format_RGBX16FPx4:
5537 case QImage::Format_RGBA16FPx4:
5538 case QImage::Format_RGBA16FPx4_Premultiplied:
5539 tmpFormat = QImage::Format_RGBA32FPx4;
5541 case QImage::Format_Alpha8:
5542 return convertedTo(QImage::Format_Alpha8);
5543 case QImage::Format_Invalid:
5544 case QImage::NImageFormats:
5548 QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
5549 QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
5551 if (inColorData != outColorData) {
5552 if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
5553 tmpFormat = QImage::Format_RGB32;
5554 else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
5555 tmpFormat = QImage::Format_Grayscale16;
5556 else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
5557 tmpFormat = QImage::Format_RGBX64;
5559 if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
5560 tmpFormat = QImage::Format_Grayscale16;
5561 else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
5562 tmpFormat = QImage::Format_RGBA32FPx4;
5563 else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(),
true))
5564 tmpFormat = QImage::Format_RGBA64;
5567 QImage toImage(size(), tmpFormat);
5568 copyMetadata(&toImage, *
this);
5570 std::function<
void(
int,
int)> transformSegment;
5571 QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
5573 if (inColorData != outColorData) {
5575 if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
5577 if (format() == QImage::Format_Grayscale8) {
5578 transformSegment = [&](
int yStart,
int yEnd) {
5579 for (
int y = yStart; y < yEnd; ++y) {
5580 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5581 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5582 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5586 transformSegment = [&](
int yStart,
int yEnd) {
5587 for (
int y = yStart; y < yEnd; ++y) {
5588 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5589 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5590 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5594 }
else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
5596 if (format() == QImage::Format_Grayscale8) {
5597 transformSegment = [&](
int yStart,
int yEnd) {
5598 for (
int y = yStart; y < yEnd; ++y) {
5599 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5600 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5601 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5605 transformSegment = [&](
int yStart,
int yEnd) {
5606 for (
int y = yStart; y < yEnd; ++y) {
5607 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5608 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5609 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5613 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
5615 if (tmpFormat == QImage::Format_Grayscale8) {
5616 fromImage.convertTo(QImage::Format_RGB32);
5617 transformSegment = [&](
int yStart,
int yEnd) {
5618 for (
int y = yStart; y < yEnd; ++y) {
5619 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5620 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5621 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5625 fromImage.convertTo(QImage::Format_RGBX64);
5626 transformSegment = [&](
int yStart,
int yEnd) {
5627 for (
int y = yStart; y < yEnd; ++y) {
5628 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5629 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5630 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5634 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
5636 if (tmpFormat == QImage::Format_Grayscale8) {
5637 transformSegment = [&](
int yStart,
int yEnd) {
5638 for (
int y = yStart; y < yEnd; ++y) {
5639 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5640 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5641 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5645 transformSegment = [&](
int yStart,
int yEnd) {
5646 for (
int y = yStart; y < yEnd; ++y) {
5647 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5648 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5649 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5653 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
5655 if (isRgb32Data(tmpFormat) ) {
5656 transformSegment = [&](
int yStart,
int yEnd) {
5657 for (
int y = yStart; y < yEnd; ++y) {
5658 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5659 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5660 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5663 }
else if (isRgb64Data(tmpFormat)) {
5664 transformSegment = [&](
int yStart,
int yEnd) {
5665 for (
int y = yStart; y < yEnd; ++y) {
5666 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5667 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5668 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5672 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5673 transformSegment = [&](
int yStart,
int yEnd) {
5674 for (
int y = yStart; y < yEnd; ++y) {
5675 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5676 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5677 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5681 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
5683 if (!fromImage.hasAlphaChannel())
5684 transFlags = QColorTransformPrivate::InputOpaque;
5685 else if (qPixelLayouts[fromImage.format()].premultiplied)
5686 transFlags = QColorTransformPrivate::Premultiplied;
5687 if (isRgb32Data(fromImage.format()) ) {
5688 transformSegment = [&](
int yStart,
int yEnd) {
5689 for (
int y = yStart; y < yEnd; ++y) {
5690 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5691 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5692 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5695 }
else if (isRgb64Data(fromImage.format())) {
5696 transformSegment = [&](
int yStart,
int yEnd) {
5697 for (
int y = yStart; y < yEnd; ++y) {
5698 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5699 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5700 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5704 Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
5705 transformSegment = [&](
int yStart,
int yEnd) {
5706 for (
int y = yStart; y < yEnd; ++y) {
5707 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5708 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5709 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5718 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5719 for (
int i = 0; i < d->colortable.size(); ++i)
5720 fromImage.d->colortable[i] = transform.map(d->colortable[i]);
5721 return fromImage.convertedTo(toFormat, flags);
5724 QImage::Format oldFormat = format();
5725 if (qt_fpColorPrecision(oldFormat)) {
5726 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5727 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5728 fromImage.convertTo(QImage::Format_RGBA32FPx4);
5729 }
else if (qt_highColorPrecision(oldFormat,
true)) {
5730 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5731 && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
5732 fromImage.convertTo(QImage::Format_RGBA64);
5733 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5734 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5735 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5736 if (hasAlphaChannel())
5737 fromImage.convertTo(QImage::Format_ARGB32);
5739 fromImage.convertTo(QImage::Format_RGB32);
5742 if (!fromImage.hasAlphaChannel())
5743 transFlags = QColorTransformPrivate::InputOpaque;
5744 else if (qPixelLayouts[fromImage.format()].premultiplied)
5745 transFlags = QColorTransformPrivate::Premultiplied;
5747 if (fromImage.format() == Format_Grayscale8) {
5748 transformSegment = [&](
int yStart,
int yEnd) {
5749 for (
int y = yStart; y < yEnd; ++y) {
5750 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5751 if (tmpFormat == Format_Grayscale8) {
5752 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5753 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5755 Q_ASSERT(tmpFormat == Format_Grayscale16);
5756 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5757 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5761 }
else if (fromImage.format() == Format_Grayscale16) {
5762 transformSegment = [&](
int yStart,
int yEnd) {
5763 for (
int y = yStart; y < yEnd; ++y) {
5764 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5765 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5766 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5769 }
else if (fromImage.format() == Format_CMYK8888) {
5770 Q_ASSERT(tmpFormat == Format_CMYK8888);
5771 transformSegment = [&](
int yStart,
int yEnd) {
5772 for (
int y = yStart; y < yEnd; ++y) {
5773 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5774 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5775 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5778 }
else if (isRgb32fpx4Data(fromImage.format())) {
5779 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5780 transformSegment = [&](
int yStart,
int yEnd) {
5781 for (
int y = yStart; y < yEnd; ++y) {
5782 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5783 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5784 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5787 }
else if (isRgb64Data(fromImage.format())) {
5788 transformSegment = [&](
int yStart,
int yEnd) {
5789 for (
int y = yStart; y < yEnd; ++y) {
5790 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5791 if (isRgb32fpx4Data(tmpFormat)) {
5792 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5793 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5795 Q_ASSERT(isRgb64Data(tmpFormat));
5796 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5797 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5802 transformSegment = [&](
int yStart,
int yEnd) {
5803 for (
int y = yStart; y < yEnd; ++y) {
5804 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5805 if (isRgb32fpx4Data(tmpFormat)) {
5806 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5807 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5808 }
else if (isRgb64Data(tmpFormat)) {
5809 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5810 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5812 Q_ASSERT(isRgb32Data(tmpFormat));
5813 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5814 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5821#if QT_CONFIG(qtgui_threadpool)
5822 int segments = (qsizetype(width()) * height()) >> 16;
5823 segments = std::min(segments, height());
5824 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5825 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5826 QSemaphore semaphore;
5828 for (
int i = 0; i < segments; ++i) {
5829 int yn = (height() - y) / (segments - i);
5830 threadPool->start([&, y, yn]() {
5831 transformSegment(y, y + yn);
5832 semaphore.release(1);
5836 semaphore.acquire(segments);
5839 transformSegment(0, height());
5841 if (tmpFormat != toFormat)
5842 toImage.convertTo(toFormat);
5848
5849
5850
5851
5852
5853
5854
5855QImage QImage::colorTransformed(
const QColorTransform &transform) &&
5860 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5861 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5862 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5863 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5866 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5868 switch (outColorSpace->colorModel) {
5869 case QColorSpace::ColorModel::Rgb:
5870 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5871 case QColorSpace::ColorModel::Gray:
5872 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5873 case QColorSpace::ColorModel::Cmyk:
5874 return colorTransformed(transform, QImage::Format_CMYK8888);
5875 case QColorSpace::ColorModel::Undefined:
5881 applyColorTransform(transform);
5882 return std::move(*
this);
5886
5887
5888
5889
5890
5891
5892
5893QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
5896 return colorTransformed(transform, format, flags);
5899bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
5901 if (format == newFormat)
5905 if (ref.loadRelaxed() > 1 || !own_data)
5908 InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat];
5910 return converter(
this, flags);
5911 if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8 && !qimage_converter_map[format][newFormat]) {
5914 if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
5915 && qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
5916#if QT_CONFIG(raster_fp)
5917 if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
5918 return convert_generic_inplace_over_rgba32f(
this, newFormat, flags);
5920 return convert_generic_inplace_over_rgb64(
this, newFormat, flags);
5922 return convert_generic_inplace(
this, newFormat, flags);
5928
5929
5930
5933
5934
5935
5937#ifndef QT_NO_DEBUG_STREAM
5938QDebug operator<<(QDebug dbg,
const QImage &i)
5940 QDebugStateSaver saver(dbg);
5947 dbg << i.size() <<
",format=" << i.format() <<
",depth=" << i.depth();
5949 dbg <<
",colorCount=" << i.colorCount();
5950 const int bytesPerLine = i.bytesPerLine();
5951 dbg <<
",devicePixelRatio=" << i.devicePixelRatio()
5952 <<
",bytesPerLine=" << bytesPerLine <<
",sizeInBytes=" << i.sizeInBytes();
5953 if (dbg.verbosity() > 2 && i.height() > 0) {
5954 const int outputLength = qMin(bytesPerLine, 24);
5956 << QByteArray(
reinterpret_cast<
const char *>(i.scanLine(0)), outputLength).toHex()
5965static constexpr QPixelFormat pixelformats[] = {
5969 QPixelFormat(QPixelFormat::Indexed,
5976 QPixelFormat::IgnoresAlpha,
5977 QPixelFormat::AtBeginning,
5978 QPixelFormat::NotPremultiplied,
5979 QPixelFormat::UnsignedByte,
5980 QPixelFormat::CurrentSystemEndian),
5982 QPixelFormat(QPixelFormat::Indexed,
5989 QPixelFormat::IgnoresAlpha,
5990 QPixelFormat::AtBeginning,
5991 QPixelFormat::NotPremultiplied,
5992 QPixelFormat::UnsignedByte,
5993 QPixelFormat::CurrentSystemEndian),
5995 QPixelFormat(QPixelFormat::Indexed,
6002 QPixelFormat::IgnoresAlpha,
6003 QPixelFormat::AtBeginning,
6004 QPixelFormat::NotPremultiplied,
6005 QPixelFormat::UnsignedByte,
6006 QPixelFormat::CurrentSystemEndian),
6008 QPixelFormat(QPixelFormat::RGB,
6015 QPixelFormat::IgnoresAlpha,
6016 QPixelFormat::AtBeginning,
6017 QPixelFormat::NotPremultiplied,
6018 QPixelFormat::UnsignedInteger,
6019 QPixelFormat::CurrentSystemEndian),
6021 QPixelFormat(QPixelFormat::RGB,
6028 QPixelFormat::UsesAlpha,
6029 QPixelFormat::AtBeginning,
6030 QPixelFormat::NotPremultiplied,
6031 QPixelFormat::UnsignedInteger,
6032 QPixelFormat::CurrentSystemEndian),
6034 QPixelFormat(QPixelFormat::RGB,
6041 QPixelFormat::UsesAlpha,
6042 QPixelFormat::AtBeginning,
6043 QPixelFormat::Premultiplied,
6044 QPixelFormat::UnsignedInteger,
6045 QPixelFormat::CurrentSystemEndian),
6047 QPixelFormat(QPixelFormat::RGB,
6054 QPixelFormat::IgnoresAlpha,
6055 QPixelFormat::AtBeginning,
6056 QPixelFormat::NotPremultiplied,
6057 QPixelFormat::UnsignedShort,
6058 QPixelFormat::CurrentSystemEndian),
6060 QPixelFormat(QPixelFormat::RGB,
6067 QPixelFormat::UsesAlpha,
6068 QPixelFormat::AtBeginning,
6069 QPixelFormat::Premultiplied,
6070 QPixelFormat::UnsignedInteger,
6071 QPixelFormat::CurrentSystemEndian),
6073 QPixelFormat(QPixelFormat::RGB,
6080 QPixelFormat::IgnoresAlpha,
6081 QPixelFormat::AtBeginning,
6082 QPixelFormat::NotPremultiplied,
6083 QPixelFormat::UnsignedInteger,
6084 QPixelFormat::CurrentSystemEndian),
6086 QPixelFormat(QPixelFormat::RGB,
6093 QPixelFormat::UsesAlpha,
6094 QPixelFormat::AtEnd,
6095 QPixelFormat::Premultiplied,
6096 QPixelFormat::UnsignedInteger,
6097 QPixelFormat::CurrentSystemEndian),
6099 QPixelFormat(QPixelFormat::RGB,
6106 QPixelFormat::IgnoresAlpha,
6107 QPixelFormat::AtBeginning,
6108 QPixelFormat::NotPremultiplied,
6109 QPixelFormat::UnsignedShort,
6110 QPixelFormat::CurrentSystemEndian),
6112 QPixelFormat(QPixelFormat::RGB,
6119 QPixelFormat::UsesAlpha,
6120 QPixelFormat::AtBeginning,
6121 QPixelFormat::Premultiplied,
6122 QPixelFormat::UnsignedInteger,
6123 QPixelFormat::CurrentSystemEndian),
6125 QPixelFormat(QPixelFormat::RGB,
6132 QPixelFormat::IgnoresAlpha,
6133 QPixelFormat::AtBeginning,
6134 QPixelFormat::NotPremultiplied,
6135 QPixelFormat::UnsignedByte,
6136 QPixelFormat::CurrentSystemEndian),
6138 QPixelFormat(QPixelFormat::RGB,
6145 QPixelFormat::IgnoresAlpha,
6146 QPixelFormat::AtBeginning,
6147 QPixelFormat::NotPremultiplied,
6148 QPixelFormat::UnsignedShort,
6149 QPixelFormat::CurrentSystemEndian),
6151 QPixelFormat(QPixelFormat::RGB,
6158 QPixelFormat::UsesAlpha,
6159 QPixelFormat::AtEnd,
6160 QPixelFormat::Premultiplied,
6161 QPixelFormat::UnsignedShort,
6162 QPixelFormat::CurrentSystemEndian),
6164 QPixelFormat(QPixelFormat::RGB,
6171 QPixelFormat::IgnoresAlpha,
6172 QPixelFormat::AtEnd,
6173 QPixelFormat::NotPremultiplied,
6174 QPixelFormat::UnsignedByte,
6175 QPixelFormat::CurrentSystemEndian),
6177 QPixelFormat(QPixelFormat::RGB,
6184 QPixelFormat::UsesAlpha,
6185 QPixelFormat::AtEnd,
6186 QPixelFormat::NotPremultiplied,
6187 QPixelFormat::UnsignedByte,
6188 QPixelFormat::CurrentSystemEndian),
6190 QPixelFormat(QPixelFormat::RGB,
6197 QPixelFormat::UsesAlpha,
6198 QPixelFormat::AtEnd,
6199 QPixelFormat::Premultiplied,
6200 QPixelFormat::UnsignedByte,
6201 QPixelFormat::CurrentSystemEndian),
6203 QPixelFormat(QPixelFormat::BGR,
6210 QPixelFormat::IgnoresAlpha,
6211 QPixelFormat::AtBeginning,
6212 QPixelFormat::NotPremultiplied,
6213 QPixelFormat::UnsignedInteger,
6214 QPixelFormat::CurrentSystemEndian),
6216 QPixelFormat(QPixelFormat::BGR,
6223 QPixelFormat::UsesAlpha,
6224 QPixelFormat::AtBeginning,
6225 QPixelFormat::Premultiplied,
6226 QPixelFormat::UnsignedInteger,
6227 QPixelFormat::CurrentSystemEndian),
6229 QPixelFormat(QPixelFormat::RGB,
6236 QPixelFormat::IgnoresAlpha,
6237 QPixelFormat::AtBeginning,
6238 QPixelFormat::NotPremultiplied,
6239 QPixelFormat::UnsignedInteger,
6240 QPixelFormat::CurrentSystemEndian),
6242 QPixelFormat(QPixelFormat::RGB,
6249 QPixelFormat::UsesAlpha,
6250 QPixelFormat::AtBeginning,
6251 QPixelFormat::Premultiplied,
6252 QPixelFormat::UnsignedInteger,
6253 QPixelFormat::CurrentSystemEndian),
6255 QPixelFormat(QPixelFormat::Alpha,
6262 QPixelFormat::UsesAlpha,
6263 QPixelFormat::AtBeginning,
6264 QPixelFormat::Premultiplied,
6265 QPixelFormat::UnsignedByte,
6266 QPixelFormat::CurrentSystemEndian),
6268 QPixelFormat(QPixelFormat::Grayscale,
6275 QPixelFormat::IgnoresAlpha,
6276 QPixelFormat::AtBeginning,
6277 QPixelFormat::NotPremultiplied,
6278 QPixelFormat::UnsignedByte,
6279 QPixelFormat::CurrentSystemEndian),
6281 QPixelFormat(QPixelFormat::RGB,
6288 QPixelFormat::IgnoresAlpha,
6289 QPixelFormat::AtEnd,
6290 QPixelFormat::NotPremultiplied,
6291 QPixelFormat::UnsignedShort,
6292 QPixelFormat::CurrentSystemEndian),
6294 QPixelFormat(QPixelFormat::RGB,
6301 QPixelFormat::UsesAlpha,
6302 QPixelFormat::AtEnd,
6303 QPixelFormat::NotPremultiplied,
6304 QPixelFormat::UnsignedShort,
6305 QPixelFormat::CurrentSystemEndian),
6307 QPixelFormat(QPixelFormat::RGB,
6314 QPixelFormat::UsesAlpha,
6315 QPixelFormat::AtEnd,
6316 QPixelFormat::Premultiplied,
6317 QPixelFormat::UnsignedShort,
6318 QPixelFormat::CurrentSystemEndian),
6320 QPixelFormat(QPixelFormat::Grayscale,
6327 QPixelFormat::IgnoresAlpha,
6328 QPixelFormat::AtBeginning,
6329 QPixelFormat::NotPremultiplied,
6330 QPixelFormat::UnsignedShort,
6331 QPixelFormat::CurrentSystemEndian),
6333 QPixelFormat(QPixelFormat::BGR,
6340 QPixelFormat::IgnoresAlpha,
6341 QPixelFormat::AtBeginning,
6342 QPixelFormat::NotPremultiplied,
6343 QPixelFormat::UnsignedByte,
6344 QPixelFormat::CurrentSystemEndian),
6346 QPixelFormat(QPixelFormat::RGB,
6353 QPixelFormat::IgnoresAlpha,
6354 QPixelFormat::AtEnd,
6355 QPixelFormat::NotPremultiplied,
6356 QPixelFormat::FloatingPoint,
6357 QPixelFormat::CurrentSystemEndian),
6359 QPixelFormat(QPixelFormat::RGB,
6366 QPixelFormat::UsesAlpha,
6367 QPixelFormat::AtEnd,
6368 QPixelFormat::NotPremultiplied,
6369 QPixelFormat::FloatingPoint,
6370 QPixelFormat::CurrentSystemEndian),
6372 QPixelFormat(QPixelFormat::RGB,
6379 QPixelFormat::UsesAlpha,
6380 QPixelFormat::AtEnd,
6381 QPixelFormat::Premultiplied,
6382 QPixelFormat::FloatingPoint,
6383 QPixelFormat::CurrentSystemEndian),
6385 QPixelFormat(QPixelFormat::RGB,
6392 QPixelFormat::IgnoresAlpha,
6393 QPixelFormat::AtEnd,
6394 QPixelFormat::NotPremultiplied,
6395 QPixelFormat::FloatingPoint,
6396 QPixelFormat::CurrentSystemEndian),
6398 QPixelFormat(QPixelFormat::RGB,
6405 QPixelFormat::UsesAlpha,
6406 QPixelFormat::AtEnd,
6407 QPixelFormat::NotPremultiplied,
6408 QPixelFormat::FloatingPoint,
6409 QPixelFormat::CurrentSystemEndian),
6411 QPixelFormat(QPixelFormat::RGB,
6418 QPixelFormat::UsesAlpha,
6419 QPixelFormat::AtEnd,
6420 QPixelFormat::Premultiplied,
6421 QPixelFormat::FloatingPoint,
6422 QPixelFormat::CurrentSystemEndian),
6424 QPixelFormat(QPixelFormat::CMYK,
6431 QPixelFormat::IgnoresAlpha,
6432 QPixelFormat::AtBeginning,
6433 QPixelFormat::NotPremultiplied,
6434 QPixelFormat::UnsignedInteger,
6435 QPixelFormat::CurrentSystemEndian),
6437static_assert(
sizeof(pixelformats) /
sizeof(*pixelformats) == QImage::NImageFormats);
6440
6441
6442QPixelFormat QImage::pixelFormat()
const noexcept
6444 return toPixelFormat(format());
6448
6449
6450QPixelFormat QImage::toPixelFormat(QImage::Format format)
noexcept
6452 Q_ASSERT(
static_cast<
int>(format) < NImageFormats &&
static_cast<
int>(format) >= 0);
6453 return pixelformats[format];
6457
6458
6459QImage::Format QImage::toImageFormat(QPixelFormat format)
noexcept
6461 for (
int i = 0; i < NImageFormats; i++) {
6462 if (format == pixelformats[i])
6465 return Format_Invalid;
6470 Qt::Orientations orients = {};
6471 if (orient.testFlag(QImageIOHandler::TransformationMirror))
6472 orients |= Qt::Horizontal;
6473 if (orient.testFlag(QImageIOHandler::TransformationFlip))
6474 orients |= Qt::Vertical;
6480 if (orient == QImageIOHandler::TransformationNone)
6482 if (orient == QImageIOHandler::TransformationRotate270) {
6483 src = rotated270(src);
6485 src.flip(toOrientations(orient));
6486 if (orient & QImageIOHandler::TransformationRotate90)
6487 src = rotated90(src);
6493 QMap<QString, QString> text = qt_getImageTextFromDescription(description);
6494 const auto textKeys = image.textKeys();
6495 for (
const QString &key : textKeys) {
6496 if (!key.isEmpty() && !text.contains(key))
6497 text.insert(key, image.text(key));
6504 QMap<QString, QString> text;
6505 for (
const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
6506 int index = pair.indexOf(u':');
6507 if (index >= 0 && pair.indexOf(u' ') < index) {
6508 if (!pair.trimmed().isEmpty())
6509 text.insert(
"Description"_L1, pair.toString().simplified());
6511 const auto key = pair.left(index);
6512 if (!key.trimmed().isEmpty())
6513 text.insert(key.toString(), pair.mid(index + 2).toString().simplified());
6521#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)
static void copyMetadata(QImageData *dst, const QImageData *src)
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)