source: trunk/src/opengl/glide/cvg/texus/tga.c

Last change on this file was 6653, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 12.3 KB
Line 
1/* $Id: tga.c,v 1.2 2001-09-05 14:30:47 bird Exp $ */
2/*
3** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
4** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
5** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
6** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
7** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
8** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
9** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
10** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
11**
12** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
13** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
14** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
15** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
16** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
17** THE UNITED STATES.
18**
19** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
20**
21** $Revision: 1.2 $
22** $Date: 2001-09-05 14:30:47 $
23*/
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <math.h>
29
30#include "texusint.h"
31
32
33typedef struct _tgaHeader{
34 FxU8 IDLength;
35 FxU8 CMapType;
36 FxU8 ImgType;
37 FxU8 CMapStartLo;
38 FxU8 CMapStartHi;
39 FxU8 CMapLengthLo;
40 FxU8 CMapLengthHi;
41 FxU8 CMapDepth;
42 FxU8 XOffSetLo;
43 FxU8 XOffSetHi;
44 FxU8 YOffSetLo;
45 FxU8 YOffSetHi;
46 FxU8 WidthLo;
47 FxU8 WidthHi;
48 FxU8 HeightLo;
49 FxU8 HeightHi;
50 FxU8 PixelDepth;
51 FxU8 ImageDescriptor;
52} TgaHeader;
53
54/* Definitions for image types. */
55#define TGA_NULL 0
56#define TGA_CMAP 1
57#define TGA_TRUE 2
58#define TGA_MONO 3
59#define TGA_CMAP_RLE 9
60#define TGA_TRUE_RLE 10
61#define TGA_MONO_RLE 11
62
63FxBool
64_txReadTGAHeader( FILE *stream, FxU32 cookie, TxMip *info)
65{
66 TgaHeader *tgaHeader = (TgaHeader *) info->pal;
67 int i;
68
69 // Fill up rest of the TGA header.
70 if ( fread( &(tgaHeader->ImgType), 1, sizeof(TgaHeader)-2, stream ) !=
71 sizeof(TgaHeader)-2) {
72 txPanic("Unexpected end of file.");
73 return FXFALSE;
74 }
75 tgaHeader->IDLength = (FxU8) ((cookie >> 8) & 0xFF);
76 tgaHeader->CMapType = (FxU8) ((cookie ) & 0xFF);
77
78 // Optionally, skip the image id fields.
79 for (i= (tgaHeader->IDLength) & 0xFF; i; i--) {
80 int c;
81
82 if ((c = getc(stream)) == EOF) {
83 txPanic("Unexpected EOF.");
84 return FXFALSE;
85 }
86 }
87
88 // 3Dfx specific part here.
89 info->width = tgaHeader->WidthHi << 8 | tgaHeader->WidthLo;
90 info->height = tgaHeader->HeightHi << 8 | tgaHeader->HeightLo;
91 info->depth = 1;
92
93 if ((info->width <= 0) || (info->height <= 0)) {
94 txError("TGA Image: width or height is 0.");
95 return FXFALSE;
96 }
97
98 switch(tgaHeader->ImgType) {
99 case TGA_MONO:
100 case TGA_MONO_RLE: // True color image.
101 if (tgaHeader->PixelDepth != 8) {
102 txError("TGA Image: Mono image is not 8 bits/pixel.");
103 return FXFALSE;
104 }
105 info->format = GR_TEXFMT_I_8;
106 break;
107
108 case TGA_TRUE:
109 case TGA_TRUE_RLE:
110 switch (tgaHeader->PixelDepth ) {
111 case 15:
112 case 16:
113 info->format = GR_TEXFMT_ARGB_1555; break;
114 case 24:
115 case 32:
116 info->format = GR_TEXFMT_ARGB_8888; break;
117 default:
118 txError("TGA Image: True color image is not 24/32 bits/pixel.");
119 return FXFALSE;
120 break;
121 }
122 break;
123
124 case TGA_CMAP:
125 case TGA_CMAP_RLE: // Color mapped image.
126 if ( tgaHeader->CMapType != 1 ) {
127 txError("TGA Image: Color-mapped TGA image has no palette");
128 return FXFALSE;
129 }
130 if (((tgaHeader->CMapLengthLo + tgaHeader->CMapLengthHi * 256L)
131 +(tgaHeader->CMapStartLo + tgaHeader->CMapStartHi * 256L)) > 256){
132 txError("TGA Image: Color-mapped image has > 256 colors");
133 return FXFALSE;
134 }
135 info->format = GR_TEXFMT_P_8;
136 break;
137
138 default:
139 txError("TGA Image: unsupported format");
140 return FXFALSE;
141 }
142 info->size = info->width*info->height*GR_TEXFMT_SIZE(info->format);
143
144 return FXTRUE;
145}
146
147static FxBool
148_txReadTGAColorMap(FILE *stream, const TgaHeader *tgaHeader, FxU32 *palette)
149{
150 int cmapStart;
151 int cmapLength;
152 int cmapDepth;
153 int i;
154
155 cmapStart = tgaHeader->CMapStartLo;
156 cmapStart += tgaHeader->CMapStartHi * 256L;
157
158 cmapLength = tgaHeader->CMapLengthLo;
159 cmapLength += tgaHeader->CMapLengthHi * 256L;
160
161 cmapDepth = tgaHeader->CMapDepth;
162
163 if (tgaHeader->CMapType == 0) return FXTRUE; // no colormap.
164
165 /* Validate some parameters */
166 if (cmapStart < 0) {
167 txError("TGA Image: Bad Color Map start value.");
168 return FXFALSE;
169 }
170
171 cmapDepth = (cmapDepth + 1) >> 3; // to bytes.
172 if ((cmapDepth <= 0) || (cmapDepth > 4)) {
173 txError("TGA Image: Bad Color Map depth.");
174 return FXFALSE;
175 }
176
177 // May have to skip the color map.
178 if ((tgaHeader->ImgType != TGA_CMAP) &&
179 (tgaHeader->ImgType != TGA_CMAP_RLE)) {
180 /* True color, yet there is a palette, this is OK, just skip. */
181
182 cmapLength *= cmapDepth;
183 while (cmapLength--) {
184 int c;
185
186 c = getc(stream);
187 if (c == EOF) {
188 txError("TGA Image: Unexpected EOF reading Color Map.");
189 return FXFALSE;
190 }
191 }
192 return FXTRUE;
193 }
194
195 // This is a real palette that's going to be used.
196
197 // Verify that it's not too large.
198 if ((cmapStart + cmapLength) > 256) {
199 txError("TGA Image: Color Map > 256 entries.");
200 return FXFALSE;
201 }
202
203
204 // printf("cmapdepth = %d, start = %d, length = %d\n", cmapDepth,
205 // cmapStart, cmapLength);
206 for (i=0; i<256; i++) {
207 int r, g, b, a;
208
209 if ((i < cmapStart) || (i >= (cmapStart + cmapLength))) {
210 palette[i] = 0;
211 // printf("Skipping palette entry %d\n", i);
212 continue;
213 }
214
215 // Read this colormap entry.
216 switch (cmapDepth) {
217 case 1: // 8 bpp
218 r = getc(stream);
219 if (r == EOF) {
220 txError("TGA Image: Unexpected End of File.");
221 return FXFALSE;
222 }
223 r &= 0xFF;
224 palette[i] = (r << 24) | (r << 16) | (r << 8) | (r);
225 break;
226
227 case 2: // 15, 16 bpp.
228
229 b = getc(stream);
230 r = getc(stream);
231 if ((r == EOF) || (b == EOF)) {
232 txError("TGA Image: Unexpected End of File.");
233 return FXFALSE;
234 }
235 r &= 0xFF;
236 b &= 0xFF;
237 g = ((r & 0x3) << 6) + ((b & 0xE0) >> 2);
238 r = (r & 0x7C) << 1;
239 b = (b & 0x1F) << 3;
240
241 palette[i] = (r << 16) | (g << 8) | (b) | 0xFF000000L;
242 break;
243
244 case 3:
245 case 4:
246 b = getc(stream);
247 g = getc(stream);
248 r = getc(stream);
249 a = (cmapDepth == 4) ? getc(stream) : 0x0FF;
250
251 if ((r == EOF) || (g == EOF) || (b == EOF) | (a == EOF)) {
252 txError("TGA Image: Unexpected End of File.");
253 return FXFALSE;
254 }
255 palette[i] = (a << 24) | (r << 16) | (g << 8) | b;
256 // printf("Setting palette %3d to %.08x\n", i, palette[i]);
257 break;
258
259 default:
260 txError("TGA Image: Bad Color Map depth.");
261 return FXFALSE;
262 }
263 }
264 return FXTRUE;
265}
266
267static int tgaRLE, tgaRLEflag, tgaRLEcount, tgaRLEsav[4];
268
269static FxBool
270_txReadTGARLEPixel( FILE *stream, FxU8 *data, int pixsize)
271{
272 int c, i;
273
274 // Run length encoded data Only
275 if (tgaRLEcount == 0) {
276 // Need to restart the run.
277 if ( (tgaRLEcount = c = getc( stream )) == EOF) {
278 txError("TGA Image: Unexpected End of File.");
279 return FXFALSE;
280 }
281 tgaRLEflag = tgaRLEcount & 0x80;
282 tgaRLEcount = (tgaRLEcount & 0x7F) + 1;
283
284 if (tgaRLEflag) {
285 // Replicated color, read the color to be replicated
286 for (i=0; i<pixsize; i++) {
287 if ( (c = getc( stream )) == EOF) {
288 txError("TGA Image: Unexpected End of File\n");
289 return FXFALSE;
290 }
291 tgaRLEsav[i] = (FxU8) c;
292 }
293 }
294 }
295
296 // Now deliver the data either from input or from saved values.
297 tgaRLEcount--;
298 if (tgaRLEflag) {
299 // deliver from saved data.
300 for (i=0; i<pixsize; i++) *data++ = (FxU8) tgaRLEsav[i];
301 } else {
302 for (i=0; i<pixsize; i++) {
303 if ( (c = getc( stream )) == EOF) {
304 txError("TGA Image: Unexpected End of File\n");
305 return FXFALSE;
306 }
307 *data++ = (FxU8) c;
308 }
309 }
310 return FXTRUE;
311}
312
313static FxBool
314_txReadTGASpan( FILE *stream, FxU8 *data, int w, int pixsize)
315{
316 if (tgaRLE == 0) {
317 if ( fread( data, 1, w * pixsize, stream) != (FxU32)(w * pixsize)) {
318 txError("TGA Image: Unexpected End of File\n");
319 return FXFALSE;
320 }
321 return FXTRUE;
322 }
323
324 // Otherwise, RLE data.
325 while (w--) {
326 if (!_txReadTGARLEPixel( stream, data, pixsize)) {
327 return FXFALSE;
328 }
329 data += pixsize;
330 }
331 return FXTRUE;
332}
333
334FxBool
335_txReadTGAData( FILE *stream, TxMip *info)
336{
337 TgaHeader *tgaHeader = (TgaHeader *) info->pal;
338 int i, stride;
339 int bpp; // bytesPerPixel
340 FxU8* data;
341 long BigEndian = 0xff000000;
342
343 // printf("TxREAD TGA DATA\n");
344 tgaRLEcount = 0;
345
346 bpp = (tgaHeader->PixelDepth + 1) >> 3;
347
348 switch (tgaHeader->ImgType) {
349 case TGA_MONO: tgaRLE = 0; info->format = GR_TEXFMT_I_8; break;
350 case TGA_MONO_RLE: tgaRLE = 1; info->format = GR_TEXFMT_I_8; break;
351
352 case TGA_TRUE: tgaRLE = 0; info->format = (bpp == 2) ?
353 GR_TEXFMT_ARGB_1555 : GR_TEXFMT_ARGB_8888; break;
354 case TGA_TRUE_RLE: tgaRLE = 1; info->format = (bpp == 2) ?
355 GR_TEXFMT_ARGB_1555 : GR_TEXFMT_ARGB_8888; break;
356
357 case TGA_CMAP: tgaRLE = 0; info->format = GR_TEXFMT_P_8; break;
358 case TGA_CMAP_RLE: tgaRLE = 1; info->format = GR_TEXFMT_P_8; break;
359 }
360
361 // printf("bpp = %d, rle = %d\n", bpp, tgaRLE);
362
363 stride = info->width * bpp;
364 data = info->data[0];
365 if ((tgaHeader->ImageDescriptor & 0x20) == 0) {
366 // Origin is lower left
367 data = data + (info->height-1) * stride;
368 stride = -stride;
369 }
370
371 /* If there's a colormap, read it now. */
372 if (!_txReadTGAColorMap(stream, tgaHeader, (FxU32 *) &(info->pal[0])))
373 return FXFALSE;
374 // printf("read in color map\n");
375
376 /* Read in all the data */
377 for ( i = 0; i < info->height; i++) {
378 if (!_txReadTGASpan( stream, data, info->width, bpp)) {
379 txError("TGA Image: Unexpected end of file.");
380 return FXFALSE;
381 }
382 data += stride;
383 }
384
385 /*
386 * BPP == 1 -> P8 or I8 formatted data.
387 * BPP == 2 -> ARGB1555 formatted data.
388 * BPP == 4 -> ARGB8888 formatted data.
389 * BPP == 3 should be translated to ARGB8888 from RGB888.
390 */
391 // printf("Repacking\n");
392 if (bpp == 3) {
393 int npixels = info->width * info->height;
394 FxU8 *src = ((FxU8 *) info->data[0]) + (npixels - 1) * 3;
395 FxU8 *dst = ((FxU8 *) info->data[0]) + (npixels - 1) * 4;
396
397 while (npixels--) {
398 dst[3] = 0xFF;
399 dst[2] = src[2];
400 dst[1] = src[1];
401 dst[0] = src[0];
402 dst -= 4;
403 src -= 3;
404 }
405 }
406 // printf("Done\n");
407 if (*(FxU8 *)&BigEndian) {
408 /* Repack 16bpp and 32bpp cases */
409 if (bpp == 2) {
410 int npixels = info->width * info->height;
411 FxU16 *src = (FxU16 *) info->data[0];
412
413 while (npixels--) {
414 *src = (*src << 8) | ((*src >> 8) & 0xff);
415 src++;
416 }
417 }
418 if ((bpp == 3) || (bpp == 4)) {
419 int npixels = info->width * info->height;
420 FxU32 *src = (FxU32 *) info->data[0];
421
422 while (npixels--) {
423 *src = (((*src ) & 0xff) << 24)|
424 (((*src >> 8) & 0xff) << 16)|
425 (((*src >> 16) & 0xff) << 8)|
426 (((*src >> 24) & 0xff) );
427 src++;
428 }
429 }
430 }
431 return FXTRUE;
432}
Note: See TracBrowser for help on using the repository browser.