]>
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"
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
53 HDR_PALETTELENGTH
= 5,
71 // ============================================================================
73 // ============================================================================
75 IMPLEMENT_DYNAMIC_CLASS(wxTGAHandler
, wxImageHandler
)
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
84 void FlipTGA(unsigned char* imageData
, int width
, int height
, short pixelSize
)
86 int lineLength
= width
* pixelSize
;
87 unsigned char *line1
= imageData
;
88 unsigned char *line2
= &imageData
[lineLength
* (height
- 1)];
91 for ( ; line1
< line2
; line2
-= (lineLength
* 2))
93 for (int index
= 0; index
< lineLength
; line1
++, line2
++, index
++)
103 void DecodeRLE(unsigned char* imageData
, unsigned long imageSize
,
104 short pixelSize
, wxInputStream
& stream
)
106 unsigned long index
= 0;
107 unsigned char current
;
109 unsigned char buf
[4];
111 while (index
< imageSize
)
113 current
= stream
.GetC();
116 if ( current
& 0x80 )
118 // Get the run length of the packet.
125 index
+= current
* pixelSize
;
127 // Repeat the pixel length times.
128 stream
.Read(buf
, pixelSize
);
130 for (unsigned int i
= 0; i
< length
; i
++)
132 memcpy(imageData
, buf
, pixelSize
);
134 imageData
+= pixelSize
;
139 // Get the run length of the packet.
142 length
= current
* pixelSize
;
146 // Write the next length pixels directly to the image data.
147 stream
.Read(imageData
, length
);
155 int ReadTGA(wxImage
* image
, wxInputStream
& stream
)
157 // Read in the TGA header
158 unsigned char hdr
[HDR_SIZE
];
159 stream
.Read(hdr
, HDR_SIZE
);
161 short offset
= hdr
[HDR_OFFSET
] + HDR_SIZE
;
162 short colorType
= hdr
[HDR_COLORTYPE
];
163 short imageType
= hdr
[HDR_IMAGETYPE
];
164 int paletteLength
= hdr
[HDR_PALETTELENGTH
] + 256 * hdr
[HDR_PALETTELENGTH
+ 1];
165 int width
= (hdr
[HDR_WIDTH
] + 256 * hdr
[HDR_WIDTH
+ 1]) -
166 (hdr
[HDR_XORIGIN
] + 256 * hdr
[HDR_XORIGIN
+ 1]);
167 int height
= (hdr
[HDR_HEIGHT
] + 256 * hdr
[HDR_HEIGHT
+ 1]) -
168 (hdr
[HDR_YORIGIN
] + 256 * hdr
[HDR_YORIGIN
+ 1]);
169 short bpp
= hdr
[HDR_BPP
];
170 short orientation
= hdr
[HDR_ORIENTATION
] & 0x20;
172 image
->Create(width
, height
);
179 const short pixelSize
= bpp
/ 8;
181 const unsigned long imageSize
= width
* height
* pixelSize
;
183 unsigned char *imageData
= (unsigned char* )malloc(imageSize
);
190 unsigned char *dst
= image
->GetData();
192 unsigned char* alpha
= NULL
;
193 if (bpp
== 16 || bpp
== 32)
197 alpha
= image
->GetAlpha();
200 // Seek from the offset we got from the TGA header.
201 stream
.SeekI(offset
, wxFromStart
);
203 // Load a palette if we have one.
204 if (colorType
== wxTGA_MAPPED
)
206 unsigned char buf
[3];
208 unsigned char* r
= new unsigned char[paletteLength
];
209 unsigned char* g
= new unsigned char[paletteLength
];
210 unsigned char* b
= new unsigned char[paletteLength
];
212 for (int i
= 0; i
< paletteLength
; i
++)
223 // Set the palette of the image.
225 image
->SetPalette(wxPalette(paletteLength
, r
, g
, b
));
227 #endif // wxUSE_PALETTE
234 // Handle the various TGA formats we support.
242 const wxPalette
& palette
= image
->GetPalette();
247 // No compression read the data directly to imageData.
249 stream
.Read(imageData
, imageSize
);
251 // If orientation == 0, then the image is stored upside down.
252 // We need to store it right side up.
254 if (orientation
== 0)
256 FlipTGA(imageData
, width
, height
, pixelSize
);
259 // Handle the different pixel depths.
267 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
269 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
282 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
284 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
289 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
295 return wxTGA_INVFORMAT
;
304 // No compression read the data directly to imageData.
306 stream
.Read(imageData
, imageSize
);
308 // If orientation == 0, then the image is stored upside down.
309 // We need to store it right side up.
311 if (orientation
== 0)
313 FlipTGA(imageData
, width
, height
, pixelSize
);
316 // Handle the different pixel depths.
326 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
328 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
332 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
336 temp
= (imageData
[index
] & 0x1f) << 3;
340 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
349 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
351 *(dst
++) = imageData
[index
+ 2];
352 *(dst
++) = imageData
[index
+ 1];
353 *(dst
++) = imageData
[index
];
362 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
364 *(dst
++) = imageData
[index
+ 2];
365 *(dst
++) = imageData
[index
+ 1];
366 *(dst
++) = imageData
[index
];
367 *(alpha
++) = imageData
[index
+ 3];
373 return wxTGA_INVFORMAT
;
382 // No compression read the data directly to imageData.
384 stream
.Read(imageData
, imageSize
);
386 // If orientation == 0, then the image is stored upside down.
387 // We need to store it right side up.
389 if (orientation
== 0)
391 FlipTGA(imageData
, width
, height
, pixelSize
);
394 // Handle the different pixel depths.
402 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
404 *(dst
++) = imageData
[index
];
405 *(dst
++) = imageData
[index
];
406 *(dst
++) = imageData
[index
];
415 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
417 *(dst
++) = imageData
[index
];
418 *(dst
++) = imageData
[index
];
419 *(dst
++) = imageData
[index
];
420 *(alpha
++) = imageData
[index
+ 1];
426 return wxTGA_INVFORMAT
;
435 const wxPalette
& palette
= image
->GetPalette();
440 // Decode the RLE data.
442 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
444 // If orientation == 0, then the image is stored upside down.
445 // We need to store it right side up.
447 if (orientation
== 0)
449 FlipTGA(imageData
, width
, height
, pixelSize
);
452 // Handle the different pixel depths.
460 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
462 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
475 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
477 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
482 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
488 return wxTGA_INVFORMAT
;
497 // Decode the RLE data.
499 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
501 // If orientation == 0, then the image is stored upside down.
502 // We need to store it right side up.
504 if (orientation
== 0)
506 FlipTGA(imageData
, width
, height
, pixelSize
);
509 // Handle the different pixel depths.
519 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
521 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
525 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
529 temp
= (imageData
[index
] & 0x1f) << 3;
533 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
542 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
544 *(dst
++) = imageData
[index
+ 2];
545 *(dst
++) = imageData
[index
+ 1];
546 *(dst
++) = imageData
[index
];
555 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
557 *(dst
++) = imageData
[index
+ 2];
558 *(dst
++) = imageData
[index
+ 1];
559 *(dst
++) = imageData
[index
];
560 *(alpha
++) = imageData
[index
+ 3];
566 return wxTGA_INVFORMAT
;
575 // Decode the RLE data.
577 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
579 // If orientation == 0, then the image is stored upside down.
580 // We need to store it right side up.
582 if (orientation
== 0)
584 FlipTGA(imageData
, width
, height
, pixelSize
);
587 // Handle the different pixel depths.
595 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
597 *(dst
++) = imageData
[index
];
598 *(dst
++) = imageData
[index
];
599 *(dst
++) = imageData
[index
];
608 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
610 *(dst
++) = imageData
[index
];
611 *(dst
++) = imageData
[index
];
612 *(dst
++) = imageData
[index
];
613 *(alpha
++) = imageData
[index
+ 1];
619 return wxTGA_INVFORMAT
;
625 return wxTGA_INVFORMAT
;
634 int SaveTGA(wxImage
* WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
))
636 wxLogError(wxT("Saving in TGA format is not implemented."));
641 // ----------------------------------------------------------------------------
643 // ----------------------------------------------------------------------------
645 bool wxTGAHandler::LoadFile(wxImage
* image
,
646 wxInputStream
& stream
,
650 if ( !CanRead(stream
) )
653 wxLogError(wxT("TGA: this is not a TGA file."));
660 int error
= ReadTGA(image
, stream
);
661 if ( error
!= wxTGA_OK
)
667 case wxTGA_INVFORMAT
:
668 wxLogError(wxT("TGA: image format unsupported."));
672 wxLogError(wxT("TGA: couldn't allocate memory."));
676 wxLogError(wxT("TGA: unknown error!"));
688 bool wxTGAHandler::SaveFile(wxImage
* image
, wxOutputStream
& stream
, bool verbose
)
690 int error
= SaveTGA(image
, stream
);
692 if ( error
!= wxTGA_OK
)
698 case wxTGA_INVFORMAT
:
699 wxLogError(wxT("TGA: invalid image."));
703 wxLogError(wxT("TGA: couldn't allocate memory."));
707 wxLogError(wxT("TGA: unknown error!"));
717 bool wxTGAHandler::DoCanRead(wxInputStream
& stream
)
719 // read the fixed-size TGA headers
720 unsigned char hdr
[HDR_SIZE
];
721 stream
.Read(hdr
, HDR_SIZE
);
723 // Check wether we can read the file or not.
725 short colorType
= hdr
[HDR_COLORTYPE
];
726 if ( colorType
!= wxTGA_UNMAPPED
&& colorType
!= wxTGA_MAPPED
)
731 short imageType
= hdr
[HDR_IMAGETYPE
];
732 if ( imageType
== 0 || imageType
== 32 || imageType
== 33 )
737 short bpp
= hdr
[HDR_BPP
];
738 if ( bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32 )
746 #endif // wxUSE_STREAMS
748 #endif // wxUSE_IMAGE && wxUSE_TGA