]> 4ch.mooo.com Git - 16.git/blob - 16/v2/source/verge/ENGINE/IMAGE.C
new file: 16/v2/CONSOLE.TXT
[16.git] / 16 / v2 / source / verge / ENGINE / IMAGE.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 // Mega kudos to aen for porting that GIF code.\r
18 \r
19 #include <conio.h>\r
20 #include "verge.h"\r
21 \r
22 // ========================= PCX Imaging routines ============================\r
23 \r
24 char manufacturer;                     // pcx header\r
25 char version;\r
26 char encoding;\r
27 char bits_per_pixel;\r
28 word xmin, ymin;\r
29 word xmax, ymax;\r
30 word hres, vres;\r
31 char palette[48];\r
32 char reserved;\r
33 char color_planes;\r
34 word bytes_per_line;\r
35 word palette_type;\r
36 char filler[58];\r
37 \r
38 word width, depth;\r
39 word bytes;\r
40 byte c, run, ss=0;\r
41 quad vidoffset, n=0;\r
42 VFILE *pcxf;\r
43 char *cb,*src;\r
44 int i;\r
45 \r
46 // ================================= Code ====================================\r
47 \r
48 void ReadPCXLine(byte *dest)\r
49 { n=0;\r
50   while (n<width)\r
51   {\r
52     run=1;\r
53     c=vgetc(pcxf); //*src++;\r
54     if (c>=0xc0) //(c & 0xc0)==0xc0)\r
55     {\r
56       run=c & 0x3f;\r
57       c=vgetc(pcxf); //*src++;\r
58     }\r
59     while (run--)\r
60       dest[vidoffset+n++]=c;\r
61   }\r
62   vseek(pcxf, bytes_per_line-width, 1);\r
63 }\r
64 \r
65 void LoadPCXHeader(char *fname)\r
66 {\r
67   if (!(pcxf=vopen(fname))) err("Could not open PCX file %s.",fname);\r
68   vread(&manufacturer,1,pcxf);\r
69   vread(&version,1,pcxf);\r
70   vread(&encoding,1,pcxf);\r
71   vread(&bits_per_pixel,1,pcxf);\r
72   vread(&xmin,2,pcxf);\r
73   vread(&ymin,2,pcxf);\r
74   vread(&xmax,2,pcxf);\r
75   vread(&ymax,2,pcxf);\r
76   vread(&hres,2,pcxf);\r
77   vread(&vres,2,pcxf);\r
78   vread(&palette,48,pcxf);\r
79   vread(&reserved,1,pcxf);\r
80   vread(&color_planes,1,pcxf);\r
81   vread(&bytes_per_line,2,pcxf);\r
82   vread(&palette_type,2,pcxf);\r
83   vread(&filler,58,pcxf);\r
84   //vseek(pcxf,filesize(pcxf)-768,SEEK_SET);\r
85   //vread(&pal,768,pcxf);\r
86   vseek(pcxf,128L,SEEK_SET);\r
87   width=xmax-xmin+1;\r
88   depth=ymax-ymin+1;\r
89 \r
90   bytes=bytes_per_line;\r
91 \r
92   //for (i=0; i<768; i++)\r
93   //  pal[i]=pal[i] >> 2;\r
94 //  SetPalette((byte *) &pal);\r
95 \r
96   //i=filesize(pcxf);\r
97   //cb=(char *) valloc(i-896, "LoadPCXHeader:cb", OID_TEMP);\r
98   //vread(cb, i-(128+768+1), pcxf);\r
99 }\r
100 \r
101 void LoadPCXHeaderNP(char *fname)\r
102 {\r
103   if (!(pcxf=vopen(fname))) err("Could not open PCX file %s.",fname);\r
104   vread(&manufacturer,1,pcxf);\r
105   vread(&version,1,pcxf);\r
106   vread(&encoding,1,pcxf);\r
107   vread(&bits_per_pixel,1,pcxf);\r
108   vread(&xmin,2,pcxf);\r
109   vread(&ymin,2,pcxf);\r
110   vread(&xmax,2,pcxf);\r
111   vread(&ymax,2,pcxf);\r
112   vread(&hres,2,pcxf);\r
113   vread(&vres,2,pcxf);\r
114   vread(&palette,48,pcxf);\r
115   vread(&reserved,1,pcxf);\r
116   vread(&color_planes,1,pcxf);\r
117   vread(&bytes_per_line,2,pcxf);\r
118   vread(&palette_type,2,pcxf);\r
119   vread(&filler,58,pcxf);\r
120   vseek(pcxf,filesize(pcxf)-768,SEEK_SET);\r
121   vread(&pal,768,pcxf);\r
122   vseek(pcxf,128L,SEEK_SET);\r
123   width=xmax-xmin+1;\r
124   depth=ymax-ymin+1;\r
125   bytes=bytes_per_line;\r
126 \r
127   i=filesize(pcxf);\r
128   cb=(char *) valloc(i-896, "LoadPCXHeaderNP:cb", OID_TEMP);\r
129   vread(cb, i-896, pcxf);\r
130 }\r
131 \r
132 void LoadPCX(char *fname, byte *dest)\r
133 {\r
134   LoadPCXHeader(fname);\r
135 \r
136   src=cb;\r
137   for (i=0; i<depth; i++)\r
138   {\r
139     vidoffset=(i*width);\r
140     ReadPCXLine(dest);\r
141   }\r
142   vfree(cb);\r
143   vclose(pcxf);\r
144 }\r
145 \r
146 byte *LoadPCXBuf(char *fname)\r
147 { byte *buf=0;\r
148 \r
149 //  LoadPCXHeaderNP(fname);\r
150   LoadPCXHeader(fname);\r
151   buf=(byte *) valloc(width*(depth+1), "LoadPCXBuf:buf", OID_IMAGE);\r
152   //src=cb;\r
153   for (vidoffset=0,i=0; i<depth; i++,vidoffset+=width)\r
154     ReadPCXLine(buf);\r
155   // palette avail?\r
156   if (12==vgetc(pcxf))\r
157   {\r
158     vread(pal,768,pcxf);\r
159     for (i=0; i<768; i++)\r
160       pal[i]>>=2;\r
161   }\r
162   //vfree(cb);\r
163   vclose(pcxf);\r
164   return buf;\r
165 }\r
166 \r
167 // ========================= BMP Imaging routines ============================\r
168 \r
169 struct RGBQUAD\r
170 {\r
171   unsigned char r,g,b,a;\r
172 };\r
173 \r
174 struct RGBQUAD bmppalette[256];\r
175 \r
176 // ================================= Code ====================================\r
177 \r
178 byte *LoadBMPBuf(char *fname)\r
179 { byte pad[4], *buf;\r
180   VFILE* bmpfile;\r
181   int bwidth, bheight, y;\r
182 \r
183   if (!(bmpfile=vopen(fname))) err("Could not open BMP file %s.",fname);\r
184   vseek(bmpfile, 18, SEEK_SET);\r
185   vread(&bwidth, 4, bmpfile); width=bwidth;\r
186   vread(&bheight, 4, bmpfile); depth=bheight;\r
187   vseek(bmpfile, 54, SEEK_SET);\r
188   vread(bmppalette, 1024, bmpfile);\r
189   buf=(byte*) valloc(bwidth*bheight, "LoadBMPBuf:buf", OID_IMAGE);\r
190 \r
191   for (y=bheight-1; y>=0; y--)\r
192   {\r
193     vread((char *)((int)buf+y*width),width,bmpfile);\r
194     vread(pad,width%4,bmpfile);\r
195   }\r
196   for (y=0; y<256; y++)\r
197   {\r
198     pal[y*3]=bmppalette[y].b >> 2;\r
199     pal[y*3+1]=bmppalette[y].g >> 2;\r
200     pal[y*3+2]=bmppalette[y].r >> 2;\r
201   }\r
202   SetPalette((byte*)pal);\r
203   vclose(bmpfile);\r
204   return buf;\r
205 }\r
206 \r
207 // ========================== GIF Imaging routines ===========================\r
208 \r
209 typedef unsigned char u8;\r
210 typedef unsigned short u16;\r
211 typedef unsigned long u32;\r
212 \r
213 typedef signed char s8;\r
214 typedef signed short s16;\r
215 typedef signed long s32;\r
216 \r
217 typedef struct\r
218 {\r
219   u8 bits;\r
220   u8 background;\r
221   u8 * palette;\r
222   u8 * image;\r
223   s16 wide, deep;\r
224 } gif_image_info;\r
225 \r
226 typedef struct\r
227 {\r
228   char sig[7];\r
229   s16 screenwide, screendeep;\r
230   u8 hflags;\r
231   u8 background;\r
232   u8 aspect;\r
233 } gif_header;\r
234 \r
235 typedef struct\r
236 {\r
237   s16 top, left;\r
238   s16 wide, deep;\r
239   u8 iflags;\r
240 } gif_image_descriptor;\r
241 \r
242 int NO_CODE = -1,// TRUE = 1,\r
243     ERROR_EOF = 0, ERROR_BAD_CODE = 1,\r
244     ERROR_BAD_HEADER = 2, ERROR_BAD_STARTCODE = 3,\r
245     ERROR_BAD_FIRST_CODE = 4, ERROR_BAD_FILE = 5,\r
246     ERROR_NO_IMAGE = 6;\r
247 \r
248 char* gif_error_messages[] =\r
249 {\r
250   "Unexpected end of file\n",\r
251   "Bad code\n",\r
252   "Bad gif header\n",\r
253   "Bad symbol size\n",\r
254   "Bad first code\n",\r
255   "Error opening file\n",\r
256   "This file doesn't contain an image\n"\r
257 };\r
258 \r
259 // read colour palette, vga palette values are 6 bit numbers\r
260 // while gif allows for 8 bit so shift right to get correct colours\r
261 \r
262 u8* gif_read_palette(FILE* fp, s32 bytes)\r
263 {\r
264   s32 i = 0;\r
265   u8* block = 0L;\r
266   s32 components = (bytes / 3) * 3;\r
267 \r
268   block  = (unsigned char *)valloc(components, "gif_read_palette:block", OID_IMAGE);\r
269 \r
270   for (i = 0; i < components; ++i)\r
271     block[i] = fgetc(fp) >> 2;\r
272 \r
273   return block;\r
274 }\r
275 \r
276 // read a block of bytes into memory\r
277 s32 block_mem_read(FILE* fp, u8* buffer, s32 bytes)\r
278 {\r
279   s32 status = 0;\r
280 \r
281   status = fread(buffer, 1, bytes, fp);\r
282   if (status != bytes) return EOF;\r
283 \r
284   return TRUE;\r
285 }\r
286 \r
287 // read a unsigned 16 bit value from file, low byte first; note that this\r
288 // is reverse endian-ness (ie. fwrite(&s,1,2,fp); writes high byte first).\r
289 \r
290 s16 read_word_lbf(FILE* fp)\r
291 {\r
292   s32 a, b;\r
293 \r
294   a = fgetc(fp);\r
295   b = fgetc(fp);\r
296 \r
297   return (b << 8) | a;\r
298 }\r
299 \r
300 // read the GIF file header structure into a sequence\r
301 gif_header* get_gif_header(FILE* fp)\r
302 {\r
303   gif_header* h = 0L;\r
304 \r
305   h = (gif_header *)valloc(sizeof(gif_header), "get_gif_header:h", OID_IMAGE);\r
306 \r
307   fread(h->sig, 1, 6, fp);\r
308   h->sig[6] = 0;\r
309 \r
310   if (strncmp(h->sig, "GIF", 3) != 0)\r
311     return NULL;\r
312 \r
313   h->screenwide = read_word_lbf(fp); width=h->screenwide;\r
314   h->screendeep = read_word_lbf(fp); depth=h->screendeep;\r
315   h->hflags = fgetc(fp);\r
316   h->background = fgetc(fp);\r
317   h->aspect = fgetc(fp);\r
318 \r
319   return h;\r
320 }\r
321 \r
322 // gif file can contain more than one image,\r
323 // each image is preceeded by a header structure\r
324 gif_image_descriptor* get_image_descriptor(FILE* fp)\r
325 {\r
326   gif_image_descriptor* id = 0L;\r
327 \r
328   id = (gif_image_descriptor *)valloc(sizeof(gif_image_descriptor), "get_image_descriptor:id", OID_IMAGE);\r
329 \r
330   id->left = read_word_lbf(fp);\r
331   id->top = read_word_lbf(fp);\r
332   id->wide = read_word_lbf(fp);\r
333   id->deep = read_word_lbf(fp);\r
334   id->iflags = fgetc(fp);\r
335 \r
336   return id;\r
337 }\r
338 \r
339 static u16 word_mask_table[] =\r
340 {\r
341   0x0000, 0x0001, 0x0003, 0x0007,\r
342   0x000F, 0x001F, 0x003F, 0x007F,\r
343   0x00FF, 0x01FF, 0x03FF, 0x07FF,\r
344   0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF\r
345 };\r
346 \r
347 static u8 inc_table[] = { 8,8,4,2,0 };\r
348 static u8 start_table[] = { 0,4,2,1,0 };\r
349 \r
350 // enables me to use indices as per EUPHORiA (ie. converts to C's 0 base)\r
351 #define eui(i) ((i)-1)\r
352 \r
353 // unpack an LZW compressed image\r
354 // returns a sequence containing screen display lines of the image\r
355 u8* unpack_image(FILE* fp, s32 start_code_size, u32 width, u32 depth, u32 flags)\r
356 {\r
357   u8* buffer;\r
358   u8* line_buffer;\r
359 \r
360   u16 first_code_stack[4096];\r
361   u16 last_code_stack[4096];\r
362   u16 code_stack[4096];\r
363 \r
364   s32 bits_left;\r
365   s32 clear_code;\r
366   s32 code_size;\r
367   s32 code_size2;\r
368   s32 next_code;\r
369   s32 this_code;\r
370   s32 old_token;\r
371   s32 current_code;\r
372   s32 old_code;\r
373   s32 block_size=0;\r
374   s32 line;\r
375   s32 a_byte;\r
376   s32 pass;\r
377   s32 u;\r
378 \r
379   u8 b[256]; // read buffer; for block reads\r
380   u8* p; // current byte in read buffer\r
381   u8* q; // last byte in read buffer + 1\r
382 \r
383   line_buffer = (u8 *)valloc(width, "unpack_image:line_buffer", OID_TEMP);\r
384   buffer      = (u8 *)valloc(width * depth, "unpack_image:buffer", OID_IMAGE);\r
385 \r
386   a_byte = 0;\r
387   line = 0;\r
388   pass = 0;\r
389   bits_left = 8;\r
390 \r
391   if (start_code_size < 2 || start_code_size > 8)\r
392     err("\nERROR_BAD_STARTCODE"); // bad symbol size\r
393 \r
394   p = b;\r
395   q = b;\r
396 \r
397   clear_code = 1 << start_code_size; //pow(2, start_code_size);\r
398   next_code = clear_code + 2;\r
399   code_size = start_code_size + 1;\r
400   code_size2 = 1 << code_size; //pow(2, code_size);\r
401   old_code = NO_CODE;\r
402   old_token = NO_CODE;\r
403 \r
404   while (1)\r
405   {\r
406     if (bits_left == 8)\r
407     {\r
408       ++p;\r
409       if (p >= q)\r
410       {\r
411         block_size = fgetc(fp);\r
412         if (block_mem_read(fp, b, block_size) == EOF)\r
413           err("\nERROR_EOF");\r
414         p = b;\r
415         q = b + block_size;\r
416       }\r
417       bits_left = 0;\r
418     }\r
419 \r
420     this_code = *p;\r
421     current_code = code_size + bits_left;\r
422 \r
423     if (current_code <= 8)\r
424     {\r
425       *p = *p >> code_size;\r
426       bits_left = current_code;\r
427     }\r
428     else\r
429     {\r
430       ++p;\r
431       if (p >= q)\r
432       {\r
433         block_size = fgetc(fp);\r
434         if (block_mem_read(fp, b, block_size) == EOF)\r
435           err("\nERROR_EOF");\r
436         p = b;\r
437         q = b + block_size;\r
438       }\r
439 \r
440       this_code |= (*p << (8 - bits_left));\r
441 \r
442       if (current_code <= 16)\r
443       {\r
444         bits_left = current_code - 8;\r
445         *p = *p >> bits_left;\r
446       }\r
447       else\r
448       {\r
449         if (++p >= q)\r
450         {\r
451           block_size = fgetc(fp);\r
452           if (block_mem_read(fp, b, block_size) == EOF)\r
453             err("\nERROR_EOF");\r
454           p = b;\r
455           q = b + block_size;\r
456         }\r
457 \r
458         this_code |= (*p << (16 - bits_left));\r
459 \r
460         bits_left = current_code - 16;\r
461         *p = *p >> bits_left;\r
462       }\r
463     }\r
464 \r
465     this_code &= word_mask_table[code_size];\r
466     current_code = this_code;\r
467 \r
468     if (this_code == (clear_code+1) || block_size == 0)\r
469       break;\r
470     if (this_code > next_code)\r
471       err("\nERROR_BAD_CODE");\r
472 \r
473     if (this_code == clear_code)\r
474     {\r
475       next_code = clear_code + 2;\r
476       code_size = start_code_size + 1;\r
477       code_size2 = 1 << code_size; //pow(2, code_size);\r
478       old_code = NO_CODE;\r
479       old_token = NO_CODE;\r
480     }\r
481     else\r
482     {\r
483       u = 1;\r
484       if (this_code == next_code)\r
485       {\r
486         if (old_code == NO_CODE)\r
487           err("\nERROR_BAD_FIRST_CODE");\r
488 \r
489         first_code_stack[eui(u)] = old_token;\r
490         u++;\r
491         this_code = old_code;\r
492       }\r
493 \r
494       while (this_code >= clear_code)\r
495       {\r
496         first_code_stack[eui(u)] = last_code_stack[eui(this_code)];\r
497         u++;\r
498         this_code = code_stack[eui(this_code)];\r
499       }\r
500 \r
501       old_token = this_code;\r
502       while (1)\r
503       {\r
504         line_buffer[a_byte] = this_code;\r
505         a_byte++;\r
506         if (a_byte >= width)\r
507         {\r
508           // full image line so add it into screen image\r
509           memcpy(buffer + (line * width), line_buffer, width);\r
510 \r
511           a_byte = 0;\r
512           if (flags & 0x40)\r
513           {\r
514             line += inc_table[pass];\r
515             if (line >= depth)\r
516             {\r
517               pass++;\r
518               line = start_table[pass];\r
519             }\r
520           }\r
521           else\r
522           {\r
523             line++;\r
524           }\r
525         }\r
526 \r
527         // no more bytes on stack\r
528         if (u == 1) break;\r
529 \r
530         u--;\r
531         this_code = first_code_stack[eui(u)];\r
532       }\r
533 \r
534       if (next_code < 4096 && old_code != NO_CODE)\r
535       {\r
536         code_stack[eui(next_code)] = old_code;\r
537         last_code_stack[eui(next_code)] = old_token;\r
538         next_code++;\r
539         if (next_code >= code_size2 && code_size < 12)\r
540         {\r
541           code_size++;\r
542           code_size2 = 1 << code_size; //pow(2, code_size);\r
543         }\r
544       }\r
545 \r
546       old_code = current_code;\r
547     }\r
548   }\r
549 \r
550   // completed reading the image so return it\r
551   free(b);\r
552   return buffer;\r
553 }\r
554 \r
555 // skip the extension blocks as we are only after the image\r
556 void skip_extension(FILE* fp)\r
557 {\r
558   s32 n;\r
559   char temp[256];\r
560 \r
561   n = fgetc(fp); // throwaway extension function code\r
562   n = fgetc(fp); // get length of block\r
563 \r
564   while (n > 0 && n != EOF)\r
565   {\r
566     // throwaway block\r
567     fread(temp, 1, n, fp);\r
568 \r
569     n = fgetc(fp); // get length of next block\r
570   }\r
571 }\r
572 \r
573 // unpack the GIF file\r
574 // returns ImageInfo sequence containing image and image data\r
575 gif_image_info* unpack_gif(char* filename)\r
576 {\r
577   VFILE *f;\r
578   FILE* fp;\r
579   s32 c, b;\r
580   gif_header* h = 0L;\r
581   gif_image_info* ii = 0L;\r
582   gif_image_descriptor* id = 0L;\r
583   u8* local_palette = 0L;\r
584 \r
585   ii = (gif_image_info *)valloc(sizeof(gif_image_info), "unpack_gif:ii", OID_IMAGE);\r
586 \r
587   f = vopen(filename);\r
588   if (!f) err("Could not open GIF file %s.",filename);\r
589   fp = f->fp;\r
590   if (!fp) err("\nBad filename");\r
591 \r
592   // file starts with the Logical Screen Descriptor structure\r
593   h = get_gif_header(fp);\r
594 \r
595   // Size of Global Color Table\r
596   ii->bits = (h->hflags & 7) + 1;\r
597   ii->background = h->background;\r
598 \r
599   // get Global colour palette if there is one\r
600   if (h->hflags & 0x80) // is flags bit 8 set?\r
601   {\r
602     c = 3 << ii->bits; // size of global colour map\r
603     ii->palette = gif_read_palette(fp, c);\r
604 \r
605 /*    outp(968, 0);\r
606     // enforce global color map\r
607     for (s32 i=0; i < 768; ++i)\r
608       outp(969, ii->palette[i]); */\r
609     memcpy(pal, ii->palette, 768);\r
610   }\r
611 \r
612   c = fgetc(fp);\r
613 \r
614   while (c == 0x2c || c == 0x21 || c == 0)\r
615   {\r
616     // image separator so unpack the image\r
617     if (c == 0x2c)\r
618     {\r
619       id = get_image_descriptor(fp); // get the Image Descriptor\r
620       // if there is a local Color Table then overwrite the global table\r
621       if (id->iflags & 0x80)\r
622       {\r
623         ii->bits = (id->iflags & 7) + 1;\r
624         b = 3 << ii->bits;\r
625         if (local_palette)\r
626           free(local_palette);\r
627         local_palette = gif_read_palette(fp, b);\r
628       }\r
629 \r
630       c = fgetc(fp); // get the LZW Minimum Code Size\r
631       ii->image = unpack_image(fp, c, id->wide, id->deep, id->iflags);\r
632       vclose(f);\r
633 \r
634       // error reading image\r
635       if (!ii->image)\r
636         err("\nerror reading image data");\r
637 \r
638       ii->wide = id->wide;\r
639       ii->deep = id->deep;\r
640 \r
641       // return imagedata\r
642       return ii;\r
643     }\r
644     // extension introducer\r
645     else if (c == 0x21)\r
646     {\r
647       skip_extension(fp); // throw the extension away\r
648     }\r
649 \r
650     c = fgetc(fp);\r
651   }\r
652 \r
653   // no image?\r
654   return NULL;\r
655 }\r
656 \r
657 byte *LoadGIFBuf(char *fname)\r
658 {\r
659   gif_image_info *ii=0;\r
660   byte *t;\r
661 \r
662   ii=unpack_gif(fname);\r
663   width=ii->wide;\r
664   depth=ii->deep;\r
665   t=ii->image;\r
666   free(ii);\r
667   return t;\r
668 }\r
669 \r
670 // ====================== Universal Imaging Interface ========================\r
671 \r
672 byte imagetype;\r
673 \r
674 // ================================= Code ====================================\r
675 \r
676 void DetermineFileType(char *fname)\r
677 {\r
678   strlwr(fname);\r
679   if (!strcmp(fname+(strlen(fname)-3),"pcx")) imagetype=0;\r
680   if (!strcmp(fname+(strlen(fname)-3),"gif")) imagetype=1;\r
681   if (!strcmp(fname+(strlen(fname)-3),"bmp")) imagetype=2;\r
682 }\r
683 \r
684 void VLoadImage(char *fname, byte *dest)\r
685 {\r
686   imagetype=255;\r
687   DetermineFileType(fname);\r
688   switch (imagetype)\r
689   {\r
690     case 0: LoadPCX(fname, dest); break;\r
691     case 1: err("VLoadImage() for GIF not supported; use VLoadImageBuf()"); break;\r
692     case 2: err("VLoadImage() for BMP not supported; use VLoadImageBuf()"); break;\r
693     default: err("%s: Unrecognized image type.",fname);\r
694   }\r
695 }\r
696 \r
697 byte *VLoadImageBuf(char *fname)\r
698 {\r
699   imagetype=255;\r
700   DetermineFileType(fname);\r
701   switch (imagetype)\r
702   {\r
703     case 0: return LoadPCXBuf(fname); break;\r
704     case 1: return LoadGIFBuf(fname); break;\r
705     case 2: return LoadBMPBuf(fname); break;\r
706     default: err("%s: Unrecognized image type.",fname);\r
707   }\r
708   return 0;\r
709 }\r