19#include <qpa/qplatformintegration.h>
20#include <private/qguiapplication_p.h>
24#include <qpa/qplatformpixmap.h>
26#include <private/qcolorspace_p.h>
27#include <private/qcolortransform_p.h>
28#include <private/qmemrotate_p.h>
29#include <private/qimagescale_p.h>
30#include <private/qpixellayout_p.h>
31#include <private/qsimd_p.h>
35#include <private/qpaintengine_raster_p.h>
37#include <private/qimage_p.h>
38#include <private/qfont_p.h>
40#if QT_CONFIG(qtgui_threadpool)
41#include <private/qlatch_p.h>
42#include <qthreadpool.h>
43#include <private/qthreadpool_p.h>
46#include <qtgui_tracepoints_p.h>
50#define QT_XFORM_TYPE_MSBFIRST 0
51#define QT_XFORM_TYPE_LSBFIRST 1
56using namespace Qt::StringLiterals;
61QT_WARNING_DISABLE_MSVC(4723)
63#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0
>= 50190001
)
64#pragma message disable narrowptr
68#define QIMAGE_SANITYCHECK_MEMORY(image)
69 if ((image).isNull()) {
70 qWarning("QImage: out of memory, returning null image");
75 "#include <qimagereader.h>"
79"ENUM { } QImage::Format;" \
80"FLAGS { } Qt::ImageConversionFlags;"
83Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode,
int);
84Q_TRACE_PARAM_REPLACE(Qt::TransformationMode,
int);
86static QImage
rotated90(
const QImage &src);
92 Q_CONSTINIT
static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
93 return 1 + serial.fetchAndAddRelaxed(1);
96QImageData::QImageData()
97 : ref(0), width(0), height(0), depth(0), nbytes(0), devicePixelRatio(1.0), data(
nullptr),
98 format(QImage::Format_ARGB32), bytes_per_line(0),
99 ser_no(next_qimage_serial_number()),
101 dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
102 dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
103 offset(0, 0), own_data(
true), ro_data(
false), has_alpha_clut(
false),
104 is_cached(
false), cleanupFunction(
nullptr), cleanupInfo(
nullptr),
110
111
112
113
114
115
116QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(
const QSize &size, QImage::Format format)
118 if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
121 Q_TRACE_SCOPE(QImageData_create, size, format);
123 int width = size.width();
124 int height = size.height();
125 int depth = qt_depthForFormat(format);
126 auto params = calculateImageParameters(width, height, depth);
127 if (!params.isValid())
130 auto d = std::make_unique<QImageData>();
133 case QImage::Format_Mono:
134 case QImage::Format_MonoLSB:
135 d->colortable.resize(2);
136 d->colortable[0] = QColor(Qt::black).rgba();
137 d->colortable[1] = QColor(Qt::white).rgba();
147 d->has_alpha_clut =
false;
148 d->is_cached =
false;
150 d->bytes_per_line = params.bytesPerLine;
151 d->nbytes = params.totalSize;
152 d->data = (uchar *)malloc(d->nbytes);
161QImageData::~QImageData()
164 cleanupFunction(cleanupInfo);
166 QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
168 if (data && own_data)
169 QtPrivate::sizedFree(data, nbytes);
173#if defined(_M_ARM) && defined(_MSC_VER)
174#pragma optimize("", off)
177bool QImageData::checkForAlphaPixels()
const
179 bool has_alpha_pixels =
false;
183 case QImage::Format_Mono:
184 case QImage::Format_MonoLSB:
185 case QImage::Format_Indexed8:
186 has_alpha_pixels = has_alpha_clut;
188 case QImage::Format_Alpha8:
189 has_alpha_pixels =
true;
191 case QImage::Format_ARGB32:
192 case QImage::Format_ARGB32_Premultiplied: {
193 const uchar *bits = data;
194 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
195 uint alphaAnd = 0xff000000;
196 for (
int x=0; x<width; ++x)
197 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
198 has_alpha_pixels = (alphaAnd != 0xff000000);
199 bits += bytes_per_line;
203 case QImage::Format_RGBA8888:
204 case QImage::Format_RGBA8888_Premultiplied: {
205 const uchar *bits = data;
206 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
207 uchar alphaAnd = 0xff;
208 for (
int x=0; x<width; ++x)
209 alphaAnd &= bits[x * 4+ 3];
210 has_alpha_pixels = (alphaAnd != 0xff);
211 bits += bytes_per_line;
215 case QImage::Format_A2BGR30_Premultiplied:
216 case QImage::Format_A2RGB30_Premultiplied: {
217 const uchar *bits = data;
218 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
219 uint alphaAnd = 0xc0000000;
220 for (
int x=0; x<width; ++x)
221 alphaAnd &=
reinterpret_cast<
const uint*>(bits)[x];
222 has_alpha_pixels = (alphaAnd != 0xc0000000);
223 bits += bytes_per_line;
227 case QImage::Format_ARGB8555_Premultiplied:
228 case QImage::Format_ARGB8565_Premultiplied: {
229 const uchar *bits = data;
230 const uchar *end_bits = data + bytes_per_line;
232 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
233 uchar alphaAnd = 0xff;
234 while (bits < end_bits) {
238 has_alpha_pixels = (alphaAnd != 0xff);
240 end_bits += bytes_per_line;
244 case QImage::Format_ARGB6666_Premultiplied: {
245 const uchar *bits = data;
246 const uchar *end_bits = data + bytes_per_line;
248 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
249 uchar alphaAnd = 0xfc;
250 while (bits < end_bits) {
254 has_alpha_pixels = (alphaAnd != 0xfc);
256 end_bits += bytes_per_line;
260 case QImage::Format_ARGB4444_Premultiplied: {
261 const uchar *bits = data;
262 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
263 ushort alphaAnd = 0xf000;
264 for (
int x=0; x<width; ++x)
265 alphaAnd &=
reinterpret_cast<
const ushort*>(bits)[x];
266 has_alpha_pixels = (alphaAnd != 0xf000);
267 bits += bytes_per_line;
270 case QImage::Format_RGBA64:
271 case QImage::Format_RGBA64_Premultiplied: {
273 for (
int y=0; y<height && !has_alpha_pixels; ++y) {
274 for (
int x=0; x<width; ++x) {
275 has_alpha_pixels |= !(((QRgba64 *)bits)[x].isOpaque());
277 bits += bytes_per_line;
280 case QImage::Format_RGBA16FPx4:
281 case QImage::Format_RGBA16FPx4_Premultiplied: {
283 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
284 for (
int x = 0; x < width; ++x)
285 has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
286 bits += bytes_per_line;
289 case QImage::Format_RGBA32FPx4:
290 case QImage::Format_RGBA32FPx4_Premultiplied: {
292 for (
int y = 0; y < height && !has_alpha_pixels; ++y) {
293 for (
int x = 0; x < width; ++x)
294 has_alpha_pixels |= ((
float *)bits)[x * 4 + 3] < 1.0f;
295 bits += bytes_per_line;
299 case QImage::Format_RGB32:
300 case QImage::Format_RGB16:
301 case QImage::Format_RGB444:
302 case QImage::Format_RGB555:
303 case QImage::Format_RGB666:
304 case QImage::Format_RGB888:
305 case QImage::Format_BGR888:
306 case QImage::Format_RGBX8888:
307 case QImage::Format_BGR30:
308 case QImage::Format_RGB30:
309 case QImage::Format_Grayscale8:
310 case QImage::Format_Grayscale16:
311 case QImage::Format_RGBX64:
312 case QImage::Format_RGBX16FPx4:
313 case QImage::Format_RGBX32FPx4:
314 case QImage::Format_CMYK8888:
316 case QImage::Format_Invalid:
317 case QImage::NImageFormats:
322 return has_alpha_pixels;
324#if defined(_M_ARM) && defined(_MSC_VER)
325#pragma optimize("", on)
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
623
624
625
626
627
630
631
632
633
634
635
636
639
640
641
642
643
644
648
649
650
651
652
653
654
655
656
657
660
661
662
663
664
665
666
667
668
669
670
671
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
778
779
780
781
782
783
784
785
788
789
792
793
794
795
797QImage::QImage()
noexcept
804
805
806
807
808
809
810
811
812
813QImage::QImage(
int width,
int height, Format format)
814 : QImage(QSize(width, height), format)
819
820
821
822
823
824
825
826
827QImage::QImage(
const QSize &size, Format format)
830 d = QImageData::create(size, format);
835QImageData *QImageData::create(uchar *data,
int width,
int height, qsizetype bpl, QImage::Format format,
bool readOnly, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
837 if (width <= 0 || height <= 0 || !data || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
840 const int depth = qt_depthForFormat(format);
841 auto params = calculateImageParameters(width, height, depth);
842 if (!params.isValid())
847 const qsizetype min_bytes_per_line = (qsizetype(width) * depth + 7)/8;
848 if (bpl < min_bytes_per_line)
852 params.bytesPerLine = bpl;
853 if (qMulOverflow<qsizetype>(bpl, height, ¶ms.totalSize))
857 QImageData *d =
new QImageData;
861 d->ro_data = readOnly;
868 d->bytes_per_line = params.bytesPerLine;
869 d->nbytes = params.totalSize;
871 d->cleanupFunction = cleanupFunction;
872 d->cleanupInfo = cleanupInfo;
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894QImage::QImage(uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
897 d = QImageData::create(data, width, height, 0, format,
false, cleanupFunction, cleanupInfo);
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925QImage::QImage(
const uchar* data,
int width,
int height, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
928 d = QImageData::create(
const_cast<uchar*>(data), width, height, 0, format,
true, cleanupFunction, cleanupInfo);
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
949QImage::QImage(uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
952 d = QImageData::create(data, width, height, bytesPerLine, format,
false, cleanupFunction, cleanupInfo);
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
980QImage::QImage(
const uchar *data,
int width,
int height, qsizetype bytesPerLine, Format format, QImageCleanupFunction cleanupFunction,
void *cleanupInfo)
983 d = QImageData::create(
const_cast<uchar*>(data), width, height, bytesPerLine, format,
true, cleanupFunction, cleanupInfo);
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1006QImage::QImage(
const QString &fileName,
const char *format)
1010 load(fileName, format);
1013#ifndef QT_NO_IMAGEFORMAT_XPM
1014extern bool qt_read_xpm_image_or_array(QIODevice *device,
const char *
const *source, QImage &image);
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1032QImage::QImage(
const char *
const xpm[])
1038 if (!qt_read_xpm_image_or_array(
nullptr, xpm, *
this))
1040 qWarning(
"QImage::QImage(), XPM is not supported");
1045
1046
1047
1048
1049
1050
1051
1053QImage::QImage(
const QImage &image)
1056 if (image.paintingActive()) {
1058 image.copy().swap(*
this);
1067
1068
1072 if (d && !d->ref.deref())
1077
1078
1079
1080
1081
1082
1083
1084
1086QImage &QImage::operator=(
const QImage &image)
1088 if (image.paintingActive()) {
1089 operator=(image.copy());
1093 if (d && !d->ref.deref())
1101
1102
1103
1106
1107
1108int QImage::devType()
const
1110 return QInternal::Image;
1114
1115
1116QImage::operator QVariant()
const
1118 return QVariant::fromValue(*
this);
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132void QImage::detach()
1135 if (d->is_cached && d->ref.loadRelaxed() == 1)
1136 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1138 if (d->ref.loadRelaxed() != 1 || d->ro_data)
1148
1149
1150
1151
1152
1153
1154
1155void QImage::detachMetadata(
bool invalidateCache)
1158 if (d->is_cached && d->ref.loadRelaxed() == 1)
1159 QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
1161 if (d->ref.loadRelaxed() != 1)
1164 if (d && invalidateCache)
1171 dst->dpmx = src->dpmx;
1172 dst->dpmy = src->dpmy;
1173 dst->devicePixelRatio = src->devicePixelRatio;
1180 dst->text = src->text;
1181 dst->offset = src->offset;
1182 dst->colorSpace = src->colorSpace;
1187 dst->setDotsPerMeterX(src.dotsPerMeterX());
1188 dst->setDotsPerMeterY(src.dotsPerMeterY());
1189 dst->setDevicePixelRatio(src.devicePixelRatio());
1190 const auto textKeys = src.textKeys();
1191 for (
const auto &key: textKeys)
1192 dst->setText(key, src.text(key));
1197
1198
1199
1200
1201
1202
1203
1204
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(
const QRect& r)
const
1228 Q_TRACE_SCOPE(QImage_copy, r);
1233 QImage image(d->width, d->height, d->format);
1239 if (image.d->nbytes != d->nbytes) {
1240 qsizetype bpl = qMin(bytesPerLine(), image.bytesPerLine());
1241 for (
int i = 0; i < height(); i++)
1242 memcpy(image.scanLine(i), scanLine(i), bpl);
1244 memcpy(image.bits(), bits(), d->nbytes);
1245 image.d->colortable = d->colortable;
1246 image.d->has_alpha_clut = d->has_alpha_clut;
1247 copyMetadata(image.d, d);
1258 if (w <= 0 || h <= 0)
1261 QImage image(w, h, d->format);
1265 if (x < 0 || y < 0 || x + w > d->width || y + h > d->height) {
1278 image.d->colortable = d->colortable;
1280 int pixels_to_copy = qMax(w - dx, 0);
1283 else if (pixels_to_copy > d->width - x)
1284 pixels_to_copy = d->width - x;
1285 int lines_to_copy = qMax(h - dy, 0);
1288 else if (lines_to_copy > d->height - y)
1289 lines_to_copy = d->height - y;
1291 bool byteAligned =
true;
1292 if (d->format == Format_Mono || d->format == Format_MonoLSB)
1293 byteAligned = !(dx & 7) && !(x & 7) && !(pixels_to_copy & 7);
1296 const uchar *src = d->data + ((x * d->depth) >> 3) + y * d->bytes_per_line;
1297 uchar *dest = image.d->data + ((dx * d->depth) >> 3) + dy * image.d->bytes_per_line;
1298 const qsizetype bytes_to_copy = (qsizetype(pixels_to_copy) * d->depth) >> 3;
1299 for (
int i = 0; i < lines_to_copy; ++i) {
1300 memcpy(dest, src, bytes_to_copy);
1301 src += d->bytes_per_line;
1302 dest += image.d->bytes_per_line;
1304 }
else if (d->format == Format_Mono) {
1305 const uchar *src = d->data + y * d->bytes_per_line;
1306 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1307 for (
int i = 0; i < lines_to_copy; ++i) {
1308 for (
int j = 0; j < pixels_to_copy; ++j) {
1309 if (src[(x + j) >> 3] & (0x80 >> ((x + j) & 7)))
1310 dest[(dx + j) >> 3] |= (0x80 >> ((dx + j) & 7));
1312 dest[(dx + j) >> 3] &= ~(0x80 >> ((dx + j) & 7));
1314 src += d->bytes_per_line;
1315 dest += image.d->bytes_per_line;
1318 Q_ASSERT(d->format == Format_MonoLSB);
1319 const uchar *src = d->data + y * d->bytes_per_line;
1320 uchar *dest = image.d->data + dy * image.d->bytes_per_line;
1321 for (
int i = 0; i < lines_to_copy; ++i) {
1322 for (
int j = 0; j < pixels_to_copy; ++j) {
1323 if (src[(x + j) >> 3] & (0x1 << ((x + j) & 7)))
1324 dest[(dx + j) >> 3] |= (0x1 << ((dx + j) & 7));
1326 dest[(dx + j) >> 3] &= ~(0x1 << ((dx + j) & 7));
1328 src += d->bytes_per_line;
1329 dest += image.d->bytes_per_line;
1333 copyMetadata(image.d, d);
1334 image.d->has_alpha_clut = d->has_alpha_clut;
1341
1342
1343
1344
1345
1346bool QImage::isNull()
const
1352
1353
1354
1355
1356
1357
1358int QImage::width()
const
1360 return d ? d->width : 0;
1364
1365
1366
1367
1368
1369
1370int QImage::height()
const
1372 return d ? d->height : 0;
1376
1377
1378
1379
1380
1381
1382QSize QImage::size()
const
1384 return d ? QSize(d->width, d->height) : QSize(0, 0);
1388
1389
1390
1391
1392
1393
1394
1395QRect QImage::rect()
const
1397 return d ? QRect(0, 0, d->width, d->height) : QRect();
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412int QImage::depth()
const
1414 return d ? d->depth : 0;
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428int QImage::colorCount()
const
1430 return d ? d->colortable.size() : 0;
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444void QImage::setColorTable(
const QList<QRgb> &colors)
1448 detachMetadata(
true);
1454 d->colortable = colors;
1455 d->has_alpha_clut =
false;
1456 for (
int i = 0; i < d->colortable.size(); ++i) {
1457 if (qAlpha(d->colortable.at(i)) != 255) {
1458 d->has_alpha_clut =
true;
1465
1466
1467
1468
1469
1470QList<QRgb> QImage::colorTable()
const
1472 return d ? d->colortable : QList<QRgb>();
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486qreal QImage::devicePixelRatio()
const
1490 return d->devicePixelRatio;
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514void QImage::setDevicePixelRatio(qreal scaleFactor)
1519 if (scaleFactor == d->devicePixelRatio)
1524 d->devicePixelRatio = scaleFactor;
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537QSizeF QImage::deviceIndependentSize()
const
1540 return QSizeF(0, 0);
1541 return QSizeF(d->width, d->height) / d->devicePixelRatio;
1546
1547
1548
1549
1550
1551
1552qsizetype QImage::sizeInBytes()
const
1554 return d ? d->nbytes : 0;
1558
1559
1560
1561
1562
1563
1564qsizetype QImage::bytesPerLine()
const
1566 return d ? d->bytes_per_line : 0;
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581QRgb QImage::color(
int i)
const
1583 Q_ASSERT(i < colorCount());
1584 return d ? d->colortable.at(i) : QRgb(uint(-1));
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599void QImage::setColor(
int i, QRgb c)
1603 if (i < 0 || d->depth > 8 || i >= 1<<d->depth) {
1604 qWarning(
"QImage::setColor: Index out of bound %d", i);
1607 detachMetadata(
true);
1613 if (i >= d->colortable.size())
1615 d->colortable[i] = c;
1616 d->has_alpha_clut |= (qAlpha(c) != 255);
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641uchar *QImage::scanLine(
int i)
1652 return d->data + i * d->bytes_per_line;
1656
1657
1658const uchar *QImage::scanLine(
int i)
const
1663 Q_ASSERT(i >= 0 && i < height());
1664 return d->data + i * d->bytes_per_line;
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682const uchar *QImage::constScanLine(
int i)
const
1687 Q_ASSERT(i >= 0 && i < height());
1688 return d->data + i * d->bytes_per_line;
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702uchar *QImage::bits()
1716
1717
1718
1719
1720
1721
1722const uchar *QImage::bits()
const
1724 return d ? d->data :
nullptr;
1729
1730
1731
1732
1733
1734
1735
1736
1737const uchar *QImage::constBits()
const
1739 return d ? d->data :
nullptr;
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1762void QImage::fill(uint pixel)
1773 if (d->depth == 1 || d->depth == 8) {
1775 if (d->depth == 1) {
1784 qt_rectfill<quint8>(d->data, pixel, 0, 0,
1785 w, d->height, d->bytes_per_line);
1787 }
else if (d->depth == 16) {
1788 if (d->format == Format_RGB444)
1790 qt_rectfill<quint16>(
reinterpret_cast<quint16*>(d->data), pixel,
1791 0, 0, d->width, d->height, d->bytes_per_line);
1793 }
else if (d->depth == 24) {
1794 if (d->format == Format_RGB666)
1796 qt_rectfill<quint24>(
reinterpret_cast<quint24*>(d->data), pixel,
1797 0, 0, d->width, d->height, d->bytes_per_line);
1799 }
else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
1800 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
1801 0, 0, d->width, d->height, d->bytes_per_line);
1803 }
else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
1805 QRgbaFloat16 cf = QRgbaFloat16::fromArgb32(pixel);
1806 ::memcpy(&cu, &cf,
sizeof(quint64));
1807 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), cu,
1808 0, 0, d->width, d->height, d->bytes_per_line);
1810 }
else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
1811 QRgbaFloat32 cf = QRgbaFloat32::fromArgb32(pixel);
1812 uchar *data = d->data;
1813 for (
int y = 0; y < d->height; ++y) {
1814 QRgbaFloat32 *line =
reinterpret_cast<QRgbaFloat32 *>(data);
1815 for (
int x = 0; x < d->width; ++x)
1817 data += d->bytes_per_line;
1821 Q_ASSERT(d->depth == 32);
1823 if (d->format == Format_RGB32)
1824 pixel |= 0xff000000;
1825 if (d->format == Format_RGBX8888)
1826#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1827 pixel |= 0xff000000;
1829 pixel |= 0x000000ff;
1831 if (d->format == Format_BGR30 || d->format == Format_RGB30)
1832 pixel |= 0xc0000000;
1834 qt_rectfill<uint>(
reinterpret_cast<uint*>(d->data), pixel,
1835 0, 0, d->width, d->height, d->bytes_per_line);
1840
1841
1842
1843
1844
1845
1847void QImage::fill(Qt::GlobalColor color)
1849 fill(QColor(color));
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1869void QImage::fill(
const QColor &color)
1879 QRgba64 opaque = color.rgba64();
1880 opaque.setAlpha(65535);
1881 switch (d->format) {
1882 case QImage::Format_RGB32:
1883 case QImage::Format_ARGB32:
1886 case QImage::Format_ARGB32_Premultiplied:
1887 fill(qPremultiply(color.rgba()));
1889 case QImage::Format_RGBX8888:
1890 fill(ARGB2RGBA(color.rgba() | 0xff000000));
1892 case QImage::Format_RGBA8888:
1893 fill(ARGB2RGBA(color.rgba()));
1895 case QImage::Format_RGBA8888_Premultiplied:
1896 fill(ARGB2RGBA(qPremultiply(color.rgba())));
1898 case QImage::Format_BGR30:
1899 fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
1901 case QImage::Format_RGB30:
1902 fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
1904 case QImage::Format_RGB16:
1905 fill((uint) qConvertRgb32To16(color.rgba()));
1907 case QImage::Format_Indexed8: {
1909 for (
int i=0; i<d->colortable.size(); ++i) {
1910 if (color.rgba() == d->colortable.at(i)) {
1918 case QImage::Format_Mono:
1919 case QImage::Format_MonoLSB:
1920 if (color == Qt::color1)
1925 case QImage::Format_RGBX64:
1926 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), opaque,
1927 0, 0, d->width, d->height, d->bytes_per_line);
1929 case QImage::Format_RGBA64:
1930 qt_rectfill<quint64>(
reinterpret_cast<quint64*>(d->data), color.rgba64(),
1931 0, 0, d->width, d->height, d->bytes_per_line);
1933 case QImage::Format_RGBA64_Premultiplied:
1934 qt_rectfill<quint64>(
reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
1935 0, 0, d->width, d->height, d->bytes_per_line);
1937 case QImage::Format_RGBX16FPx4:
1938 case QImage::Format_RGBA16FPx4:
1939 case QImage::Format_RGBA16FPx4_Premultiplied:
1940 case QImage::Format_RGBX32FPx4:
1941 case QImage::Format_RGBA32FPx4:
1942 case QImage::Format_RGBA32FPx4_Premultiplied:{
1944 color.getRgbF(&r, &g, &b, &a);
1945 if (!hasAlphaChannel())
1947 if (depth() == 64) {
1948 QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
1949 if (d->format == Format_RGBA16FPx4_Premultiplied)
1950 c16 = c16.premultiplied();
1951 qt_rectfill<QRgbaFloat16>(
reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
1952 0, 0, d->width, d->height, d->bytes_per_line);
1954 QRgbaFloat32 c32{r, g, b, a};
1955 if (d->format == Format_RGBA32FPx4_Premultiplied)
1956 c32 = c32.premultiplied();
1957 qt_rectfill<QRgbaFloat32>(
reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
1958 0, 0, d->width, d->height, d->bytes_per_line);
1964 p.setCompositionMode(QPainter::CompositionMode_Source);
1965 p.fillRect(rect(), color);
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1991void QImage::invertPixels(InvertMode mode)
2002 QImage::Format originalFormat = d->format;
2004 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
2005 if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
2006 if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
2007 *
this = convertToFormat(QImage::Format_RGBA16FPx4);
2008 }
else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
2009 if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
2010 *
this = convertToFormat(QImage::Format_RGBA32FPx4);
2011 }
else if (depth() > 32) {
2012 if (!d->convertInPlace(QImage::Format_RGBA64, { }))
2013 *
this = convertToFormat(QImage::Format_RGBA64);
2015 if (!d->convertInPlace(QImage::Format_ARGB32, { }))
2016 *
this = convertToFormat(QImage::Format_ARGB32);
2022 qsizetype bpl = (qsizetype(d->width) * d->depth + 7) / 8;
2023 int pad = d->bytes_per_line - bpl;
2024 uchar *sl = d->data;
2025 for (
int y=0; y<d->height; ++y) {
2026 for (qsizetype x=0; x<bpl; ++x)
2030 }
else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
2031 qfloat16 *p =
reinterpret_cast<qfloat16 *>(d->data);
2032 qfloat16 *end =
reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
2034 p[0] = qfloat16(1) - p[0];
2035 p[1] = qfloat16(1) - p[1];
2036 p[2] = qfloat16(1) - p[2];
2037 if (mode == InvertRgba)
2038 p[3] = qfloat16(1) - p[3];
2041 }
else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
2042 uchar *data = d->data;
2043 for (
int y = 0; y < d->height; ++y) {
2044 float *p =
reinterpret_cast<
float *>(data);
2045 for (
int x = 0; x < d->width; ++x) {
2049 if (mode == InvertRgba)
2053 data += d->bytes_per_line;
2055 }
else if (depth() == 64) {
2056 quint16 *p = (quint16*)d->data;
2057 quint16 *end = (quint16*)(d->data + d->nbytes);
2058 quint16 xorbits = 0xffff;
2063 if (mode == InvertRgba)
2069 quint32 *p = (quint32*)d->data;
2070 quint32 *end = (quint32*)(d->data + d->nbytes);
2071 quint32 xorbits = 0xffffffff;
2072 switch (d->format) {
2073 case QImage::Format_RGBA8888:
2074 if (mode == InvertRgba)
2077 case QImage::Format_RGBX8888:
2078#if Q_BYTE_ORDER == Q_BIG_ENDIAN
2079 xorbits = 0xffffff00;
2082 xorbits = 0x00ffffff;
2085 case QImage::Format_ARGB32:
2086 if (mode == InvertRgba)
2089 case QImage::Format_RGB32:
2090 xorbits = 0x00ffffff;
2092 case QImage::Format_BGR30:
2093 case QImage::Format_RGB30:
2094 xorbits = 0x3fffffff;
2105 if (originalFormat != d->format) {
2106 if (!d->convertInPlace(originalFormat, { }))
2107 *
this = convertToFormat(originalFormat);
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2136void QImage::setColorCount(
int colorCount)
2139 qWarning(
"QImage::setColorCount: null image");
2143 detachMetadata(
true);
2149 if (colorCount == d->colortable.size())
2151 if (colorCount <= 0) {
2152 d->colortable.clear();
2155 int nc = d->colortable.size();
2156 d->colortable.resize(colorCount);
2157 for (
int i = nc; i < colorCount; ++i)
2158 d->colortable[i] = 0;
2162
2163
2164
2165
2166QImage::Format QImage::format()
const
2170 Q_ASSERT(d->format < NImageFormats);
2171 Q_ASSERT(d->format > Format_Invalid);
2173 return d ? d->format : Format_Invalid;
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2202
2203
2204QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags flags)
const
2206 if (!d || d->format == format)
2209 if (d->format == Format_Invalid || format <= Format_Invalid || format >= NImageFormats)
2212 const QPixelLayout *destLayout = &qPixelLayouts[format];
2213 Image_Converter converter = qimage_converter_map[d->format][format];
2214 if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
2215 if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
2216 && qt_highColorPrecision(format, !hasAlphaChannel())) {
2217#if QT_CONFIG(raster_fp)
2218 if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
2219 converter = convert_generic_over_rgba32f;
2222 converter = convert_generic_over_rgb64;
2224 converter = convert_generic;
2227 QImage image(d->width, d->height, format);
2231 copyMetadata(image.d, d);
2233 converter(image.d, d, flags);
2238 Q_ASSERT(format != QImage::Format_ARGB32 && format != QImage::Format_RGB32);
2239 Q_ASSERT(d->format != QImage::Format_ARGB32 && d->format != QImage::Format_RGB32);
2241 if (!hasAlphaChannel())
2242 return convertToFormat(Format_RGB32, flags).convertToFormat(format, flags);
2244 return convertToFormat(Format_ARGB32, flags).convertToFormat(format, flags);
2248
2249
2250bool QImage::convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags)
2252 return d && d->convertInPlace(format, flags);
2255static inline int pixel_distance(QRgb p1, QRgb p2) {
2257 int g1 = qGreen(p1);
2259 int a1 = qAlpha(p1);
2262 int g2 = qGreen(p2);
2264 int a2 = qAlpha(p2);
2266 return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) + abs(a1 - a2);
2269static inline int closestMatch(QRgb pixel,
const QList<QRgb> &clut) {
2271 int current_distance = INT_MAX;
2272 for (
int i=0; i<clut.size(); ++i) {
2273 int dist = pixel_distance(pixel, clut.at(i));
2274 if (dist < current_distance) {
2275 current_distance = dist;
2282static QImage convertWithPalette(
const QImage &src, QImage::Format format,
2283 const QList<QRgb> &clut) {
2284 QImage dest(src.size(), format);
2285 dest.setColorTable(clut);
2287 copyMetadata(QImageData::get(dest), QImageData::get(src));
2289 int h = src.height();
2290 int w = src.width();
2292 QHash<QRgb,
int> cache;
2294 if (format == QImage::Format_Indexed8) {
2295 for (
int y=0; y<h; ++y) {
2296 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2297 uchar *dest_pixels = (uchar *) dest.scanLine(y);
2298 for (
int x=0; x<w; ++x) {
2299 int src_pixel = src_pixels[x];
2300 int value = cache.value(src_pixel, -1);
2302 value = closestMatch(src_pixel, clut);
2303 cache.insert(src_pixel, value);
2305 dest_pixels[x] = (uchar) value;
2309 QList<QRgb> table = clut;
2311 for (
int y=0; y<h; ++y) {
2312 const QRgb *src_pixels = (
const QRgb *) src.scanLine(y);
2313 for (
int x=0; x<w; ++x) {
2314 int src_pixel = src_pixels[x];
2315 int value = cache.value(src_pixel, -1);
2317 value = closestMatch(src_pixel, table);
2318 cache.insert(src_pixel, value);
2320 dest.setPixel(x, y, value);
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338QImage QImage::convertToFormat(Format format,
const QList<QRgb> &colorTable, Qt::ImageConversionFlags flags)
const
2340 if (!d || d->format == format)
2343 if (format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2345 if (format <= QImage::Format_Indexed8)
2346 return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
2348 return convertToFormat(format, flags);
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2374bool QImage::reinterpretAsFormat(Format format)
2376 if (format <= Format_Invalid || format >= NImageFormats)
2380 if (d->format == format)
2382 if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
2384 if (!isDetached()) {
2385 QImageData *oldD = d;
2400
2401
2402
2403
2404
2405
2406
2407
2408
2410void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
2412 if (!d || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
2415 if (d->format == format)
2419 if (convertToFormat_inplace(format, flags))
2422 *
this = convertToFormat_helper(format, flags);
2426
2427
2428
2429
2430
2431
2432
2435
2436
2437
2438
2439
2440bool QImage::valid(
int x,
int y)
const
2443 && x >= 0 && x < d->width
2444 && y >= 0 && y < d->height;
2448
2449
2450
2451
2452
2453
2454
2455
2456
2459
2460
2461
2462
2463int QImage::pixelIndex(
int x,
int y)
const
2465 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2466 qWarning(
"QImage::pixelIndex: coordinate (%d,%d) out of range", x, y);
2469 const uchar * s = scanLine(y);
2472 return (*(s + (x >> 3)) >> (7- (x & 7))) & 1;
2473 case Format_MonoLSB:
2474 return (*(s + (x >> 3)) >> (x & 7)) & 1;
2475 case Format_Indexed8:
2478 qWarning(
"QImage::pixelIndex: Not applicable for %d-bpp images (no palette)", d->depth);
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2500
2501
2502
2503
2504QRgb QImage::pixel(
int x,
int y)
const
2506 if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) {
2507 qWarning(
"QImage::pixel: coordinate (%d,%d) out of range", x, y);
2511 const uchar *s = d->data + y * d->bytes_per_line;
2514 switch (d->format) {
2516 index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
2518 case Format_MonoLSB:
2519 index = (*(s + (x >> 3)) >> (x & 7)) & 1;
2521 case Format_Indexed8:
2528 if (index >= d->colortable.size()) {
2529 qWarning(
"QImage::pixel: color table index %d out of range.", index);
2532 return d->colortable.at(index);
2534 std::optional<QRgb> out;
2535 switch (d->format) {
2538 case Format_ARGB32_Premultiplied:
2539 out =
reinterpret_cast<
const QRgb *>(s)[x];
2541 case Format_RGBX8888:
2542 case Format_RGBA8888:
2543 case Format_RGBA8888_Premultiplied:
2544 out = RGBA2ARGB(
reinterpret_cast<
const quint32 *>(s)[x]);
2547 case Format_A2BGR30_Premultiplied:
2548 out = qConvertA2rgb30ToArgb32<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2551 case Format_A2RGB30_Premultiplied:
2552 out = qConvertA2rgb30ToArgb32<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2555 return qConvertRgb16To32(
reinterpret_cast<
const quint16 *>(s)[x]);
2558 case Format_RGBA64_Premultiplied:
2559 out =
reinterpret_cast<
const QRgba64 *>(s)[x].toArgb32();
2561 case Format_RGBX16FPx4:
2562 case Format_RGBA16FPx4:
2563 case Format_RGBA16FPx4_Premultiplied:
2564 out =
reinterpret_cast<
const QRgbaFloat16 *>(s)[x].toArgb32();
2566 case Format_RGBX32FPx4:
2567 case Format_RGBA32FPx4:
2568 case Format_RGBA32FPx4_Premultiplied:
2569 out =
reinterpret_cast<
const QRgbaFloat32 *>(s)[x].toArgb32();
2573 const QPixelLayout *layout = &qPixelLayouts[d->format];
2576 if (!layout->hasAlphaChannel)
2581 return *layout->fetchToARGB32PM(&result, s, x, 1,
nullptr,
nullptr);
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2606
2607
2608
2609
2610void QImage::setPixel(
int x,
int y, uint index_or_rgb)
2612 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2613 qWarning(
"QImage::setPixel: coordinate (%d,%d) out of range", x, y);
2617 uchar * s = scanLine(y);
2620 case Format_MonoLSB:
2621 if (index_or_rgb > 1) {
2622 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2623 }
else if (format() == Format_MonoLSB) {
2624 if (index_or_rgb==0)
2625 *(s + (x >> 3)) &= ~(1 << (x & 7));
2627 *(s + (x >> 3)) |= (1 << (x & 7));
2629 if (index_or_rgb==0)
2630 *(s + (x >> 3)) &= ~(1 << (7-(x & 7)));
2632 *(s + (x >> 3)) |= (1 << (7-(x & 7)));
2635 case Format_Indexed8:
2636 if (index_or_rgb >= (uint)d->colortable.size()) {
2637 qWarning(
"QImage::setPixel: Index %d out of range", index_or_rgb);
2640 s[x] = index_or_rgb;
2645 ((uint *)s)[x] = 0xff000000 | index_or_rgb;
2648 case Format_ARGB32_Premultiplied:
2649 ((uint *)s)[x] = index_or_rgb;
2652 ((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
2654 case Format_RGBX8888:
2655 ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
2657 case Format_RGBA8888:
2658 case Format_RGBA8888_Premultiplied:
2659 ((uint *)s)[x] = ARGB2RGBA(index_or_rgb);
2662 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderBGR>(index_or_rgb);
2664 case Format_A2BGR30_Premultiplied:
2665 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderBGR>(index_or_rgb);
2668 ((uint *)s)[x] = qConvertRgb32ToRgb30<PixelOrderRGB>(index_or_rgb);
2670 case Format_A2RGB30_Premultiplied:
2671 ((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
2674 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
2677 case Format_RGBA64_Premultiplied:
2678 ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
2680 case Format_RGBX16FPx4:
2681 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb | 0xff000000);
2683 case Format_RGBA16FPx4:
2684 case Format_RGBA16FPx4_Premultiplied:
2685 ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb);
2687 case Format_RGBX32FPx4:
2688 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb | 0xff000000);
2690 case Format_RGBA32FPx4:
2691 case Format_RGBA32FPx4_Premultiplied:
2692 ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb);
2694 case Format_Invalid:
2702 const QPixelLayout *layout = &qPixelLayouts[d->format];
2703 if (!hasAlphaChannel())
2704 layout->storeFromRGB32(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2706 layout->storeFromARGB32PM(s, &index_or_rgb, x, 1,
nullptr,
nullptr);
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2726
2727
2728
2729
2730
2731QColor QImage::pixelColor(
int x,
int y)
const
2733 if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) {
2734 qWarning(
"QImage::pixelColor: coordinate (%d,%d) out of range", x, y);
2739 const uchar * s = constScanLine(y);
2740 switch (d->format) {
2742 case Format_A2BGR30_Premultiplied:
2743 c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(
reinterpret_cast<
const quint32 *>(s)[x]);
2746 case Format_A2RGB30_Premultiplied:
2747 c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(
reinterpret_cast<
const quint32 *>(s)[x]);
2751 case Format_RGBA64_Premultiplied:
2752 c =
reinterpret_cast<
const QRgba64 *>(s)[x];
2754 case Format_Grayscale16: {
2755 quint16 v =
reinterpret_cast<
const quint16 *>(s)[x];
2756 return QColor(qRgba64(v, v, v, 0xffff));
2758 case Format_RGBX16FPx4:
2759 case Format_RGBA16FPx4:
2760 case Format_RGBA16FPx4_Premultiplied: {
2761 QRgbaFloat16 p =
reinterpret_cast<
const QRgbaFloat16 *>(s)[x];
2762 if (d->format == Format_RGBA16FPx4_Premultiplied)
2763 p = p.unpremultiplied();
2764 else if (d->format == Format_RGBX16FPx4)
2767 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2770 case Format_RGBX32FPx4:
2771 case Format_RGBA32FPx4:
2772 case Format_RGBA32FPx4_Premultiplied: {
2773 QRgbaFloat32 p =
reinterpret_cast<
const QRgbaFloat32 *>(s)[x];
2774 if (d->format == Format_RGBA32FPx4_Premultiplied)
2775 p = p.unpremultiplied();
2776 else if (d->format == Format_RGBX32FPx4)
2779 color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
2783 c = QRgba64::fromArgb32(pixel(x, y));
2787 switch (d->format) {
2797 if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
2798 c = c.unpremultiplied();
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2819
2820
2821
2822
2823
2824void QImage::setPixelColor(
int x,
int y,
const QColor &color)
2826 if (!d || x < 0 || x >= width() || y < 0 || y >= height()) {
2827 qWarning(
"QImage::setPixelColor: coordinate (%d,%d) out of range", x, y);
2831 if (!color.isValid()) {
2832 qWarning(
"QImage::setPixelColor: color is invalid");
2837 QRgba64 c = color.rgba64();
2838 if (!hasAlphaChannel())
2840 else if (qPixelLayouts[d->format].premultiplied)
2841 c = c.premultiplied();
2843 uchar * s = scanLine(y);
2844 switch (d->format) {
2846 case Format_MonoLSB:
2847 case Format_Indexed8:
2848 qWarning(
"QImage::setPixelColor: called on monochrome or indexed format");
2851 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000;
2853 case Format_A2BGR30_Premultiplied:
2854 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c);
2857 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000;
2859 case Format_A2RGB30_Premultiplied:
2860 ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
2864 case Format_RGBA64_Premultiplied:
2865 ((QRgba64 *)s)[x] = c;
2867 case Format_RGBX16FPx4:
2868 case Format_RGBA16FPx4:
2869 case Format_RGBA16FPx4_Premultiplied: {
2871 color.getRgbF(&r, &g, &b, &a);
2872 if (d->format == Format_RGBX16FPx4)
2874 QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
2875 if (d->format == Format_RGBA16FPx4_Premultiplied)
2876 c16f = c16f.premultiplied();
2877 ((QRgbaFloat16 *)s)[x] = c16f;
2880 case Format_RGBX32FPx4:
2881 case Format_RGBA32FPx4:
2882 case Format_RGBA32FPx4_Premultiplied: {
2884 color.getRgbF(&r, &g, &b, &a);
2885 if (d->format == Format_RGBX32FPx4)
2887 QRgbaFloat32 c32f{r, g, b, a};
2888 if (d->format == Format_RGBA32FPx4_Premultiplied)
2889 c32f = c32f.premultiplied();
2890 ((QRgbaFloat32 *)s)[x] = c32f;
2894 setPixel(x, y, c.toArgb32());
2900
2901
2902
2903
2904
2905
2906
2907
2908bool QImage::allGray()
const
2913 switch (d->format) {
2915 case Format_MonoLSB:
2916 case Format_Indexed8:
2917 for (
int i = 0; i < d->colortable.size(); ++i) {
2918 if (!qIsGray(d->colortable.at(i)))
2924 case Format_Grayscale8:
2925 case Format_Grayscale16:
2929 case Format_ARGB32_Premultiplied:
2930#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
2931 case Format_RGBX8888:
2932 case Format_RGBA8888:
2933 case Format_RGBA8888_Premultiplied:
2935 for (
int j = 0; j < d->height; ++j) {
2936 const QRgb *b = (
const QRgb *)constScanLine(j);
2937 for (
int i = 0; i < d->width; ++i) {
2944 for (
int j = 0; j < d->height; ++j) {
2945 const quint16 *b = (
const quint16 *)constScanLine(j);
2946 for (
int i = 0; i < d->width; ++i) {
2947 if (!qIsGray(qConvertRgb16To32(b[i])))
2956 Q_DECL_UNINITIALIZED uint buffer[BufferSize];
2957 const QPixelLayout *layout = &qPixelLayouts[d->format];
2958 const auto fetch = layout->fetchToARGB32PM;
2959 for (
int j = 0; j < d->height; ++j) {
2960 const uchar *b = constScanLine(j);
2962 while (x < d->width) {
2963 int l = qMin(d->width - x, BufferSize);
2964 const uint *ptr = fetch(buffer, b, x, l,
nullptr,
nullptr);
2965 for (
int i = 0; i < l; ++i) {
2966 if (!qIsGray(ptr[i]))
2976
2977
2978
2979
2980
2981
2982
2983
2984bool QImage::isGrayscale()
const
2989 if (d->format == QImage::Format_Alpha8)
2992 if (d->format == QImage::Format_Grayscale8 || d->format == QImage::Format_Grayscale16)
3001 Q_ASSERT(d->format == QImage::Format_Indexed8);
3002 for (
int i = 0; i < colorCount(); i++)
3003 if (d->colortable.at(i) != qRgb(i,i,i))
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(
const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
const
3053 qWarning(
"QImage::scaled: Image is a null image");
3059 QSize newSize = size();
3060 newSize.scale(s, aspectMode);
3061 newSize.rwidth() = qMax(newSize.width(), 1);
3062 newSize.rheight() = qMax(newSize.height(), 1);
3063 if (newSize == size())
3066 Q_TRACE_SCOPE(QImage_scaled, s, aspectMode, mode);
3068 QTransform wm = QTransform::fromScale((qreal)newSize.width() / width(), (qreal)newSize.height() / height());
3069 QImage img = transformed(wm, mode);
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(
int w, Qt::TransformationMode mode)
const
3090 qWarning(
"QImage::scaleWidth: Image is a null image");
3096 Q_TRACE_SCOPE(QImage_scaledToWidth, w, mode);
3098 qreal factor = (qreal) w / width();
3099 QTransform wm = QTransform::fromScale(factor, factor);
3100 return transformed(wm, mode);
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(
int h, Qt::TransformationMode mode)
const
3120 qWarning(
"QImage::scaleHeight: Image is a null image");
3126 Q_TRACE_SCOPE(QImage_scaledToHeight, h, mode);
3128 qreal factor = (qreal) h / height();
3129 QTransform wm = QTransform::fromScale(factor, factor);
3130 return transformed(wm, mode);
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags)
const
3152 if (!d || d->format == QImage::Format_RGB32)
3155 if (d->depth == 1) {
3158 return convertToFormat(Format_Indexed8, flags).createAlphaMask(flags);
3161 QImage mask(d->width, d->height, Format_MonoLSB);
3162 if (!mask.isNull()) {
3163 dither_to_Mono(mask.d, d, flags,
true);
3164 copyPhysicalMetadata(mask.d, d);
3169#ifndef QT_NO_IMAGE_HEURISTIC_MASK
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3194QImage QImage::createHeuristicMask(
bool clipTight)
const
3199 if (d->depth != 32) {
3200 QImage img32 = convertToFormat(Format_RGB32);
3201 return img32.createHeuristicMask(clipTight);
3204#define PIX(x,y) (*((const QRgb*)scanLine(y)+x) & 0x00ffffff
)
3208 QImage m(w, h, Format_MonoLSB);
3211 m.setColor(0, QColor(Qt::color0).rgba());
3212 m.setColor(1, QColor(Qt::color1).rgba());
3215 QRgb background =
PIX(0,0);
3216 if (background !=
PIX(w-1,0) &&
3217 background !=
PIX(0,h-1) &&
3218 background !=
PIX(w-1,h-1)) {
3219 background =
PIX(w-1,0);
3220 if (background !=
PIX(w-1,h-1) &&
3221 background !=
PIX(0,h-1) &&
3222 PIX(0,h-1) ==
PIX(w-1,h-1)) {
3223 background =
PIX(w-1,h-1);
3229 uchar *ypp, *ypc, *ypn;
3232 ypn = m.scanLine(0);
3234 for (y = 0; y < h; y++) {
3237 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3238 const QRgb *p = (
const QRgb *)scanLine(y);
3239 for (x = 0; x < w; x++) {
3242 if ((x == 0 || y == 0 || x == w-1 || y == h-1 ||
3243 !(*(ypc + ((x-1) >> 3)) & (1 << ((x-1) & 7))) ||
3244 !(*(ypc + ((x+1) >> 3)) & (1 << ((x+1) & 7))) ||
3245 !(*(ypp + (x >> 3)) & (1 << (x & 7))) ||
3246 !(*(ypn + (x >> 3)) & (1 << (x & 7)))) &&
3247 ( (*(ypc + (x >> 3)) & (1 << (x & 7)))) &&
3248 ((*p & 0x00ffffff) == background)) {
3250 *(ypc + (x >> 3)) &= ~(1 << (x & 7));
3258 ypn = m.scanLine(0);
3260 for (y = 0; y < h; y++) {
3263 ypn = (y == h-1) ?
nullptr : m.scanLine(y+1);
3264 const QRgb *p = (
const QRgb *)scanLine(y);
3265 for (x = 0; x < w; x++) {
3266 if ((*p & 0x00ffffff) != background) {
3268 *(ypc + ((x-1) >> 3)) |= (1 << ((x-1) & 7));
3270 *(ypc + ((x+1) >> 3)) |= (1 << ((x+1) & 7));
3272 *(ypp + (x >> 3)) |= (1 << (x & 7));
3274 *(ypn + (x >> 3)) |= (1 << (x & 7));
3283 copyPhysicalMetadata(m.d, d);
3289
3290
3291
3292
3293
3294
3295
3296
3298QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode)
const
3302 QImage maskImage(size(), QImage::Format_MonoLSB);
3305 uchar *s = maskImage.bits();
3309 if (depth() == 32) {
3310 for (
int h = 0; h < d->height; h++) {
3311 const uint *sl = (
const uint *) scanLine(h);
3312 for (
int w = 0; w < d->width; w++) {
3314 *(s + (w >> 3)) |= (1 << (w & 7));
3316 s += maskImage.bytesPerLine();
3319 for (
int h = 0; h < d->height; h++) {
3320 for (
int w = 0; w < d->width; w++) {
3321 if ((uint) pixel(w, h) == color)
3322 *(s + (w >> 3)) |= (1 << (w & 7));
3324 s += maskImage.bytesPerLine();
3327 if (mode == Qt::MaskOutColor)
3328 maskImage.invertPixels();
3330 copyPhysicalMetadata(maskImage.d, d);
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3349
3350
3351
3352
3353
3354
3355
3356
3357
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3373
3374
3375
3376
3377
3378
3379
3380
3382template<
class T>
inline void do_mirror_data(QImageData *dst, QImageData *src,
3383 int dstX0,
int dstY0,
3384 int dstXIncr,
int dstYIncr,
3390 const int srcXEnd = (dstX0 && !dstY0) ? w / 2 : w;
3391 const int srcYEnd = dstY0 ? h / 2 : h;
3392 for (
int srcY = 0, dstY = dstY0; srcY < srcYEnd; ++srcY, dstY += dstYIncr) {
3393 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3394 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3395 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd; ++srcX, dstX += dstXIncr)
3396 std::swap(srcPtr[srcX], dstPtr[dstX]);
3399 if (dstX0 && dstY0 && (h & 1)) {
3401 int srcXEnd2 = w / 2;
3402 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3403 for (
int srcX = 0, dstX = dstX0; srcX < srcXEnd2; ++srcX, dstX += dstXIncr)
3404 std::swap(srcPtr[srcX], srcPtr[dstX]);
3407 for (
int srcY = 0, dstY = dstY0; srcY < h; ++srcY, dstY += dstYIncr) {
3408 T *srcPtr = (T *) (src->data + srcY * src->bytes_per_line);
3409 T *dstPtr = (T *) (dst->data + dstY * dst->bytes_per_line);
3410 for (
int srcX = 0, dstX = dstX0; srcX < w; ++srcX, dstX += dstXIncr)
3411 dstPtr[dstX] = srcPtr[srcX];
3416inline void do_flip(QImageData *dst, QImageData *src,
int w,
int h,
int depth)
3418 const int data_bytes_per_line = w * (depth / 8);
3420 uint *srcPtr =
reinterpret_cast<uint *>(src->data);
3421 uint *dstPtr =
reinterpret_cast<uint *>(dst->data + (h - 1) * dst->bytes_per_line);
3423 const int uint_per_line = (data_bytes_per_line + 3) >> 2;
3424 for (
int y = 0; y < h; ++y) {
3426 for (
int x = 0; x < uint_per_line; x++) {
3427 const uint d = dstPtr[x];
3428 const uint s = srcPtr[x];
3432 srcPtr += src->bytes_per_line >> 2;
3433 dstPtr -= dst->bytes_per_line >> 2;
3437 const uchar *srcPtr = src->data;
3438 uchar *dstPtr = dst->data + (h - 1) * dst->bytes_per_line;
3439 for (
int y = 0; y < h; ++y) {
3440 memcpy(dstPtr, srcPtr, data_bytes_per_line);
3441 srcPtr += src->bytes_per_line;
3442 dstPtr -= dst->bytes_per_line;
3447inline void do_mirror(QImageData *dst, QImageData *src,
bool horizontal,
bool vertical)
3449 Q_ASSERT(src->width == dst->width && src->height == dst->height && src->depth == dst->depth);
3451 int h = src->height;
3452 int depth = src->depth;
3454 if (src->depth == 1) {
3459 if (vertical && !horizontal) {
3461 do_flip(dst, src, w, h, depth);
3465 int dstX0 = 0, dstXIncr = 1;
3466 int dstY0 = 0, dstYIncr = 1;
3480 do_mirror_data<QRgbaFloat32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3483 do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3486 do_mirror_data<quint32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3489 do_mirror_data<quint24>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3492 do_mirror_data<quint16>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3495 do_mirror_data<quint8>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
3504 if (horizontal && dst->depth == 1) {
3505 Q_ASSERT(dst->format == QImage::Format_Mono || dst->format == QImage::Format_MonoLSB);
3506 const int shift = 8 - (dst->width % 8);
3507 const uchar *bitflip = qt_get_bitflip_array();
3508 for (
int y = 0; y < h; ++y) {
3509 uchar *begin = dst->data + y * dst->bytes_per_line;
3510 uchar *end = begin + dst->bytes_per_line;
3511 for (uchar *p = begin; p < end; ++p) {
3515 if (shift != 8 && p != begin) {
3516 if (dst->format == QImage::Format_Mono) {
3517 for (
int i = 0; i < shift; ++i) {
3519 p[-1] |= (*p & (128 >> i)) >> (7 - i);
3522 for (
int i = 0; i < shift; ++i) {
3524 p[-1] |= (*p & (1 << i)) << (7 - i);
3530 if (dst->format == QImage::Format_Mono)
3540
3541
3542QImage QImage::mirrored_helper(
bool horizontal,
bool vertical)
const
3547 if ((d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3551 QImage result(d->width, d->height, d->format);
3558 result.d->colortable = d->colortable;
3559 result.d->has_alpha_clut = d->has_alpha_clut;
3560 copyMetadata(result.d, d);
3562 do_mirror(result.d, d, horizontal, vertical);
3568
3569
3570void QImage::mirrored_inplace(
bool horizontal,
bool vertical)
3572 if (!d || (d->width <= 1 && d->height <= 1) || (!horizontal && !vertical))
3581 do_mirror(d, d, horizontal, vertical);
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3598
3599
3600
3601
3602
3603
3604
3605
3607static inline void rgbSwapped_generic(
int width,
int height,
const QImage *src, QImage *dst,
const QPixelLayout* layout)
3609 const RbSwapFunc func = layout->rbSwap;
3611 qWarning(
"Trying to rb-swap an image format where it doesn't make sense");
3617 for (
int i = 0; i < height; ++i) {
3618 uchar *q = dst->scanLine(i);
3619 const uchar *p = src->constScanLine(i);
3625
3626
3627QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper()
const
3632 Q_TRACE_SCOPE(QImage_rgbSwapped_helper);
3636 switch (d->format) {
3637 case Format_Invalid:
3642 case Format_Grayscale8:
3643 case Format_Grayscale16:
3646 case Format_MonoLSB:
3647 case Format_Indexed8:
3649 for (
int i = 0; i < res.d->colortable.size(); i++) {
3650 QRgb c = res.d->colortable.at(i);
3651 res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3654 case Format_RGBX8888:
3655 case Format_RGBA8888:
3656 case Format_RGBA8888_Premultiplied:
3657#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3658 res = QImage(d->width, d->height, d->format);
3660 for (
int i = 0; i < d->height; i++) {
3661 uint *q = (uint*)res.scanLine(i);
3662 const uint *p = (
const uint*)constScanLine(i);
3663 const uint *end = p + d->width;
3666 *q = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3678 case Format_ARGB32_Premultiplied:
3679 res = QImage(d->width, d->height, d->format);
3681 for (
int i = 0; i < d->height; i++) {
3682 uint *q = (uint*)res.scanLine(i);
3683 const uint *p = (
const uint*)constScanLine(i);
3684 const uint *end = p + d->width;
3687 *q = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3694 res = QImage(d->width, d->height, d->format);
3696 for (
int i = 0; i < d->height; i++) {
3697 ushort *q = (ushort*)res.scanLine(i);
3698 const ushort *p = (
const ushort*)constScanLine(i);
3699 const ushort *end = p + d->width;
3702 *q = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3709 res = QImage(d->width, d->height, d->format);
3711 rgbSwapped_generic(d->width, d->height,
this, &res, &qPixelLayouts[d->format]);
3714 copyMetadata(res.d, d);
3719
3720
3721void QImage::rgbSwapped_inplace()
3732 switch (d->format) {
3733 case Format_Invalid:
3738 case Format_Grayscale8:
3739 case Format_Grayscale16:
3742 case Format_MonoLSB:
3743 case Format_Indexed8:
3744 for (
int i = 0; i < d->colortable.size(); i++) {
3745 QRgb c = d->colortable.at(i);
3746 d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
3749 case Format_RGBX8888:
3750 case Format_RGBA8888:
3751 case Format_RGBA8888_Premultiplied:
3752#if Q_BYTE_ORDER == Q_BIG_ENDIAN
3753 for (
int i = 0; i < d->height; i++) {
3754 uint *p = (uint*)scanLine(i);
3755 uint *end = p + d->width;
3758 *p = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
3769 case Format_ARGB32_Premultiplied:
3770 for (
int i = 0; i < d->height; i++) {
3771 uint *p = (uint*)scanLine(i);
3772 uint *end = p + d->width;
3775 *p = ((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00);
3781 for (
int i = 0; i < d->height; i++) {
3782 ushort *p = (ushort*)scanLine(i);
3783 ushort *end = p + d->width;
3786 *p = ((c << 11) & 0xf800) | ((c >> 11) & 0x1f) | (c & 0x07e0);
3792 case Format_A2BGR30_Premultiplied:
3794 case Format_A2RGB30_Premultiplied:
3795 for (
int i = 0; i < d->height; i++) {
3796 uint *p = (uint*)scanLine(i);
3797 uint *end = p + d->width;
3799 *p = qRgbSwapRgb30(*p);
3805 rgbSwapped_generic(d->width, d->height,
this,
this, &qPixelLayouts[d->format]);
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3829bool QImage::load(
const QString &fileName,
const char* format)
3831 *
this = QImageReader(fileName, format).read();
3836
3837
3838
3839
3840
3842bool QImage::load(QIODevice* device,
const char* format)
3844 *
this = QImageReader(device, format).read();
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3861bool QImage::loadFromData(QByteArrayView data,
const char *format)
3863 *
this = fromData(data, format);
3868
3869
3870
3871
3872
3873
3875bool QImage::loadFromData(
const uchar *buf,
int len,
const char *format)
3877 return loadFromData(QByteArrayView(buf, len), format);
3881
3882
3883
3884
3885
3886
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3903QImage QImage::fromData(QByteArrayView data,
const char *format)
3905 QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
3908 b.open(QIODevice::ReadOnly);
3909 return QImageReader(&b, format).read();
3913
3914
3915
3916
3917
3918
3920QImage QImage::fromData(
const uchar *data,
int size,
const char *format)
3922 return fromData(QByteArrayView(data, size), format);
3926
3927
3928
3929
3930
3931
3932
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950bool QImage::save(
const QString &fileName,
const char *format,
int quality)
const
3954 QImageWriter writer(fileName, format);
3955 return d->doImageIO(
this, &writer, quality);
3959
3960
3961
3962
3963
3964
3965
3966
3967
3969bool QImage::save(QIODevice* device,
const char* format,
int quality)
const
3973 QImageWriter writer(device, format);
3974 return d->doImageIO(
this, &writer, quality);
3978
3980bool QImageData::doImageIO(
const QImage *image, QImageWriter *writer,
int quality)
const
3982 if (quality > 100 || quality < -1)
3983 qWarning(
"QImage::save: Quality out of range [-1, 100]");
3985 writer->setQuality(qMin(quality,100));
3986 const bool result = writer->write(*image);
3989 qWarning(
"QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
3995
3996
3997#if !defined(QT_NO_DATASTREAM)
3999
4000
4001
4002
4003
4004
4005
4006
4007
4009QDataStream &operator<<(QDataStream &s,
const QImage &image)
4011 if (s.version() >= 5) {
4012 if (image.isNull()) {
4020 QImageWriter writer(s.device(), s.version() == 1 ?
"bmp" :
"png");
4021 writer.write(image);
4026
4027
4028
4029
4030
4031
4032
4033
4035QDataStream &operator>>(QDataStream &s, QImage &image)
4037 if (s.version() >= 5) {
4045 image = QImageReader(s.device(), s.version() == 1 ?
"bmp" :
"png").read();
4046 if (image.isNull() && s.version() >= 5)
4047 s.setStatus(QDataStream::ReadPastEnd);
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4067bool QImage::operator==(
const QImage & i)
const
4076 if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
4079 if (d->format != Format_RGB32) {
4080 if (d->format >= Format_ARGB32) {
4081 const int n = d->width * d->depth / 8;
4082 if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
4083 if (memcmp(bits(), i.bits(), d->nbytes))
4086 for (
int y = 0; y < d->height; ++y) {
4087 if (memcmp(scanLine(y), i.scanLine(y), n))
4092 const int w = width();
4093 const int h = height();
4094 const QList<QRgb> &colortable = d->colortable;
4095 const QList<QRgb> &icolortable = i.d->colortable;
4096 for (
int y=0; y<h; ++y) {
4097 for (
int x=0; x<w; ++x) {
4098 if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
4105 for(
int l = 0; l < d->height; l++) {
4107 const uint *p1 =
reinterpret_cast<
const uint*>(scanLine(l));
4108 const uint *p2 =
reinterpret_cast<
const uint*>(i.scanLine(l));
4110 if ((*p1++ & 0x00ffffff) != (*p2++ & 0x00ffffff))
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4132bool QImage::operator!=(
const QImage & i)
const
4134 return !(*
this == i);
4141
4142
4143
4144
4145
4146
4147
4148int QImage::dotsPerMeterX()
const
4150 return d ? qRound(d->dpmx) : 0;
4154
4155
4156
4157
4158
4159
4160
4161int QImage::dotsPerMeterY()
const
4163 return d ? qRound(d->dpmy) : 0;
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178void QImage::setDotsPerMeterX(
int x)
4180 if (!d || !x || d->dpmx == x)
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200void QImage::setDotsPerMeterY(
int y)
4202 if (!d || !y || d->dpmy == y)
4211
4212
4213
4214
4215
4216
4217
4218QPoint QImage::offset()
const
4220 return d ? d->offset : QPoint();
4225
4226
4227
4228
4229
4230
4231
4232void QImage::setOffset(
const QPoint& p)
4234 if (!d || d->offset == p)
4243
4244
4245
4246
4247
4248
4249
4250QStringList QImage::textKeys()
const
4252 return d ? QStringList(d->text.keys()) : QStringList();
4256
4257
4258
4259
4260
4261
4262QString QImage::text(
const QString &key)
const
4268 return d->text.value(key);
4271 for (
auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
4272 tmp += it.key() +
": "_L1 + it.value().simplified() +
"\n\n"_L1;
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302void QImage::setText(
const QString &key,
const QString &value)
4309 d->text.insert(key, value);
4313
4314
4315
4316
4317QPaintEngine *QImage::paintEngine()
const
4322 if (!d->paintEngine) {
4323 QPaintDevice *paintDevice =
const_cast<QImage *>(
this);
4324 QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
4325 if (platformIntegration)
4326 d->paintEngine = platformIntegration->createImagePaintEngine(paintDevice);
4327 if (!d->paintEngine)
4328 d->paintEngine =
new QRasterPaintEngine(paintDevice);
4331 return d->paintEngine;
4336
4337
4338
4339
4340int QImage::metric(PaintDeviceMetric metric)
const
4353 return qRound(d->width * 1000 / d->dpmx);
4356 return qRound(d->height * 1000 / d->dpmy);
4359 return d->colortable.size();
4365 return qRound(d->dpmx * 0.0254);
4369 return qRound(d->dpmy * 0.0254);
4372 case PdmPhysicalDpiX:
4373 return qRound(d->dpmx * 0.0254);
4376 case PdmPhysicalDpiY:
4377 return qRound(d->dpmy * 0.0254);
4380 case PdmDevicePixelRatio:
4381 return d->devicePixelRatio;
4384 case PdmDevicePixelRatioScaled:
4385 return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
4388 case PdmDevicePixelRatioF_EncodedA:
4390 case PdmDevicePixelRatioF_EncodedB:
4391 return QPaintDevice::encodeMetricF(metric, d->devicePixelRatio);
4395 qWarning(
"QImage::metric(): Unhandled metric type %d", metric);
4404
4405
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4427#define IWX_MSB(b) if (trigx < maxws && trigy < maxhs) {
4428 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4429 (1
<< (7
-((trigx>>12
)&7
))))
4436#define IWX_LSB(b) if (trigx < maxws && trigy < maxhs) {
4437 if (*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4438 (1
<< ((trigx>>12
)&7
)))
4445#define IWX_PIX(b) if (trigx < maxws && trigy < maxhs) {
4446 if ((*(sptr+sbpl*(trigy>>12
)+(trigx>>15
)) &
4447 (1
<< (7
-((trigx>>12
)&7
)))) == 0
)
4455bool qt_xForm_helper(
const QTransform &trueMat,
int xoffset,
int type,
int depth,
4456 uchar *dptr, qsizetype dbpl,
int p_inc,
int dHeight,
4457 const uchar *sptr, qsizetype sbpl,
int sWidth,
int sHeight)
4459 int m11 =
int(trueMat.m11()*4096.0);
4460 int m12 =
int(trueMat.m12()*4096.0);
4461 int m21 =
int(trueMat.m21()*4096.0);
4462 int m22 =
int(trueMat.m22()*4096.0);
4463 int dx = qRound(trueMat.dx()*4096.0);
4464 int dy = qRound(trueMat.dy()*4096.0);
4466 int m21ydx = dx + (xoffset<<16) + (m11 + m21) / 2;
4467 int m22ydy = dy + (m12 + m22) / 2;
4470 uint maxws = sWidth<<12;
4471 uint maxhs = sHeight<<12;
4473 for (
int y=0; y<dHeight; y++) {
4476 uchar *maxp = dptr + dbpl;
4480 while (dptr < maxp) {
4481 if (trigx < maxws && trigy < maxhs)
4482 *dptr = *(sptr+sbpl*(trigy>>12)+(trigx>>12));
4490 while (dptr < maxp) {
4491 if (trigx < maxws && trigy < maxhs)
4492 *((ushort*)dptr) = *((
const ushort *)(sptr+sbpl*(trigy>>12) +
4502 while (dptr < maxp) {
4503 if (trigx < maxws && trigy < maxhs) {
4504 const uchar *p2 = sptr+sbpl*(trigy>>12) + ((trigx>>12)*3);
4516 while (dptr < maxp) {
4517 if (trigx < maxws && trigy < maxhs)
4518 *((uint*)dptr) = *((
const uint *)(sptr+sbpl*(trigy>>12) +
4533 while (dptr < maxp) {
4546 while (dptr < maxp) {
4571
4572
4573
4574
4575
4576
4577qint64 QImage::cacheKey()
const
4582 return (((qint64) d->ser_no) << 32) | ((qint64) d->detach_no);
4586
4587
4588
4589
4590
4591
4593bool QImage::isDetached()
const
4595 return d && d->ref.loadRelaxed() == 1;
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4618void QImage::setAlphaChannel(
const QImage &alphaChannel)
4620 if (!d || alphaChannel.isNull())
4623 if (d->paintEngine && d->paintEngine->isActive()) {
4624 qWarning(
"QImage::setAlphaChannel: "
4625 "Unable to set alpha channel while image is being painted on");
4629 const Format alphaFormat = qt_alphaVersionForPainting(d->format);
4630 if (d->format == alphaFormat)
4633 convertTo(alphaFormat);
4639 if (alphaChannel.format() == QImage::Format_Alpha8 || (alphaChannel.d->depth == 8 && alphaChannel.isGrayscale()))
4640 sourceImage = alphaChannel;
4642 sourceImage = alphaChannel.convertToFormat(QImage::Format_Grayscale8);
4643 if (!sourceImage.reinterpretAsFormat(QImage::Format_Alpha8))
4646 QPainter painter(
this);
4647 if (sourceImage.size() != size())
4648 painter.setRenderHint(QPainter::SmoothPixmapTransform);
4649 painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
4650 painter.drawImage(rect(), sourceImage);
4654
4655
4656
4657
4658
4659bool QImage::hasAlphaChannel()
const
4663 const QPixelFormat format = pixelFormat();
4664 if (format.alphaUsage() == QPixelFormat::UsesAlpha)
4666 if (format.colorModel() == QPixelFormat::Indexed)
4667 return d->has_alpha_clut;
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681int QImage::bitPlaneCount()
const
4686 switch (d->format) {
4687 case QImage::Format_Invalid:
4689 case QImage::Format_BGR30:
4690 case QImage::Format_RGB30:
4693 case QImage::Format_RGB32:
4694 case QImage::Format_RGBX8888:
4697 case QImage::Format_RGB666:
4700 case QImage::Format_RGB555:
4703 case QImage::Format_ARGB8555_Premultiplied:
4706 case QImage::Format_RGB444:
4709 case QImage::Format_RGBX64:
4710 case QImage::Format_RGBX16FPx4:
4713 case QImage::Format_RGBX32FPx4:
4717 bpc = qt_depthForFormat(d->format);
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734QImage QImage::smoothScaled(
int w,
int h)
const
4737 switch (src.format()) {
4738 case QImage::Format_RGB32:
4739 case QImage::Format_ARGB32_Premultiplied:
4740#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4741 case QImage::Format_RGBX8888:
4743 case QImage::Format_RGBA8888_Premultiplied:
4744#if QT_CONFIG(raster_64bit)
4745 case QImage::Format_RGBX64:
4746 case QImage::Format_RGBA64_Premultiplied:
4748 case QImage::Format_RGBA64:
4749 case QImage::Format_Grayscale16:
4750 src.convertTo(QImage::Format_RGBA64_Premultiplied);
4753#if QT_CONFIG(raster_fp)
4754 case QImage::Format_RGBX32FPx4:
4755 case QImage::Format_RGBA32FPx4_Premultiplied:
4757 case QImage::Format_RGBX16FPx4:
4758 src.convertTo(QImage::Format_RGBX32FPx4);
4760 case QImage::Format_RGBA16FPx4:
4761 case QImage::Format_RGBA16FPx4_Premultiplied:
4762 case QImage::Format_RGBA32FPx4:
4763 src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
4766 case QImage::Format_CMYK8888:
4769 if (src.hasAlphaChannel())
4770 src.convertTo(QImage::Format_ARGB32_Premultiplied);
4772 src.convertTo(QImage::Format_RGB32);
4774 src = qSmoothScaleImage(src, w, h);
4776 copyMetadata(src.d, d);
4780static QImage rotated90(
const QImage &image)
4782 QImage out(image.height(), image.width(), image.format());
4785 copyMetadata(QImageData::get(out), QImageData::get(image));
4786 if (image.colorCount() > 0)
4787 out.setColorTable(image.colorTable());
4788 int w = image.width();
4789 int h = image.height();
4790 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][2];
4792 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4794 for (
int y=0; y<h; ++y) {
4795 if (image.colorCount())
4796 for (
int x=0; x<w; ++x)
4797 out.setPixel(h-y-1, x, image.pixelIndex(x, y));
4799 for (
int x=0; x<w; ++x)
4800 out.setPixel(h-y-1, x, image.pixel(x, y));
4806static QImage rotated180(
const QImage &image)
4808 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][1];
4810 return image.flipped(Qt::Horizontal | Qt::Vertical);
4812 QImage out(image.width(), image.height(), image.format());
4815 copyMetadata(QImageData::get(out), QImageData::get(image));
4816 if (image.colorCount() > 0)
4817 out.setColorTable(image.colorTable());
4818 int w = image.width();
4819 int h = image.height();
4820 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4824static QImage rotated270(
const QImage &image)
4826 QImage out(image.height(), image.width(), image.format());
4829 copyMetadata(QImageData::get(out), QImageData::get(image));
4830 if (image.colorCount() > 0)
4831 out.setColorTable(image.colorTable());
4832 int w = image.width();
4833 int h = image.height();
4834 const MemRotateFunc memrotate = qMemRotateFunctions[qPixelLayouts[image.format()].bpp][0];
4836 memrotate(image.constBits(), w, h, image.bytesPerLine(), out.bits(), out.bytesPerLine());
4838 for (
int y=0; y<h; ++y) {
4839 if (image.colorCount())
4840 for (
int x=0; x<w; ++x)
4841 out.setPixel(y, w-x-1, image.pixelIndex(x, y));
4843 for (
int x=0; x<w; ++x)
4844 out.setPixel(y, w-x-1, image.pixel(x, y));
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4874QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(
const QTransform &matrix, Qt::TransformationMode mode )
const
4879 Q_TRACE_PARAM_REPLACE(
const QTransform &,
double[9]);
4880 Q_TRACE_SCOPE(QImage_transformed, QList<
double>({matrix.m11(), matrix.m12(), matrix.m13(),
4881 matrix.m21(), matrix.m22(), matrix.m23(),
4882 matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
4885 const int ws = width();
4886 const int hs = height();
4893 QTransform mat = trueMatrix(matrix, ws, hs);
4894 bool complex_xform =
false;
4895 bool scale_xform =
false;
4896 bool nonpaintable_scale_xform =
false;
4897 if (mat.type() <= QTransform::TxScale) {
4898 if (mat.type() == QTransform::TxNone)
4900 else if (mat.m11() == -1. && mat.m22() == -1.)
4901 return rotated180(*
this);
4903 hd = qRound(qAbs(mat.m22()) * hs);
4904 wd = qRound(qAbs(mat.m11()) * ws);
4908 if (hd * 2 < hs || wd * 2 < ws)
4909 nonpaintable_scale_xform =
true;
4911 if (format() == QImage::Format_CMYK8888)
4912 nonpaintable_scale_xform =
true;
4914 if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
4915 if (mat.m12() == 1. && mat.m21() == -1.)
4916 return rotated90(*
this);
4917 else if (mat.m12() == -1. && mat.m21() == 1.)
4918 return rotated270(*
this);
4921 QPolygonF a(QRectF(0, 0, ws, hs));
4923 QRect r = a.boundingRect().toAlignedRect();
4926 complex_xform =
true;
4929 if (wd == 0 || hd == 0)
4932 if (scale_xform && mode == Qt::SmoothTransformation) {
4934 case QImage::Format_RGB32:
4935 case QImage::Format_ARGB32_Premultiplied:
4936#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
4937 case QImage::Format_RGBX8888:
4939 case QImage::Format_RGBA8888_Premultiplied:
4940#if QT_CONFIG(raster_64bit)
4941 case QImage::Format_RGBX64:
4942 case QImage::Format_RGBA64_Premultiplied:
4944 case QImage::Format_CMYK8888:
4946 if (mat.m11() > 0.0F && mat.m22() > 0.0F)
4947 return smoothScaled(wd, hd);
4953 if (nonpaintable_scale_xform
4954#if QT_CONFIG(qtgui_threadpool)
4955 || (ws * hs) >= (1<<20)
4959 if (mat.m11() < 0.0F && mat.m22() < 0.0F) {
4960 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal | Qt::Vertical);
4961 }
else if (mat.m11() < 0.0F) {
4962 scaledImage = smoothScaled(wd, hd).flipped(Qt::Horizontal);
4963 }
else if (mat.m22() < 0.0F) {
4964 scaledImage = smoothScaled(wd, hd).flipped(Qt::Vertical);
4966 scaledImage = smoothScaled(wd, hd);
4970 case QImage::Format_Mono:
4971 case QImage::Format_MonoLSB:
4972 case QImage::Format_Indexed8:
4975 return scaledImage.convertToFormat(format());
4982 qsizetype sbpl = bytesPerLine();
4983 const uchar *sptr = bits();
4985 QImage::Format target_format = d->format;
4987 if (complex_xform || mode == Qt::SmoothTransformation) {
4988 if (d->format < QImage::Format_RGB32 || (!hasAlphaChannel() && complex_xform)) {
4989 target_format = qt_alphaVersion(d->format);
4993 QImage dImage(wd, hd, target_format);
4996 if (target_format == QImage::Format_MonoLSB
4997 || target_format == QImage::Format_Mono
4998 || target_format == QImage::Format_Indexed8) {
4999 dImage.d->colortable = d->colortable;
5000 dImage.d->has_alpha_clut = d->has_alpha_clut | complex_xform;
5004 if (target_format == QImage::Format_Indexed8) {
5005 if (dImage.d->colortable.size() < 256) {
5007 dImage.d->colortable.append(0x0);
5008 memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
5010 memset(dImage.bits(), 0, dImage.d->nbytes);
5013 memset(dImage.bits(), 0x00, dImage.d->nbytes);
5015 if (target_format >= QImage::Format_RGB32 && target_format != QImage::Format_CMYK8888) {
5017 QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *
this;
5019 && (d->format == QImage::Format_MonoLSB
5020 || d->format == QImage::Format_Mono
5021 || d->format == QImage::Format_Indexed8)) {
5022 sImage.d->colortable = d->colortable;
5023 sImage.d->has_alpha_clut = d->has_alpha_clut;
5026 Q_ASSERT(sImage.devicePixelRatio() == 1);
5027 Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
5029 QPainter p(&dImage);
5030 if (mode == Qt::SmoothTransformation) {
5031 p.setRenderHint(QPainter::Antialiasing);
5032 p.setRenderHint(QPainter::SmoothPixmapTransform);
5034 p.setTransform(mat);
5035 p.drawImage(QPoint(0, 0), sImage);
5038 mat = mat.inverted(&invertible);
5044 qsizetype dbpl = dImage.bytesPerLine();
5045 qt_xForm_helper(mat, 0, type, bpp, dImage.bits(), dbpl, 0, hd, sptr, sbpl, ws, hs);
5047 copyMetadata(dImage.d, d);
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5073QTransform QImage::trueMatrix(
const QTransform &matrix,
int w,
int h)
5075 const QRectF rect(0, 0, w, h);
5076 const QRect mapped = matrix.mapRect(rect).toAlignedRect();
5077 const QPoint delta = mapped.topLeft();
5078 return matrix * QTransform().translate(-delta.x(), -delta.y());
5082
5083
5084
5085
5086
5087
5088void QImage::setColorSpace(
const QColorSpace &colorSpace)
5092 if (d->colorSpace == colorSpace)
5094 if (colorSpace.isValid() && !qt_compatibleColorModelSource(pixelFormat().colorModel(), colorSpace.colorModel()))
5097 detachMetadata(
false);
5099 d->colorSpace = colorSpace;
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114void QImage::convertToColorSpace(
const QColorSpace &colorSpace)
5116 if (!d || !d->colorSpace.isValid())
5118 if (!colorSpace.isValidTarget()) {
5119 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5122 if (d->colorSpace == colorSpace)
5124 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(),
5125 colorSpace.colorModel(), colorSpace.transformModel())) {
5126 *
this = convertedToColorSpace(colorSpace);
5129 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
5130 if (d->ref.loadRelaxed() != 1)
5131 detachMetadata(
false);
5132 d->colorSpace = colorSpace;
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148void QImage::convertToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
5150 if (!d || !d->colorSpace.isValid())
5152 if (!colorSpace.isValidTarget()) {
5153 qWarning() <<
"QImage::convertToColorSpace: Output colorspace is not valid";
5156 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5157 colorSpace.colorModel(), colorSpace.transformModel())) {
5158 qWarning() <<
"QImage::convertToColorSpace: Color space is not compatible with format";
5162 if (d->colorSpace == colorSpace)
5163 return convertTo(format, flags);
5164 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5165 d->colorSpace = colorSpace;
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace)
const
5184 if (!d || !d->colorSpace.isValid())
5186 if (!colorSpace.isValidTarget()) {
5187 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5190 if (d->colorSpace == colorSpace)
5192 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
5193 image.setColorSpace(colorSpace);
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
const &
5213 if (!d || !d->colorSpace.isValid())
5215 if (!colorSpace.isValidTarget()) {
5216 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5219 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5220 colorSpace.colorModel(), colorSpace.transformModel())) {
5221 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5224 if (d->colorSpace == colorSpace)
5225 return convertedTo(format, flags);
5226 QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5227 image.setColorSpace(colorSpace);
5231QImage QImage::convertedToColorSpace(
const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) &&
5233 if (!d || !d->colorSpace.isValid())
5235 if (!colorSpace.isValidTarget()) {
5236 qWarning() <<
"QImage::convertedToColorSpace: Output colorspace is not valid";
5239 if (!qt_compatibleColorModelTarget(toPixelFormat(format).colorModel(),
5240 colorSpace.colorModel(), colorSpace.transformModel())) {
5241 qWarning() <<
"QImage::convertedToColorSpace: Color space is not compatible with format";
5244 if (d->colorSpace == colorSpace)
5245 return convertedTo(format, flags);
5246 applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
5247 return std::move(*
this);
5251
5252
5253
5254
5255QColorSpace QImage::colorSpace()
const
5258 return QColorSpace();
5259 return d->colorSpace;
5263
5264
5265
5266
5267void QImage::applyColorTransform(
const QColorTransform &transform)
5269 if (transform.isIdentity())
5272 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
5273 !qt_compatibleColorModelTarget(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel,
5274 QColorTransformPrivate::get(transform)->colorSpaceOut->transformModel)) {
5275 qWarning() <<
"QImage::applyColorTransform can not apply format switching transform without switching format";
5282 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5283 for (
int i = 0; i < d->colortable.size(); ++i)
5284 d->colortable[i] = transform.map(d->colortable[i]);
5287 QImage::Format oldFormat = format();
5288 if (qt_fpColorPrecision(oldFormat)) {
5289 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5290 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5291 convertTo(QImage::Format_RGBA32FPx4);
5292 }
else if (depth() > 32) {
5293 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5294 && oldFormat != QImage::Format_RGBA64_Premultiplied)
5295 convertTo(QImage::Format_RGBA64);
5296 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5297 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5298 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5299 if (hasAlphaChannel())
5300 convertTo(QImage::Format_ARGB32);
5302 convertTo(QImage::Format_RGB32);
5305 QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
5307 case Format_ARGB32_Premultiplied:
5308 case Format_RGBA64_Premultiplied:
5309 case Format_RGBA32FPx4_Premultiplied:
5310 flags = QColorTransformPrivate::Premultiplied;
5312 case Format_Grayscale8:
5313 case Format_Grayscale16:
5315 case Format_CMYK8888:
5317 case Format_RGBX32FPx4:
5318 flags = QColorTransformPrivate::InputOpaque;
5322 case Format_RGBA32FPx4:
5328 std::function<
void(
int,
int)> transformSegment;
5330 if (format() == Format_Grayscale8) {
5331 transformSegment = [&](
int yStart,
int yEnd) {
5332 for (
int y = yStart; y < yEnd; ++y) {
5333 uint8_t *scanline =
reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
5334 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5337 }
else if (format() == Format_Grayscale16) {
5338 transformSegment = [&](
int yStart,
int yEnd) {
5339 for (
int y = yStart; y < yEnd; ++y) {
5340 uint16_t *scanline =
reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
5341 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5344 }
else if (qt_fpColorPrecision(format())) {
5345 transformSegment = [&](
int yStart,
int yEnd) {
5346 for (
int y = yStart; y < yEnd; ++y) {
5347 QRgbaFloat32 *scanline =
reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
5348 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5351 }
else if (depth() > 32) {
5352 transformSegment = [&](
int yStart,
int yEnd) {
5353 for (
int y = yStart; y < yEnd; ++y) {
5354 QRgba64 *scanline =
reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
5355 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5358 }
else if (oldFormat == QImage::Format_CMYK8888) {
5359 transformSegment = [&](
int yStart,
int yEnd) {
5360 for (
int y = yStart; y < yEnd; ++y) {
5361 QCmyk32 *scanline =
reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
5362 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5366 transformSegment = [&](
int yStart,
int yEnd) {
5367 for (
int y = yStart; y < yEnd; ++y) {
5368 QRgb *scanline =
reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
5369 QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
5374#if QT_CONFIG(qtgui_threadpool)
5375 int segments = (qsizetype(width()) * height()) >> 16;
5376 segments = std::min(segments, height());
5377 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5378 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5379 QLatch latch(segments);
5381 for (
int i = 0; i < segments; ++i) {
5382 int yn = (height() - y) / (segments - i);
5383 threadPool->start([&, y, yn]() {
5384 transformSegment(y, y + yn);
5392 transformSegment(0, height());
5394 if (oldFormat != format())
5395 *
this = std::move(*
this).convertToFormat(oldFormat);
5399
5400
5401
5402
5403
5404
5405
5406void QImage::applyColorTransform(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
5410 if (transform.isIdentity())
5411 return convertTo(toFormat, flags);
5413 *
this = colorTransformed(transform, toFormat, flags);
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428QImage QImage::colorTransformed(
const QColorTransform &transform)
const &
5432 if (transform.isIdentity())
5435 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5436 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5437 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5438 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5441 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5443 switch (outColorSpace->colorModel) {
5444 case QColorSpace::ColorModel::Rgb:
5445 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5446 case QColorSpace::ColorModel::Gray:
5447 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5448 case QColorSpace::ColorModel::Cmyk:
5449 return colorTransformed(transform, QImage::Format_CMYK8888);
5450 case QColorSpace::ColorModel::Undefined:
5456 QImage image = copy();
5457 image.applyColorTransform(transform);
5461static bool isRgb32Data(QImage::Format f)
5464 case QImage::Format_RGB32:
5465 case QImage::Format_ARGB32:
5466 case QImage::Format_ARGB32_Premultiplied:
5474static bool isRgb64Data(QImage::Format f)
5477 case QImage::Format_RGBX64:
5478 case QImage::Format_RGBA64:
5479 case QImage::Format_RGBA64_Premultiplied:
5487static bool isRgb32fpx4Data(QImage::Format f)
5490 case QImage::Format_RGBX32FPx4:
5491 case QImage::Format_RGBA32FPx4:
5492 case QImage::Format_RGBA32FPx4_Premultiplied:
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
const &
5517 if (toFormat == QImage::Format_Invalid)
5518 toFormat = format();
5519 if (transform.isIdentity())
5520 return convertedTo(toFormat, flags);
5522 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5523 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5524 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5525 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5528 if (!qt_compatibleColorModelTarget(toPixelFormat(toFormat).colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5529 qWarning() <<
"QImage::colorTransformed: Invalid output color space for transform";
5533 QImage fromImage = *
this;
5535 QImage::Format tmpFormat = toFormat;
5537 case QImage::Format_RGB32:
5538 case QImage::Format_ARGB32:
5539 case QImage::Format_ARGB32_Premultiplied:
5540 case QImage::Format_RGBX32FPx4:
5541 case QImage::Format_RGBA32FPx4:
5542 case QImage::Format_RGBA32FPx4_Premultiplied:
5543 case QImage::Format_RGBX64:
5544 case QImage::Format_RGBA64:
5545 case QImage::Format_RGBA64_Premultiplied:
5546 case QImage::Format_Grayscale8:
5547 case QImage::Format_Grayscale16:
5548 case QImage::Format_CMYK8888:
5551 case QImage::Format_RGB16:
5552 case QImage::Format_RGB444:
5553 case QImage::Format_RGB555:
5554 case QImage::Format_RGB666:
5555 case QImage::Format_RGB888:
5556 case QImage::Format_BGR888:
5557 case QImage::Format_RGBX8888:
5558 tmpFormat = QImage::Format_RGB32;
5560 case QImage::Format_Mono:
5561 case QImage::Format_MonoLSB:
5562 case QImage::Format_Indexed8:
5563 case QImage::Format_ARGB8565_Premultiplied:
5564 case QImage::Format_ARGB6666_Premultiplied:
5565 case QImage::Format_ARGB8555_Premultiplied:
5566 case QImage::Format_ARGB4444_Premultiplied:
5567 case QImage::Format_RGBA8888:
5568 case QImage::Format_RGBA8888_Premultiplied:
5569 tmpFormat = QImage::Format_ARGB32;
5571 case QImage::Format_BGR30:
5572 case QImage::Format_RGB30:
5573 tmpFormat = QImage::Format_RGBX64;
5575 case QImage::Format_A2BGR30_Premultiplied:
5576 case QImage::Format_A2RGB30_Premultiplied:
5577 tmpFormat = QImage::Format_RGBA64;
5579 case QImage::Format_RGBX16FPx4:
5580 case QImage::Format_RGBA16FPx4:
5581 case QImage::Format_RGBA16FPx4_Premultiplied:
5582 tmpFormat = QImage::Format_RGBA32FPx4;
5584 case QImage::Format_Alpha8:
5585 return convertedTo(QImage::Format_Alpha8);
5586 case QImage::Format_Invalid:
5587 case QImage::NImageFormats:
5591 QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
5592 QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
5594 if (inColorData != outColorData) {
5595 if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
5596 tmpFormat = QImage::Format_RGB32;
5597 else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
5598 tmpFormat = QImage::Format_Grayscale16;
5599 else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
5600 tmpFormat = QImage::Format_RGBX64;
5602 if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
5603 tmpFormat = QImage::Format_Grayscale16;
5604 else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
5605 tmpFormat = QImage::Format_RGBA32FPx4;
5606 else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(),
true))
5607 tmpFormat = QImage::Format_RGBA64;
5610 QImage toImage(size(), tmpFormat);
5611 copyMetadata(&toImage, *
this);
5613 std::function<
void(
int,
int)> transformSegment;
5614 QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
5616 if (inColorData != outColorData) {
5618 if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
5620 if (format() == QImage::Format_Grayscale8) {
5621 transformSegment = [&](
int yStart,
int yEnd) {
5622 for (
int y = yStart; y < yEnd; ++y) {
5623 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5624 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5625 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5629 transformSegment = [&](
int yStart,
int yEnd) {
5630 for (
int y = yStart; y < yEnd; ++y) {
5631 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5632 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5633 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5637 }
else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
5639 if (format() == QImage::Format_Grayscale8) {
5640 transformSegment = [&](
int yStart,
int yEnd) {
5641 for (
int y = yStart; y < yEnd; ++y) {
5642 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(d->data + y * d->bytes_per_line);
5643 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5644 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5648 transformSegment = [&](
int yStart,
int yEnd) {
5649 for (
int y = yStart; y < yEnd; ++y) {
5650 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(d->data + y * d->bytes_per_line);
5651 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5652 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5656 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
5658 if (tmpFormat == QImage::Format_Grayscale8) {
5659 fromImage.convertTo(QImage::Format_RGB32);
5660 transformSegment = [&](
int yStart,
int yEnd) {
5661 for (
int y = yStart; y < yEnd; ++y) {
5662 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5663 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5664 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5668 fromImage.convertTo(QImage::Format_RGBX64);
5669 transformSegment = [&](
int yStart,
int yEnd) {
5670 for (
int y = yStart; y < yEnd; ++y) {
5671 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5672 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5673 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5677 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
5679 if (tmpFormat == QImage::Format_Grayscale8) {
5680 transformSegment = [&](
int yStart,
int yEnd) {
5681 for (
int y = yStart; y < yEnd; ++y) {
5682 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5683 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5684 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5688 transformSegment = [&](
int yStart,
int yEnd) {
5689 for (
int y = yStart; y < yEnd; ++y) {
5690 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5691 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5692 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5696 }
else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
5698 if (isRgb32Data(tmpFormat) ) {
5699 transformSegment = [&](
int yStart,
int yEnd) {
5700 for (
int y = yStart; y < yEnd; ++y) {
5701 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5702 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5703 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5706 }
else if (isRgb64Data(tmpFormat)) {
5707 transformSegment = [&](
int yStart,
int yEnd) {
5708 for (
int y = yStart; y < yEnd; ++y) {
5709 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5710 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5711 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5715 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5716 transformSegment = [&](
int yStart,
int yEnd) {
5717 for (
int y = yStart; y < yEnd; ++y) {
5718 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5719 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5720 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
5724 }
else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
5726 if (!fromImage.hasAlphaChannel())
5727 transFlags = QColorTransformPrivate::InputOpaque;
5728 else if (qPixelLayouts[fromImage.format()].premultiplied)
5729 transFlags = QColorTransformPrivate::Premultiplied;
5730 if (isRgb32Data(fromImage.format()) ) {
5731 transformSegment = [&](
int yStart,
int yEnd) {
5732 for (
int y = yStart; y < yEnd; ++y) {
5733 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5734 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5735 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5738 }
else if (isRgb64Data(fromImage.format())) {
5739 transformSegment = [&](
int yStart,
int yEnd) {
5740 for (
int y = yStart; y < yEnd; ++y) {
5741 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5742 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5743 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5747 Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
5748 transformSegment = [&](
int yStart,
int yEnd) {
5749 for (
int y = yStart; y < yEnd; ++y) {
5750 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5751 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5752 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5761 if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
5762 for (
int i = 0; i < d->colortable.size(); ++i)
5763 fromImage.d->colortable[i] = transform.map(d->colortable[i]);
5764 return fromImage.convertedTo(toFormat, flags);
5767 QImage::Format oldFormat = format();
5768 if (qt_fpColorPrecision(oldFormat)) {
5769 if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
5770 && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
5771 fromImage.convertTo(QImage::Format_RGBA32FPx4);
5772 }
else if (qt_highColorPrecision(oldFormat,
true)) {
5773 if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
5774 && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
5775 fromImage.convertTo(QImage::Format_RGBA64);
5776 }
else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
5777 && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
5778 && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
5779 if (hasAlphaChannel())
5780 fromImage.convertTo(QImage::Format_ARGB32);
5782 fromImage.convertTo(QImage::Format_RGB32);
5785 if (!fromImage.hasAlphaChannel())
5786 transFlags = QColorTransformPrivate::InputOpaque;
5787 else if (qPixelLayouts[fromImage.format()].premultiplied)
5788 transFlags = QColorTransformPrivate::Premultiplied;
5790 if (fromImage.format() == Format_Grayscale8) {
5791 transformSegment = [&](
int yStart,
int yEnd) {
5792 for (
int y = yStart; y < yEnd; ++y) {
5793 const quint8 *in_scanline =
reinterpret_cast<
const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5794 if (tmpFormat == Format_Grayscale8) {
5795 quint8 *out_scanline =
reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
5796 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5798 Q_ASSERT(tmpFormat == Format_Grayscale16);
5799 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5800 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5804 }
else if (fromImage.format() == Format_Grayscale16) {
5805 transformSegment = [&](
int yStart,
int yEnd) {
5806 for (
int y = yStart; y < yEnd; ++y) {
5807 const quint16 *in_scanline =
reinterpret_cast<
const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5808 quint16 *out_scanline =
reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
5809 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5812 }
else if (fromImage.format() == Format_CMYK8888) {
5813 Q_ASSERT(tmpFormat == Format_CMYK8888);
5814 transformSegment = [&](
int yStart,
int yEnd) {
5815 for (
int y = yStart; y < yEnd; ++y) {
5816 const QCmyk32 *in_scanline =
reinterpret_cast<
const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5817 QCmyk32 *out_scanline =
reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
5818 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5821 }
else if (isRgb32fpx4Data(fromImage.format())) {
5822 Q_ASSERT(isRgb32fpx4Data(tmpFormat));
5823 transformSegment = [&](
int yStart,
int yEnd) {
5824 for (
int y = yStart; y < yEnd; ++y) {
5825 const QRgbaFloat32 *in_scanline =
reinterpret_cast<
const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5826 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5827 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5830 }
else if (isRgb64Data(fromImage.format())) {
5831 transformSegment = [&](
int yStart,
int yEnd) {
5832 for (
int y = yStart; y < yEnd; ++y) {
5833 const QRgba64 *in_scanline =
reinterpret_cast<
const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5834 if (isRgb32fpx4Data(tmpFormat)) {
5835 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5836 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5838 Q_ASSERT(isRgb64Data(tmpFormat));
5839 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5840 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5845 transformSegment = [&](
int yStart,
int yEnd) {
5846 for (
int y = yStart; y < yEnd; ++y) {
5847 const QRgb *in_scanline =
reinterpret_cast<
const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
5848 if (isRgb32fpx4Data(tmpFormat)) {
5849 QRgbaFloat32 *out_scanline =
reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
5850 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5851 }
else if (isRgb64Data(tmpFormat)) {
5852 QRgba64 *out_scanline =
reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
5853 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5855 Q_ASSERT(isRgb32Data(tmpFormat));
5856 QRgb *out_scanline =
reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
5857 QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
5864#if QT_CONFIG(qtgui_threadpool)
5865 int segments = (qsizetype(width()) * height()) >> 16;
5866 segments = std::min(segments, height());
5867 QThreadPool *threadPool = QGuiApplicationPrivate::qtGuiThreadPool();
5868 if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
5869 QLatch latch(segments);
5871 for (
int i = 0; i < segments; ++i) {
5872 int yn = (height() - y) / (segments - i);
5873 threadPool->start([&, y, yn]() {
5874 transformSegment(y, y + yn);
5882 transformSegment(0, height());
5884 if (tmpFormat != toFormat)
5885 toImage.convertTo(toFormat);
5891
5892
5893
5894
5895
5896
5897
5898QImage QImage::colorTransformed(
const QColorTransform &transform) &&
5903 const QColorSpacePrivate *inColorSpace = QColorTransformPrivate::get(transform)->colorSpaceIn.constData();
5904 const QColorSpacePrivate *outColorSpace = QColorTransformPrivate::get(transform)->colorSpaceOut.constData();
5905 if (!qt_compatibleColorModelSource(pixelFormat().colorModel(), inColorSpace->colorModel)) {
5906 qWarning() <<
"QImage::colorTransformed: Invalid input color space for transform";
5909 if (!qt_compatibleColorModelTarget(pixelFormat().colorModel(), outColorSpace->colorModel, outColorSpace->transformModel)) {
5911 switch (outColorSpace->colorModel) {
5912 case QColorSpace::ColorModel::Rgb:
5913 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
5914 case QColorSpace::ColorModel::Gray:
5915 return colorTransformed(transform, qt_highColorPrecision(format(),
true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
5916 case QColorSpace::ColorModel::Cmyk:
5917 return colorTransformed(transform, QImage::Format_CMYK8888);
5918 case QColorSpace::ColorModel::Undefined:
5924 applyColorTransform(transform);
5925 return std::move(*
this);
5929
5930
5931
5932
5933
5934
5935
5936QImage QImage::colorTransformed(
const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
5939 return colorTransformed(transform, format, flags);
5942bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
5944 if (format == newFormat)
5948 if (ref.loadRelaxed() > 1 || !own_data)
5951 InPlace_Image_Converter converter = qimage_inplace_converter_map[format][newFormat];
5953 return converter(
this, flags);
5954 if (format > QImage::Format_Indexed8 && newFormat > QImage::Format_Indexed8 && !qimage_converter_map[format][newFormat]) {
5957 if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
5958 && qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
5959#if QT_CONFIG(raster_fp)
5960 if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
5961 return convert_generic_inplace_over_rgba32f(
this, newFormat, flags);
5963 return convert_generic_inplace_over_rgb64(
this, newFormat, flags);
5965 return convert_generic_inplace(
this, newFormat, flags);
5971
5972
5973
5976
5977
5978
5980#ifndef QT_NO_DEBUG_STREAM
5981QDebug operator<<(QDebug dbg,
const QImage &i)
5983 QDebugStateSaver saver(dbg);
5990 dbg << i.size() <<
",format=" << i.format() <<
",depth=" << i.depth();
5992 dbg <<
",colorCount=" << i.colorCount();
5993 const int bytesPerLine = i.bytesPerLine();
5994 dbg <<
",devicePixelRatio=" << i.devicePixelRatio()
5995 <<
",bytesPerLine=" << bytesPerLine <<
",sizeInBytes=" << i.sizeInBytes();
5996 if (dbg.verbosity() > 2 && i.height() > 0) {
5997 const int outputLength = qMin(bytesPerLine, 24);
5999 << QByteArray(
reinterpret_cast<
const char *>(i.scanLine(0)), outputLength).toHex()
6008static constexpr QPixelFormat pixelformats[] = {
6012 QPixelFormat(QPixelFormat::Indexed,
6019 QPixelFormat::IgnoresAlpha,
6020 QPixelFormat::AtBeginning,
6021 QPixelFormat::NotPremultiplied,
6022 QPixelFormat::UnsignedByte,
6023 QPixelFormat::BigEndian),
6025 QPixelFormat(QPixelFormat::Indexed,
6032 QPixelFormat::IgnoresAlpha,
6033 QPixelFormat::AtBeginning,
6034 QPixelFormat::NotPremultiplied,
6035 QPixelFormat::UnsignedByte,
6036 QPixelFormat::BigEndian),
6038 QPixelFormat(QPixelFormat::Indexed,
6045 QPixelFormat::IgnoresAlpha,
6046 QPixelFormat::AtBeginning,
6047 QPixelFormat::NotPremultiplied,
6048 QPixelFormat::UnsignedByte,
6049 QPixelFormat::BigEndian),
6051 QPixelFormat(QPixelFormat::RGB,
6058 QPixelFormat::IgnoresAlpha,
6059 QPixelFormat::AtBeginning,
6060 QPixelFormat::NotPremultiplied,
6061 QPixelFormat::UnsignedInteger,
6062 QPixelFormat::CurrentSystemEndian),
6064 QPixelFormat(QPixelFormat::RGB,
6071 QPixelFormat::UsesAlpha,
6072 QPixelFormat::AtBeginning,
6073 QPixelFormat::NotPremultiplied,
6074 QPixelFormat::UnsignedInteger,
6075 QPixelFormat::CurrentSystemEndian),
6077 QPixelFormat(QPixelFormat::RGB,
6084 QPixelFormat::UsesAlpha,
6085 QPixelFormat::AtBeginning,
6086 QPixelFormat::Premultiplied,
6087 QPixelFormat::UnsignedInteger,
6088 QPixelFormat::CurrentSystemEndian),
6090 QPixelFormat(QPixelFormat::RGB,
6097 QPixelFormat::IgnoresAlpha,
6098 QPixelFormat::AtBeginning,
6099 QPixelFormat::NotPremultiplied,
6100 QPixelFormat::UnsignedShort,
6101 QPixelFormat::CurrentSystemEndian),
6103 QPixelFormat(QPixelFormat::RGB,
6110 QPixelFormat::UsesAlpha,
6111 QPixelFormat::AtBeginning,
6112 QPixelFormat::Premultiplied,
6113 QPixelFormat::UnsignedInteger,
6114 QPixelFormat::CurrentSystemEndian),
6116 QPixelFormat(QPixelFormat::RGB,
6123 QPixelFormat::IgnoresAlpha,
6124 QPixelFormat::AtBeginning,
6125 QPixelFormat::NotPremultiplied,
6126 QPixelFormat::UnsignedInteger,
6127 QPixelFormat::CurrentSystemEndian),
6129 QPixelFormat(QPixelFormat::RGB,
6136 QPixelFormat::UsesAlpha,
6137 QPixelFormat::AtEnd,
6138 QPixelFormat::Premultiplied,
6139 QPixelFormat::UnsignedInteger,
6140 QPixelFormat::CurrentSystemEndian),
6142 QPixelFormat(QPixelFormat::RGB,
6149 QPixelFormat::IgnoresAlpha,
6150 QPixelFormat::AtBeginning,
6151 QPixelFormat::NotPremultiplied,
6152 QPixelFormat::UnsignedShort,
6153 QPixelFormat::CurrentSystemEndian),
6155 QPixelFormat(QPixelFormat::RGB,
6162 QPixelFormat::UsesAlpha,
6163 QPixelFormat::AtBeginning,
6164 QPixelFormat::Premultiplied,
6165 QPixelFormat::UnsignedInteger,
6166 QPixelFormat::CurrentSystemEndian),
6168 QPixelFormat(QPixelFormat::RGB,
6175 QPixelFormat::IgnoresAlpha,
6176 QPixelFormat::AtBeginning,
6177 QPixelFormat::NotPremultiplied,
6178 QPixelFormat::UnsignedByte,
6179 QPixelFormat::BigEndian),
6181 QPixelFormat(QPixelFormat::RGB,
6188 QPixelFormat::IgnoresAlpha,
6189 QPixelFormat::AtBeginning,
6190 QPixelFormat::NotPremultiplied,
6191 QPixelFormat::UnsignedShort,
6192 QPixelFormat::CurrentSystemEndian),
6194 QPixelFormat(QPixelFormat::RGB,
6201 QPixelFormat::UsesAlpha,
6202 QPixelFormat::AtBeginning,
6203 QPixelFormat::Premultiplied,
6204 QPixelFormat::UnsignedShort,
6205 QPixelFormat::CurrentSystemEndian),
6207 QPixelFormat(QPixelFormat::RGB,
6214 QPixelFormat::IgnoresAlpha,
6215 QPixelFormat::AtEnd,
6216 QPixelFormat::NotPremultiplied,
6217 QPixelFormat::UnsignedByte,
6218 QPixelFormat::BigEndian),
6220 QPixelFormat(QPixelFormat::RGB,
6227 QPixelFormat::UsesAlpha,
6228 QPixelFormat::AtEnd,
6229 QPixelFormat::NotPremultiplied,
6230 QPixelFormat::UnsignedByte,
6231 QPixelFormat::BigEndian),
6233 QPixelFormat(QPixelFormat::RGB,
6240 QPixelFormat::UsesAlpha,
6241 QPixelFormat::AtEnd,
6242 QPixelFormat::Premultiplied,
6243 QPixelFormat::UnsignedByte,
6244 QPixelFormat::BigEndian),
6246 QPixelFormat(QPixelFormat::BGR,
6253 QPixelFormat::IgnoresAlpha,
6254 QPixelFormat::AtBeginning,
6255 QPixelFormat::NotPremultiplied,
6256 QPixelFormat::UnsignedInteger,
6257 QPixelFormat::CurrentSystemEndian),
6259 QPixelFormat(QPixelFormat::BGR,
6266 QPixelFormat::UsesAlpha,
6267 QPixelFormat::AtBeginning,
6268 QPixelFormat::Premultiplied,
6269 QPixelFormat::UnsignedInteger,
6270 QPixelFormat::CurrentSystemEndian),
6272 QPixelFormat(QPixelFormat::RGB,
6279 QPixelFormat::IgnoresAlpha,
6280 QPixelFormat::AtBeginning,
6281 QPixelFormat::NotPremultiplied,
6282 QPixelFormat::UnsignedInteger,
6283 QPixelFormat::CurrentSystemEndian),
6285 QPixelFormat(QPixelFormat::RGB,
6292 QPixelFormat::UsesAlpha,
6293 QPixelFormat::AtBeginning,
6294 QPixelFormat::Premultiplied,
6295 QPixelFormat::UnsignedInteger,
6296 QPixelFormat::CurrentSystemEndian),
6298 QPixelFormat(QPixelFormat::Alpha,
6305 QPixelFormat::UsesAlpha,
6306 QPixelFormat::AtBeginning,
6307 QPixelFormat::Premultiplied,
6308 QPixelFormat::UnsignedByte,
6309 QPixelFormat::BigEndian),
6311 QPixelFormat(QPixelFormat::Grayscale,
6318 QPixelFormat::IgnoresAlpha,
6319 QPixelFormat::AtBeginning,
6320 QPixelFormat::NotPremultiplied,
6321 QPixelFormat::UnsignedByte,
6322 QPixelFormat::BigEndian),
6324 QPixelFormat(QPixelFormat::RGB,
6331 QPixelFormat::IgnoresAlpha,
6332 QPixelFormat::AtEnd,
6333 QPixelFormat::NotPremultiplied,
6334 QPixelFormat::UnsignedShort,
6335 QPixelFormat::CurrentSystemEndian),
6337 QPixelFormat(QPixelFormat::RGB,
6344 QPixelFormat::UsesAlpha,
6345 QPixelFormat::AtEnd,
6346 QPixelFormat::NotPremultiplied,
6347 QPixelFormat::UnsignedShort,
6348 QPixelFormat::CurrentSystemEndian),
6350 QPixelFormat(QPixelFormat::RGB,
6357 QPixelFormat::UsesAlpha,
6358 QPixelFormat::AtEnd,
6359 QPixelFormat::Premultiplied,
6360 QPixelFormat::UnsignedShort,
6361 QPixelFormat::CurrentSystemEndian),
6363 QPixelFormat(QPixelFormat::Grayscale,
6370 QPixelFormat::IgnoresAlpha,
6371 QPixelFormat::AtBeginning,
6372 QPixelFormat::NotPremultiplied,
6373 QPixelFormat::UnsignedShort,
6374 QPixelFormat::CurrentSystemEndian),
6376 QPixelFormat(QPixelFormat::BGR,
6383 QPixelFormat::IgnoresAlpha,
6384 QPixelFormat::AtBeginning,
6385 QPixelFormat::NotPremultiplied,
6386 QPixelFormat::UnsignedByte,
6387 QPixelFormat::BigEndian),
6389 QPixelFormat(QPixelFormat::RGB,
6396 QPixelFormat::IgnoresAlpha,
6397 QPixelFormat::AtEnd,
6398 QPixelFormat::NotPremultiplied,
6399 QPixelFormat::FloatingPoint,
6400 QPixelFormat::CurrentSystemEndian),
6402 QPixelFormat(QPixelFormat::RGB,
6409 QPixelFormat::UsesAlpha,
6410 QPixelFormat::AtEnd,
6411 QPixelFormat::NotPremultiplied,
6412 QPixelFormat::FloatingPoint,
6413 QPixelFormat::CurrentSystemEndian),
6415 QPixelFormat(QPixelFormat::RGB,
6422 QPixelFormat::UsesAlpha,
6423 QPixelFormat::AtEnd,
6424 QPixelFormat::Premultiplied,
6425 QPixelFormat::FloatingPoint,
6426 QPixelFormat::CurrentSystemEndian),
6428 QPixelFormat(QPixelFormat::RGB,
6435 QPixelFormat::IgnoresAlpha,
6436 QPixelFormat::AtEnd,
6437 QPixelFormat::NotPremultiplied,
6438 QPixelFormat::FloatingPoint,
6439 QPixelFormat::CurrentSystemEndian),
6441 QPixelFormat(QPixelFormat::RGB,
6448 QPixelFormat::UsesAlpha,
6449 QPixelFormat::AtEnd,
6450 QPixelFormat::NotPremultiplied,
6451 QPixelFormat::FloatingPoint,
6452 QPixelFormat::CurrentSystemEndian),
6454 QPixelFormat(QPixelFormat::RGB,
6461 QPixelFormat::UsesAlpha,
6462 QPixelFormat::AtEnd,
6463 QPixelFormat::Premultiplied,
6464 QPixelFormat::FloatingPoint,
6465 QPixelFormat::CurrentSystemEndian),
6467 QPixelFormat(QPixelFormat::CMYK,
6474 QPixelFormat::IgnoresAlpha,
6475 QPixelFormat::AtBeginning,
6476 QPixelFormat::NotPremultiplied,
6477 QPixelFormat::UnsignedInteger,
6478 QPixelFormat::CurrentSystemEndian),
6480static_assert(
sizeof(pixelformats) /
sizeof(*pixelformats) == QImage::NImageFormats);
6483
6484
6485QPixelFormat QImage::pixelFormat()
const noexcept
6487 return toPixelFormat(format());
6491
6492
6493QPixelFormat QImage::toPixelFormat(QImage::Format format)
noexcept
6495 Q_ASSERT(
static_cast<
int>(format) < NImageFormats &&
static_cast<
int>(format) >= 0);
6496 return pixelformats[format];
6500
6501
6502QImage::Format QImage::toImageFormat(QPixelFormat format)
noexcept
6504 for (
int i = 0; i < NImageFormats; i++) {
6505 if (format == pixelformats[i])
6508 return Format_Invalid;
6513 Qt::Orientations orients = {};
6514 if (orient.testFlag(QImageIOHandler::TransformationMirror))
6515 orients |= Qt::Horizontal;
6516 if (orient.testFlag(QImageIOHandler::TransformationFlip))
6517 orients |= Qt::Vertical;
6523 if (orient == QImageIOHandler::TransformationNone)
6525 if (orient == QImageIOHandler::TransformationRotate270) {
6526 src = rotated270(src);
6528 src.flip(toOrientations(orient));
6529 if (orient & QImageIOHandler::TransformationRotate90)
6530 src = rotated90(src);
6536 QMap<QString, QString> text = qt_getImageTextFromDescription(description);
6537 const auto textKeys = image.textKeys();
6538 for (
const QString &key : textKeys) {
6539 if (!key.isEmpty() && !text.contains(key))
6540 text.insert(key, image.text(key));
6547 QMap<QString, QString> text;
6548 for (
const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
6549 int index = pair.indexOf(u':');
6550 if (index >= 0 && pair.indexOf(u' ') < index) {
6551 if (!pair.trimmed().isEmpty())
6552 text.insert(
"Description"_L1, pair.toString().simplified());
6554 const auto key = pair.left(index);
6555 if (!key.trimmed().isEmpty())
6556 text.insert(key.toString(), pair.mid(index + 2).toString().simplified());
6564#include "moc_qimage.cpp"
Combined button and popup list for selecting options.
Q_TRACE_METADATA(qtcore, "ENUM { AUTO, RANGE User ... MaxUser } QEvent::Type;")
static QImage rotated90(const QImage &src)
static void copyMetadata(QImage *dst, const QImage &src)
#define QT_XFORM_TYPE_LSBFIRST
static void copyMetadata(QImageData *dst, const QImageData *src)
#define QT_XFORM_TYPE_MSBFIRST
static int next_qimage_serial_number()
#define QIMAGE_SANITYCHECK_MEMORY(image)
static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
static QImage rotated270(const QImage &src)
QMap< QString, QString > qt_getImageText(const QImage &image, const QString &description)
Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
static QImage rotated180(const QImage &src)
static Qt::Orientations toOrientations(QImageIOHandler::Transformations orient)
QMap< QString, QString > qt_getImageTextFromDescription(const QString &description)