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 <QColorSpace>
28#include <QDebug>
29#include <QImage>
30#include <QList>
31#include <QMap>
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 = reinterpret_cast<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 = reinterpret_cast<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 = reinterpret_cast<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 = reinterpret_cast<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 if (_stream.status() != QDataStream::Ok) {
320 return false;
321 }
322 }
323 for (; l < _numrows; l++) {
324 _starttab[l] = 0;
325 }
326
327 _lengthtab = new quint32[_numrows];
328 for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
329 _stream >> _lengthtab[l];
330 if (_stream.status() != QDataStream::Ok) {
331 return false;
332 }
333 }
334 }
335
336 if (_stream.status() != QDataStream::Ok) {
337 return false;
338 }
339
340 _data = _dev->readAll();
341
342 // sanity check
343 if (_rle) {
344 for (uint o = 0; o < _numrows; o++) {
345 // don't change to greater-or-equal!
346 if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
347 // qDebug() << "image corrupt (sanity check failed)";
348 return false;
349 }
350 }
351 }
352
353 if (!readData(img)) {
354 // qDebug() << "image corrupt (incomplete scanline)";
355 return false;
356 }
357
358 return true;
359}
360
361///////////////////////////////////////////////////////////////////////////////
362
363void RLEData::write(QDataStream &s)
364{
365 for (int i = 0; i < size(); i++) {
366 s << at(i);
367 }
368}
369
370bool RLEData::operator<(const RLEData &b) const
371{
372 uchar ac;
373 uchar bc;
374 for (int i = 0; i < qMin(size(), b.size()); i++) {
375 ac = at(i);
376 bc = b[i];
377 if (ac != bc) {
378 return ac < bc;
379 }
380 }
381 return size() < b.size();
382}
383
384uint RLEMap::insert(const uchar *d, uint l)
385{
386 RLEData data = RLEData(d, l, _offset);
387 Iterator it = find(data);
388 if (it != end()) {
389 return it.value();
390 }
391
392 _offset += l;
393 return QMap<RLEData, uint>::insert(data, _counter++).value();
394}
395
396QList<const RLEData *> RLEMap::vector()
397{
399 for (Iterator it = begin(); it != end(); ++it) {
400 v.replace(it.value(), &it.key());
401 }
402
403 return v;
404}
405
406uchar SGIImagePrivate::intensity(uchar c)
407{
408 if (c < _pixmin) {
409 _pixmin = c;
410 }
411 if (c > _pixmax) {
412 _pixmax = c;
413 }
414 return c;
415}
416
417uint SGIImagePrivate::compact(uchar *d, uchar *s)
418{
419 uchar *dest = d;
420 uchar *src = s;
421 uchar patt;
422 uchar *t;
423 uchar *end = s + _xsize;
424 int i;
425 int n;
426 while (src < end) {
427 for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++) {
428 n++;
429 }
430
431 while (n) {
432 i = n > 126 ? 126 : n;
433 n -= i;
434 *dest++ = 0x80 | i;
435 while (i--) {
436 *dest++ = *src++;
437 }
438 }
439
440 if (src == end) {
441 break;
442 }
443
444 patt = *src++;
445 for (n = 1; src < end && *src == patt; src++) {
446 n++;
447 }
448
449 while (n) {
450 i = n > 126 ? 126 : n;
451 n -= i;
452 *dest++ = i;
453 *dest++ = patt;
454 }
455 }
456 *dest++ = 0;
457 return dest - d;
458}
459
460bool SGIImagePrivate::scanData(const QImage &img)
461{
462 quint32 *start = _starttab;
463 QByteArray lineguard(_xsize * 2, 0);
464 QByteArray bufguard(_xsize, 0);
465 uchar *line = (uchar *)lineguard.data();
466 uchar *buf = (uchar *)bufguard.data();
467 const QRgb *c;
468 unsigned x;
469 unsigned y;
470 uint len;
471
472 for (y = 0; y < _ysize; y++) {
473 const int yPos = _ysize - y - 1; // scanline doesn't do any sanity checking
474 if (yPos >= img.height()) {
475 qWarning() << "Failed to get scanline for" << yPos;
476 return false;
477 }
478
479 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
480
481 for (x = 0; x < _xsize; x++) {
482 buf[x] = intensity(qRed(*c++));
483 }
484 len = compact(line, buf);
485 *start++ = _rlemap.insert(line, len);
486 }
487
488 if (_zsize == 1) {
489 return true;
490 }
491
492 if (_zsize != 2) {
493 for (y = 0; y < _ysize; y++) {
494 const int yPos = _ysize - y - 1;
495 if (yPos >= img.height()) {
496 qWarning() << "Failed to get scanline for" << yPos;
497 return false;
498 }
499
500 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
501 for (x = 0; x < _xsize; x++) {
502 buf[x] = intensity(qGreen(*c++));
503 }
504 len = compact(line, buf);
505 *start++ = _rlemap.insert(line, len);
506 }
507
508 for (y = 0; y < _ysize; y++) {
509 const int yPos = _ysize - y - 1;
510 if (yPos >= img.height()) {
511 qWarning() << "Failed to get scanline for" << yPos;
512 return false;
513 }
514
515 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
516 for (x = 0; x < _xsize; x++) {
517 buf[x] = intensity(qBlue(*c++));
518 }
519 len = compact(line, buf);
520 *start++ = _rlemap.insert(line, len);
521 }
522
523 if (_zsize == 3) {
524 return true;
525 }
526 }
527
528 for (y = 0; y < _ysize; y++) {
529 const int yPos = _ysize - y - 1;
530 if (yPos >= img.height()) {
531 qWarning() << "Failed to get scanline for" << yPos;
532 return false;
533 }
534
535 c = reinterpret_cast<const QRgb *>(img.scanLine(yPos));
536 for (x = 0; x < _xsize; x++) {
537 buf[x] = intensity(qAlpha(*c++));
538 }
539 len = compact(line, buf);
540 *start++ = _rlemap.insert(line, len);
541 }
542
543 return true;
544}
545
546bool SGIImagePrivate::isValid() const
547{
548 // File signature/magic number
549 if (_magic != 0x01da) {
550 return false;
551 }
552 // Compression, 0 = Uncompressed, 1 = RLE compressed
553 if (_rle > 1) {
554 return false;
555 }
556 // Bytes per pixel, 1 = 8 bit, 2 = 16 bit
557 if (_bpc != 1 && _bpc != 2) {
558 return false;
559 }
560 // Image dimension, 3 for RGBA image
561 if (_dim < 1 || _dim > 3) {
562 return false;
563 }
564 // Number channels in the image file, 4 for RGBA image
565 if (_zsize < 1) {
566 return false;
567 }
568 return true;
569}
570
571bool SGIImagePrivate::isSupported() const
572{
573 if (!isValid()) {
574 return false;
575 }
576 if (_colormap != NORMAL) {
577 return false; // only NORMAL supported
578 }
579 if (_dim == 1) {
580 return false;
581 }
582 return true;
583}
584
585bool SGIImagePrivate::peekHeader(QIODevice *device)
586{
587 QDataStream ds(device->peek(512));
588 return SGIImagePrivate::readHeader(ds, this) && isValid();
589}
590
591QSize SGIImagePrivate::size() const
592{
593 return QSize(_xsize, _ysize);
594}
595
596QImage::Format SGIImagePrivate::format() const
597{
598 if (_zsize == 2 || _zsize == 4) {
600 }
602}
603
604bool SGIImagePrivate::readHeader()
605{
606 return readHeader(_stream, this);
607}
608
609bool SGIImagePrivate::readHeader(QDataStream &ds, SGIImagePrivate *sgi)
610{
611 // magic
612 ds >> sgi->_magic;
613
614 // verbatim/rle
615 ds >> sgi->_rle;
616
617 // bytes per channel
618 ds >> sgi->_bpc;
619
620 // number of dimensions
621 ds >> sgi->_dim;
622
623 ds >> sgi->_xsize >> sgi->_ysize >> sgi->_zsize >> sgi->_pixmin >> sgi->_pixmax >> sgi->_unused32;
624
625 // name
626 ds.readRawData(sgi->_imagename, 80);
627 sgi->_imagename[79] = '\0';
628
629 ds >> sgi->_colormap;
630
631 for (size_t i = 0; i < sizeof(_unused); i++) {
632 ds >> sgi->_unused[i];
633 }
634
635 return ds.status() == QDataStream::Ok;
636}
637
638bool SGIImagePrivate::writeHeader()
639{
640 _stream << _magic;
641 _stream << _rle << _bpc << _dim;
642 _stream << _xsize << _ysize << _zsize;
643 _stream << _pixmin << _pixmax;
644 _stream << _unused32;
645
646 for (int i = 0; i < 80; i++) {
647 _imagename[i] = '\0';
648 }
649 _stream.writeRawData(_imagename, 80);
650
651 _stream << _colormap;
652 for (size_t i = 0; i < sizeof(_unused); i++) {
653 _stream << _unused[i];
654 }
655 return _stream.status() == QDataStream::Ok;
656}
657
658bool SGIImagePrivate::writeRle()
659{
660 _rle = 1;
661 // qDebug() << "writing RLE data";
662 if (!writeHeader()) {
663 return false;
664 }
665
666 uint i;
667
668 // write start table
669 for (i = 0; i < _numrows; i++) {
670 _stream << quint32(_rlevector[_starttab[i]]->offset());
671 }
672
673 // write length table
674 for (i = 0; i < _numrows; i++) {
675 _stream << quint32(_rlevector[_starttab[i]]->size());
676 }
677
678 // write data
679 for (i = 0; (int)i < _rlevector.size(); i++) {
680 const_cast<RLEData *>(_rlevector[i])->write(_stream);
681 }
682
683 return _stream.status() == QDataStream::Ok;
684}
685
686bool SGIImagePrivate::writeVerbatim(const QImage &img)
687{
688 _rle = 0;
689 if (!writeHeader()) {
690 return false;
691 }
692
693 const QRgb *c;
694 unsigned x;
695 unsigned y;
696
697 for (y = 0; y < _ysize; y++) {
698 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
699 for (x = 0; x < _xsize; x++) {
700 _stream << quint8(qRed(*c++));
701 }
702 }
703
704 if (_zsize == 1) {
705 return _stream.status() == QDataStream::Ok;
706 }
707
708 if (_zsize != 2) {
709 for (y = 0; y < _ysize; y++) {
710 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
711 for (x = 0; x < _xsize; x++) {
712 _stream << quint8(qGreen(*c++));
713 }
714 }
715
716 for (y = 0; y < _ysize; y++) {
717 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
718 for (x = 0; x < _xsize; x++) {
719 _stream << quint8(qBlue(*c++));
720 }
721 }
722
723 if (_zsize == 3) {
724 return _stream.status() == QDataStream::Ok;
725 }
726 }
727
728 for (y = 0; y < _ysize; y++) {
729 c = reinterpret_cast<const QRgb *>(img.scanLine(_ysize - y - 1));
730 for (x = 0; x < _xsize; x++) {
731 _stream << quint8(qAlpha(*c++));
732 }
733 }
734
735 return _stream.status() == QDataStream::Ok;
736}
737
738bool SGIImagePrivate::writeImage(const QImage &image)
739{
740 // qDebug() << "writing "; // TODO add filename
741 QImage img = image;
742 if (img.allGray()) {
743 _dim = 2, _zsize = 1;
744 } else {
745 _dim = 3, _zsize = 3;
746 }
747
748 auto hasAlpha = img.hasAlphaChannel();
749 if (hasAlpha) {
750 _dim = 3, _zsize++;
751 }
752
753#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
754 auto cs = image.colorSpace();
755 if (cs.isValid() && cs.colorModel() == QColorSpace::ColorModel::Cmyk && image.format() == QImage::Format_CMYK8888) {
757 } else if (hasAlpha && img.format() != QImage::Format_ARGB32) {
758#else
759 if (hasAlpha && img.format() != QImage::Format_ARGB32) {
760#endif
762 } else if (!hasAlpha && img.format() != QImage::Format_RGB32) {
764 }
765 if (img.isNull()) {
766 // qDebug() << "can't convert image to depth 32";
767 return false;
768 }
769
770 const int w = img.width();
771 const int h = img.height();
772
773 if (w > 65535 || h > 65535) {
774 return false;
775 }
776
777 _magic = 0x01da;
778 _bpc = 1;
779 _xsize = w;
780 _ysize = h;
781 _pixmin = ~0u;
782 _pixmax = 0;
783 _colormap = NORMAL;
784 _numrows = _ysize * _zsize;
785 _starttab = new quint32[_numrows];
786 _rlemap.setBaseOffset(512 + _numrows * 2 * sizeof(quint32));
787
788 if (!scanData(img)) {
789 // qDebug() << "this can't happen";
790 return false;
791 }
792
793 _rlevector = _rlemap.vector();
794
795 long verbatim_size = _numrows * _xsize;
796 long rle_size = _numrows * 2 * sizeof(quint32);
797 for (int i = 0; i < _rlevector.size(); i++) {
798 rle_size += _rlevector[i]->size();
799 }
800
801 if (verbatim_size <= rle_size) {
802 return writeVerbatim(img);
803 }
804 return writeRle();
805}
806
807///////////////////////////////////////////////////////////////////////////////
808
809RGBHandler::RGBHandler()
811 , d(new SGIImagePrivate)
812{
813}
814
815bool RGBHandler::canRead() const
816{
817 if (canRead(device())) {
818 setFormat("rgb");
819 return true;
820 }
821 return false;
822}
823
824bool RGBHandler::read(QImage *outImage)
825{
826 d->setDevice(device());
827 return d->readImage(*outImage);
828}
829
830bool RGBHandler::write(const QImage &image)
831{
832 d->setDevice(device());
833 return d->writeImage(image);
834}
835
836bool RGBHandler::supportsOption(ImageOption option) const
837{
838 if (option == QImageIOHandler::Size) {
839 return true;
840 }
841 if (option == QImageIOHandler::ImageFormat) {
842 return true;
843 }
844 return false;
845}
846
847QVariant RGBHandler::option(ImageOption option) const
848{
849 QVariant v;
850
851 if (option == QImageIOHandler::Size) {
852 auto &&sgi = d;
853 if (sgi->isSupported()) {
854 v = QVariant::fromValue(sgi->size());
855 } else if (auto dev = device()) {
856 if (d->peekHeader(dev) && sgi->isSupported()) {
857 v = QVariant::fromValue(sgi->size());
858 }
859 }
860 }
861
862 if (option == QImageIOHandler::ImageFormat) {
863 auto &&sgi = d;
864 if (sgi->isSupported()) {
865 v = QVariant::fromValue(sgi->format());
866 } else if (auto dev = device()) {
867 if (d->peekHeader(dev) && sgi->isSupported()) {
868 v = QVariant::fromValue(sgi->format());
869 }
870 }
871 }
872
873 return v;
874}
875
876bool RGBHandler::canRead(QIODevice *device)
877{
878 if (!device) {
879 qWarning("RGBHandler::canRead() called with no device");
880 return false;
881 }
882
883 SGIImagePrivate sgi;
884 return sgi.peekHeader(device) && sgi.isSupported();
885}
886
887///////////////////////////////////////////////////////////////////////////////
888
889QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device, const QByteArray &format) const
890{
891 if (format == "rgb" || format == "rgba" || format == "bw" || format == "sgi") {
892 return Capabilities(CanRead | CanWrite);
893 }
894 if (!format.isEmpty()) {
895 return {};
896 }
897 if (!device->isOpen()) {
898 return {};
899 }
900
901 Capabilities cap;
902 if (device->isReadable() && RGBHandler::canRead(device)) {
903 cap |= CanRead;
904 }
905 if (device->isWritable()) {
906 cap |= CanWrite;
907 }
908 return cap;
909}
910
911QImageIOHandler *RGBPlugin::create(QIODevice *device, const QByteArray &format) const
912{
913 QImageIOHandler *handler = new RGBHandler;
914 handler->setDevice(device);
915 handler->setFormat(format);
916 return handler;
917}
918
919#include "moc_rgb_p.cpp"
Q_SCRIPTABLE Q_NOREPLY void start()
QFlags< Capability > Capabilities
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
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
QColorSpace colorSpace() const const
QImage convertToFormat(Format format, Qt::ImageConversionFlags flags) &&
QImage convertedToColorSpace(const QColorSpace &colorSpace) const const
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 Nov 29 2024 11:57:32 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.