KImageFormats

rgb.cpp
1/*
2 kimgio module for SGI images
3 SPDX-FileCopyrightText: 2004 Melchior FRANZ <mfranz@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8/* this code supports:
9 * reading:
10 * everything, except images with 1 dimension or images with
11 * mapmode != NORMAL (e.g. dithered); Images with 16 bit
12 * precision or more than 4 layers are stripped down.
13 * writing:
14 * Run Length Encoded (RLE) or Verbatim (uncompressed)
15 * (whichever is smaller)
16 *
17 * Please report if you come across rgb/rgba/sgi/bw files that aren't
18 * recognized. Also report applications that can't deal with images
19 * saved by this filter.
20 */
21
22#include "rgb_p.h"
23#include "util_p.h"
24
25#include <cstring>
26
27#include <QList>
28#include <QMap>
29
30#include <QDebug>
31#include <QImage>
32
33class RLEData : public QList<uchar>
34{
35public:
36 RLEData()
37 {
38 }
39 RLEData(const uchar *d, uint l, uint o)
40 : _offset(o)
41 {
42 for (uint i = 0; i < l; i++) {
43 append(d[i]);
44 }
45 }
46 bool operator<(const RLEData &) const;
47 void write(QDataStream &s);
48 uint offset() const
49 {
50 return _offset;
51 }
52
53private:
54 uint _offset;
55};
56
57class RLEMap : public QMap<RLEData, uint>
58{
59public:
60 RLEMap()
61 : _counter(0)
62 , _offset(0)
63 {
64 }
65 uint insert(const uchar *d, uint l);
67 void setBaseOffset(uint o)
68 {
69 _offset = o;
70 }
71
72private:
73 uint _counter;
74 uint _offset;
75};
76
77class SGIImagePrivate
78{
79public:
80 SGIImagePrivate();
81 ~SGIImagePrivate();
82
83 bool readImage(QImage &);
84 bool writeImage(const QImage &);
85
86 bool isValid() const;
87 bool isSupported() const;
88
89 bool peekHeader(QIODevice *device);
90
91 QSize size() const;
92 QImage::Format format() const;
93
94 void setDevice(QIODevice *device);
95
96private:
97 enum {
98 NORMAL,
99 DITHERED,
100 SCREEN,
101 COLORMAP,
102 }; // colormap
103 QIODevice *_dev;
104 QDataStream _stream;
105
106 quint16 _magic = 0;
107 quint8 _rle = 0;
108 quint8 _bpc = 0;
109 quint16 _dim = 0;
110 quint16 _xsize = 0;
111 quint16 _ysize = 0;
112 quint16 _zsize = 0;
113 quint32 _pixmin = 0;
114 quint32 _pixmax = 0;
115 char _imagename[80];
116 quint32 _colormap = 0;
117 quint8 _unused[404];
118 quint32 _unused32 = 0;
119
120 quint32 *_starttab;
121 quint32 *_lengthtab;
122 QByteArray _data;
123 QByteArray::Iterator _pos;
124 RLEMap _rlemap;
125 QList<const RLEData *> _rlevector;
126 uint _numrows;
127
128 bool readData(QImage &);
129 bool getRow(uchar *dest);
130 bool readHeader();
131
132 static bool readHeader(QDataStream &ds, SGIImagePrivate *sgi);
133
134 bool writeHeader();
135 bool writeRle();
136 bool writeVerbatim(const QImage &);
137 bool scanData(const QImage &);
138 uint compact(uchar *, uchar *);
139 uchar intensity(uchar);
140};
141
142SGIImagePrivate::SGIImagePrivate()
143 : _dev(nullptr)
144 , _starttab(nullptr)
145 , _lengthtab(nullptr)
146{
147 std::memset(_imagename, 0, sizeof(_imagename));
148 std::memset(_unused, 0, sizeof(_unused));
149}
150
151SGIImagePrivate::~SGIImagePrivate()
152{
153 delete[] _starttab;
154 delete[] _lengthtab;
155}
156
157///////////////////////////////////////////////////////////////////////////////
158
159void SGIImagePrivate::setDevice(QIODevice *device)
160{
161 _dev = device;
162 _stream.setDevice(_dev);
163}
164
165bool SGIImagePrivate::getRow(uchar *dest)
166{
167 int n;
168 int i;
169 if (!_rle) {
170 for (i = 0; i < _xsize; i++) {
171 if (_pos >= _data.end()) {
172 return false;
173 }
174 dest[i] = uchar(*_pos);
175 _pos += _bpc;
176 }
177 return true;
178 }
179
180 for (i = 0; i < _xsize;) {
181 if (_bpc == 2) {
182 _pos++;
183 }
184 if (_pos >= _data.end()) {
185 return false;
186 }
187 n = *_pos & 0x7f;
188 if (!n) {
189 break;
190 }
191
192 if (*_pos++ & 0x80) {
193 for (; i < _xsize && _pos < _data.end() && n--; i++) {
194 *dest++ = *_pos;
195 _pos += _bpc;
196 }
197 } else {
198 for (; i < _xsize && n--; i++) {
199 *dest++ = *_pos;
200 }
201
202 _pos += _bpc;
203 }
204 }
205 return i == _xsize;
206}
207
208bool SGIImagePrivate::readData(QImage &img)
209{
210 QRgb *c;
211 quint32 *start = _starttab;
212 QByteArray lguard(_xsize, 0);
213 uchar *line = (uchar *)lguard.data();
214 unsigned x;
215 unsigned y;
216
217 if (!_rle) {
218 _pos = _data.begin();
219 }
220
221 for (y = 0; y < _ysize; y++) {
222 if (_rle) {
223 _pos = _data.begin() + *start++;
224 }
225 if (!getRow(line)) {
226 return false;
227 }
228 c = (QRgb *)img.scanLine(_ysize - y - 1);
229 for (x = 0; x < _xsize; x++, c++) {
230 *c = qRgb(line[x], line[x], line[x]);
231 }
232 }
233
234 if (_zsize == 1) {
235 return true;
236 }
237
238 if (_zsize != 2) {
239 for (y = 0; y < _ysize; y++) {
240 if (_rle) {
241 _pos = _data.begin() + *start++;
242 }
243 if (!getRow(line)) {
244 return false;
245 }
246 c = (QRgb *)img.scanLine(_ysize - y - 1);
247 for (x = 0; x < _xsize; x++, c++) {
248 *c = qRgb(qRed(*c), line[x], line[x]);
249 }
250 }
251
252 for (y = 0; y < _ysize; y++) {
253 if (_rle) {
254 _pos = _data.begin() + *start++;
255 }
256 if (!getRow(line)) {
257 return false;
258 }
259 c = (QRgb *)img.scanLine(_ysize - y - 1);
260 for (x = 0; x < _xsize; x++, c++) {
261 *c = qRgb(qRed(*c), qGreen(*c), line[x]);
262 }
263 }
264
265 if (_zsize == 3) {
266 return true;
267 }
268 }
269
270 for (y = 0; y < _ysize; y++) {
271 if (_rle) {
272 _pos = _data.begin() + *start++;
273 }
274 if (!getRow(line)) {
275 return false;
276 }
277 c = (QRgb *)img.scanLine(_ysize - y - 1);
278 for (x = 0; x < _xsize; x++, c++) {
279 *c = qRgba(qRed(*c), qGreen(*c), qBlue(*c), line[x]);
280 }
281 }
282
283 return true;
284}
285
286bool SGIImagePrivate::readImage(QImage &img)
287{
288 if (!readHeader() || !isSupported()) {
289 return false;
290 }
291
292 if (_stream.atEnd()) {
293 return false;
294 }
295
296 img = imageAlloc(size(), format());
297 if (img.isNull()) {
298 qWarning() << "Failed to allocate image, invalid dimensions?" << QSize(_xsize, _ysize);
299 return false;
300 }
301
302 if (_zsize > 4) {
303 // qDebug() << "using first 4 of " << _zsize << " channels";
304 // Only let this continue if it won't cause a int overflow later
305 // this is most likely a broken file anyway
306 if (_ysize > std::numeric_limits<int>::max() / _zsize) {
307 return false;
308 }
309 }
310
311 _numrows = _ysize * _zsize;
312
313 if (_rle) {
314 uint l;
315 _starttab = new quint32[_numrows];
316 for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
317 _stream >> _starttab[l];
318 _starttab[l] -= 512 + _numrows * 2 * sizeof(quint32);
319 }
320 for (; l < _numrows; l++) {
321 _starttab[l] = 0;
322 }
323
324 _lengthtab = new quint32[_numrows];
325 for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
326 _stream >> _lengthtab[l];
327 }
328 }
329
330 if (_stream.status() != QDataStream::Ok) {
331 return false;
332 }
333
334 _data = _dev->readAll();
335
336 // sanity check
337 if (_rle) {
338 for (uint o = 0; o < _numrows; o++) {
339 // don't change to greater-or-equal!
340 if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
341 // qDebug() << "image corrupt (sanity check failed)";
342 return false;
343 }
344 }
345 }
346
347 if (!readData(img)) {
348 // qDebug() << "image corrupt (incomplete scanline)";
349 return false;
350 }
351
352 return true;
353}
354
355///////////////////////////////////////////////////////////////////////////////
356
357void RLEData::write(QDataStream &s)
358{
359 for (int i = 0; i < size(); i++) {
360 s << at(i);
361 }
362}
363
364bool RLEData::operator<(const RLEData &b) const
365{
366 uchar ac;
367 uchar bc;
368 for (int i = 0; i < qMin(size(), b.size()); i++) {
369 ac = at(i);
370 bc = b[i];
371 if (ac != bc) {
372 return ac < bc;
373 }
374 }
375 return size() < b.size();
376}
377
378uint RLEMap::insert(const uchar *d, uint l)
379{
380 RLEData data = RLEData(d, l, _offset);
381 Iterator it = find(data);
382 if (it != end()) {
383 return it.value();
384 }
385
386 _offset += l;
387 return QMap<RLEData, uint>::insert(data, _counter++).value();
388}
389
390QList<const RLEData *> RLEMap::vector()
391{
393 for (Iterator it = begin(); it != end(); ++it) {
394 v.replace(it.value(), &it.key());
395 }
396
397 return v;
398}
399
400uchar SGIImagePrivate::intensity(uchar c)
401{
402 if (c < _pixmin) {
403 _pixmin = c;
404 }
405 if (c > _pixmax) {
406 _pixmax = c;
407 }
408 return c;
409}
410
411uint SGIImagePrivate::compact(uchar *d, uchar *s)
412{
413 uchar *dest = d;
414 uchar *src = s;
415 uchar patt;
416 uchar *t;
417 uchar *end = s + _xsize;
418 int i;
419 int n;
420 while (src < end) {
421 for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++) {
422 n++;
423 }
424
425 while (n) {
426 i = n > 126 ? 126 : n;
427 n -= i;
428 *dest++ = 0x80 | i;
429 while (i--) {
430 *dest++ = *src++;
431 }
432 }
433
434 if (src == end) {
435 break;
436 }
437
438 patt = *src++;
439 for (n = 1; src < end && *src == patt; src++) {
440 n++;
441 }
442
443 while (n) {
444 i = n > 126 ? 126 : n;
445 n -= i;
446 *dest++ = i;
447 *dest++ = patt;
448 }
449 }
450 *dest++ = 0;
451 return dest - d;
452}
453
454bool SGIImagePrivate::scanData(const QImage &img)
455{
456 quint32 *start = _starttab;
457 QByteArray lineguard(_xsize * 2, 0);
458 QByteArray bufguard(_xsize, 0);
459 uchar *line = (uchar *)lineguard.data();
460 uchar *buf = (uchar *)bufguard.data();
461 const QRgb *c;
462 unsigned x;
463 unsigned y;
464 uint len;
465
466 for (y = 0; y < _ysize; y++) {
467 const int yPos = _ysize - y - 1; // scanline doesn't do any sanity checking
468 if (yPos >= img.height()) {
469 qWarning() << "Failed to get scanline for" << yPos;
470 return false;
471 }
472
473 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
474
475 for (x = 0; x < _xsize; x++) {
476 buf[x] = intensity(qRed(*c++));
477 }
478 len = compact(line, buf);
479 *start++ = _rlemap.insert(line, len);
480 }
481
482 if (_zsize == 1) {
483 return true;
484 }
485
486 if (_zsize != 2) {
487 for (y = 0; y < _ysize; y++) {
488 const int yPos = _ysize - y - 1;
489 if (yPos >= img.height()) {
490 qWarning() << "Failed to get scanline for" << yPos;
491 return false;
492 }
493
494 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
495 for (x = 0; x < _xsize; x++) {
496 buf[x] = intensity(qGreen(*c++));
497 }
498 len = compact(line, buf);
499 *start++ = _rlemap.insert(line, len);
500 }
501
502 for (y = 0; y < _ysize; y++) {
503 const int yPos = _ysize - y - 1;
504 if (yPos >= img.height()) {
505 qWarning() << "Failed to get scanline for" << yPos;
506 return false;
507 }
508
509 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
510 for (x = 0; x < _xsize; x++) {
511 buf[x] = intensity(qBlue(*c++));
512 }
513 len = compact(line, buf);
514 *start++ = _rlemap.insert(line, len);
515 }
516
517 if (_zsize == 3) {
518 return true;
519 }
520 }
521
522 for (y = 0; y < _ysize; y++) {
523 const int yPos = _ysize - y - 1;
524 if (yPos >= img.height()) {
525 qWarning() << "Failed to get scanline for" << yPos;
526 return false;
527 }
528
529 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
530 for (x = 0; x < _xsize; x++) {
531 buf[x] = intensity(qAlpha(*c++));
532 }
533 len = compact(line, buf);
534 *start++ = _rlemap.insert(line, len);
535 }
536
537 return true;
538}
539
540bool SGIImagePrivate::isValid() const
541{
542 // File signature/magic number
543 if (_magic != 0x01da) {
544 return false;
545 }
546 // Compression, 0 = Uncompressed, 1 = RLE compressed
547 if (_rle > 1) {
548 return false;
549 }
550 // Bytes per pixel, 1 = 8 bit, 2 = 16 bit
551 if (_bpc != 1 && _bpc != 2) {
552 return false;
553 }
554 // Image dimension, 3 for RGBA image
555 if (_dim < 1 || _dim > 3) {
556 return false;
557 }
558 // Number channels in the image file, 4 for RGBA image
559 if (_zsize < 1) {
560 return false;
561 }
562 return true;
563}
564
565bool SGIImagePrivate::isSupported() const
566{
567 if (!isValid()) {
568 return false;
569 }
570 if (_colormap != NORMAL) {
571 return false; // only NORMAL supported
572 }
573 if (_dim == 1) {
574 return false;
575 }
576 return true;
577}
578
579bool SGIImagePrivate::peekHeader(QIODevice *device)
580{
581 QDataStream ds(device->peek(512));
582 return SGIImagePrivate::readHeader(ds, this) && isValid();
583}
584
585QSize SGIImagePrivate::size() const
586{
587 return QSize(_xsize, _ysize);
588}
589
590QImage::Format SGIImagePrivate::format() const
591{
592 if (_zsize == 2 || _zsize == 4) {
594 }
596}
597
598bool SGIImagePrivate::readHeader()
599{
600 return readHeader(_stream, this);
601}
602
603bool SGIImagePrivate::readHeader(QDataStream &ds, SGIImagePrivate *sgi)
604{
605 // magic
606 ds >> sgi->_magic;
607
608 // verbatim/rle
609 ds >> sgi->_rle;
610
611 // bytes per channel
612 ds >> sgi->_bpc;
613
614 // number of dimensions
615 ds >> sgi->_dim;
616
617 ds >> sgi->_xsize >> sgi->_ysize >> sgi->_zsize >> sgi->_pixmin >> sgi->_pixmax >> sgi->_unused32;
618
619 // name
620 ds.readRawData(sgi->_imagename, 80);
621 sgi->_imagename[79] = '\0';
622
623 ds >> sgi->_colormap;
624
625 for (size_t i = 0; i < sizeof(_unused); i++) {
626 ds >> sgi->_unused[i];
627 }
628
629 return ds.status() == QDataStream::Ok;
630}
631
632bool SGIImagePrivate::writeHeader()
633{
634 _stream << _magic;
635 _stream << _rle << _bpc << _dim;
636 _stream << _xsize << _ysize << _zsize;
637 _stream << _pixmin << _pixmax;
638 _stream << _unused32;
639
640 for (int i = 0; i < 80; i++) {
641 _imagename[i] = '\0';
642 }
643 _stream.writeRawData(_imagename, 80);
644
645 _stream << _colormap;
646 for (size_t i = 0; i < sizeof(_unused); i++) {
647 _stream << _unused[i];
648 }
649 return _stream.status() == QDataStream::Ok;
650}
651
652bool SGIImagePrivate::writeRle()
653{
654 _rle = 1;
655 // qDebug() << "writing RLE data";
656 if (!writeHeader()) {
657 return false;
658 }
659
660 uint i;
661
662 // write start table
663 for (i = 0; i < _numrows; i++) {
664 _stream << quint32(_rlevector[_starttab[i]]->offset());
665 }
666
667 // write length table
668 for (i = 0; i < _numrows; i++) {
669 _stream << quint32(_rlevector[_starttab[i]]->size());
670 }
671
672 // write data
673 for (i = 0; (int)i < _rlevector.size(); i++) {
674 const_cast<RLEData *>(_rlevector[i])->write(_stream);
675 }
676
677 return _stream.status() == QDataStream::Ok;
678}
679
680bool SGIImagePrivate::writeVerbatim(const QImage &img)
681{
682 _rle = 0;
683 if (!writeHeader()) {
684 return false;
685 }
686
687 const QRgb *c;
688 unsigned x;
689 unsigned y;
690
691 for (y = 0; y < _ysize; y++) {
692 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
693 for (x = 0; x < _xsize; x++) {
694 _stream << quint8(qRed(*c++));
695 }
696 }
697
698 if (_zsize == 1) {
699 return _stream.status() == QDataStream::Ok;
700 }
701
702 if (_zsize != 2) {
703 for (y = 0; y < _ysize; y++) {
704 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
705 for (x = 0; x < _xsize; x++) {
706 _stream << quint8(qGreen(*c++));
707 }
708 }
709
710 for (y = 0; y < _ysize; y++) {
711 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
712 for (x = 0; x < _xsize; x++) {
713 _stream << quint8(qBlue(*c++));
714 }
715 }
716
717 if (_zsize == 3) {
718 return _stream.status() == QDataStream::Ok;
719 }
720 }
721
722 for (y = 0; y < _ysize; y++) {
723 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
724 for (x = 0; x < _xsize; x++) {
725 _stream << quint8(qAlpha(*c++));
726 }
727 }
728
729 return _stream.status() == QDataStream::Ok;
730}
731
732bool SGIImagePrivate::writeImage(const QImage &image)
733{
734 // qDebug() << "writing "; // TODO add filename
735 QImage img = image;
736 if (img.allGray()) {
737 _dim = 2, _zsize = 1;
738 } else {
739 _dim = 3, _zsize = 3;
740 }
741
742 auto hasAlpha = img.hasAlphaChannel();
743 if (hasAlpha) {
744 _dim = 3, _zsize++;
745 }
746
747 if (hasAlpha && img.format() != QImage::Format_ARGB32) {
749 } else if (!hasAlpha && img.format() != QImage::Format_RGB32) {
751 }
752 if (img.isNull()) {
753 // qDebug() << "can't convert image to depth 32";
754 return false;
755 }
756
757 const int w = img.width();
758 const int h = img.height();
759
760 if (w > 65535 || h > 65535) {
761 return false;
762 }
763
764 _magic = 0x01da;
765 _bpc = 1;
766 _xsize = w;
767 _ysize = h;
768 _pixmin = ~0u;
769 _pixmax = 0;
770 _colormap = NORMAL;
771 _numrows = _ysize * _zsize;
772 _starttab = new quint32[_numrows];
773 _rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
774
775 if (!scanData(img)) {
776 // qDebug() << "this can't happen";
777 return false;
778 }
779
780 _rlevector = _rlemap.vector();
781
782 long verbatim_size = _numrows * _xsize;
783 long rle_size = _numrows * 2 * sizeof(quint32);
784 for (int i = 0; i < _rlevector.size(); i++) {
785 rle_size += _rlevector[i]->size();
786 }
787
788 if (verbatim_size <= rle_size) {
789 return writeVerbatim(img);
790 }
791 return writeRle();
792}
793
794///////////////////////////////////////////////////////////////////////////////
795
796RGBHandler::RGBHandler()
798 , d(new SGIImagePrivate)
799{
800}
801
802bool RGBHandler::canRead() const
803{
804 if (canRead(device())) {
805 setFormat("rgb");
806 return true;
807 }
808 return false;
809}
810
811bool RGBHandler::read(QImage *outImage)
812{
813 d->setDevice(device());
814 return d->readImage(*outImage);
815}
816
817bool RGBHandler::write(const QImage &image)
818{
819 d->setDevice(device());
820 return d->writeImage(image);
821}
822
823bool RGBHandler::supportsOption(ImageOption option) const
824{
825 if (option == QImageIOHandler::Size) {
826 return true;
827 }
828 if (option == QImageIOHandler::ImageFormat) {
829 return true;
830 }
831 return false;
832}
833
834QVariant RGBHandler::option(ImageOption option) const
835{
836 QVariant v;
837
838 if (option == QImageIOHandler::Size) {
839 auto &&sgi = d;
840 if (sgi->isSupported()) {
841 v = QVariant::fromValue(sgi->size());
842 } else if (auto dev = device()) {
843 if (d->peekHeader(dev) && sgi->isSupported()) {
844 v = QVariant::fromValue(sgi->size());
845 }
846 }
847 }
848
849 if (option == QImageIOHandler::ImageFormat) {
850 auto &&sgi = d;
851 if (sgi->isSupported()) {
852 v = QVariant::fromValue(sgi->format());
853 } else if (auto dev = device()) {
854 if (d->peekHeader(dev) && sgi->isSupported()) {
855 v = QVariant::fromValue(sgi->format());
856 }
857 }
858 }
859
860 return v;
861}
862
863bool RGBHandler::canRead(QIODevice *device)
864{
865 if (!device) {
866 qWarning("RGBHandler::canRead() called with no device");
867 return false;
868 }
869
870 SGIImagePrivate sgi;
871 return sgi.peekHeader(device) && sgi.isSupported();
872}
873
874///////////////////////////////////////////////////////////////////////////////
875
876QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const
877{
878 if (format == "rgb" || format == "rgba" || format == "bw" || format == "sgi") {
879 return Capabilities(CanRead | CanWrite);
880 }
881 if (!format.isEmpty()) {
882 return {};
883 }
884 if (!device->isOpen()) {
885 return {};
886 }
887
888 Capabilities cap;
889 if (device->isReadable() && RGBHandler::canRead(device)) {
890 cap |= CanRead;
891 }
892 if (device->isWritable()) {
893 cap |= CanWrite;
894 }
895 return cap;
896}
897
898QImageIOHandler *RGBPlugin::create(QIODevice *device, const QByteArray &format) const
899{
900 QImageIOHandler *handler = new RGBHandler;
901 handler->setDevice(device);
902 handler->setFormat(format);
903 return handler;
904}
905
906#include "moc_rgb_p.cpp"
Q_SCRIPTABLE Q_NOREPLY void start()
QFlags< Capability > Capabilities
const QList< QKeySequence > & end()
iterator begin()
iterator end()
bool isEmpty() const const
qsizetype size() const const
bool atEnd() const const
int readRawData(char *s, int len)
void setDevice(QIODevice *d)
Status status() const const
int writeRawData(const char *s, int len)
bool allGray() const const
QImage convertToFormat(Format format, Qt::ImageConversionFlags flags) &&
Format format() const const
bool hasAlphaChannel() const const
int height() const const
bool isNull() const const
uchar * scanLine(int i)
int width() const const
void setDevice(QIODevice *device)
void setFormat(const QByteArray &format)
bool isOpen() const const
bool isReadable() const const
bool isWritable() const const
QByteArray peek(qint64 maxSize)
QByteArray readAll()
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype size() const const
iterator find(const Key &key)
iterator insert(const Key &key, const T &value)
size_type size() const const
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:15:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.