• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kimgio
 

kimgio

  • kimgio
pcx.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2002-2005 Nadeem Hasan <nhasan@kde.org>
3 
4  This program is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License (LGPL) as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 */
9 
10 #include "pcx.h"
11 
12 #include <tqimage.h>
13 
14 #include <kdebug.h>
15 
16 static TQDataStream &operator>>( TQDataStream &s, RGB &rgb )
17 {
18  s >> rgb.r >> rgb.g >> rgb.b;
19 
20  return s;
21 }
22 
23 static TQDataStream &operator>>( TQDataStream &s, Palette &pal )
24 {
25  for ( int i=0; i<16; ++i )
26  s >> pal.rgb[ i ];
27 
28  return s;
29 }
30 
31 static TQDataStream &operator>>( TQDataStream &s, PCXHEADER &ph )
32 {
33  s >> ph.Manufacturer;
34  s >> ph.Version;
35  s >> ph.Encoding;
36  s >> ph.Bpp;
37  s >> ph.XMin >> ph.YMin >> ph.XMax >> ph.YMax;
38  s >> ph.HDpi >> ph.YDpi;
39  s >> ph.ColorMap;
40  s >> ph.Reserved;
41  s >> ph.NPlanes;
42  s >> ph.BytesPerLine;
43  s >> ph.PaletteInfo;
44  s >> ph.HScreenSize;
45  s >> ph.VScreenSize;
46 
47  // Skip the rest of the header
48  TQ_UINT8 byte;
49  while ( s.device()->at() < 128 )
50  s >> byte;
51 
52  return s;
53 }
54 
55 static TQDataStream &operator<<( TQDataStream &s, const RGB &rgb )
56 {
57  s << rgb.r << rgb.g << rgb.b;
58 
59  return s;
60 }
61 
62 static TQDataStream &operator<<( TQDataStream &s, const Palette &pal )
63 {
64  for ( int i=0; i<16; ++i )
65  s << pal.rgb[ i ];
66 
67  return s;
68 }
69 
70 static TQDataStream &operator<<( TQDataStream &s, const PCXHEADER &ph )
71 {
72  s << ph.Manufacturer;
73  s << ph.Version;
74  s << ph.Encoding;
75  s << ph.Bpp;
76  s << ph.XMin << ph.YMin << ph.XMax << ph.YMax;
77  s << ph.HDpi << ph.YDpi;
78  s << ph.ColorMap;
79  s << ph.Reserved;
80  s << ph.NPlanes;
81  s << ph.BytesPerLine;
82  s << ph.PaletteInfo;
83  s << ph.HScreenSize;
84  s << ph.VScreenSize;
85 
86  TQ_UINT8 byte = 0;
87  for ( int i=0; i<54; ++i )
88  s << byte;
89 
90  return s;
91 }
92 
93 PCXHEADER::PCXHEADER()
94 {
95  // Initialize all data to zero
96  TQByteArray dummy( 128 );
97  dummy.fill( 0 );
98  TQDataStream s( dummy, IO_ReadOnly );
99  s >> *this;
100 }
101 
102 static void readLine( TQDataStream &s, TQByteArray &buf, const PCXHEADER &header )
103 {
104  TQ_UINT32 i=0;
105  TQ_UINT32 size = buf.size();
106  TQ_UINT8 byte, count;
107 
108  if ( header.isCompressed() )
109  {
110  // Uncompress the image data
111  while ( i < size )
112  {
113  count = 1;
114  s >> byte;
115  if ( byte > 0xc0 )
116  {
117  count = byte - 0xc0;
118  s >> byte;
119  }
120  while ( count-- && i < size )
121  buf[ i++ ] = byte;
122  }
123  }
124  else
125  {
126  // Image is not compressed (possible?)
127  while ( i < size )
128  {
129  s >> byte;
130  buf[ i++ ] = byte;
131  }
132  }
133 }
134 
135 static void readImage1( TQImage &img, TQDataStream &s, const PCXHEADER &header )
136 {
137  TQByteArray buf( header.BytesPerLine );
138 
139  if(!img.create( header.width(), header.height(), 1, 2, TQImage::BigEndian ))
140  return;
141 
142  for ( int y=0; y<header.height(); ++y )
143  {
144  if ( s.atEnd() )
145  {
146  img.reset();
147  return;
148  }
149 
150  readLine( s, buf, header );
151  uchar *p = img.scanLine( y );
152  unsigned int bpl = TQMIN((header.width()+7)/8, header.BytesPerLine);
153  for ( unsigned int x=0; x< bpl; ++x )
154  p[ x ] = buf[x];
155  }
156 
157  // Set the color palette
158  img.setColor( 0, tqRgb( 0, 0, 0 ) );
159  img.setColor( 1, tqRgb( 255, 255, 255 ) );
160 }
161 
162 static void readImage4( TQImage &img, TQDataStream &s, const PCXHEADER &header )
163 {
164  TQByteArray buf( header.BytesPerLine*4 );
165  TQByteArray pixbuf( header.width() );
166 
167  if(!img.create( header.width(), header.height(), 8, 16 ))
168  return;
169 
170  for ( int y=0; y<header.height(); ++y )
171  {
172  if ( s.atEnd() )
173  {
174  img.reset();
175  return;
176  }
177 
178  pixbuf.fill( 0 );
179  readLine( s, buf, header );
180 
181  for ( int i=0; i<4; i++ )
182  {
183  TQ_UINT32 offset = i*header.BytesPerLine;
184  for ( unsigned int x=0; x<header.width(); ++x )
185  if ( buf[ offset + ( x/8 ) ] & ( 128 >> ( x%8 ) ) )
186  pixbuf[ x ] = static_cast<const char>(pixbuf.at(x)) + ( 1 << i );
187  }
188 
189  uchar *p = img.scanLine( y );
190  for ( unsigned int x=0; x<header.width(); ++x )
191  p[ x ] = pixbuf[ x ];
192  }
193 
194  // Read the palette
195  for ( int i=0; i<16; ++i )
196  img.setColor( i, header.ColorMap.color( i ) );
197 }
198 
199 static void readImage8( TQImage &img, TQDataStream &s, const PCXHEADER &header )
200 {
201  TQByteArray buf( header.BytesPerLine );
202 
203  if(!img.create( header.width(), header.height(), 8, 256 ))
204  return;
205 
206  for ( int y=0; y<header.height(); ++y )
207  {
208  if ( s.atEnd() )
209  {
210  img.reset();
211  return;
212  }
213 
214  readLine( s, buf, header );
215 
216  uchar *p = img.scanLine( y );
217  unsigned int bpl = TQMIN(header.BytesPerLine, header.width());
218  for ( unsigned int x=0; x<bpl; ++x )
219  p[ x ] = buf[ x ];
220  }
221 
222  TQ_UINT8 flag;
223  s >> flag;
224  kdDebug( 399 ) << "Palette Flag: " << flag << endl;
225 
226  if ( flag == 12 && ( header.Version == 5 || header.Version == 2 ) )
227  {
228  // Read the palette
229  TQ_UINT8 r, g, b;
230  for ( int i=0; i<256; ++i )
231  {
232  s >> r >> g >> b;
233  img.setColor( i, tqRgb( r, g, b ) );
234  }
235  }
236 }
237 
238 static void readImage24( TQImage &img, TQDataStream &s, const PCXHEADER &header )
239 {
240  TQByteArray r_buf( header.BytesPerLine );
241  TQByteArray g_buf( header.BytesPerLine );
242  TQByteArray b_buf( header.BytesPerLine );
243 
244  if(!img.create( header.width(), header.height(), 32 ))
245  return;
246 
247  for ( int y=0; y<header.height(); ++y )
248  {
249  if ( s.atEnd() )
250  {
251  img.reset();
252  return;
253  }
254 
255  readLine( s, r_buf, header );
256  readLine( s, g_buf, header );
257  readLine( s, b_buf, header );
258 
259  uint *p = ( uint * )img.scanLine( y );
260  for ( unsigned int x=0; x<header.width(); ++x )
261  p[ x ] = tqRgb( r_buf[ x ], g_buf[ x ], b_buf[ x ] );
262  }
263 }
264 
265 KDE_EXPORT void kimgio_pcx_read( TQImageIO *io )
266 {
267  TQDataStream s( io->ioDevice() );
268  s.setByteOrder( TQDataStream::LittleEndian );
269 
270  if ( s.device()->size() < 128 )
271  {
272  io->setStatus( -1 );
273  return;
274  }
275 
276  PCXHEADER header;
277 
278  s >> header;
279 
280  if ( header.Manufacturer != 10 || s.atEnd())
281  {
282  io->setStatus( -1 );
283  return;
284  }
285 
286  int w = header.width();
287  int h = header.height();
288 
289  kdDebug( 399 ) << "Manufacturer: " << header.Manufacturer << endl;
290  kdDebug( 399 ) << "Version: " << header.Version << endl;
291  kdDebug( 399 ) << "Encoding: " << header.Encoding << endl;
292  kdDebug( 399 ) << "Bpp: " << header.Bpp << endl;
293  kdDebug( 399 ) << "Width: " << w << endl;
294  kdDebug( 399 ) << "Height: " << h << endl;
295  kdDebug( 399 ) << "Window: " << header.XMin << "," << header.XMax << ","
296  << header.YMin << "," << header.YMax << endl;
297  kdDebug( 399 ) << "BytesPerLine: " << header.BytesPerLine << endl;
298  kdDebug( 399 ) << "NPlanes: " << header.NPlanes << endl;
299 
300  TQImage img;
301 
302  if ( header.Bpp == 1 && header.NPlanes == 1 )
303  {
304  readImage1( img, s, header );
305  }
306  else if ( header.Bpp == 1 && header.NPlanes == 4 )
307  {
308  readImage4( img, s, header );
309  }
310  else if ( header.Bpp == 8 && header.NPlanes == 1 )
311  {
312  readImage8( img, s, header );
313  }
314  else if ( header.Bpp == 8 && header.NPlanes == 3 )
315  {
316  readImage24( img, s, header );
317  }
318 
319  kdDebug( 399 ) << "Image Bytes: " << img.numBytes() << endl;
320  kdDebug( 399 ) << "Image Bytes Per Line: " << img.bytesPerLine() << endl;
321  kdDebug( 399 ) << "Image Depth: " << img.depth() << endl;
322 
323  if ( !img.isNull() )
324  {
325  io->setImage( img );
326  io->setStatus( 0 );
327  }
328  else
329  {
330  io->setStatus( -1 );
331  }
332 }
333 
334 static void writeLine( TQDataStream &s, TQByteArray &buf )
335 {
336  TQ_UINT32 i = 0;
337  TQ_UINT32 size = buf.size();
338  TQ_UINT8 count, data;
339  char byte;
340 
341  while ( i < size )
342  {
343  count = 1;
344  byte = buf[ i++ ];
345 
346  while ( ( i < size ) && ( TQChar(byte) == buf.at(i) ) && ( count < 63 ) )
347  {
348  ++i;
349  ++count;
350  }
351 
352  data = byte;
353 
354  if ( count > 1 || data >= 0xc0 )
355  {
356  count |= 0xc0;
357  s << count;
358  }
359 
360  s << data;
361  }
362 }
363 
364 static void writeImage1( TQImage &img, TQDataStream &s, PCXHEADER &header )
365 {
366  img = img.convertBitOrder( TQImage::BigEndian );
367 
368  header.Bpp = 1;
369  header.NPlanes = 1;
370  header.BytesPerLine = img.bytesPerLine();
371 
372  s << header;
373 
374  TQByteArray buf( header.BytesPerLine );
375 
376  for ( int y=0; y<header.height(); ++y )
377  {
378  TQ_UINT8 *p = img.scanLine( y );
379 
380  // Invert as TQImage uses reverse palette for monochrome images?
381  for ( int i=0; i<header.BytesPerLine; ++i )
382  buf[ i ] = ~p[ i ];
383 
384  writeLine( s, buf );
385  }
386 }
387 
388 static void writeImage4( TQImage &img, TQDataStream &s, PCXHEADER &header )
389 {
390  header.Bpp = 1;
391  header.NPlanes = 4;
392  header.BytesPerLine = header.width()/8;
393 
394  for ( int i=0; i<16; ++i )
395  header.ColorMap.setColor( i, img.color( i ) );
396 
397  s << header;
398 
399  TQByteArray buf[ 4 ];
400 
401  for ( int i=0; i<4; ++i )
402  buf[ i ].resize( header.BytesPerLine );
403 
404  for ( int y=0; y<header.height(); ++y )
405  {
406  TQ_UINT8 *p = img.scanLine( y );
407 
408  for ( int i=0; i<4; ++i )
409  buf[ i ].fill( 0 );
410 
411  for ( unsigned int x=0; x<header.width(); ++x )
412  {
413  for ( int i=0; i<4; ++i )
414  if ( *( p+x ) & ( 1 << i ) )
415  buf[ i ][ x/8 ] = buf[ i ].at(x/8) | 1 << ( 7-x%8 );
416  }
417 
418  for ( int i=0; i<4; ++i )
419  writeLine( s, buf[ i ] );
420  }
421 }
422 
423 static void writeImage8( TQImage &img, TQDataStream &s, PCXHEADER &header )
424 {
425  header.Bpp = 8;
426  header.NPlanes = 1;
427  header.BytesPerLine = img.bytesPerLine();
428 
429  s << header;
430 
431  TQByteArray buf( header.BytesPerLine );
432 
433  for ( int y=0; y<header.height(); ++y )
434  {
435  TQ_UINT8 *p = img.scanLine( y );
436 
437  for ( int i=0; i<header.BytesPerLine; ++i )
438  buf[ i ] = p[ i ];
439 
440  writeLine( s, buf );
441  }
442 
443  // Write palette flag
444  TQ_UINT8 byte = 12;
445  s << byte;
446 
447  // Write palette
448  for ( int i=0; i<256; ++i )
449  s << RGB( img.color( i ) );
450 }
451 
452 static void writeImage24( TQImage &img, TQDataStream &s, PCXHEADER &header )
453 {
454  header.Bpp = 8;
455  header.NPlanes = 3;
456  header.BytesPerLine = header.width();
457 
458  s << header;
459 
460  TQByteArray r_buf( header.width() );
461  TQByteArray g_buf( header.width() );
462  TQByteArray b_buf( header.width() );
463 
464  for ( int y=0; y<header.height(); ++y )
465  {
466  uint *p = ( uint * )img.scanLine( y );
467 
468  for ( unsigned int x=0; x<header.width(); ++x )
469  {
470  QRgb rgb = *p++;
471  r_buf[ x ] = tqRed( rgb );
472  g_buf[ x ] = tqGreen( rgb );
473  b_buf[ x ] = tqBlue( rgb );
474  }
475 
476  writeLine( s, r_buf );
477  writeLine( s, g_buf );
478  writeLine( s, b_buf );
479  }
480 }
481 
482 KDE_EXPORT void kimgio_pcx_write( TQImageIO *io )
483 {
484  TQDataStream s( io->ioDevice() );
485  s.setByteOrder( TQDataStream::LittleEndian );
486 
487  TQImage img = io->image();
488 
489  int w = img.width();
490  int h = img.height();
491 
492  kdDebug( 399 ) << "Width: " << w << endl;
493  kdDebug( 399 ) << "Height: " << h << endl;
494  kdDebug( 399 ) << "Depth: " << img.depth() << endl;
495  kdDebug( 399 ) << "BytesPerLine: " << img.bytesPerLine() << endl;
496  kdDebug( 399 ) << "Num Colors: " << img.numColors() << endl;
497 
498  PCXHEADER header;
499 
500  header.Manufacturer = 10;
501  header.Version = 5;
502  header.Encoding = 1;
503  header.XMin = 0;
504  header.YMin = 0;
505  header.XMax = w-1;
506  header.YMax = h-1;
507  header.HDpi = 300;
508  header.YDpi = 300;
509  header.Reserved = 0;
510  header.PaletteInfo =1;
511 
512  if ( img.depth() == 1 )
513  {
514  writeImage1( img, s, header );
515  }
516  else if ( img.depth() == 8 && img.numColors() <= 16 )
517  {
518  writeImage4( img, s, header );
519  }
520  else if ( img.depth() == 8 )
521  {
522  writeImage8( img, s, header );
523  }
524  else if ( img.depth() == 32 )
525  {
526  writeImage24( img, s, header );
527  }
528 
529  io->setStatus( 0 );
530 }

kimgio

Skip menu "kimgio"
  • Main Page
  • File List
  • Related Pages

kimgio

Skip menu "kimgio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.8.8
This website is maintained by Timothy Pearson.