]>
git.saurik.com Git - wxWidgets.git/blob - src/common/imagtga.cpp
1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxImage TGA handler
4 // Author: Seth Jackson
6 // Copyright: (c) 2005 Seth Jackson
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
10 // ============================================================================
12 // ============================================================================
14 // ----------------------------------------------------------------------------
16 // ----------------------------------------------------------------------------
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
25 #if wxUSE_IMAGE && wxUSE_TGA
28 #include "wx/palette.h"
31 #include "wx/imagtga.h"
33 #include "wx/scopeguard.h"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
54 HDR_PALETTELENGTH
= 5,
72 // ============================================================================
74 // ============================================================================
76 IMPLEMENT_DYNAMIC_CLASS(wxTGAHandler
, wxImageHandler
)
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
85 void FlipTGA(unsigned char* imageData
, int width
, int height
, short pixelSize
)
87 int lineLength
= width
* pixelSize
;
88 unsigned char *line1
= imageData
;
89 unsigned char *line2
= &imageData
[lineLength
* (height
- 1)];
92 for ( ; line1
< line2
; line2
-= (lineLength
* 2))
94 for (int index
= 0; index
< lineLength
; line1
++, line2
++, index
++)
104 void DecodeRLE(unsigned char* imageData
, unsigned long imageSize
,
105 short pixelSize
, wxInputStream
& stream
)
107 unsigned long index
= 0;
108 unsigned char current
;
110 unsigned char buf
[4];
112 while (index
< imageSize
)
114 current
= stream
.GetC();
117 if ( current
& 0x80 )
119 // Get the run length of the packet.
126 index
+= current
* pixelSize
;
128 // Repeat the pixel length times.
129 stream
.Read(buf
, pixelSize
);
131 for (unsigned int i
= 0; i
< length
; i
++)
133 memcpy(imageData
, buf
, pixelSize
);
135 imageData
+= pixelSize
;
140 // Get the run length of the packet.
143 length
= current
* pixelSize
;
147 // Write the next length pixels directly to the image data.
148 stream
.Read(imageData
, length
);
156 int ReadTGA(wxImage
* image
, wxInputStream
& stream
)
158 // Read in the TGA header
159 unsigned char hdr
[HDR_SIZE
];
160 stream
.Read(hdr
, HDR_SIZE
);
162 short offset
= hdr
[HDR_OFFSET
] + HDR_SIZE
;
163 short colorType
= hdr
[HDR_COLORTYPE
];
164 short imageType
= hdr
[HDR_IMAGETYPE
];
165 int paletteLength
= hdr
[HDR_PALETTELENGTH
] + 256 * hdr
[HDR_PALETTELENGTH
+ 1];
166 int width
= (hdr
[HDR_WIDTH
] + 256 * hdr
[HDR_WIDTH
+ 1]) -
167 (hdr
[HDR_XORIGIN
] + 256 * hdr
[HDR_XORIGIN
+ 1]);
168 int height
= (hdr
[HDR_HEIGHT
] + 256 * hdr
[HDR_HEIGHT
+ 1]) -
169 (hdr
[HDR_YORIGIN
] + 256 * hdr
[HDR_YORIGIN
+ 1]);
170 short bpp
= hdr
[HDR_BPP
];
171 short orientation
= hdr
[HDR_ORIENTATION
] & 0x20;
173 image
->Create(width
, height
);
180 const short pixelSize
= bpp
/ 8;
182 const unsigned long imageSize
= width
* height
* pixelSize
;
184 unsigned char *imageData
= (unsigned char* )malloc(imageSize
);
191 wxON_BLOCK_EXIT1(free
, imageData
);
193 unsigned char *dst
= image
->GetData();
195 unsigned char* alpha
= NULL
;
196 if (bpp
== 16 || bpp
== 32)
200 alpha
= image
->GetAlpha();
203 // Seek from the offset we got from the TGA header.
204 stream
.SeekI(offset
, wxFromStart
);
206 // Load a palette if we have one.
207 if (colorType
== wxTGA_MAPPED
)
209 unsigned char buf
[3];
211 unsigned char* r
= new unsigned char[paletteLength
];
212 unsigned char* g
= new unsigned char[paletteLength
];
213 unsigned char* b
= new unsigned char[paletteLength
];
215 for (int i
= 0; i
< paletteLength
; i
++)
225 // Set the palette of the image.
226 image
->SetPalette(wxPalette(paletteLength
, r
, g
, b
));
227 #endif // wxUSE_PALETTE
234 // Handle the various TGA formats we support.
243 const wxPalette
& palette
= image
->GetPalette();
248 // No compression read the data directly to imageData.
250 stream
.Read(imageData
, imageSize
);
252 // If orientation == 0, then the image is stored upside down.
253 // We need to store it right side up.
255 if (orientation
== 0)
257 FlipTGA(imageData
, width
, height
, pixelSize
);
260 // Handle the different pixel depths.
268 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
270 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
283 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
285 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
290 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
296 return wxTGA_INVFORMAT
;
300 #endif // wxUSE_PALETTE
306 // No compression read the data directly to imageData.
308 stream
.Read(imageData
, imageSize
);
310 // If orientation == 0, then the image is stored upside down.
311 // We need to store it right side up.
313 if (orientation
== 0)
315 FlipTGA(imageData
, width
, height
, pixelSize
);
318 // Handle the different pixel depths.
328 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
330 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
334 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
338 temp
= (imageData
[index
] & 0x1f) << 3;
342 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
351 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
353 *(dst
++) = imageData
[index
+ 2];
354 *(dst
++) = imageData
[index
+ 1];
355 *(dst
++) = imageData
[index
];
364 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
366 *(dst
++) = imageData
[index
+ 2];
367 *(dst
++) = imageData
[index
+ 1];
368 *(dst
++) = imageData
[index
];
369 *(alpha
++) = imageData
[index
+ 3];
375 return wxTGA_INVFORMAT
;
384 // No compression read the data directly to imageData.
386 stream
.Read(imageData
, imageSize
);
388 // If orientation == 0, then the image is stored upside down.
389 // We need to store it right side up.
391 if (orientation
== 0)
393 FlipTGA(imageData
, width
, height
, pixelSize
);
396 // Handle the different pixel depths.
404 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
406 *(dst
++) = imageData
[index
];
407 *(dst
++) = imageData
[index
];
408 *(dst
++) = imageData
[index
];
417 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
419 *(dst
++) = imageData
[index
];
420 *(dst
++) = imageData
[index
];
421 *(dst
++) = imageData
[index
];
422 *(alpha
++) = imageData
[index
+ 1];
428 return wxTGA_INVFORMAT
;
438 const wxPalette
& palette
= image
->GetPalette();
443 // Decode the RLE data.
445 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
447 // If orientation == 0, then the image is stored upside down.
448 // We need to store it right side up.
450 if (orientation
== 0)
452 FlipTGA(imageData
, width
, height
, pixelSize
);
455 // Handle the different pixel depths.
463 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
465 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
478 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
480 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
485 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
491 return wxTGA_INVFORMAT
;
495 #endif // wxUSE_PALETTE
501 // Decode the RLE data.
503 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
505 // If orientation == 0, then the image is stored upside down.
506 // We need to store it right side up.
508 if (orientation
== 0)
510 FlipTGA(imageData
, width
, height
, pixelSize
);
513 // Handle the different pixel depths.
523 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
525 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
529 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
533 temp
= (imageData
[index
] & 0x1f) << 3;
537 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
546 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
548 *(dst
++) = imageData
[index
+ 2];
549 *(dst
++) = imageData
[index
+ 1];
550 *(dst
++) = imageData
[index
];
559 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
561 *(dst
++) = imageData
[index
+ 2];
562 *(dst
++) = imageData
[index
+ 1];
563 *(dst
++) = imageData
[index
];
564 *(alpha
++) = imageData
[index
+ 3];
570 return wxTGA_INVFORMAT
;
579 // Decode the RLE data.
581 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
583 // If orientation == 0, then the image is stored upside down.
584 // We need to store it right side up.
586 if (orientation
== 0)
588 FlipTGA(imageData
, width
, height
, pixelSize
);
591 // Handle the different pixel depths.
599 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
601 *(dst
++) = imageData
[index
];
602 *(dst
++) = imageData
[index
];
603 *(dst
++) = imageData
[index
];
612 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
614 *(dst
++) = imageData
[index
];
615 *(dst
++) = imageData
[index
];
616 *(dst
++) = imageData
[index
];
617 *(alpha
++) = imageData
[index
+ 1];
623 return wxTGA_INVFORMAT
;
629 return wxTGA_INVFORMAT
;
636 int SaveTGA(wxImage
* WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
))
638 wxLogError(wxT("Saving in TGA format is not implemented."));
643 // ----------------------------------------------------------------------------
645 // ----------------------------------------------------------------------------
647 bool wxTGAHandler::LoadFile(wxImage
* image
,
648 wxInputStream
& stream
,
652 if ( !CanRead(stream
) )
655 wxLogError(wxT("TGA: this is not a TGA file."));
662 int error
= ReadTGA(image
, stream
);
663 if ( error
!= wxTGA_OK
)
669 case wxTGA_INVFORMAT
:
670 wxLogError(wxT("TGA: image format unsupported."));
674 wxLogError(wxT("TGA: couldn't allocate memory."));
678 wxLogError(wxT("TGA: unknown error!"));
690 bool wxTGAHandler::SaveFile(wxImage
* image
, wxOutputStream
& stream
, bool verbose
)
692 int error
= SaveTGA(image
, stream
);
694 if ( error
!= wxTGA_OK
)
700 case wxTGA_INVFORMAT
:
701 wxLogError(wxT("TGA: invalid image."));
705 wxLogError(wxT("TGA: couldn't allocate memory."));
709 wxLogError(wxT("TGA: unknown error!"));
719 bool wxTGAHandler::DoCanRead(wxInputStream
& stream
)
721 // read the fixed-size TGA headers
722 unsigned char hdr
[HDR_SIZE
];
723 stream
.Read(hdr
, HDR_SIZE
);
725 // Check wether we can read the file or not.
727 short colorType
= hdr
[HDR_COLORTYPE
];
728 if ( colorType
!= wxTGA_UNMAPPED
&& colorType
!= wxTGA_MAPPED
)
733 short imageType
= hdr
[HDR_IMAGETYPE
];
734 if ( imageType
== 0 || imageType
== 32 || imageType
== 33 )
739 short bpp
= hdr
[HDR_BPP
];
740 if ( bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32 )
748 #endif // wxUSE_STREAMS
750 #endif // wxUSE_IMAGE && wxUSE_TGA