]> git.saurik.com Git - wxWidgets.git/blame - src/common/imagtga.cpp
No changes, just move mouse capturing bookkeeping data out of wxWindow.
[wxWidgets.git] / src / common / imagtga.cpp
CommitLineData
3af706cc 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/common/imagtga.cpp
3af706cc
VZ
3// Purpose: wxImage TGA handler
4// Author: Seth Jackson
3af706cc
VZ
5// Copyright: (c) 2005 Seth Jackson
6// Licence: wxWindows licence
7/////////////////////////////////////////////////////////////////////////////
8
9// ============================================================================
10// declarations
11// ============================================================================
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
21 #pragma hdrstop
22#endif
23
24#if wxUSE_IMAGE && wxUSE_TGA
25
26#ifndef WX_PRECOMP
27 #include "wx/palette.h"
28#endif
29
30#include "wx/imagtga.h"
31#include "wx/log.h"
56692119 32#include "wx/scopeguard.h"
3af706cc
VZ
33
34// ----------------------------------------------------------------------------
35// constants
36// ----------------------------------------------------------------------------
37
38// TGA error codes.
39enum
40{
8fee6306
VZ
41 wxTGA_OK,
42 wxTGA_INVFORMAT,
43 wxTGA_MEMERR,
44 wxTGA_IOERR
3af706cc
VZ
45};
46
47// TGA header bytes.
48enum
49{
50 HDR_OFFSET = 0,
51 HDR_COLORTYPE = 1,
52 HDR_IMAGETYPE = 2,
53 HDR_PALETTESTART = 3,
54 HDR_PALETTELENGTH = 5,
55 HDR_PALETTEBITS = 7,
56 HDR_XORIGIN = 8,
57 HDR_YORIGIN = 10,
58 HDR_WIDTH = 12,
59 HDR_HEIGHT = 14,
60 HDR_BPP = 16,
61 HDR_ORIENTATION = 17,
62 HDR_SIZE
63};
64
65// TGA color types.
66enum
67{
68 wxTGA_UNMAPPED = 0,
69 wxTGA_MAPPED = 1
70};
71
72// ============================================================================
73// implementation
74// ============================================================================
75
76IMPLEMENT_DYNAMIC_CLASS(wxTGAHandler, wxImageHandler)
77
78#if wxUSE_STREAMS
79
80// ----------------------------------------------------------------------------
81// worker functions
82// ----------------------------------------------------------------------------
83
84static
85void FlipTGA(unsigned char* imageData, int width, int height, short pixelSize)
86{
87 int lineLength = width * pixelSize;
88 unsigned char *line1 = imageData;
89 unsigned char *line2 = &imageData[lineLength * (height - 1)];
90
91 unsigned char temp;
92 for ( ; line1 < line2; line2 -= (lineLength * 2))
93 {
94 for (int index = 0; index < lineLength; line1++, line2++, index++)
95 {
96 temp = *line1;
97 *line1 = *line2;
98 *line2 = temp;
99 }
100 }
101}
102
8fee6306 103// return wxTGA_OK or wxTGA_IOERR
3af706cc 104static
8fee6306 105int DecodeRLE(unsigned char* imageData, unsigned long imageSize,
3af706cc
VZ
106 short pixelSize, wxInputStream& stream)
107{
108 unsigned long index = 0;
109 unsigned char current;
110 unsigned int length;
111 unsigned char buf[4];
112
113 while (index < imageSize)
114 {
8fee6306
VZ
115 int ch = stream.GetC();
116 if ( ch == wxEOF )
117 return wxTGA_IOERR;
118
119 current = ch;
3af706cc
VZ
120
121 // RLE packet.
122 if ( current & 0x80 )
123 {
124 // Get the run length of the packet.
125 current &= 0x7f;
126
127 current++;
128
129 length = current;
130
131 index += current * pixelSize;
132
fdfedfc0
DS
133 if (index >= imageSize)
134 {
135 return wxTGA_IOERR;
136 }
137
3af706cc 138 // Repeat the pixel length times.
8fee6306
VZ
139 if ( !stream.Read(buf, pixelSize) )
140 return wxTGA_IOERR;
3af706cc
VZ
141
142 for (unsigned int i = 0; i < length; i++)
143 {
144 memcpy(imageData, buf, pixelSize);
145
146 imageData += pixelSize;
147 }
148 }
149 else // Raw packet.
150 {
151 // Get the run length of the packet.
152 current++;
153
154 length = current * pixelSize;
155
156 index += length;
157
fdfedfc0
DS
158 if (index >= imageSize)
159 {
160 return wxTGA_IOERR;
161 }
162
3af706cc 163 // Write the next length pixels directly to the image data.
8fee6306
VZ
164 if ( !stream.Read(imageData, length) )
165 return wxTGA_IOERR;
3af706cc
VZ
166
167 imageData += length;
168 }
169 }
8fee6306
VZ
170
171 return wxTGA_OK;
3af706cc
VZ
172}
173
07e99d87
DS
174/*
175Mimic the behaviour of wxPalette.GetRGB and the way the TGA image handler
176used it. That is: don't check the return value of GetRGB and continue decoding
177using previous RGB values.
178
179It might be better to check for palette index bounds and stop decoding if
180it's out of range (and add something like wxTGA_DATAERR to indicate unexpected
181pixel data).
182*/
183static
184void Palette_GetRGB(const unsigned char *palette, unsigned int paletteCount,
185 unsigned int index,
186 unsigned char *red, unsigned char *green, unsigned char *blue)
187{
188 if (index >= paletteCount)
189 {
190 return;
191 }
192
193 *red = palette[index];
194 *green = palette[(paletteCount * 1) + index];
195 *blue = palette[(paletteCount * 2) + index];
196}
197
198static
199void Palette_SetRGB(unsigned char *palette, unsigned int paletteCount,
200 unsigned int index,
201 unsigned char red, unsigned char green, unsigned char blue)
202{
203 palette[index] = red;
204 palette[(paletteCount * 1) + index] = green;
205 palette[(paletteCount * 2) + index] = blue;
206}
207
3af706cc
VZ
208static
209int ReadTGA(wxImage* image, wxInputStream& stream)
210{
211 // Read in the TGA header
212 unsigned char hdr[HDR_SIZE];
213 stream.Read(hdr, HDR_SIZE);
214
215 short offset = hdr[HDR_OFFSET] + HDR_SIZE;
216 short colorType = hdr[HDR_COLORTYPE];
217 short imageType = hdr[HDR_IMAGETYPE];
07e99d87
DS
218 unsigned int paletteLength = hdr[HDR_PALETTELENGTH]
219 + 256 * hdr[HDR_PALETTELENGTH + 1];
3af706cc
VZ
220 int width = (hdr[HDR_WIDTH] + 256 * hdr[HDR_WIDTH + 1]) -
221 (hdr[HDR_XORIGIN] + 256 * hdr[HDR_XORIGIN + 1]);
222 int height = (hdr[HDR_HEIGHT] + 256 * hdr[HDR_HEIGHT + 1]) -
223 (hdr[HDR_YORIGIN] + 256 * hdr[HDR_YORIGIN + 1]);
224 short bpp = hdr[HDR_BPP];
225 short orientation = hdr[HDR_ORIENTATION] & 0x20;
226
227 image->Create(width, height);
228
a1b806b9 229 if (!image->IsOk())
3af706cc
VZ
230 {
231 return wxTGA_MEMERR;
232 }
233
234 const short pixelSize = bpp / 8;
235
236 const unsigned long imageSize = width * height * pixelSize;
237
238 unsigned char *imageData = (unsigned char* )malloc(imageSize);
239
240 if (!imageData)
241 {
242 return wxTGA_MEMERR;
243 }
244
56692119
VZ
245 wxON_BLOCK_EXIT1(free, imageData);
246
3af706cc
VZ
247 unsigned char *dst = image->GetData();
248
249 unsigned char* alpha = NULL;
250 if (bpp == 16 || bpp == 32)
251 {
252 image->SetAlpha();
253
254 alpha = image->GetAlpha();
255 }
256
257 // Seek from the offset we got from the TGA header.
b81e4506
FM
258 if (stream.SeekI(offset, wxFromStart) == wxInvalidOffset)
259 return wxTGA_INVFORMAT;
3af706cc 260
07e99d87 261 unsigned char *palette = NULL;
3af706cc
VZ
262 // Load a palette if we have one.
263 if (colorType == wxTGA_MAPPED)
264 {
265 unsigned char buf[3];
266
07e99d87 267 palette = (unsigned char *) malloc(paletteLength * 3);
3af706cc 268
07e99d87 269 for (unsigned int i = 0; i < paletteLength; i++)
3af706cc
VZ
270 {
271 stream.Read(buf, 3);
272
07e99d87 273 Palette_SetRGB(palette, paletteLength, i, buf[2], buf[1], buf[0]);
3af706cc
VZ
274 }
275
6e3d5828 276#if wxUSE_PALETTE
3af706cc 277 // Set the palette of the image.
07e99d87
DS
278 image->SetPalette(wxPalette((int) paletteLength, &palette[0],
279 &palette[paletteLength * 1], &palette[paletteLength * 2]));
6e3d5828 280#endif // wxUSE_PALETTE
3af706cc 281
3af706cc
VZ
282 }
283
07e99d87
DS
284 wxON_BLOCK_EXIT1(free, palette);
285
3af706cc
VZ
286 // Handle the various TGA formats we support.
287
288 switch (imageType)
289 {
290 // Raw indexed.
291
292 case 1:
293 {
9d261cbb
VZ
294 unsigned char r = 0;
295 unsigned char g = 0;
296 unsigned char b = 0;
3af706cc
VZ
297
298 // No compression read the data directly to imageData.
299
300 stream.Read(imageData, imageSize);
301
302 // If orientation == 0, then the image is stored upside down.
303 // We need to store it right side up.
304
305 if (orientation == 0)
306 {
307 FlipTGA(imageData, width, height, pixelSize);
308 }
309
310 // Handle the different pixel depths.
311
312 switch (bpp)
313 {
314 // 8 bpp.
315
316 case 8:
317 {
318 for (unsigned long index = 0; index < imageSize; index += pixelSize)
319 {
07e99d87
DS
320 Palette_GetRGB(palette, paletteLength,
321 imageData[index], &r, &g, &b);
3af706cc
VZ
322
323 *(dst++) = r;
324 *(dst++) = g;
325 *(dst++) = b;
326 }
327 }
328 break;
329
330 // 16 bpp.
331
332 case 16:
333 {
334 for (unsigned long index = 0; index < imageSize; index += pixelSize)
335 {
07e99d87
DS
336 Palette_GetRGB(palette, paletteLength,
337 imageData[index], &r, &g, &b);
3af706cc
VZ
338
339 *(dst++) = r;
340 *(dst++) = g;
341 *(dst++) = b;
342 *(alpha++) = (imageData[index + 1] & 0x80) ? 0 : 255;
343 }
344 }
345 break;
346
347 default:
348 return wxTGA_INVFORMAT;
349 }
350 }
351 break;
352
353 // Raw RGB.
354
355 case 2:
356 {
357 // No compression read the data directly to imageData.
358
359 stream.Read(imageData, imageSize);
360
361 // If orientation == 0, then the image is stored upside down.
362 // We need to store it right side up.
363
364 if (orientation == 0)
365 {
366 FlipTGA(imageData, width, height, pixelSize);
367 }
368
369 // Handle the different pixel depths.
370
371 switch (bpp)
372 {
373 //16 bpp.
374
375 case 16:
376 {
377 unsigned char temp;
378
379 for (unsigned long index = 0; index < imageSize; index += pixelSize)
380 {
381 temp = (imageData[index + 1] & 0x7c) << 1;
382 temp |= temp >> 5;
383 *(dst++) = temp;
384
385 temp = ((imageData[index + 1] & 0x03) << 6) | ((imageData[index] & 0xe0) >> 2);
386 temp |= temp >> 5;
387 *(dst++) = temp;
388
389 temp = (imageData[index] & 0x1f) << 3;
390 temp |= temp >> 5;
391 *(dst++) = temp;
392
393 *(alpha++) = (imageData[index + 1] & 0x80) ? 0 : 255;
394 }
395 }
396 break;
397
398 // 24 bpp.
399
400 case 24:
401 {
402 for (unsigned long index = 0; index < imageSize; index += pixelSize)
403 {
404 *(dst++) = imageData[index + 2];
405 *(dst++) = imageData[index + 1];
406 *(dst++) = imageData[index];
407 }
408 }
409 break;
410
411 // 32 bpp.
412
413 case 32:
414 {
415 for (unsigned long index = 0; index < imageSize; index += pixelSize)
416 {
417 *(dst++) = imageData[index + 2];
418 *(dst++) = imageData[index + 1];
419 *(dst++) = imageData[index];
420 *(alpha++) = imageData[index + 3];
421 }
422 }
423 break;
424
425 default:
426 return wxTGA_INVFORMAT;
427 }
428 }
429 break;
430
431 // Raw grayscale.
432
433 case 3:
434 {
435 // No compression read the data directly to imageData.
436
437 stream.Read(imageData, imageSize);
438
439 // If orientation == 0, then the image is stored upside down.
440 // We need to store it right side up.
441
442 if (orientation == 0)
443 {
444 FlipTGA(imageData, width, height, pixelSize);
445 }
446
447 // Handle the different pixel depths.
448
449 switch (bpp)
450 {
451 // 8 bpp.
452
453 case 8:
454 {
455 for (unsigned long index = 0; index < imageSize; index += pixelSize)
456 {
457 *(dst++) = imageData[index];
458 *(dst++) = imageData[index];
459 *(dst++) = imageData[index];
460 }
461 }
462 break;
463
464 // 16 bpp.
465
466 case 16:
467 {
468 for (unsigned long index = 0; index < imageSize; index += pixelSize)
469 {
470 *(dst++) = imageData[index];
471 *(dst++) = imageData[index];
472 *(dst++) = imageData[index];
473 *(alpha++) = imageData[index + 1];
474 }
475 }
476 break;
477
478 default:
479 return wxTGA_INVFORMAT;
480 }
481 }
482 break;
483
484 // RLE indexed.
485
486 case 9:
487 {
9d261cbb
VZ
488 unsigned char r = 0;
489 unsigned char g = 0;
490 unsigned char b = 0;
3af706cc
VZ
491
492 // Decode the RLE data.
493
8fee6306
VZ
494 int rc = DecodeRLE(imageData, imageSize, pixelSize, stream);
495 if ( rc != wxTGA_OK )
496 return rc;
3af706cc
VZ
497
498 // If orientation == 0, then the image is stored upside down.
499 // We need to store it right side up.
500
501 if (orientation == 0)
502 {
503 FlipTGA(imageData, width, height, pixelSize);
504 }
505
506 // Handle the different pixel depths.
507
508 switch (bpp)
509 {
510 // 8 bpp.
511
512 case 8:
513 {
514 for (unsigned long index = 0; index < imageSize; index += pixelSize)
515 {
07e99d87
DS
516 Palette_GetRGB(palette, paletteLength,
517 imageData[index], &r, &g, &b);
3af706cc
VZ
518
519 *(dst++) = r;
520 *(dst++) = g;
521 *(dst++) = b;
522 }
523 }
524 break;
525
526 // 16 bpp.
527
528 case 16:
529 {
530 for (unsigned long index = 0; index < imageSize; index += pixelSize)
531 {
07e99d87
DS
532 Palette_GetRGB(palette, paletteLength,
533 imageData[index], &r, &g, &b);
3af706cc
VZ
534
535 *(dst++) = r;
536 *(dst++) = g;
537 *(dst++) = b;
538 *(alpha++) = (imageData[index + 1] & 0x80) ? 0 : 255;
539 }
540 }
541 break;
542
543 default:
544 return wxTGA_INVFORMAT;
545 }
546 }
547 break;
548
549 // RLE RGB.
550
551 case 10:
552 {
553 // Decode the RLE data.
554
8fee6306
VZ
555 int rc = DecodeRLE(imageData, imageSize, pixelSize, stream);
556 if ( rc != wxTGA_OK )
557 return rc;
3af706cc
VZ
558
559 // If orientation == 0, then the image is stored upside down.
560 // We need to store it right side up.
561
562 if (orientation == 0)
563 {
564 FlipTGA(imageData, width, height, pixelSize);
565 }
566
567 // Handle the different pixel depths.
568
569 switch (bpp)
570 {
571 //16 bpp.
572
573 case 16:
574 {
575 unsigned char temp;
576
577 for (unsigned long index = 0; index < imageSize; index += pixelSize)
578 {
579 temp = (imageData[index + 1] & 0x7c) << 1;
580 temp |= temp >> 5;
581 *(dst++) = temp;
582
583 temp = ((imageData[index + 1] & 0x03) << 6) | ((imageData[index] & 0xe0) >> 2);
584 temp |= temp >> 5;
585 *(dst++) = temp;
586
587 temp = (imageData[index] & 0x1f) << 3;
588 temp |= temp >> 5;
589 *(dst++) = temp;
590
591 *(alpha++) = (imageData[index + 1] & 0x80) ? 0 : 255;
592 }
593 }
594 break;
595
596 // 24 bpp.
597
598 case 24:
599 {
600 for (unsigned long index = 0; index < imageSize; index += pixelSize)
601 {
602 *(dst++) = imageData[index + 2];
603 *(dst++) = imageData[index + 1];
604 *(dst++) = imageData[index];
605 }
606 }
607 break;
608
609 // 32 bpp.
610
611 case 32:
612 {
613 for (unsigned long index = 0; index < imageSize; index += pixelSize)
614 {
615 *(dst++) = imageData[index + 2];
616 *(dst++) = imageData[index + 1];
617 *(dst++) = imageData[index];
618 *(alpha++) = imageData[index + 3];
619 }
620 }
621 break;
622
623 default:
624 return wxTGA_INVFORMAT;
625 }
626 }
627 break;
628
629 // RLE grayscale.
630
631 case 11:
632 {
633 // Decode the RLE data.
634
8fee6306
VZ
635 int rc = DecodeRLE(imageData, imageSize, pixelSize, stream);
636 if ( rc != wxTGA_OK )
637 return rc;
3af706cc
VZ
638
639 // If orientation == 0, then the image is stored upside down.
640 // We need to store it right side up.
641
642 if (orientation == 0)
643 {
644 FlipTGA(imageData, width, height, pixelSize);
645 }
646
647 // Handle the different pixel depths.
648
649 switch (bpp)
650 {
651 // 8 bpp.
652
653 case 8:
654 {
655 for (unsigned long index = 0; index < imageSize; index += pixelSize)
656 {
657 *(dst++) = imageData[index];
658 *(dst++) = imageData[index];
659 *(dst++) = imageData[index];
660 }
661 }
662 break;
663
664 // 16 bpp.
665
666 case 16:
667 {
668 for (unsigned long index = 0; index < imageSize; index += pixelSize)
669 {
670 *(dst++) = imageData[index];
671 *(dst++) = imageData[index];
672 *(dst++) = imageData[index];
673 *(alpha++) = imageData[index + 1];
674 }
675 }
676 break;
677
678 default:
679 return wxTGA_INVFORMAT;
680 }
681 }
682 break;
683
684 default:
685 return wxTGA_INVFORMAT;
686 }
687
3af706cc
VZ
688 return wxTGA_OK;
689}
690
691static
3d926ff8 692int SaveTGA(const wxImage& image, wxOutputStream *stream)
3af706cc 693{
3d926ff8
DS
694 bool hasAlpha = image.HasAlpha();
695 unsigned bytesPerPixel = 3 + (hasAlpha ? 1 : 0);
696 wxSize size = image.GetSize();
697 size_t scanlineSize = size.x * bytesPerPixel;
698 unsigned char *scanlineData = (unsigned char *) malloc(scanlineSize);
699 if (!scanlineData)
700 {
701 return wxTGA_MEMERR;
702 }
703
704 wxON_BLOCK_EXIT1(free, scanlineData);
705
706 // Compose and write the TGA header
707 unsigned char hdr[HDR_SIZE];
708 (void) memset(&hdr, 0, HDR_SIZE);
709
710 hdr[HDR_COLORTYPE] = wxTGA_UNMAPPED;
711 hdr[HDR_IMAGETYPE] = 2 /* Uncompressed truecolour */;
712
713 hdr[HDR_WIDTH] = size.x & 0xFF;
714 hdr[HDR_WIDTH + 1] = (size.x >> 8) & 0xFF;
715
716 hdr[HDR_HEIGHT] = size.y & 0xFF;
717 hdr[HDR_HEIGHT + 1] = (size.y >> 8) & 0xFF;
718
719 hdr[HDR_BPP] = hasAlpha ? 32 : 24;
720 hdr[HDR_ORIENTATION] = 1 << 5; // set bit to indicate top-down order
721 if (hasAlpha)
722 {
723 hdr[HDR_ORIENTATION] |= 8; // number of alpha bits
724 }
725
726 if ( !stream->Write(hdr, HDR_SIZE) )
727 {
728 return wxTGA_IOERR;
729 }
730
731
732 // Write image data, converting RGB to BGR and adding alpha if applicable
733
734 unsigned char *src = image.GetData();
735 unsigned char *alpha = image.GetAlpha();
736 for (int y = 0; y < size.y; ++y)
737 {
738 unsigned char *dst = scanlineData;
739 for (int x = 0; x < size.x; ++x)
740 {
741 dst[0] = src[2];
742 dst[1] = src[1];
743 dst[2] = src[0];
744 if (alpha)
745 {
746 dst[3] = *(alpha++);
747 }
748 src += 3;
749 dst += bytesPerPixel;
750 }
751 if ( !stream->Write(scanlineData, scanlineSize) )
752 {
753 return wxTGA_IOERR;
754 }
755 }
3af706cc
VZ
756
757 return wxTGA_OK;
758}
759
760// ----------------------------------------------------------------------------
761// wxTGAHandler
762// ----------------------------------------------------------------------------
763
764bool wxTGAHandler::LoadFile(wxImage* image,
765 wxInputStream& stream,
766 bool verbose,
767 int WXUNUSED(index))
768{
769 if ( !CanRead(stream) )
770 {
771 if ( verbose )
af588446 772 {
3af706cc 773 wxLogError(wxT("TGA: this is not a TGA file."));
af588446 774 }
3af706cc
VZ
775
776 return false;
777 }
778
779 image->Destroy();
780
781 int error = ReadTGA(image, stream);
782 if ( error != wxTGA_OK )
783 {
784 if ( verbose )
785 {
786 switch ( error )
787 {
788 case wxTGA_INVFORMAT:
789 wxLogError(wxT("TGA: image format unsupported."));
790 break;
791
792 case wxTGA_MEMERR:
793 wxLogError(wxT("TGA: couldn't allocate memory."));
794 break;
795
8fee6306
VZ
796 case wxTGA_IOERR:
797 wxLogError(wxT("TGA: couldn't read image data."));
798 break;
799
3af706cc
VZ
800 default:
801 wxLogError(wxT("TGA: unknown error!"));
802 }
803 }
804
805 image->Destroy();
806
807 return false;
808 }
809
810 return true;
811}
812
813bool wxTGAHandler::SaveFile(wxImage* image, wxOutputStream& stream, bool verbose)
814{
3d926ff8 815 int error = SaveTGA(*image, &stream);
3af706cc
VZ
816
817 if ( error != wxTGA_OK )
818 {
819 if ( verbose )
820 {
821 switch ( error )
822 {
3af706cc
VZ
823 case wxTGA_MEMERR:
824 wxLogError(wxT("TGA: couldn't allocate memory."));
825 break;
826
3d926ff8
DS
827 case wxTGA_IOERR:
828 wxLogError(wxT("TGA: couldn't write image data."));
829 break;
830
3af706cc
VZ
831 default:
832 wxLogError(wxT("TGA: unknown error!"));
833 }
834 }
835
836 return false;
837 }
838
839 return true;
840}
841
842bool wxTGAHandler::DoCanRead(wxInputStream& stream)
843{
844 // read the fixed-size TGA headers
845 unsigned char hdr[HDR_SIZE];
8faef7cc 846 stream.Read(hdr, HDR_SIZE); // it's ok to modify the stream position here
3af706cc 847
d13b34d3 848 // Check whether we can read the file or not.
3af706cc
VZ
849
850 short colorType = hdr[HDR_COLORTYPE];
851 if ( colorType != wxTGA_UNMAPPED && colorType != wxTGA_MAPPED )
852 {
853 return false;
854 }
855
856 short imageType = hdr[HDR_IMAGETYPE];
857 if ( imageType == 0 || imageType == 32 || imageType == 33 )
858 {
859 return false;
860 }
861
862 short bpp = hdr[HDR_BPP];
863 if ( bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32 )
864 {
865 return false;
866 }
867
868 return true;
869}
870
871#endif // wxUSE_STREAMS
872
873#endif // wxUSE_IMAGE && wxUSE_TGA