27 #include <QtGui/QImage>
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;
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;
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)
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];
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++) {
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;
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';
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)
492 kDebug(399) <<
"can't convert image to depth 32";
497 _xsize = img.
width();
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();
579 int readBytes = head.
size();
582 while (readBytes > 0)
583 device->
ungetChar(head[readBytes-- - 1]);
586 device->
seek(oldPos);
589 const QRegExp regexp(
"^\x01\xda\x01[\x01\x02]");
610 return QStringList() <<
"rgb" <<
"RGB" <<
"rgba" <<
"RGBA" <<
"bw" <<
"BW" <<
"sgi" <<
"SGI";
616 if (format ==
"rgb" || format ==
"RGB" || format ==
"rgba" || format ==
"RGBA"
617 || format ==
"bw" || format ==
"BW" || format ==
"sgi" || format ==
"SGI")
618 return Capabilities(CanRead|CanWrite);
643 Q_EXPORT_STATIC_PLUGIN(RGBPlugin)
644 Q_EXPORT_PLUGIN2(rgb, RGBPlugin)
virtual QImageIOHandler * create(QIODevice *device, const QByteArray &format) const =0
QIODevice * device() const
virtual bool seek(qint64 pos)
uint insert(const uchar *d, uint l)
void write(QDataStream &s)
void setDevice(QIODevice *d)
virtual bool isSequential() const
int readRawData(char *s, int len)
virtual qint64 pos() const
SGIImage(QIODevice *device)
void setDevice(QIODevice *device)
virtual Capabilities capabilities(QIODevice *device, const QByteArray &format) const =0
QVector< const RLEData * > vector()
bool write(const QImage &image)
void setBaseOffset(uint o)
bool contains(QChar ch, Qt::CaseSensitivity cs) const
const T & at(int i) const
virtual QStringList keys() const =0
int writeRawData(const char *s, int len)
QRgb qRgba(const QRgb &rgb, int a)
Change a QRgb value's alpha only.
void replace(int i, const T &value)
iterator insert(const Key &key, const T &value)
bool operator<(const RLEData &) const
bool writeImage(const QImage &)
iterator find(const Key &key)
qint64 readLine(char *data, qint64 maxSize)