27 #include <QtGui/QImage>
36 _stream.setDevice(_dev);
50 bool SGIImage::getRow(
uchar *dest)
54 for (i = 0; i < _xsize; i++) {
55 if (_pos >= _data.end())
57 dest[i] =
uchar(*_pos);
63 for (i = 0; i < _xsize;) {
71 for (; i < _xsize && n--; i++) {
76 for (; i < _xsize && n--; i++)
86 bool SGIImage::readData(QImage& img)
89 quint32 *start = _starttab;
90 QByteArray lguard(_xsize, 0);
97 for (y = 0; y < _ysize; y++) {
99 _pos = _data.begin() + *start++;
102 c = (QRgb *)img.scanLine(_ysize - y - 1);
103 for (x = 0; x < _xsize; x++, c++)
104 *c = qRgb(line[x], line[x], line[x]);
111 for (y = 0; y < _ysize; y++) {
113 _pos = _data.begin() + *start++;
116 c = (QRgb *)img.scanLine(_ysize - y - 1);
117 for (x = 0; x < _xsize; x++, c++)
118 *c = qRgb(qRed(*c), line[x], line[x]);
121 for (y = 0; y < _ysize; y++) {
123 _pos = _data.begin() + *start++;
126 c = (QRgb *)img.scanLine(_ysize - y - 1);
127 for (x = 0; x < _xsize; x++, c++)
128 *c = qRgb(qRed(*c), qGreen(*c), line[x]);
135 for (y = 0; y < _ysize; y++) {
137 _pos = _data.begin() + *start++;
140 c = (QRgb *)img.scanLine(_ysize - y - 1);
141 for (x = 0; x < _xsize; x++, c++)
142 *c =
qRgba(qRed(*c), qGreen(*c), qBlue(*c), line[x]);
155 kDebug(399) <<
"reading rgb ";
164 kDebug(399) << (_rle ?
"RLE" :
"verbatim");
170 kDebug(399) <<
"bytes per channel: " << int(_bpc);
174 kDebug(399) <<
"dropping least significant byte";
180 kDebug(399) <<
"dimensions: " << _dim;
181 if (_dim < 1 || _dim > 3)
184 _stream >> _xsize >> _ysize >> _zsize >> _pixmin >> _pixmax >> u32;
185 kDebug(399) <<
"x: " << _xsize;
186 kDebug(399) <<
"y: " << _ysize;
187 kDebug(399) <<
"z: " << _zsize;
190 _stream.readRawData(_imagename, 80);
191 _imagename[79] =
'\0';
193 _stream >> _colormap;
194 kDebug(399) <<
"colormap: " << _colormap;
195 if (_colormap != NORMAL)
198 for (
int i = 0; i < 404; i++)
202 kDebug(399) <<
"1-dimensional images aren't supported yet";
209 _numrows = _ysize * _zsize;
211 img = QImage( _xsize, _ysize, QImage::Format_RGB32 );
213 if (_zsize == 2 || _zsize == 4)
214 img = img.convertToFormat(QImage::Format_ARGB32);
216 kDebug(399) <<
"using first 4 of " << _zsize <<
" channels";
220 _starttab =
new quint32[_numrows];
221 for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
222 _stream >> _starttab[l];
223 _starttab[l] -= 512 + _numrows * 2 *
sizeof(quint32);
226 _lengthtab =
new quint32[_numrows];
227 for (l = 0; l < _numrows; l++)
228 _stream >> _lengthtab[l];
231 _data = _dev->readAll();
235 for (
uint o = 0; o < _numrows; o++)
237 if (_starttab[o] + _lengthtab[o] > (
uint)_data.size()) {
238 kDebug(399) <<
"image corrupt (sanity check failed)";
242 if (!readData(img)) {
243 kDebug(399) <<
"image corrupt (incomplete scanline)";
256 for (
int i = 0; i < size(); i++)
264 for (
int i = 0; i < qMin(size(), b.size()); i++) {
270 return size() < b.size();
277 Iterator it = find(data);
289 for (Iterator it = begin(); it != end(); ++it)
290 v.replace(it.value(), &it.key());
308 uchar *dest = d, *src = s, patt, *t, *end = s + _xsize;
311 for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++)
315 i = n > 126 ? 126 : n;
326 for (n = 1; src < end && *src == patt; src++)
330 i = n > 126 ? 126 : n;
341 bool SGIImage::scanData(
const QImage& img)
343 quint32 *start = _starttab;
344 QByteArray lineguard(_xsize * 2, 0);
345 QByteArray bufguard(_xsize, 0);
352 for (y = 0; y < _ysize; y++) {
353 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
354 for (x = 0; x < _xsize; x++)
355 buf[x] = intensity(qRed(*c++));
356 len = compact(line, buf);
357 *start++ = _rlemap.
insert(line, len);
364 for (y = 0; y < _ysize; y++) {
365 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
366 for (x = 0; x < _xsize; x++)
367 buf[x] = intensity(qGreen(*c++));
368 len = compact(line, buf);
369 *start++ = _rlemap.
insert(line, len);
372 for (y = 0; y < _ysize; y++) {
373 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
374 for (x = 0; x < _xsize; x++)
375 buf[x] = intensity(qBlue(*c++));
376 len = compact(line, buf);
377 *start++ = _rlemap.
insert(line, len);
384 for (y = 0; y < _ysize; y++) {
385 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
386 for (x = 0; x < _xsize; x++)
387 buf[x] = intensity(qAlpha(*c++));
388 len = compact(line, buf);
389 *start++ = _rlemap.
insert(line, len);
396 void SGIImage::writeHeader()
398 _stream << quint16(0x01da);
399 _stream << _rle << _bpc << _dim;
400 _stream << _xsize << _ysize << _zsize;
401 _stream << _pixmin << _pixmax;
402 _stream << quint32(0);
404 for (
int i = 0; i < 80; i++)
405 _imagename[i] =
'\0';
406 _stream.writeRawData(_imagename, 80);
408 _stream << _colormap;
409 for (
int i = 0; i < 404; i++)
410 _stream << quint8(0);
414 void SGIImage::writeRle()
417 kDebug(399) <<
"writing RLE data";
422 for (i = 0; i < _numrows; i++)
423 _stream << quint32(_rlevector[_starttab[i]]->offset());
426 for (i = 0; i < _numrows; i++)
427 _stream << quint32(_rlevector[_starttab[i]]->size());
430 for (i = 0; (int)i < _rlevector.size(); i++)
431 const_cast<RLEData*>(_rlevector[i])->write(_stream);
435 void SGIImage::writeVerbatim(
const QImage& img)
438 kDebug(399) <<
"writing verbatim data";
444 for (y = 0; y < _ysize; y++) {
445 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
446 for (x = 0; x < _xsize; x++)
447 _stream << quint8(qRed(*c++));
454 for (y = 0; y < _ysize; y++) {
455 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
456 for (x = 0; x < _xsize; x++)
457 _stream << quint8(qGreen(*c++));
460 for (y = 0; y < _ysize; y++) {
461 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
462 for (x = 0; x < _xsize; x++)
463 _stream << quint8(qBlue(*c++));
470 for (y = 0; y < _ysize; y++) {
471 c =
reinterpret_cast<const QRgb *
>(img.scanLine(_ysize - y - 1));
472 for (x = 0; x < _xsize; x++)
473 _stream << quint8(qAlpha(*c++));
480 kDebug(399) <<
"writing ";
483 _dim = 2, _zsize = 1;
485 _dim = 3, _zsize = 3;
487 if (img.format() == QImage::Format_ARGB32)
490 img = img.convertToFormat(QImage::Format_RGB32);
492 kDebug(399) <<
"can't convert image to depth 32";
497 _xsize = img.width();
498 _ysize = img.height();
502 _numrows = _ysize * _zsize;
503 _starttab =
new quint32[_numrows];
506 if (!scanData(img)) {
507 kDebug(399) <<
"this can't happen";
511 _rlevector = _rlemap.
vector();
513 long verbatim_size = _numrows * _xsize;
514 long rle_size = _numrows * 2 *
sizeof(quint32);
515 for (
int i = 0; i < _rlevector.size(); i++)
516 rle_size += _rlevector[i]->size();
518 kDebug(399) <<
"minimum intensity: " << _pixmin;
519 kDebug(399) <<
"maximum intensity: " << _pixmax;
520 kDebug(399) <<
"saved scanlines: " << _numrows - _rlemap.size();
521 kDebug(399) <<
"total savings: " << (verbatim_size - rle_size) <<
" bytes";
522 kDebug(399) <<
"compression: " << (rle_size * 100.0 / verbatim_size) <<
'%';
524 if (verbatim_size <= rle_size)
573 qWarning(
"RGBHandler::canRead() called with no device");
577 qint64 oldPos = device->pos();
578 QByteArray head = device->readLine(64);
579 int readBytes = head.size();
581 if (device->isSequential()) {
582 while (readBytes > 0)
583 device->ungetChar(head[readBytes-- - 1]);
586 device->seek(oldPos);
589 const QRegExp regexp(
"^\x01\xda\x01[\x01\x02]");
592 return data.contains(regexp);
599 class RGBPlugin :
public QImageIOPlugin
602 QStringList keys()
const;
603 Capabilities capabilities(QIODevice *device,
const QByteArray &format)
const;
604 QImageIOHandler *create(QIODevice *device,
const QByteArray &format = QByteArray())
const;
608 QStringList RGBPlugin::keys()
const
610 return QStringList() <<
"rgb" <<
"RGB" <<
"rgba" <<
"RGBA" <<
"bw" <<
"BW" <<
"sgi" <<
"SGI";
614 QImageIOPlugin::Capabilities RGBPlugin::capabilities(QIODevice *device,
const QByteArray &format)
const
616 if (format ==
"rgb" || format ==
"RGB" || format ==
"rgba" || format ==
"RGBA"
617 || format ==
"bw" || format ==
"BW" || format ==
"sgi" || format ==
"SGI")
618 return Capabilities(CanRead|CanWrite);
620 if (!format.isEmpty())
622 if (!device->isOpen())
628 if (device->isWritable())
634 QImageIOHandler *RGBPlugin::create(QIODevice *device,
const QByteArray &format)
const
637 handler->setDevice(device);
638 handler->setFormat(format);
643 Q_EXPORT_STATIC_PLUGIN(RGBPlugin)
644 Q_EXPORT_PLUGIN2(rgb, RGBPlugin)
uint insert(const uchar *d, uint l)
void write(QDataStream &s)
SGIImage(QIODevice *device)
QVector< const RLEData * > vector()
bool write(const QImage &image)
void setBaseOffset(uint o)
QRgb qRgba(const QRgb &rgb, int a)
Change a QRgb value's alpha only.
bool operator<(const RLEData &) const
bool writeImage(const QImage &)