26 #include <tqdatastream.h>
30 typedef TQ_UINT32 uint;
31 typedef TQ_UINT16 ushort;
32 typedef TQ_UINT8 uchar;
37 uchar targaMagic[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
43 TGA_TYPE_RLE_INDEXED = 9,
44 TGA_TYPE_RLE_RGB = 10,
45 TGA_TYPE_RLE_GREY = 11
48 #define TGA_INTERLEAVE_MASK 0xc0
49 #define TGA_INTERLEAVE_NONE 0x00
50 #define TGA_INTERLEAVE_2WAY 0x40
51 #define TGA_INTERLEAVE_4WAY 0x80
53 #define TGA_ORIGIN_MASK 0x30
54 #define TGA_ORIGIN_LEFT 0x00
55 #define TGA_ORIGIN_RIGHT 0x10
56 #define TGA_ORIGIN_LOWER 0x00
57 #define TGA_ORIGIN_UPPER 0x20
64 ushort colormap_index;
65 ushort colormap_length;
77 static TQDataStream & operator>> ( TQDataStream & s, TgaHeader & head )
80 s >> head.colormap_type;
82 s >> head.colormap_index;
83 s >> head.colormap_length;
84 s >> head.colormap_size;
94 static bool IsSupported(
const TgaHeader & head )
96 if( head.image_type != TGA_TYPE_INDEXED &&
97 head.image_type != TGA_TYPE_RGB &&
98 head.image_type != TGA_TYPE_GREY &&
99 head.image_type != TGA_TYPE_RLE_INDEXED &&
100 head.image_type != TGA_TYPE_RLE_RGB &&
101 head.image_type != TGA_TYPE_RLE_GREY )
105 if( head.image_type == TGA_TYPE_INDEXED ||
106 head.image_type == TGA_TYPE_RLE_INDEXED )
108 if( head.colormap_length > 256 || head.colormap_size != 24 )
113 if( head.width == 0 || head.height == 0 )
117 if( head.pixel_size != 8 && head.pixel_size != 16 &&
118 head.pixel_size != 24 && head.pixel_size != 32 )
131 struct TgaHeaderInfo {
138 TgaHeaderInfo(
const TgaHeader & tga ) : rle(false), pal(false), rgb(false), grey(false), supported(true)
140 switch( tga.image_type ) {
141 case TGA_TYPE_RLE_INDEXED:
144 case TGA_TYPE_INDEXED:
145 if( tga.colormap_type!=1 || tga.colormap_size!=24 || tga.colormap_length>256 ) {
151 case TGA_TYPE_RLE_RGB:
158 case TGA_TYPE_RLE_GREY:
172 static bool LoadTGA( TQDataStream & s,
const TgaHeader & tga, TQImage &img )
175 if( !img.create( tga.width, tga.height, 32 )) {
179 TgaHeaderInfo info(tga);
180 if( !info.supported ) {
182 kdDebug(399) <<
"This TGA file is not supported." << endl;
187 const int numAlphaBits = tga.flags & 0xf;
189 if( ( tga.pixel_size == 32 ) && ( tga.flags & 0xf ) ) {
190 img.setAlphaBuffer(
true );
193 uint pixel_size = (tga.pixel_size/8);
194 uint size = tga.width * tga.height * pixel_size;
198 kdDebug(399) <<
"This TGA file is broken with size " << size << endl;
207 s.readRawBytes( palette, 3 * tga.colormap_length );
211 uchar *
const image =
new uchar[size];
215 char * dst = (
char *)image;
223 uint count = (c & 0x7f) + 1;
224 num -= count * pixel_size;
228 assert(pixel_size <= 8);
230 s.readRawBytes( pixel, pixel_size );
232 memcpy(dst, pixel, pixel_size);
239 s.readRawBytes( dst, count );
246 s.readRawBytes( (
char *)image, size );
250 int y_start, y_step, y_end;
251 if( tga.flags & TGA_ORIGIN_UPPER ) {
257 y_start = tga.height - 1;
264 for(
int y = y_start; y != y_end; y += y_step ) {
265 TQRgb * scanline = (TQRgb *) img.scanLine( y );
269 for(
int x = 0; x < tga.width; x++ ) {
271 scanline[x] = tqRgb( palette[3*idx+2], palette[3*idx+1], palette[3*idx+0] );
274 else if( info.grey ) {
276 for(
int x = 0; x < tga.width; x++ ) {
277 scanline[x] = tqRgb( *src, *src, *src );
283 if( tga.pixel_size == 16 ) {
284 for(
int x = 0; x < tga.width; x++ ) {
285 Color555 c = *
reinterpret_cast<Color555 *
>(src);
286 scanline[x] = tqRgb( (c.r << 3) | (c.r >> 2), (c.g << 3) | (c.g >> 2), (c.b << 3) | (c.b >> 2) );
290 else if( tga.pixel_size == 24 ) {
291 for(
int x = 0; x < tga.width; x++ ) {
292 scanline[x] = tqRgb( src[2], src[1], src[0] );
296 else if( tga.pixel_size == 32 ) {
297 for(
int x = 0; x < tga.width; x++ ) {
299 const uchar alpha = ( src[3] << ( 8 - numAlphaBits ) );
300 scanline[x] = tqRgba( src[2], src[1], src[0], alpha );
316 TDE_EXPORT
void kimgio_tga_read( TQImageIO *io )
320 TQDataStream s( io->ioDevice() );
321 s.setByteOrder( TQDataStream::LittleEndian );
327 s.device()->at( TgaHeader::SIZE + tga.id_length );
331 kdDebug(399) <<
"This TGA file is not valid." << endl;
332 io->setImage( TQImage() );
338 if( !IsSupported(tga) ) {
339 kdDebug(399) <<
"This TGA file is not supported." << endl;
340 io->setImage( TQImage() );
347 bool result = LoadTGA(s, tga, img);
349 if( result ==
false ) {
350 kdDebug(399) <<
"Error loading TGA file." << endl;
351 io->setImage( TQImage() );
362 TDE_EXPORT
void kimgio_tga_write( TQImageIO *io )
364 TQDataStream s( io->ioDevice() );
365 s.setByteOrder( TQDataStream::LittleEndian );
367 const TQImage img = io->image();
368 const bool hasAlpha = img.hasAlphaBuffer();
369 for(
int i = 0; i < 12; i++ )
373 s << TQ_UINT16( img.width() );
374 s << TQ_UINT16( img.height() );
375 s << TQ_UINT8( hasAlpha ? 32 : 24 );
376 s << TQ_UINT8( hasAlpha ? 0x24 : 0x20 );
378 for(
int y = 0; y < img.height(); y++ )
379 for(
int x = 0; x < img.width(); x++ ) {
380 const TQRgb color = img.pixel( x, y );
381 s << TQ_UINT8( tqBlue( color ) );
382 s << TQ_UINT8( tqGreen( color ) );
383 s << TQ_UINT8( tqRed( color ) );
385 s << TQ_UINT8( tqAlpha( color ) );