]>
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
++)
222 // Set the palette of the image.
223 image
->SetPalette(wxPalette(paletteLength
, r
, g
, b
));
224 #endif // wxUSE_PALETTE
231 // Handle the various TGA formats we support.
240 const wxPalette
& palette
= image
->GetPalette();
245 // No compression read the data directly to imageData.
247 stream
.Read(imageData
, imageSize
);
249 // If orientation == 0, then the image is stored upside down.
250 // We need to store it right side up.
252 if (orientation
== 0)
254 FlipTGA(imageData
, width
, height
, pixelSize
);
257 // Handle the different pixel depths.
265 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
267 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
280 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
282 palette
.GetRGB(imageData
[index
], &r
, &g
, &b
);
287 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
293 return wxTGA_INVFORMAT
;
297 #endif // wxUSE_PALETTE
303 // No compression read the data directly to imageData.
305 stream
.Read(imageData
, imageSize
);
307 // If orientation == 0, then the image is stored upside down.
308 // We need to store it right side up.
310 if (orientation
== 0)
312 FlipTGA(imageData
, width
, height
, pixelSize
);
315 // Handle the different pixel depths.
325 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
327 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
331 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
335 temp
= (imageData
[index
] & 0x1f) << 3;
339 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
348 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
350 *(dst
++) = imageData
[index
+ 2];
351 *(dst
++) = imageData
[index
+ 1];
352 *(dst
++) = imageData
[index
];
361 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
363 *(dst
++) = imageData
[index
+ 2];
364 *(dst
++) = imageData
[index
+ 1];
365 *(dst
++) = imageData
[index
];
366 *(alpha
++) = imageData
[index
+ 3];
372 return wxTGA_INVFORMAT
;
381 // No compression read the data directly to imageData.
383 stream
.Read(imageData
, imageSize
);
385 // If orientation == 0, then the image is stored upside down.
386 // We need to store it right side up.
388 if (orientation
== 0)
390 FlipTGA(imageData
, width
, height
, pixelSize
);
393 // Handle the different pixel depths.
401 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
403 *(dst
++) = imageData
[index
];
404 *(dst
++) = imageData
[index
];
405 *(dst
++) = imageData
[index
];
414 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
416 *(dst
++) = imageData
[index
];
417 *(dst
++) = imageData
[index
];
418 *(dst
++) = imageData
[index
];
419 *(alpha
++) = imageData
[index
+ 1];
425 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
;
492 #endif // wxUSE_PALETTE
498 // Decode the RLE data.
500 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
502 // If orientation == 0, then the image is stored upside down.
503 // We need to store it right side up.
505 if (orientation
== 0)
507 FlipTGA(imageData
, width
, height
, pixelSize
);
510 // Handle the different pixel depths.
520 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
522 temp
= (imageData
[index
+ 1] & 0x7c) << 1;
526 temp
= ((imageData
[index
+ 1] & 0x03) << 6) | ((imageData
[index
] & 0xe0) >> 2);
530 temp
= (imageData
[index
] & 0x1f) << 3;
534 *(alpha
++) = (imageData
[index
+ 1] & 0x80) ? 0 : 255;
543 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
545 *(dst
++) = imageData
[index
+ 2];
546 *(dst
++) = imageData
[index
+ 1];
547 *(dst
++) = imageData
[index
];
556 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
558 *(dst
++) = imageData
[index
+ 2];
559 *(dst
++) = imageData
[index
+ 1];
560 *(dst
++) = imageData
[index
];
561 *(alpha
++) = imageData
[index
+ 3];
567 return wxTGA_INVFORMAT
;
576 // Decode the RLE data.
578 DecodeRLE(imageData
, imageSize
, pixelSize
, stream
);
580 // If orientation == 0, then the image is stored upside down.
581 // We need to store it right side up.
583 if (orientation
== 0)
585 FlipTGA(imageData
, width
, height
, pixelSize
);
588 // Handle the different pixel depths.
596 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
598 *(dst
++) = imageData
[index
];
599 *(dst
++) = imageData
[index
];
600 *(dst
++) = imageData
[index
];
609 for (unsigned long index
= 0; index
< imageSize
; index
+= pixelSize
)
611 *(dst
++) = imageData
[index
];
612 *(dst
++) = imageData
[index
];
613 *(dst
++) = imageData
[index
];
614 *(alpha
++) = imageData
[index
+ 1];
620 return wxTGA_INVFORMAT
;
626 return wxTGA_INVFORMAT
;
635 int SaveTGA(wxImage
* WXUNUSED(image
), wxOutputStream
& WXUNUSED(stream
))
637 wxLogError(wxT("Saving in TGA format is not implemented."));
642 // ----------------------------------------------------------------------------
644 // ----------------------------------------------------------------------------
646 bool wxTGAHandler::LoadFile(wxImage
* image
,
647 wxInputStream
& stream
,
651 if ( !CanRead(stream
) )
654 wxLogError(wxT("TGA: this is not a TGA file."));
661 int error
= ReadTGA(image
, stream
);
662 if ( error
!= wxTGA_OK
)
668 case wxTGA_INVFORMAT
:
669 wxLogError(wxT("TGA: image format unsupported."));
673 wxLogError(wxT("TGA: couldn't allocate memory."));
677 wxLogError(wxT("TGA: unknown error!"));
689 bool wxTGAHandler::SaveFile(wxImage
* image
, wxOutputStream
& stream
, bool verbose
)
691 int error
= SaveTGA(image
, stream
);
693 if ( error
!= wxTGA_OK
)
699 case wxTGA_INVFORMAT
:
700 wxLogError(wxT("TGA: invalid image."));
704 wxLogError(wxT("TGA: couldn't allocate memory."));
708 wxLogError(wxT("TGA: unknown error!"));
718 bool wxTGAHandler::DoCanRead(wxInputStream
& stream
)
720 // read the fixed-size TGA headers
721 unsigned char hdr
[HDR_SIZE
];
722 stream
.Read(hdr
, HDR_SIZE
);
724 // Check wether we can read the file or not.
726 short colorType
= hdr
[HDR_COLORTYPE
];
727 if ( colorType
!= wxTGA_UNMAPPED
&& colorType
!= wxTGA_MAPPED
)
732 short imageType
= hdr
[HDR_IMAGETYPE
];
733 if ( imageType
== 0 || imageType
== 32 || imageType
== 33 )
738 short bpp
= hdr
[HDR_BPP
];
739 if ( bpp
!= 8 && bpp
!= 16 && bpp
!= 24 && bpp
!= 32 )
747 #endif // wxUSE_STREAMS
749 #endif // wxUSE_IMAGE && wxUSE_TGA