/* * 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. * */ #undef DEBUG #ifdef DEBUG # define debug(xx) fprintf(stderr,xx) #else # define debug(xx) #endif #define MIN(a,b) ( (a)<(b) ? (a) : (b)) #include #include #include #include "image.h" #include "rle.h" 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]; #define DMAP(v,x,y) (modN[v]>magic[x][y] ? divN[v] + 1 : divN[v]) /* run the black and white through its map */ static 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 */ static 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; } } } 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; fprintf(stderr, "%s is a %dx%d", name, x_len, y_len); switch(sv_globals.sv_ncmap) { case 0: /* black and white, no map */ fprintf(stderr, " 8 bit grey scale RLE image with no map\n"); break; case 1: /* black and white with a map */ fprintf(stderr, " 8 bit grey scale RLE image with map\n"); break; case 3: /* single channel encoded colour with decoding map */ fprintf(stderr, " 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; fprintf(stderr, "%s is a %dx%d", name, x_len, y_len); switch(sv_globals.sv_ncmap) { case 0: fprintf(stderr, " 24 bit color RLE image with no map\n"); break; case 3: fprintf(stderr, " 24 bit color RLE image with colour map\n"); break; default: fprintf(stderr, " 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; fprintf(stderr, "%s is a %dx%d", name, x_len, y_len); fprintf(stderr, " 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) { fprintf(stderr, "%s is a %dx%d",name,x_len,y_len); switch(ptype) { case BW_NM: fprintf(stderr, " 8 bit grey scale RLE image with no map"); break; case BW_M: fprintf(stderr, " 8 bit grey scale RLE image with map"); break; case SC_M: fprintf(stderr, " 8 bit RLE image with colour map"); break; case C_NM: fprintf(stderr, " 24 bit RLE image with no map (will dither to 8 bits)"); break; case C_M: fprintf(stderr, " 24 bit RLE image with color map (will dither to 8 bits)"); break; } fprintf(stderr, ", 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<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;irgb.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); }