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