31class RLEData :
public QList<uchar>
37 RLEData(
const uchar *d, uint l, uint o)
40 for (uint i = 0; i < l; i++) {
44 bool operator<(
const RLEData &)
const;
55class RLEMap :
public QMap<RLEData, uint>
63 uint insert(
const uchar *d, uint l);
65 void setBaseOffset(uint o)
82 bool writeImage(
const QImage &);
108 QByteArray::Iterator _pos;
114 bool getRow(uchar *dest);
118 void writeVerbatim(
const QImage &);
119 bool scanData(
const QImage &);
120 uint compact(uchar *, uchar *);
121 uchar intensity(uchar);
126 , _lengthtab(nullptr)
129 _stream.setDevice(_dev);
140bool SGIImage::getRow(uchar *dest)
145 for (i = 0; i < _xsize; i++) {
146 if (_pos >= _data.
end()) {
149 dest[i] = uchar(*_pos);
155 for (i = 0; i < _xsize;) {
159 if (_pos >= _data.
end()) {
167 if (*_pos++ & 0x80) {
168 for (; i < _xsize && _pos < _data.
end() && n--; i++) {
173 for (; i < _xsize && n--; i++) {
183bool SGIImage::readData(
QImage &img)
186 quint32 *
start = _starttab;
188 uchar *line = (uchar *)lguard.data();
193 _pos = _data.
begin();
196 for (y = 0; y < _ysize; y++) {
203 c = (QRgb *)img.
scanLine(_ysize - y - 1);
204 for (x = 0; x < _xsize; x++, c++) {
205 *c = qRgb(line[x], line[x], line[x]);
214 for (y = 0; y < _ysize; y++) {
221 c = (QRgb *)img.
scanLine(_ysize - y - 1);
222 for (x = 0; x < _xsize; x++, c++) {
223 *c = qRgb(qRed(*c), line[x], line[x]);
227 for (y = 0; y < _ysize; y++) {
234 c = (QRgb *)img.
scanLine(_ysize - y - 1);
235 for (x = 0; x < _xsize; x++, c++) {
236 *c = qRgb(qRed(*c), qGreen(*c), line[x]);
245 for (y = 0; y < _ysize; y++) {
252 c = (QRgb *)img.
scanLine(_ysize - y - 1);
253 for (x = 0; x < _xsize; x++, c++) {
254 *c = qRgba(qRed(*c), qGreen(*c), qBlue(*c), line[x]);
261bool SGIImage::readImage(
QImage &img)
287 }
else if (_bpc == 2) {
296 if (_dim < 1 || _dim > 3) {
300 _stream >> _xsize >> _ysize >> _zsize >> _pixmin >> _pixmax >> u32;
307 _imagename[79] =
'\0';
309 _stream >> _colormap;
311 if (_colormap != NORMAL) {
315 for (
int i = 0; i < 404; i++) {
324 if (_stream.
atEnd()) {
330 qWarning() <<
"Failed to allocate image, invalid dimensions?" <<
QSize(_xsize, _ysize);
338 if (_zsize == 2 || _zsize == 4) {
340 }
else if (_zsize > 4) {
344 if (_ysize > std::numeric_limits<int>::max() / _zsize) {
349 _numrows = _ysize * _zsize;
353 _starttab =
new quint32[_numrows];
354 for (l = 0; !_stream.
atEnd() && l < _numrows; l++) {
355 _stream >> _starttab[l];
356 _starttab[l] -= 512 + _numrows * 2 *
sizeof(quint32);
358 for (; l < _numrows; l++) {
362 _lengthtab =
new quint32[_numrows];
363 for (l = 0; l < _numrows; l++) {
364 _stream >> _lengthtab[l];
372 for (uint o = 0; o < _numrows; o++) {
374 if (_starttab[o] + _lengthtab[o] > (uint)_data.
size()) {
381 if (!readData(img)) {
393 for (
int i = 0; i <
size(); i++) {
398bool RLEData::operator<(
const RLEData &b)
const
402 for (
int i = 0; i < qMin(
size(), b.
size()); i++) {
412uint RLEMap::insert(
const uchar *d, uint l)
414 RLEData data = RLEData(d, l, _offset);
415 Iterator it =
find(data);
427 for (Iterator it =
begin(); it !=
end(); ++it) {
428 v.replace(it.value(), &it.key());
434uchar SGIImage::intensity(uchar c)
445uint SGIImage::compact(uchar *d, uchar *s)
451 uchar *
end = s + _xsize;
455 for (n = 0, t = src; t + 2 <
end && !(*t == t[1] && *t == t[2]); t++) {
460 i = n > 126 ? 126 : n;
473 for (n = 1; src <
end && *src == patt; src++) {
478 i = n > 126 ? 126 : n;
488bool SGIImage::scanData(
const QImage &img)
490 quint32 *
start = _starttab;
493 uchar *line = (uchar *)lineguard.data();
494 uchar *buf = (uchar *)bufguard.data();
500 for (y = 0; y < _ysize; y++) {
501 const int yPos = _ysize - y - 1;
502 if (yPos >= img.
height()) {
503 qWarning() <<
"Failed to get scanline for" << yPos;
507 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(yPos));
509 for (x = 0; x < _xsize; x++) {
510 buf[x] = intensity(qRed(*c++));
512 len = compact(line, buf);
513 *
start++ = _rlemap.insert(line, len);
521 for (y = 0; y < _ysize; y++) {
522 const int yPos = _ysize - y - 1;
523 if (yPos >= img.
height()) {
524 qWarning() <<
"Failed to get scanline for" << yPos;
528 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(yPos));
529 for (x = 0; x < _xsize; x++) {
530 buf[x] = intensity(qGreen(*c++));
532 len = compact(line, buf);
533 *
start++ = _rlemap.insert(line, len);
536 for (y = 0; y < _ysize; y++) {
537 const int yPos = _ysize - y - 1;
538 if (yPos >= img.
height()) {
539 qWarning() <<
"Failed to get scanline for" << yPos;
543 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(yPos));
544 for (x = 0; x < _xsize; x++) {
545 buf[x] = intensity(qBlue(*c++));
547 len = compact(line, buf);
548 *
start++ = _rlemap.insert(line, len);
556 for (y = 0; y < _ysize; y++) {
557 const int yPos = _ysize - y - 1;
558 if (yPos >= img.
height()) {
559 qWarning() <<
"Failed to get scanline for" << yPos;
563 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(yPos));
564 for (x = 0; x < _xsize; x++) {
565 buf[x] = intensity(qAlpha(*c++));
567 len = compact(line, buf);
568 *
start++ = _rlemap.insert(line, len);
574void SGIImage::writeHeader()
576 _stream << quint16(0x01da);
577 _stream << _rle << _bpc << _dim;
578 _stream << _xsize << _ysize << _zsize;
579 _stream << _pixmin << _pixmax;
580 _stream << quint32(0);
582 for (
int i = 0; i < 80; i++) {
583 _imagename[i] =
'\0';
587 _stream << _colormap;
588 for (
int i = 0; i < 404; i++) {
589 _stream << quint8(0);
593void SGIImage::writeRle()
601 for (i = 0; i < _numrows; i++) {
602 _stream << quint32(_rlevector[_starttab[i]]->offset());
606 for (i = 0; i < _numrows; i++) {
607 _stream << quint32(_rlevector[_starttab[i]]->size());
611 for (i = 0; (int)i < _rlevector.
size(); i++) {
612 const_cast<RLEData *
>(_rlevector[i])->write(_stream);
616void SGIImage::writeVerbatim(
const QImage &img)
626 for (y = 0; y < _ysize; y++) {
627 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(_ysize - y - 1));
628 for (x = 0; x < _xsize; x++) {
629 _stream << quint8(qRed(*c++));
638 for (y = 0; y < _ysize; y++) {
639 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(_ysize - y - 1));
640 for (x = 0; x < _xsize; x++) {
641 _stream << quint8(qGreen(*c++));
645 for (y = 0; y < _ysize; y++) {
646 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(_ysize - y - 1));
647 for (x = 0; x < _xsize; x++) {
648 _stream << quint8(qBlue(*c++));
657 for (y = 0; y < _ysize; y++) {
658 c =
reinterpret_cast<const QRgb *
>(img.
scanLine(_ysize - y - 1));
659 for (x = 0; x < _xsize; x++) {
660 _stream << quint8(qAlpha(*c++));
665bool SGIImage::writeImage(
const QImage &image)
670 _dim = 2, _zsize = 1;
672 _dim = 3, _zsize = 3;
690 const int w = img.
width();
691 const int h = img.
height();
693 if (w > 65535 || h > 65535) {
703 _numrows = _ysize * _zsize;
704 _starttab =
new quint32[_numrows];
705 _rlemap.setBaseOffset(512 + _numrows * 2 *
sizeof(quint32));
707 if (!scanData(img)) {
712 _rlevector = _rlemap.vector();
714 long verbatim_size = _numrows * _xsize;
715 long rle_size = _numrows * 2 *
sizeof(quint32);
716 for (
int i = 0; i < _rlevector.
size(); i++) {
717 rle_size += _rlevector[i]->
size();
720 if (verbatim_size <= rle_size) {
730RGBHandler::RGBHandler()
734bool RGBHandler::canRead()
const
736 if (canRead(device())) {
743bool RGBHandler::read(
QImage *outImage)
745 SGIImage sgi(device());
746 return sgi.readImage(*outImage);
749bool RGBHandler::write(
const QImage &image)
751 SGIImage sgi(device());
752 return sgi.writeImage(image);
755bool RGBHandler::canRead(
QIODevice *device)
758 qWarning(
"RGBHandler::canRead() called with no device");
762 const qint64 oldPos = device->
pos();
764 int readBytes = head.
size();
767 while (readBytes > 0) {
768 device->
ungetChar(head[readBytes-- - 1]);
772 device->
seek(oldPos);
775 return head.
size() >= 4 && head.
startsWith(
"\x01\xda") && (head[2] == 0 || head[2] == 1) && (head[3] == 1 || head[3] == 2);
782 if (format ==
"rgb" || format ==
"rgba" || format ==
"bw" || format ==
"sgi") {
793 if (device->
isReadable() && RGBHandler::canRead(device)) {
810#include "moc_rgb_p.cpp"
Q_SCRIPTABLE Q_NOREPLY void start()
QFlags< Capability > Capabilities
const QList< QKeySequence > & end()
bool isEmpty() const const
qsizetype size() const const
bool startsWith(QByteArrayView bv) const const
int readRawData(char *s, int len)
int writeRawData(const char *s, int len)
bool allGray() const const
bool hasAlphaChannel() const const
bool isNull() const const
void setDevice(QIODevice *device)
bool isOpen() const const
bool isReadable() const const
virtual bool isSequential() const const
bool isWritable() const const
virtual qint64 pos() const const
QByteArray readLine(qint64 maxSize)
virtual bool seek(qint64 pos)
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