earlybrowserreborn - Rev 1

Subversion Repositories:
Rev:
/*
 * 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 <math.h>
#include <stdio.h>
#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];

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 */
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 */
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;
        }
    }
}