File: rle.c

package info (click to toggle)
xloadimage 4.1-25
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,820 kB
  • sloc: ansic: 36,084; asm: 284; makefile: 282; sh: 280
file content (440 lines) | stat: -rw-r--r-- 11,512 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
/* 
 * rle - read in a Utah RLE Toolkit type image.
 * 
 * Author:	Graeme Gill
 * Date: 	30/5/90
 * 
 * Bugs - doesn't free up memory used by rle functions.
 *
 */

#define MIN(a,b) ( (a)<(b) ? (a) : (b))

#include <math.h>
#include <stdio.h>
#include "image.h"
#include "rle.h"
#include "rlelib.h"

#undef  DEBUG
#undef  debug

#ifdef DEBUG
# define debug(xx)	fprintf(stderr,xx)
#else
# define debug(xx)
#endif

void dithermap();

/* input file stuff */
static int ptype;				/* picture type : */
#define BW_NM	0		/* black and white, no map */
#define BW_M	1		/* black and white, and a map */
#define SC_M	2		/* single colour channel and colour map */
#define C_NM	3		/* full colour, no maps */
#define C_M		4		/* full colour with colour maps */
static rle_pixel **fmaps;		/* file colour maps from buildmap() */
static unsigned char **scan;	/* buffer for input data */
static int x_min;		/* copy of picture x_min */
static int y_min;		/* copy of picture y_min */

/* option stuff (Not functional) */
static float disp_gam = 1.0;	/* default display gamma correction factor */
static int iflag=0;			/* user suplied image gamma */
static float img_gam = 1.0;			/* image gamma */
static int bwflag = 0;			/* black and white flag */
static int gammamap[256];
static int background[3] = {0,0,0};	/* our background colour */

/* stuff for dithering colour pictures */
int colmap[216][3];		/* for dither map */
int magic[16][16];
int modN[256];
int divN[256];

int rleIdent(fullname, name)
     char *fullname, *name;
{
  ZFILE *rlefile;
  int x_len,y_len;
  int rv;

  debug("rleIdent called\n");
  rlefile = zopen(fullname);
  if(!rlefile)
    {
      perror("rleIdent: Unable to open file");
      return(0);
    }
  debug("rleIdent: Opened file ok\n");
  sv_globals.svfb_fd = rlefile;
  rv = rle_get_setup(&sv_globals);
  debug("rleIdent: got setup ok\n");
  zclose(rlefile);
  debug("rleIdent: closed file ok\n");
  switch(rv)
    {
    case -1:
      return 0;		/* Not rle format */
    case 0:
      /* now figure out the picture type */
      switch(sv_globals.sv_ncolors)
	{
	case 0:
	  perror("rleIdent: no colour channels to display");
	  return(0);
	case 1:
	  x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
	  y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
	  printf("%s is a %dx%d", name, x_len, y_len);
	  switch(sv_globals.sv_ncmap) {
	    case 0:
	      /* black and white, no map */
	      printf(" 8 bit grey scale RLE image with no map\n"); 
	      break;
	    case 1:
	      /* black and white with a map */
	      printf(" 8 bit grey scale RLE image with map\n"); 
	      break;
	    case 3:
	      /* single channel encoded colour with decoding map */
	      printf(" 8 bit color RLE image with color map\n");
	      break;
	    default:
	      perror(" 8 bit RLE image with an illegal color map\n");
	      return 0;
	    }
	  break;
	case 3:
	  x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
	  y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
	  printf("%s is a %dx%d", name, x_len, y_len);
	  switch(sv_globals.sv_ncmap)
	    {
	    case 0:
	      printf(" 24 bit color RLE image with no map\n");
	      break;
	    case 3:
	      printf(" 24 bit color RLE image with colour map\n");
	      break;
	    default:
	      printf(" 24 bit color RLE image with an illegal color map\n");
	      return 0;
	    }
	  break;
	default:
	  x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
	  y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
	  printf("%s is a %dx%d", name, x_len, y_len);
	  printf(" RLE image with an illegal number of color planes\n");
	  return 0;
	}
      return 1;
    default:			/* Some sort of error */
      /*			perror("rleIdent");*/
      return 0;
    }
}

Image *rleLoad(fullname,name,verbose)
     char *fullname,*name;
     unsigned int verbose;
{
  int x_len, y_len;
  int i,j;
  ZFILE *rlefile;
  int ncol;			/* number of colors */
  int depth;
  unsigned char *bufp;
  Image *image;
  unsigned char *buf;
  
  dith_levels = 256;	/* aim for 128 levels of each colour */
  
  debug("rleLoad called\n");
  rlefile = zopen(fullname);
  if(!rlefile)
    {
      perror("rleLoad: Cannot open input file");
      return(NULL);	
    }
  sv_globals.svfb_fd = rlefile;
  debug("rleLoad: About to call get_setup\n");
  if(rle_get_setup( &sv_globals )) {
    zclose(rlefile);
    return(NULL);	
  }
  
  debug("rleLoad: get_setup called ok\n");
  if(iflag == 1)	/* -i flag */
    img_gam = 1.0/img_gam;		/* convert to display gamma */
  
  /* If no image gamma on command line, check comments in file */
  if (!iflag)
    {
      char * v;
      if ( (v = rle_getcom( "image_gamma", &sv_globals )) != NULL )
	{	
	  img_gam = atof( v );
	  /* Protect against bogus information */
	  if ( img_gam == 0.0 )
	    img_gam = 1.0;
	  else
	    img_gam = 1.0 / img_gam;	/* convert to display gamma */
	}
      else if ( (v = rle_getcom( "display_gamma", &sv_globals )) != NULL )
	{
	  img_gam = atof( v );
	  /* Protect */
	  if ( img_gam == 0.0 )
	    img_gam = 1.0;
	}
    }
  
  x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
  y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
  
  x_min = sv_globals.sv_xmin;
  y_min = sv_globals.sv_ymin;
  
  /* fix this so that we don't waste space */
  sv_globals.sv_xmax -= sv_globals.sv_xmin;
  sv_globals.sv_xmin = 0;
  
  /* turn off the alpha channel (don't waste time and space)*/
  sv_globals.sv_alpha = 0;
  SV_CLR_BIT(sv_globals,SV_ALPHA);
  
  /* for now, force background clear */
  if(sv_globals.sv_background ==1)	/* danger setting */
    {
      debug("Forcing clear of background\n");
      sv_globals.sv_background = 2;
      if(sv_globals.sv_bg_color==0)	/* if none allocated */
	sv_globals.sv_bg_color = background;	/* use this one */
    }
  
  /* now figure out the picture type */
  switch(sv_globals.sv_ncolors)
    {
    case 0:
      perror("rleLoad: no colour channels to display");
      zclose(rlefile);
      return(NULL);
    case 1:
      switch(sv_globals.sv_ncmap)
	{
	case 0:
	  ptype = BW_NM;	/* black and white, no map */
	  break;
	case 1:
	  ptype = BW_M;	/* black and white with a map */
	  break;
	case 3:
	  ptype = SC_M;	/* single channel encoded colour with decoding map */
	  break;
	default:
	  zclose(rlefile);
	  perror("rleLoad: Illegal number of maps for one colour channel");
	  return(NULL);
	}
      break;
    case 3:
      switch(sv_globals.sv_ncmap)
	{
	case 0:
	  ptype = C_NM;	/* colour, no map */
	  break;
	case 3:
	  ptype = C_M;	/* colour with maps */
	  break;
	default:
	  perror("rleLoad: Illegal number of maps for colour picture");
	  zclose(rlefile);
	  return(NULL);
	}
      break;
    default:
      perror("rleLoad: Illegal number of colour channels");
      zclose(rlefile);
      return(NULL);
    }
  
  if(verbose)
    {
      printf("%s is a %dx%d",name,x_len,y_len);
      switch(ptype)
	{
	case BW_NM:
	  printf(" 8 bit grey scale RLE image with no map"); 
	  break;
	case BW_M:
	  printf(" 8 bit grey scale RLE image with map"); 
	  break;
	case SC_M:
	  printf(" 8 bit RLE image with colour map");
	  break;
	case C_NM:
	  printf(" 24 bit RLE image with no map (will dither to 8 bits)");
	  break;
	case C_M:
	  printf(" 24 bit RLE image with color map (will dither to 8 bits)");
	  break;
	}
      printf(", with gamma of %4.2f\n",img_gam);
    }
  znocache(rlefile);
  
  if(ptype==SC_M)
    {	/* don't mess with the image, but change their colour map a bit if needed */
      disp_gam /= img_gam;	/* amount to change their map */
      img_gam = 1.0;		/*  not to the image coming in */
    }
  
  /* get hold of the colour maps, and set to undo their images gamma */
  fmaps = buildmap(&sv_globals,sv_globals.sv_ncolors,img_gam);
  
  /* now we had better sort out the picture data */
  debug("done colour map\n");
  
  /* rle stufff */
  /* Get space for a full colour scan line */
  scan = (unsigned char **) lmalloc( (sv_globals.sv_ncolors +
				      sv_globals.sv_alpha) *
				    sizeof( unsigned char * ) );
  for ( i = 0; i < sv_globals.sv_ncolors + sv_globals.sv_alpha; i++ )
    scan[i] = (unsigned char *)lmalloc(x_len);
  if ( sv_globals.sv_alpha )
    scan++;
  debug("got space for get_row\n");
  
  depth = 8;		/* We always supply 8bit images */
  image = newRGBImage(x_len,y_len,depth);
  image->title = dupString(name);
  debug("got image structure\n");
  
  buf = image->data;
  
  /* If we are going to dither - then create the dither matrix. */
  if(!bwflag && ptype!=SC_M && ptype != BW_NM && ptype != BW_M)
    {
      dith_np2 = 1;		/* allow non-power of 2 dither map size */
      dithermap( 6, disp_gam, colmap, divN, modN, magic );
    }
  
  debug("About to read image in\n");
  bufp = buf + (y_len-1) * x_len;
  for(j=y_len;j>0;j--,bufp -= x_len)
    {
      rle_getrow(&sv_globals,scan);
      switch(ptype)
	{
	case SC_M:
	  memcpy(bufp,&scan[0][0],x_len);
	  break;
	case BW_NM:
	case BW_M:
	  bw_m_line(bufp,x_len);
	  break;
	case C_NM:
	case C_M:
	  c_m_line(bufp,x_len,j);
	  break;
	}
    }
  debug("Image Read in\n");
  
  /* Deal with colour maps */
  /* set up our gamma correction */
  make_gamma(disp_gam,gammamap);	/* we'll need it */
  
  debug("Creating color map\n");
  /* now load an appropriate colour map */
  if(!bwflag && ptype==SC_M)
    {
      /* use their maps  & correct their gamma */
      ncol = 1<<sv_globals.sv_cmaplen;	/* number of entries */
      for(i=0;i<ncol;i++)
	{
	  *(image->rgb.red + i) = gammamap[fmaps[0][i]]<<8;
	  *(image->rgb.green + i) = gammamap[fmaps[1][i]]<<8;
	  *(image->rgb.blue + i) = gammamap[fmaps[2][i]]<<8;
	}
    }
  else if(bwflag || ptype == BW_NM || ptype == BW_M)
    {
      /* load a black and white map (gamma corrected for this display)*/
      ncol = 256;			/* don't know whats been used */
      for(i=0;i<ncol;i++)
	{
	  *(image->rgb.red + i) = 
	    *(image->rgb.green + i) = 
	      *(image->rgb.blue + i) = gammamap[i]<<8;
	}
    }
  else
    {
      /* must be colour, so use dither map (gamma corrected for this display)*/
      ncol = 6*6*6;
      /* Dither map has already been created above */
      for(i = 0; i < ncol; i++)
	{
	  *(image->rgb.red + i) = colmap[i][0]<<8;
	  *(image->rgb.green + i) = colmap[i][1]<<8;
	  *(image->rgb.blue + i) = colmap[i][2]<<8;
	}
    }
  image->rgb.used = ncol;
  
  zclose(rlefile);
  debug("finished\n");
  return(image);
}

#define DMAP(v,x,y)	(modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])

/* run the black and white through its map */
void bw_m_line(dp,number)
     int number;
     register unsigned char *dp;
{
  register unsigned char *r;
  register int i;
  
  for(i=number,r= &scan[0][0];i>0;i--,r++,dp++)
    {
      *dp = fmaps[0][*r];
    }
}

/* convert a colour line with map to 8 bits per pixel */
void c_m_line(dp,number,line)
     int number,line;
     register unsigned char *dp;
{
  register unsigned char *r, *g, *b;
  register int i, col, row;
  
  if(!bwflag)
    {		
      for ( row = line % dith_size, col = x_min % dith_size, i = number, r = &scan[0][0]
	   ,g= &scan[1][0], b= &scan[2][0];
	   i > 0; i--, r++, g++, b++, dp++, col = ((col + 1) % dith_size) )
	{
	  *dp = DMAP(fmaps[0][*r], col, row) +
	    DMAP(fmaps[1][*g], col, row) * 6 +
	      DMAP(fmaps[2][*b], col, row) * 36;
	}
    }
  else
    {
      int red,green,blue;
      for (i = number, r= &scan[0][0], g= &scan[1][0]
	   ,b= &scan[2][0]; i>0;i--,r++,g++,b++,dp++)
	{
	  red = fmaps[0][*r];green=fmaps[1][*g];blue = fmaps[2][*b];
	  *dp = 0.35* red + 0.55* green + 0.1* blue;
	}
    }
}