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

Last change on this file was 2885, checked in by sandervl, 26 years ago

Created new Voodoo 1 Glide dir

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