• 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
16static TQDataStream &operator>>( TQDataStream &s, RGB &rgb )
17{
18 s >> rgb.r >> rgb.g >> rgb.b;
19
20 return s;
21}
22
23static 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
31static 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
55static TQDataStream &operator<<( TQDataStream &s, const RGB &rgb )
56{
57 s << rgb.r << rgb.g << rgb.b;
58
59 return s;
60}
61
62static 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
70static 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
93PCXHEADER::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
102static 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
135static 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
162static 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
199static 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
238static 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
265TDE_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
334static 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
364static 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
388static 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
423static 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
452static 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 TQRgb 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
482TDE_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
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.9.4
This website is maintained by Timothy Pearson.