1 /********************************************************************************
2 *                                                                               *
3 *                      T A R G A   I n p u t / O u t p u t                      *
4 *                                                                               *
5 *********************************************************************************
6 * Copyright (C) 2001,2006 by Janusz Ganczarski.   All Rights Reserved.          *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or                 *
9 * modify it under the terms of the GNU Lesser General Public                    *
10 * License as published by the Free Software Foundation; either                  *
11 * version 2.1 of the License, or (at your option) any later version.            *
12 *                                                                               *
13 * This library is distributed in the hope that it will be useful,               *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of                *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU             *
16 * Lesser General Public License for more details.                               *
17 *                                                                               *
18 * You should have received a copy of the GNU Lesser General Public              *
19 * License along with this library; if not, write to the Free Software           *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.    *
21 *********************************************************************************
22 * $Id: fxtargaio.cpp,v 1.30 2006/01/22 17:58:54 fox Exp $                       *
23 ********************************************************************************/
24 #include "xincs.h"
25 #include "fxver.h"
26 #include "fxdefs.h"
27 #include "FXHash.h"
28 #include "FXStream.h"
29 
30 /*
31   Notes:
32   - Need to have checks in RLE decoder for out-of-bounds checking.
33   - Need to try save image with fewer bits/pixel if possible.
34   - To map from 5-bit to 8-bit, we use value*8+floor(value/4) which
35     is almost the same as the correct value*8.225806.
36   - Yes, in 16 bit its still 5,5,5 and not 5,6,5.
37   - We need to clean this up and simplify a bit some day.
38 */
39 
40 
41 using namespace FX;
42 
43 
44 /*******************************************************************************/
45 
46 namespace FX {
47 
48 
49 extern FXAPI bool fxcheckTGA(FXStream& store);
50 extern FXAPI bool fxloadTGA(FXStream& store,FXColor*& data,FXint& width,FXint& height);
51 extern FXAPI bool fxsaveTGA(FXStream& store,const FXColor *data,FXint width,FXint height);
52 
53 
read16(FXStream & store)54 static inline FXuint read16(FXStream& store){
55   FXuchar c1,c2;
56   store >> c1 >> c2;
57   return ((FXuint)c1) | (((FXuint)c2)<<8);
58   }
59 
60 
61 
loadTarga32(FXStream & store,FXColor * data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType)62 static bool loadTarga32(FXStream& store,FXColor* data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType){
63   register FXuchar *pp;
64   register FXint i,j,rc;
65   FXuchar R,G,B,A,c;
66 
67   // 2 - Uncompressed, RGB images.
68   if(ImageType==2){
69 
70     // Origin in upper left-hand corner
71     if((imgdescriptor&0x20)==0x20){
72       pp=(FXuchar*)data;
73       for(i=0; i<height; i++){
74         for(j=0; j<width; j++){
75           store >> pp[2];       // Blue
76           store >> pp[1];       // Green
77           store >> pp[0];       // Red
78           store >> pp[3];       // Alpha
79           pp+=4;
80           }
81         }
82       }
83 
84     // Origin in lower left-hand corner
85     else{
86       for(i=height-1; i>=0; i--){
87         pp=(FXuchar*)(data+i*width);
88         for(j=0; j<width; j++){
89           store >> pp[2];       // Blue
90           store >> pp[1];       // Green
91           store >> pp[0];       // Red
92           store >> pp[3];       // Alpha
93           pp+=4;
94           }
95         }
96       }
97     }
98 
99   // 10 - Runlength encoded RGB images.
100   else if(ImageType==10){
101 
102     // Origin in upper left-hand corner
103     if((imgdescriptor&0x20)==0x20){
104       pp=(FXuchar*)data;
105       for(i=0; i<height; i++){
106         j=0;
107         while(j<width){
108 
109           // read Repetition Count field
110           store >> c;
111 
112           // check for Run-length Packet
113           if(c>127){
114             rc=c-127;
115             j+=rc;
116 
117             // read Pixel Value field - get R, G, B, A values
118             store >> B;
119             store >> G;
120             store >> R;
121             store >> A;
122 
123             while(rc--){
124               *pp++=R; // Red
125               *pp++=G; // Green
126               *pp++=B; // Blue
127               *pp++=A; // Alpha
128               }
129             }
130 
131           // Raw Packet
132           else{
133             rc=c+1;
134             j+=rc;
135             while(rc--){
136               store >> B;
137               store >> G;
138               store >> R;
139               store >> A;
140               *pp++=R; // Red
141               *pp++=G; // Green
142               *pp++=B; // Blue
143               *pp++=A; // Alpha
144               }
145             }
146           }
147         }
148       }
149 
150     // Origin in lower left-hand corner
151     else{
152       for(i=height-1; i>=0; i--){
153         j=0;
154         pp=(FXuchar*)(data+i*width);
155         while(j<width){
156 
157           // read Repetition Count field
158           store >> c;
159 
160           // check for Run-length Packet
161           if(c>127){
162             rc=c-127;
163             j+=rc;
164 
165             // read Pixel Value field - get R,G,B,A values
166             store >> B;
167             store >> G;
168             store >> R;
169             store >> A;
170             while(rc--){
171               *pp++=R; // Red
172               *pp++=G; // Green
173               *pp++=B; // Blue
174               *pp++=A; // Alpha
175               }
176             }
177           // Raw Packet
178           else{
179             rc=c+1;
180             j+=rc;
181             while(rc--){
182               store >> B;
183               store >> G;
184               store >> R;
185               store >> A;
186               *pp++=R; // Red
187               *pp++=G; // Green
188               *pp++=B; // Blue
189               *pp++=A; // Alpha
190               }
191             }
192           }
193         }
194       }
195     }
196   return true;
197   }
198 
199 
loadTarga24(FXStream & store,FXColor * data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType)200 static bool loadTarga24(FXStream& store,FXColor* data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType){
201   register int i,j,rc;
202   register FXuchar *pp;
203   FXuchar R,G,B,c;
204 
205   // 2 - Uncompressed, RGB images.
206   if(ImageType == 2){
207 
208     // Origin in upper left-hand corner
209     if((imgdescriptor&0x20)==0x20){
210       pp=(FXuchar*)data;
211       for(i=0; i<height; i++){
212         for(j=0; j<width; j++){
213           store >> pp[2];       // Blue
214           store >> pp[1];       // Green
215           store >> pp[0];       // Red
216           pp[3]=255;            // Alpha
217           pp+=4;
218           }
219         }
220       }
221 
222     // Origin in lower left-hand corner
223     else{
224       for(i=height-1; i>=0; i--){
225         pp=(FXuchar*)(data+i*width);
226         for(j=0; j<width; j++){
227           store >> pp[2];       // Blue
228           store >> pp[1];       // Green
229           store >> pp[0];       // Red
230           pp[3]=255;            // Alpha
231           pp+=4;
232           }
233         }
234       }
235     }
236 
237   // 10 - Runlength encoded RGB images.
238   else if(ImageType==10){
239 
240     // Origin in upper left-hand corner
241     if((imgdescriptor&0x20)==0x20){
242       pp=(FXuchar*)data;
243       for(i=0; i<height; i++){
244         j=0;
245         while(j<width){
246 
247           // read Repetition Count field
248           store >> c;
249 
250           // check for Run-length Packet
251           if(c>127){
252             rc=c-127;
253             j+=rc;
254 
255             // read Pixel Value field - get R, G, B values
256             store >> B;
257             store >> G;
258             store >> R;
259             while(rc--){
260               *pp++=R;          // Red
261               *pp++=G;          // Green
262               *pp++=B;          // Blue
263               *pp++=255;        // Alpha
264               }
265             }
266           // Raw Packet
267           else{
268             rc=c+1;
269             j+=rc;
270             while(rc--){
271               store >> B;
272               store >> G;
273               store >> R;
274               *pp++=R;          // Red
275               *pp++=G;          // Green
276               *pp++=B;          // Blue
277               *pp++=255;        // Alpha
278               }
279             }
280           }
281         }
282       }
283 
284     // Origin in lower left-hand corner
285     else{
286       for(i=height-1; i>=0; i--){
287         j=0;
288         pp=(FXuchar*)(data+i*width);
289         while(j<width){
290 
291           // read Repetition Count field
292           store >> c;
293 
294           // check for Run-length Packet
295           if(c>127){
296             rc=c-127;
297             j+=rc;
298 
299             // read Pixel Value field - get R,G,B values
300             store >> B;
301             store >> G;
302             store >> R;
303             while(rc--){
304               *pp++=R;          // Red
305               *pp++=G;          // Green
306               *pp++=B;          // Blue
307               *pp++=255;        // Alpha
308               }
309             }
310           // Raw Packet
311           else{
312             rc = c + 1;
313             j += rc;
314             while(rc--){
315               store >> B;
316               store >> G;
317               store >> R;
318               *pp++=R;          // Red
319               *pp++=G;          // Green
320               *pp++=B;          // Blue
321               *pp++=255;        // Alpha
322               }
323             }
324           }
325         }
326       }
327     }
328   return true;
329   }
330 
331 
loadTarga16(FXStream & store,FXColor * data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType)332 static bool loadTarga16(FXStream& store,FXColor* data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType){
333   register FXushort rgb16;
334   register FXuchar *pp;
335   register int i,j,rc;
336   FXuchar R,G,B,c;
337 
338   // 2 - Uncompressed, RGB images.
339   if(ImageType==2){
340     // check Image Descriptor
341     // Origin in upper left-hand corner
342     if((imgdescriptor&0x20)==0x20){
343       pp=(FXuchar*)data;
344       for(i=0; i<height; i++){
345         for(j=0; j<width; j++){
346           rgb16=read16(store);
347           *pp++=((rgb16>>7)&0xf8)+((rgb16>>12)&7);      // Red
348           *pp++=((rgb16>>2)&0xf8)+((rgb16>>7)&7);       // Green
349           *pp++=((rgb16<<3)&0xf8)+((rgb16>>2)&7);       // Blue
350           *pp++=255;                                    // Alpha
351           }
352         }
353       }
354     else{
355       // Origin in lower left-hand corner
356       for(i=height-1; i>=0; i--){
357         pp=(FXuchar*)(data+i*width);
358         for(j=0; j<width; j++){
359           rgb16=read16(store);
360           *pp++=((rgb16>>7)&0xf8)+((rgb16>>12)&7);      // Red
361           *pp++=((rgb16>>2)&0xf8)+((rgb16>>7)&7);       // Green
362           *pp++=((rgb16<<3)&0xf8)+((rgb16>>2)&7);       // Blue
363           *pp++=255;                                    // Alpha
364           }
365         }
366       }
367     }
368 
369   // 10 - Runlength encoded RGB images.
370   else if(ImageType==10){
371     // check Image Descriptor
372     // Origin in upper left-hand corner
373     if((imgdescriptor&0x20)==0x20){
374       pp=(FXuchar*)data;
375       for(i=0; i<height; i++){
376         j=0;
377         while(j<width){
378 
379           // read Repetition Count field
380           store >> c;
381 
382           // check for Run-length Packet
383           if(c>127){
384             rc=c-127;
385             j+=rc;
386 
387             // read Pixel Value field -
388             rgb16=read16(store);
389 
390             // get R, G, B values
391             R=((rgb16>>7)&0xf8)+((rgb16>>12)&7);      // Red
392             G=((rgb16>>2)&0xf8)+((rgb16>>7)&7);       // Green
393             B=((rgb16<<3)&0xf8)+((rgb16>>2)&7);       // Blue
394             while(rc--){
395               *pp++=R;          // Red
396               *pp++=G;          // Green
397               *pp++=B;          // Blue
398               *pp++=255;        // Alpha
399               }
400             }
401 
402           // Raw Packet
403           else{
404             rc=c+1;
405             j+=rc;
406             while(rc--){
407               rgb16=read16(store);
408               *pp++=((rgb16>>7)&0xf8)+((rgb16>>12)&7);// Red
409               *pp++=((rgb16>>2)&0xf8)+((rgb16>>7)&7); // Green
410               *pp++=((rgb16<<3)&0xf8)+((rgb16>>2)&7); // Blue
411               *pp++=255;                                // Alpha
412               }
413             }
414           }
415         }
416       }
417 
418     // Origin in lower left-hand corner
419     else{
420       for(i=height-1; i>=0; i--){
421         j=0;
422         pp=(FXuchar*)(data+i*width);
423         while(j<width){
424 
425           // read Repetition Count field
426           store >> c;
427 
428           // check for Run-length Packet
429           if(c>127){
430             rc=c-127;
431             j+=rc;
432 
433             // read Pixel Value field
434             rgb16=read16(store);
435 
436             // get R, G, B values
437             R=((rgb16>>7)&0xf8)+((rgb16>>12)&7);      // Red
438             G=((rgb16>>2)&0xf8)+((rgb16>>7)&7);       // Green
439             B=((rgb16<<3)&0xf8)+((rgb16>>2)&7);       // Blue
440             while(rc--){
441               *pp++=R;                  // Red
442               *pp++=G;                  // Green
443               *pp++=B;                  // Blue
444               *pp++=255;                // Alpha
445               }
446             }
447 
448           // Raw Packet
449           else{
450             rc=c+1;
451             j+=rc;
452             while(rc--){
453               rgb16=read16(store);
454               *pp++=((rgb16>>7)&0xf8)+((rgb16>>12)&7);// Red
455               *pp++=((rgb16>>2)&0xf8)+((rgb16>>7)&7); // Green
456               *pp++=((rgb16<<3)&0xf8)+((rgb16>>2)&7); // Blue
457               *pp++=255;                                // Alpha
458               }
459             }
460           }
461         }
462       }
463     }
464   return true;
465   }
466 
467 
loadTarga8(FXStream & store,FXColor * data,FXint width,FXint height,FXuchar colormap[][4],FXuchar imgdescriptor,FXuchar ImageType)468 static bool loadTarga8(FXStream& store,FXColor* data,FXint width,FXint height,FXuchar colormap[][4],FXuchar imgdescriptor,FXuchar ImageType){
469   register FXint i,j,rc;
470   register FXuchar *pp;
471   FXuchar R,G,B,A,c;
472 
473   // 1 - Uncompressed, color-mapped images
474   if(ImageType==1){
475     // check Image Descriptor
476     // Origin in upper left-hand corner
477     if((imgdescriptor&0x20)==0x20){
478       pp=(FXuchar*)data;
479       for(i=0; i<height; i++){
480         for(j=0; j<width; j++){
481           store >> c;
482           *pp++=colormap[c][2];         // Red
483           *pp++=colormap[c][1];         // Green
484           *pp++=colormap[c][0];         // Blue
485           *pp++=colormap[c][3];         // Alpha
486           }
487         }
488       }
489     // Origin in lower left-hand corner
490     else{
491       for(i=height-1; i>=0; i--){
492         pp=(FXuchar*)(data+i*width);
493         for(j=0; j<width; j++){
494           store >> c;
495           *pp++=colormap[c][2];         // Red
496           *pp++=colormap[c][1];         // Green
497           *pp++=colormap[c][0];         // Blue
498           *pp++=colormap[c][3];         // Alpha
499           }
500         }
501       }
502     }
503 
504   // 9 - Runlength encoded color-mapped images
505   else if(ImageType==9){
506     // check Image Descriptor
507     // Origin in upper left-hand corner
508     if((imgdescriptor&0x20)==0x20){
509       pp=(FXuchar*)data;
510       for(i=0; i<height; i++){
511         j=0;
512         while(j<width){
513           // read Repetition Count field
514           store >> c;
515 
516           // check for Run-length Packet
517           if(c>127){
518             rc=c-127;
519             j+=rc;
520 
521             // read Pixel Value field
522             store >> c;
523 
524             // get R,G,B values
525             R=colormap[c][2];
526             G=colormap[c][1];
527             B=colormap[c][0];
528             A=colormap[c][3];
529             while(rc--){
530               *pp++=R;          // Red
531               *pp++=G;          // Green
532               *pp++=B;          // Blue
533               *pp++=A;          // Alpha
534               }
535             }
536 
537           // Raw Packet
538           else{
539             rc=c+1;
540             j+=rc;
541             while(rc--){
542               store >> c;
543               *pp++=colormap[c][2];     // Red
544               *pp++=colormap[c][1];     // Green
545               *pp++=colormap[c][0];     // Blue
546               *pp++=colormap[c][3];     // Alpha
547               }
548             }
549           }
550         }
551       }
552 
553     // Origin in lower left-hand corner
554     else{
555       for(i=height-1; i>=0; i--){
556         j=0;
557         pp=(FXuchar*)(data+i*width);
558         while(j<width){
559 
560           // read Repetition Count field
561           store >> c;
562 
563           // check for Run-length Packet
564           if(c>127){
565             rc=c-127;
566             j+=rc;
567 
568             // read Pixel Value field
569             store >> c;
570 
571             // get R,G,B values
572             R=colormap[c][2];
573             G=colormap[c][1];
574             B=colormap[c][0];
575             A=colormap[c][3];
576             while(rc--){
577               *pp++=R;          // Red
578               *pp++=G;          // Green
579               *pp++=B;          // Blue
580               *pp++=A;          // Alpha
581               }
582             }
583 
584           // Raw Packet
585           else{
586             rc=c+1;
587             j+=rc;
588             while(rc--){
589               store >> c;
590               *pp++=colormap[c][2];     // Red
591               *pp++=colormap[c][1];     // Green
592               *pp++=colormap[c][0];     // Blue
593               *pp++=colormap[c][3];     // Alpha
594               }
595             }
596           }
597         }
598       }
599     }
600   return true;
601   }
602 
603 
loadTargaGray(FXStream & store,FXColor * data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType)604 static bool loadTargaGray(FXStream& store,FXColor* data,FXint width,FXint height,FXuchar imgdescriptor,FXuchar ImageType){
605   register FXint i,j,rc;
606   register FXuchar *pp;
607   FXuchar c;
608 
609   // 3 - Uncompressed, black and white images.
610   if(ImageType==3){
611     // check Image Descriptor
612     // Origin in upper left-hand corner
613     if((imgdescriptor&0x20)==0x20){
614       pp=(FXuchar*)data;
615       for(i=0; i<height; i++){
616         for(j=0; j<width; j++){
617           store >> c;
618           *pp++=c;
619           *pp++=c;
620           *pp++=c;
621           *pp++=255;
622           }
623         }
624       }
625 
626     // Origin in lower left-hand corner
627     else{
628       for(i=height-1; i>=0; i--){
629         pp=(FXuchar*)(data+i*width);
630         for(j=0; j<width; j++){
631           store >> c;
632           *pp++=c;
633           *pp++=c;
634           *pp++=c;
635           *pp++=255;
636           }
637         }
638       }
639     }
640 
641   // 11 - Compressed, black and white images.
642   else if(ImageType==11){
643 
644     // check Image Descriptor
645     // Origin in upper left-hand corner
646     if((imgdescriptor&0x20)==0x20){
647       pp=(FXuchar*)data;
648       for(i=0; i<height; i++){
649         j=0;
650         while(j<width){
651 
652           // read Repetition Count field
653           store >> c;
654 
655           // check for Run-length Packet
656           if(c>127){
657             rc=c-127;
658             j+=rc;
659 
660             // read Pixel Value field
661             store >> c;
662             while(rc--){
663               *pp++=c;
664               *pp++=c;
665               *pp++=c;
666               *pp++=255;
667               }
668             }
669 
670           // Raw Packet
671           else{
672             rc=c+1;
673             j+=rc;
674             while(rc--){
675               store >> c;
676               *pp++=c;
677               *pp++=c;
678               *pp++=c;
679               *pp++=255;
680               }
681             }
682           }
683         }
684       }
685 
686     // Origin in lower left-hand corner
687     else{
688       for(i=height-1; i>=0; i--){
689         j = 0;
690         pp=(FXuchar*)(data+i*width);
691         while(j<width){
692 
693           // read Repetition Count field
694           store >> c;
695 
696           // check for Run-length Packet
697           if(c>127){
698             rc=c-127;
699             j+=rc;
700 
701             // read Pixel Value field
702             store >> c;
703             while(rc--){
704               *pp++=c;
705               *pp++=c;
706               *pp++=c;
707               *pp++=255;
708               }
709             }
710 
711           // Raw Packet
712           else{
713             rc=c+1;
714             j+=rc;
715             while(rc--){
716               store >> c;
717               *pp++=c;
718               *pp++=c;
719               *pp++=c;
720               *pp++=255;
721               }
722             }
723           }
724         }
725       }
726     }
727   return true;
728   }
729 
730 
731 // Check if stream contains a TARGA
fxcheckTGA(FXStream & store)732 bool fxcheckTGA(FXStream& store){
733   FXuchar signature[3];
734   store.load(signature,3);
735   store.position(-3,FXFromCurrent);
736   return signature[2]==1 || signature[2]==2 || signature[2]==3 || signature[2]==9 || signature[2]==10 || signature[2]==11 || signature[2]==32 || signature[2]==33;
737   }
738 
739 
740 // Load Targa image from stream
fxloadTGA(FXStream & store,FXColor * & data,FXint & width,FXint & height)741 bool fxloadTGA(FXStream& store,FXColor*& data,FXint& width,FXint& height){
742   FXuchar IDLength,ColorMapType,ImageType,ColorMapEntrySize,PixelDepth,ImageDescriptor;
743   FXuchar colormap[256][4];
744   FXuint rgb16,ColorMapLength,i;
745   FXlong start;
746 
747   // Null out
748   data=NULL;
749   width=0;
750   height=0;
751 
752   // Remember start
753   start=store.position();
754 
755   // Length of Image ID Field
756   store >> IDLength;
757 
758   // Type of color map (if any) included with the image
759   // 0 - indicates that no color-map data is included with this image
760   // 1 - indicates that a color-map is included with this image
761   store >> ColorMapType;
762 
763   // Image Type
764   //  0 - No image data included.
765   //  1 - Uncompressed, color-mapped images.
766   //  2 - Uncompressed, RGB images.
767   //  3 - Uncompressed, black and white images.
768   //  9 - Runlength encoded color-mapped images.
769   // 10 - Runlength encoded RGB images.
770   // 11 - Compressed, black and white images.
771   // 32 - Compressed color-mapped data, using Huffman, Delta, and runlength encoding.
772   // 33 - Compressed color-mapped data, using Huffman, Delta, and runlength encoding.
773   //      4-pass quadtree-type process.
774   store >> ImageType;
775 
776 //  FXTRACE((1,"fxloadTGA IDLength=%d ColorMapType=%d ImageType=%d\n",IDLength,ColorMapType,ImageType));
777 
778   // Check for supported image type
779   if(ImageType!=1 && ImageType!=2 && ImageType!=3 && ImageType!=9 && ImageType!=10 && ImageType!=11 && ImageType!=32 && ImageType!=33) return false;
780 
781   // Color Map Specification
782 
783   // FirstEntryIndex - index of the first color map entry
784   read16(store);
785 
786   // Color map Length
787   ColorMapLength=read16(store);
788 
789   // Color map Entry Size
790   // Establishes the number of bits per entry.
791   // Typically 15, 16, 24 or 32-bit values are used.
792   store >> ColorMapEntrySize;
793 
794   // Image Specification Field
795 
796   // X-origin of Image and Y-origin of Image
797   read16(store);
798   read16(store);
799 
800   // This field specifies the width of the image in pixels
801   width=read16(store);
802 
803   // This field specifies the height of the image in pixels
804   height=read16(store);
805 
806   // This field indicates the number of bits per pixel. This number includes
807   // the Attribute or Alpha channel bits. Common values are 8, 16, 24 and 32
808   // but other pixel depths could be used.
809   store >> PixelDepth;
810 
811 //  FXTRACE((1,"fxloadTGA PixelDepth=%d ColorMapLength=%d ColorMapEntrySize=%d width=%d height=%d\n",PixelDepth,ColorMapLength,ColorMapEntrySize,width,height));
812 
813   // Don't load too many colors
814   if(ColorMapLength>256) return FALSE;
815 
816   // Verify sanity
817   if(PixelDepth!=1 && PixelDepth!=8 && PixelDepth!=15 && PixelDepth!=16 && PixelDepth!=24 && PixelDepth!=32) return false;
818 
819   // Bits 3-0 - number of attribute bits associated with each pixel
820   // Bit 4    - reserved.  Must be set to 0
821   // Bit 5    - screen origin bit:
822   //            0 = Origin in lower left-hand corner
823   //            1 = Origin in upper left-hand corner
824   //            Must be 0 for Truevision images
825   // Bits 7-6 - Data storage interleaving flag:
826   //            00 = non-interleaved
827   //            01 = two-way (even/odd) interleaving
828   //            10 = four way interleaving
829   //            11 = reserved
830   store >> ImageDescriptor;
831 
832   // skip Image ID Field (18 - standard header length)
833   store.position(start+18+IDLength);
834 
835   // color map
836   if(ColorMapLength>0){
837     switch(ColorMapEntrySize){
838       case 15:
839       case 16:          // Is this also 5:5:5 or is it 5:6:5?
840         for(i=0; i<ColorMapLength; i++){
841           rgb16=read16(store);
842           colormap[i][0]=((rgb16>>7)&0xf8)+((rgb16>>12)&7);     // Red
843           colormap[i][1]=((rgb16>>2)&0xf8)+((rgb16>>7)&7);      // Green
844           colormap[i][2]=((rgb16<<3)&0xf8)+((rgb16>>2)&7);      // Blue
845           colormap[i][3]=255;                                   // Alpha
846           }
847         break;
848 
849       // R,G,B
850       case 24:
851         for(i=0; i<ColorMapLength; i++){
852           store >> colormap[i][0];
853           store >> colormap[i][1];
854           store >> colormap[i][2];
855           colormap[i][3]=255;
856           }
857         break;
858 
859       // R,G,B,A
860       case 32:
861         for(i=0; i<ColorMapLength; i++){
862           store >> colormap[i][0];
863           store >> colormap[i][1];
864           store >> colormap[i][2];
865           store >> colormap[i][3];
866           }
867         break;
868 
869       // Huh?
870       default:
871         return false;
872       }
873     }
874 
875   FXTRACE((100,"fxloadTARGA: width=%d height=%d IDLength=%d ColorMapType=%d ColorMapLength=%d ColorMapEntrySize=%d ImageType=%d PixelDepth=%d ImageDescriptor=%02x\n",width,height,IDLength,ColorMapType,ColorMapLength,ColorMapEntrySize,ImageType,PixelDepth,ImageDescriptor));
876 
877   // Allocate memory
878   FXMALLOC(&data,FXColor,width*height);
879   if(!data) return false;
880 
881   // load up the image
882   if(PixelDepth==32 && (ImageType==2 || ImageType==10)){
883     return loadTarga32(store,data,width,height,ImageDescriptor,ImageType);
884     }
885 
886   if(PixelDepth==24 && (ImageType==2 || ImageType==10)){
887     return loadTarga24(store,data,width,height,ImageDescriptor,ImageType);
888     }
889 
890   if(PixelDepth==16 && (ImageType==2 || ImageType==10)){
891     return loadTarga16(store,data,width,height,ImageDescriptor,ImageType);
892     }
893 
894   if(PixelDepth==15 && (ImageType==2 || ImageType==10)){
895     return loadTarga16(store,data,width,height,ImageDescriptor,ImageType);
896     }
897 
898   if(PixelDepth==8 && (ImageType==1 || ImageType==9)){
899     return loadTarga8(store,data,width,height,colormap,ImageDescriptor,ImageType);
900     }
901 
902   if(ImageType==3 || ImageType==11){
903     return loadTargaGray(store,data,width,height,ImageDescriptor,ImageType);
904     }
905 
906   return false;
907   }
908 
909 /*******************************************************************************/
910 
write16(FXStream & store,FXuint i)911 static inline void write16(FXStream& store,FXuint i){
912   FXuchar c1,c2;
913   c1=i&0xff;
914   c2=(i>>8)&0xff;
915   store << c1 << c2;
916   }
917 
918 
919 // Save a Targa file to a stream
fxsaveTGA(FXStream & store,const FXColor * data,FXint width,FXint height)920 bool fxsaveTGA(FXStream& store,const FXColor *data,FXint width,FXint height){
921   FXuchar IDLength,ColorMapType,ImageType,ColorMapEntrySize,PixelDepth,ImageDescriptor;
922   const FXuchar *pp;
923   FXint i,j;
924 
925   // Must make sense
926   if(!data || width<=0 || height<=0) return false;
927 
928   IDLength=0;
929   ColorMapType=0;
930   ImageType=2;
931   PixelDepth=32;
932 
933   ImageDescriptor=0;
934   ColorMapEntrySize=0;
935 
936   // length of Image ID Field
937   store << IDLength;
938 
939   // type of color map (if any) included with the image
940   // 0 - indicates that no color-map data is included with this image
941   // 1 - indicates that a color-map is included with this image
942   store << ColorMapType;
943 
944   // Image Type
945   //  0 - No image data included.
946   //  1 - Uncompressed, color-mapped images.
947   //  2 - Uncompressed, RGB images.
948   //  3 - Uncompressed, black and white images.
949   //  9 - Runlength encoded color-mapped images.
950   // 10 - Runlength encoded RGB images.
951   // 11 - Compressed, black and white images.
952   // 32 - Compressed color-mapped data, using Huffman, Delta, and runlength encoding.
953   // 33 - Compressed color-mapped data, using Huffman, Delta, and runlength encoding.
954   //      4-pass quadtree-type process.
955   store << ImageType;
956 
957   // Color Map Specification
958 
959   // Index of the first color map entry
960   write16(store,0);
961 
962   // Color map Length
963   write16(store,0);
964 
965   // Color map Entry Size
966   // Establishes the number of bits per entry.
967   // Typically 15, 16, 24 or 32-bit values are used.
968   store << ColorMapEntrySize;
969 
970   // Image Specification Field
971 
972   // X-origin of Image and Y-origin of Image
973   write16(store,0);
974   write16(store,0);
975 
976   // This field specifies the width of the image in pixels
977   write16(store,width);
978 
979   // This field specifies the height of the image in pixels
980   write16(store,height);
981 
982   // This field indicates the number of bits per pixel. This number includes
983   // the Attribute or Alpha channel bits. Common values are 8, 16, 24 and 32
984   // but other pixel depths could be used.
985   store << PixelDepth;
986 
987   // Bits 3-0 - number of attribute bits associated with each pixel
988   // Bit 4    - reserved.  Must be set to 0
989   // Bit 5    - screen origin bit:
990   //            0 = Origin in lower left-hand corner
991   //            1 = Origin in upper left-hand corner
992   //            Must be 0 for Truevision images
993   // Bits 7-6 - Data storage interleaving flag:
994   //            00 = non-interleaved
995   //            01 = two-way (even/odd) interleaving
996   //            10 = four way interleaving
997   //            11 = reserved
998   store << ImageDescriptor;
999 
1000   // Write image
1001   for(i=height-1; i>=0; i--){
1002     pp=(FXuchar*)(data+i*width);
1003     for(j=0; j<width; j++){
1004       store << pp[2];     // blue
1005       store << pp[1];     // green
1006       store << pp[0];     // red
1007       store << pp[3];     // alpha
1008       pp+=4;
1009       }
1010     }
1011   return true;
1012   }
1013 
1014 }
1015 
1016