34 TDE_EXPORT
void kimgio_rgb_read(TQImageIO *io)
39 if (!sgi.readImage(img)) {
40 io->setImage(TQImage());
50 TDE_EXPORT
void kimgio_rgb_write(TQImageIO *io)
53 TQImage img = io->image();
55 if (!sgi.writeImage(img))
65 SGIImage::SGIImage(TQImageIO *io) :
70 m_dev = io->ioDevice();
71 m_stream.setDevice(m_dev);
85 bool SGIImage::getRow(uchar *dest)
89 for (i = 0; i < m_xsize; i++) {
90 if (m_pos >= m_data.end())
92 dest[i] = uchar(*m_pos);
98 for (i = 0; i < m_xsize;) {
105 if (*m_pos++ & 0x80) {
106 for (; i < m_xsize && n--; i++) {
111 for (; i < m_xsize && n--; i++)
121 bool SGIImage::readData(TQImage& img)
124 TQ_UINT32 *start = m_starttab;
125 TQByteArray lguard(m_xsize);
126 uchar *line = (uchar *)lguard.data();
130 m_pos = m_data.begin();
132 for (y = 0; y < m_ysize; y++) {
134 m_pos = m_data.begin() + *start++;
137 c = (TQRgb *)img.scanLine(m_ysize - y - 1);
138 for (x = 0; x < m_xsize; x++, c++)
139 *c = tqRgb(line[x], line[x], line[x]);
146 for (y = 0; y < m_ysize; y++) {
148 m_pos = m_data.begin() + *start++;
151 c = (TQRgb *)img.scanLine(m_ysize - y - 1);
152 for (x = 0; x < m_xsize; x++, c++)
153 *c = tqRgb(tqRed(*c), line[x], line[x]);
156 for (y = 0; y < m_ysize; y++) {
158 m_pos = m_data.begin() + *start++;
161 c = (TQRgb *)img.scanLine(m_ysize - y - 1);
162 for (x = 0; x < m_xsize; x++, c++)
163 *c = tqRgb(tqRed(*c), tqGreen(*c), line[x]);
170 for (y = 0; y < m_ysize; y++) {
172 m_pos = m_data.begin() + *start++;
175 c = (TQRgb *)img.scanLine(m_ysize - y - 1);
176 for (x = 0; x < m_xsize; x++, c++)
177 *c = tqRgba(tqRed(*c), tqGreen(*c), tqBlue(*c), line[x]);
184 bool SGIImage::readImage(TQImage& img)
190 kdDebug(399) <<
"reading '" << m_io->fileName() <<
'\'' << endl;
199 kdDebug(399) << (m_rle ?
"RLE" :
"verbatim") << endl;
205 kdDebug(399) <<
"bytes per channel: " << int(m_bpc) << endl;
209 kdDebug(399) <<
"dropping least significant byte" << endl;
215 kdDebug(399) <<
"dimensions: " << m_dim << endl;
216 if (m_dim < 1 || m_dim > 3)
219 m_stream >> m_xsize >> m_ysize >> m_zsize >> m_pixmin >> m_pixmax >> u32;
220 kdDebug(399) <<
"x: " << m_xsize << endl;
221 kdDebug(399) <<
"y: " << m_ysize << endl;
222 kdDebug(399) <<
"z: " << m_zsize << endl;
225 m_stream.readRawBytes(m_imagename, 80);
226 m_imagename[79] =
'\0';
227 m_io->setDescription(m_imagename);
229 m_stream >> m_colormap;
230 kdDebug(399) <<
"colormap: " << m_colormap << endl;
231 if (m_colormap != NORMAL)
234 for (
int i = 0; i < 404; i++)
238 kdDebug(399) <<
"1-dimensional images aren't supported yet" << endl;
242 if( m_stream.atEnd())
245 m_numrows = m_ysize * m_zsize;
247 if (!img.create(m_xsize, m_ysize, 32)) {
248 kdDebug(399) <<
"cannot create image" << endl;
252 if (m_zsize == 2 || m_zsize == 4)
253 img.setAlphaBuffer(
true);
254 else if (m_zsize > 4)
255 kdDebug(399) <<
"using first 4 of " << m_zsize <<
" channels" << endl;
259 m_starttab =
new TQ_UINT32[m_numrows];
260 for (l = 0; !m_stream.atEnd() && l < m_numrows; l++) {
261 m_stream >> m_starttab[l];
262 m_starttab[l] -= 512 + m_numrows * 2 *
sizeof(TQ_UINT32);
265 m_lengthtab =
new TQ_UINT32[m_numrows];
266 for (l = 0; l < m_numrows; l++)
267 m_stream >> m_lengthtab[l];
270 m_data = m_dev->readAll();
274 for (uint o = 0; o < m_numrows; o++)
276 if (m_starttab[o] + m_lengthtab[o] > m_data.size()) {
277 kdDebug(399) <<
"image corrupt (sanity check failed)" << endl;
281 if (!readData(img)) {
282 kdDebug(399) <<
"image corrupt (incomplete scanline)" << endl;
294 void RLEData::print(TQString desc)
const
296 TQString s = desc +
": ";
297 for (uint i = 0; i < size(); i++)
298 s += TQString::number(at(i)) +
",";
299 kdDebug() <<
"--- " << s << endl;
303 void RLEData::write(TQDataStream& s)
305 for (
unsigned i = 0; i < size(); i++)
310 bool RLEData::operator<(
const RLEData& b)
const
313 for (
unsigned i = 0; i < TQMIN(size(), b.size()); i++) {
319 return size() < b.size();
323 uint RLEMap::insert(
const uchar *d, uint l)
325 RLEData data = RLEData(d, l, m_offset);
326 Iterator it = find(data);
331 return TQMap<RLEData, uint>::insert(data, m_counter++).data();
335 TQPtrVector<RLEData> RLEMap::vector()
337 TQPtrVector<RLEData> v(size());
338 for (Iterator it = begin(); it != end(); ++it)
339 v.insert(it.data(), &it.key());
345 uchar SGIImage::intensity(uchar c)
355 uint SGIImage::compact(uchar *d, uchar *s)
357 uchar *dest = d, *src = s, patt, *t, *end = s + m_xsize;
360 for (n = 0, t = src; t + 2 < end && !(*t == t[1] && *t == t[2]); t++)
364 i = n > 126 ? 126 : n;
375 for (n = 1; src < end && *src == patt; src++)
379 i = n > 126 ? 126 : n;
390 bool SGIImage::scanData(
const TQImage& img)
392 TQ_UINT32 *start = m_starttab;
393 TQCString lineguard(m_xsize * 2);
394 TQCString bufguard(m_xsize);
395 uchar *line = (uchar *)lineguard.data();
396 uchar *buf = (uchar *)bufguard.data();
401 for (y = 0; y < m_ysize; y++) {
402 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
403 for (x = 0; x < m_xsize; x++)
404 buf[x] = intensity(tqRed(*c++));
405 len = compact(line, buf);
406 *start++ = m_rlemap.insert(line, len);
413 for (y = 0; y < m_ysize; y++) {
414 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
415 for (x = 0; x < m_xsize; x++)
416 buf[x] = intensity(tqGreen(*c++));
417 len = compact(line, buf);
418 *start++ = m_rlemap.insert(line, len);
421 for (y = 0; y < m_ysize; y++) {
422 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
423 for (x = 0; x < m_xsize; x++)
424 buf[x] = intensity(tqBlue(*c++));
425 len = compact(line, buf);
426 *start++ = m_rlemap.insert(line, len);
433 for (y = 0; y < m_ysize; y++) {
434 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
435 for (x = 0; x < m_xsize; x++)
436 buf[x] = intensity(tqAlpha(*c++));
437 len = compact(line, buf);
438 *start++ = m_rlemap.insert(line, len);
445 void SGIImage::writeHeader()
447 m_stream << TQ_UINT16(0x01da);
448 m_stream << m_rle << m_bpc << m_dim;
449 m_stream << m_xsize << m_ysize << m_zsize;
450 m_stream << m_pixmin << m_pixmax;
451 m_stream << TQ_UINT32(0);
454 TQString desc = m_io->description();
455 kdDebug(399) <<
"Description: " << desc << endl;
458 for (i = 0; i < desc.length(); i++)
459 m_imagename[i] = desc.latin1()[i];
461 m_imagename[i] =
'\0';
462 m_stream.writeRawBytes(m_imagename, 80);
464 m_stream << m_colormap;
465 for (i = 0; i < 404; i++)
466 m_stream << TQ_UINT8(0);
470 void SGIImage::writeRle()
473 kdDebug(399) <<
"writing RLE data" << endl;
478 for (i = 0; i < m_numrows; i++)
479 m_stream << TQ_UINT32(m_rlevector[m_starttab[i]]->offset());
482 for (i = 0; i < m_numrows; i++)
483 m_stream << TQ_UINT32(m_rlevector[m_starttab[i]]->size());
486 for (i = 0; i < m_rlevector.size(); i++)
487 m_rlevector[i]->write(m_stream);
491 void SGIImage::writeVerbatim(
const TQImage& img)
494 kdDebug(399) <<
"writing verbatim data" << endl;
500 for (y = 0; y < m_ysize; y++) {
501 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
502 for (x = 0; x < m_xsize; x++)
503 m_stream << TQ_UINT8(tqRed(*c++));
510 for (y = 0; y < m_ysize; y++) {
511 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
512 for (x = 0; x < m_xsize; x++)
513 m_stream << TQ_UINT8(tqGreen(*c++));
516 for (y = 0; y < m_ysize; y++) {
517 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
518 for (x = 0; x < m_xsize; x++)
519 m_stream << TQ_UINT8(tqBlue(*c++));
526 for (y = 0; y < m_ysize; y++) {
527 c =
reinterpret_cast<TQRgb *
>(
const_cast<TQImage&
>(img).scanLine(m_ysize - y - 1));
528 for (x = 0; x < m_xsize; x++)
529 m_stream << TQ_UINT8(tqAlpha(*c++));
534 bool SGIImage::writeImage(TQImage& img)
536 kdDebug(399) <<
"writing '" << m_io->fileName() <<
'\'' << endl;
539 m_dim = 2, m_zsize = 1;
541 m_dim = 3, m_zsize = 3;
543 if (img.hasAlphaBuffer())
544 m_dim = 3, m_zsize++;
546 img = img.convertDepth(32);
548 kdDebug(399) <<
"can't convert image to depth 32" << endl;
553 m_xsize = img.width();
554 m_ysize = img.height();
559 m_numrows = m_ysize * m_zsize;
561 m_starttab =
new TQ_UINT32[m_numrows];
562 m_rlemap.setBaseOffset(512 + m_numrows * 2 *
sizeof(TQ_UINT32));
564 if (!scanData(img)) {
565 kdDebug(399) <<
"this can't happen" << endl;
569 m_rlevector = m_rlemap.vector();
571 long verbatim_size = m_numrows * m_xsize;
572 long rle_size = m_numrows * 2 *
sizeof(TQ_UINT32);
573 for (uint i = 0; i < m_rlevector.size(); i++)
574 rle_size += m_rlevector[i]->size();
576 kdDebug(399) <<
"minimum intensity: " << m_pixmin << endl;
577 kdDebug(399) <<
"maximum intensity: " << m_pixmax << endl;
578 kdDebug(399) <<
"saved scanlines: " << m_numrows - m_rlemap.size() << endl;
579 kdDebug(399) <<
"total savings: " << (verbatim_size - rle_size) <<
" bytes" << endl;
580 kdDebug(399) <<
"compression: " << (rle_size * 100.0 / verbatim_size) <<
'%' << endl;
582 if (verbatim_size <= rle_size || m_io->quality() > 50)