# dont perform the libgen and libsocket test in configure for AROS.
[AROS-Contrib.git] / fish / surf / readilbm.c
blobc17ff3aff254a855b72090d2e0122a4e31203f03
1 #include <stdio.h>
2 #include <ctype.h>
3 #include "readilbm.h"
4 #include "mytypes.h"
6 void OutErr(char *);
8 #define RED 0
9 #define GRN 1
10 #define BLU 2
12 /* color to grey conversion methods */
14 #define AVERAGE 0
15 #define LUMIN 1
16 #define DIST 2
17 #define REDONLY 3
18 #define GREENONLY 4
19 #define BLUEONLY 5
21 #define MakeID(a,b,c,d) ( ((a)<<24) | ((b)<<16) | ((c)<<8) | (d) )
23 #define ID_FORM MakeID('F','O','R','M')
24 #define ID_ILBM MakeID('I','L','B','M')
25 #define ID_BMHD MakeID('B','M','H','D')
26 #define ID_CMAP MakeID('C','M','A','P')
27 #define ID_CAMG MakeID('C','A','M','G')
28 #define ID_BODY MakeID('B','O','D','Y')
30 #define ROUNDUP(x) ( ((x)+1) & (~1L) )
34 static struct CHUNK {
35 unsigned long Id, Size;
36 } Chunk;
38 static unsigned char cmap[32][3];
40 struct BMHD {
41 short w,h,x,y;
42 char npl,mask,compress,pad1;
43 short transparentColor;
44 char xAspect,yAspect;
45 short pageWidth,pageHeight;
49 static short Color[32], /* output colors */
50 Method = AVERAGE; /* color conversion */
51 static short numcolors;
53 static
54 FILE *fin; /* input file */
56 static void FRead();
57 static void ReadBMHD();
58 static void ReadChunk();
59 static void RastOut();
60 static void HamOut();
61 static char GetIlbmVal();
62 static void InitColorMappings();
63 static short Convert();
64 static void ReadDecomLine();
65 static void ProcessRows();
67 #define ABORT(str) { OutErr(str); goto ErrorExit; }
70 void SetGreyModel( model )
71 int model;
73 Method = model;
77 * main routine for reading in an iff file
80 void ReadIlbm(filename)
81 char *filename;
83 struct BMHD bmhd;
84 long ILBMid;
85 unsigned char cmapFlag = FALSE,
86 bmhdFlag = FALSE;
89 if ((fin = fopen (filename, "r")) == NULL) {
90 OutErr ("ERROR: cannot open input file");
91 return;
93 /* read in iff file */
95 ReadChunk ();
96 if (Chunk.Id != ID_FORM)
97 ABORT ("Not an IFF File");
99 FRead (&ILBMid, 4);
100 if (ILBMid != ID_ILBM)
101 ABORT ("Not an ILBM File");
103 while (1) {
104 long camgdata;
106 ReadChunk ();
108 if (Chunk.Id == ID_BODY)
109 break;
111 if( feof( fin ) ) {
112 ABORT("reached end of file without seeing body\n");
115 switch (Chunk.Id) {
116 case ID_CMAP:
117 FRead (cmap, Chunk.Size);
118 numcolors = Chunk.Size/3;
119 cmapFlag = TRUE;
120 break;
121 case ID_BMHD:
122 ReadBMHD (&bmhd);
123 bmhdFlag = TRUE;
124 break;
125 case ID_CAMG:
126 FRead( &camgdata, sizeof(camgdata) );
127 break;
128 default: /* unknown identifier */
129 fseek( fin, Chunk.Size, 1);
130 break;
133 if (!cmapFlag) {
134 ABORT("IFF file does not contain a CMAP chunk before the BODY\n");
137 if (!bmhdFlag) {
138 ABORT("IFF file does not contain a BMHD chunk before the BODY\n");
141 InitColorMappings();
142 if( OpenImgPix( bmhd.w, bmhd.h, Convert(0xf, 0xf, 0xf)) ) {
143 ProcessRows(&bmhd);
146 ErrorExit:
147 fclose( fin);
150 static void ProcessRows(bmhd)
151 struct BMHD *bmhd;
153 char *rastlist[6];
154 char *Raster;
155 int depth, i, v, pixwidth;
156 int BytePerLine;
158 depth = bmhd->npl;
159 pixwidth = bmhd->w;
160 BytePerLine =(pixwidth+7) / 8;
163 Raster = (char *) malloc (BytePerLine * depth);
165 if(!Raster ) {
166 OutErr("ProcessRows:could not allocate Raster");
167 return;
170 for( i = 0; i < depth; i++ ) {
171 rastlist[i] = Raster + BytePerLine*i;
174 for( v = 0; v < bmhd->h; v++) {
175 switch (bmhd->compress) {
176 case 0:
177 FRead (Raster, BytePerLine * depth);
178 break;
179 case 1:
180 for( i = 0; i < depth; i++) {
181 ReadDecomLine( BytePerLine, rastlist[i]);
183 break;
184 default:
185 ABORT ("Unknown Compression type in BODY");
188 if(depth == 6 ) {
189 HamOut( rastlist, pixwidth, v);
191 else {
192 RastOut( rastlist, pixwidth, v, depth);
196 ErrorExit:
197 if( Raster ) free(Raster);
201 static void ReadDecomLine(linebytes, rp)
202 int linebytes;
203 char *rp;
205 int runlen;
206 char pixel;
208 while (linebytes) {
209 runlen = getc (fin);
210 if (runlen > 127)
211 runlen -= 256;
212 if (runlen >= 0) {
213 runlen++;
214 FRead (rp, runlen);
215 rp += runlen;
216 linebytes -= runlen;
218 else {
219 runlen = -runlen + 1;
220 linebytes -= runlen;
221 pixel = getc (fin);
223 *(rp++) = pixel;
224 while (--runlen);
230 * Convert - convert (r,g,b) to hex greyscale.
233 static short Convert(r,g,b)
234 unsigned char r,g,b;
236 short i,
237 rd, gd, bd,
238 min,
239 dist,
240 best = 0;
242 /* convert color according to 'Method' */
243 switch (Method) {
244 case AVERAGE: /* average r,g,b to obtain grey level */
245 return ((short)((r + g + b) / 3));
246 case LUMIN: /* use NTSC luminescence as grey level */
247 return ((short)((r * 30 + g * 59 + b * 11) / 100));
248 case DIST: /* use grey with minimum distance in color */
249 min = 15*15 * 3;
250 for( i = 0; i < numcolors; i++ ) {
251 rd = r -i;
252 gd = g - i;
253 bd = b - i;
254 dist = rd * rd + gd * gd + bd * bd;
255 if( dist < min ) {
256 min = dist; best = i;
259 return( best );
260 case REDONLY:
261 return((short)r);
262 case GREENONLY:
263 return((short)g);
264 case BLUEONLY:
265 return((short)b);
266 default:
267 exit(-1); /* error, big one */
269 } /* Convert */
271 static void InitColorMappings()
273 int i;
275 /* put colors in 4-bit range and Convert */
276 for (i = 0; i < 32; i++) {
277 cmap[i][RED] >>= 4;
278 cmap[i][GRN] >>= 4;
279 cmap[i][BLU] >>= 4;
280 Color[i] = Convert (cmap[i][RED], cmap[i][GRN], cmap[i][BLU]);
286 * leftmost pixel of byte is in most significant bit of byte
288 static char GetIlbmVal( rastlist, h, bpp )
289 char *rastlist[6];
290 int h, bpp;
292 int i;
293 char value = 0;
294 short mask, bytep;
296 mask = 0x80 >> ( h & 7);
297 bytep = h >> 3;
299 for( i = bpp-1; i >= 0; i-- ) {
300 value <<= 1;
301 value |= (*(rastlist[i]+bytep) & mask) ? 1: 0;
303 return( value );
307 * HamOut - output ham image in hex.
309 static void HamOut(rastlist, pixwidth, v)
310 char *rastlist[6];
311 int pixwidth, v;
313 unsigned char lastred = 0,
314 lastgreen = 0,
315 lastblue = 0;
316 int h;
317 char pixval;
318 for( h = 0; h <pixwidth; h++ ) {
319 short shade;
321 shade = GetIlbmVal(rastlist, h, 6);
322 pixval = shade & 0x0F;
323 switch (shade & 0x30) {
324 case 0x00:
325 lastred = cmap[(int)pixval][RED];
326 lastgreen = cmap[(int)pixval][GRN];
327 lastblue = cmap[(int)pixval][BLU];
328 shade = Color[(int)pixval];
329 break;
330 case 0x10:
331 lastblue = pixval;
332 shade = Convert(lastred,lastgreen,lastblue);
333 break;
334 case 0x20:
335 lastred = pixval;
336 shade = Convert(lastred,lastgreen,lastblue);
337 break;
338 case 0x30:
339 lastgreen = pixval;
340 shade = Convert(lastred,lastgreen,lastblue);
342 SetImgPix(h, v, shade);
347 * RastOut - handle normal bit mapped images
349 static void RastOut(rastlist, pixwidth, v, depth)
350 char *rastlist[6];
351 int pixwidth, v, depth;
353 int h;
354 for( h = 0; h < pixwidth; h++ ) {
355 short shade;
356 shade = Color[(int)GetIlbmVal( rastlist, h, depth)];
357 SetImgPix( h, v, shade);
362 * ReadChunk - read in an IFF Chunk.
365 static void ReadChunk()
367 FRead (&Chunk, sizeof (Chunk));
369 } /* ReadChunk */
372 * ReadBMHD - read the BMHD structure.
375 static void ReadBMHD(bmhd)
376 struct BMHD *bmhd;
378 FRead (bmhd, Chunk.Size);
379 } /* ReadBMHD */
383 * FRead - read 'len' bytes to 'pointer' while checking for an error.
386 static void FRead(pointer,len)
387 char *pointer;
388 int len;
390 if (fread (pointer, len, 1, fin) == 0) {
391 char outbuff[90];
392 sprintf(outbuff,"Fread Error in reading input file at %d ", (int)ftell(fin));
393 OutErr(outbuff);
395 } /* FRead */