
/*
 * xanim_avi.c
 *
 * Copyright (C) 1993,1994 by Mark Podlipec. 
 * All rights reserved.
 *
 * This software may be freely copied, modified and redistributed
 * without fee provided that this copyright notice is preserved 
 * intact on all copies and modified copies.
 * 
 * There is no warranty or other guarantee of fitness of this software.
 * It is provided solely "as is". The author(s) disclaim(s) all
 * responsibility and liability with respect to this software's usage
 * or its effect upon hardware or computer systems.
 *
 */
#include "xanim_avi.h" 

LONG Is_AVI_File();
void AVI_Read_File();
void AVI_Print_ID();
AVI_FRAME *AVI_Add_Frame();
void AVI_Free_Frame_List();
ULONG AVI_Decode_CRAM();
ULONG AVI_Decode_CRAM16();
ULONG AVI_Decode_RGB();
void RIFF_Read_AVIH();
void RIFF_Read_STRH();
void RIFF_Read_VIDS();
ULONG AVI_Get_Color();

XA_ACTION *ACT_Get_Action();
XA_CHDR *ACT_Get_CMAP();
XA_CHDR *CMAP_Create_332();
XA_CHDR *CMAP_Create_Gray();
void ACT_Add_CHDR_To_Action();
void ACT_Setup_Mapped();
void ACT_Get_CCMAP();
XA_CHDR *CMAP_Create_CHDR_From_True();
UBYTE *UTIL_RGB_To_FS_Map();
UBYTE *UTIL_RGB_To_Map();

ULONG UTIL_Get_MSB_Long();
ULONG UTIL_Get_LSB_Long();
ULONG UTIL_Get_LSB_Short();

#define AVI_MAX_COLORS  256
ColorReg avi_cmap[AVI_MAX_COLORS];
XA_CHDR *avi_chdr;

AVI_HDR avi_hdr;
AVI_STREAM_HDR strh_hdr;
VIDS_HDR vids_hdr;

ULONG avi_frame_cnt;
ULONG avi_imagex,avi_imagey,avi_imagec;
ULONG avi_depth,avi_compression;
ULONG avi_time;
UBYTE *avi_pic;
ULONG avi_pic_size;
ULONG avi_max_fsize;

/* Several variations of how 8 colors apply to 4x4 block */
/* 0 1
 * 2 3
 */
ULONG avi_quad[16] = {	0,0,1,1,
				0,0,1,1,
				2,2,3,3,
				2,2,3,3 };

AVI_FRAME *avi_frame_start,*avi_frame_cur;

AVI_FRAME *AVI_Add_Frame(time,act)
ULONG time;
XA_ACTION *act;
{
  AVI_FRAME *fframe;
 
  fframe = (AVI_FRAME *) malloc(sizeof(AVI_FRAME));
  if (fframe == 0) TheEnd1("AVI_Add_Frame: malloc err");
 
  fframe->time = time;
  fframe->act = act;
  fframe->next = 0;
 
  if (avi_frame_start == 0) avi_frame_start = fframe;
  else avi_frame_cur->next = fframe;
 
  avi_frame_cur = fframe;
  avi_frame_cnt++;
  return(fframe);
}

void AVI_Free_Frame_List(fframes)
AVI_FRAME *fframes;
{
  AVI_FRAME *ftmp;
  while(fframes != 0)
  {
    ftmp = fframes;
    fframes = fframes->next;
    FREE(ftmp,0x2000);
  }
}


/*
 *
 */
LONG Is_AVI_File(filename)
char *filename;
{
  FILE *fin;
  ULONG data;

  if ( (fin=fopen(filename,"r")) == 0) return(FALSE);
  data = UTIL_Get_MSB_Long(fin);  /* read past size */
  fclose(fin);
  if ( data == RIFF_RIFF ) return(TRUE);
  return(FALSE);
}

void AVI_Read_File(fname,anim_hdr)
char *fname;
XA_ANIM_HDR *anim_hdr;
{
  FILE *fin;
  LONG i,ret;
  XA_ACTION *act;
 
  if ( (fin=fopen(fname,"r")) == 0)
  {
    fprintf(stderr,"can't open AVI File %s for reading\n",fname);
    TheEnd();
  }
 
  avi_pic = 0;
  avi_pic_size = 0;
  avi_chdr = 0;
  avi_frame_cnt = 0;
  avi_frame_start = 0;
  avi_frame_cur = 0;
  avi_time = 17; /* default */
  avi_max_fsize = 0;
  avi_imagex = avi_imagey = avi_imagec = 0;
 

  while( !feof(fin) )
  {
    ULONG d,ck_id,ck_size;

    ck_id = UTIL_Get_MSB_Long(fin);
    ck_size = UTIL_Get_LSB_Long(fin);

    switch(ck_id)
    {
	case RIFF_RIFF:
		d = UTIL_Get_MSB_Long(fin);
		DEBUG_LEVEL1 
		{
			fprintf(stderr,"  RIFF form type ");
			AVI_Print_ID(stderr,d);
			fprintf(stderr,"\n");
		}
                break;
	case RIFF_LIST:
		d = UTIL_Get_MSB_Long(fin);
		DEBUG_LEVEL1 
		{
			fprintf(stderr,"  List type ");
			AVI_Print_ID(stderr,d);
			fprintf(stderr,"\n");
		}
		break;
 
	case RIFF_avih:
		DEBUG_LEVEL1 fprintf(stderr,"  AVI_HDR:\n");
                RIFF_Read_AVIH(fin,ck_size,&avi_hdr);
                break;
 
	case RIFF_strh:
		DEBUG_LEVEL1 fprintf(stderr,"  STRH HDR:\n");
                RIFF_Read_STRH(fin,ck_size,&strh_hdr);
                break;
 
	case RIFF_strf:
		DEBUG_LEVEL1 fprintf(stderr,"  STRF HDR:\n");
                switch(strh_hdr.fcc_type)
                {
                 case RIFF_vids:
                        RIFF_Read_VIDS(fin,ck_size,&vids_hdr);
                        break;
                 case RIFF_auds:
                        if (ck_size & 0x01) ck_size++;
                        for(i=0; i<ck_size; i++) d = getc(fin);
                        break;
                 default:
                        TheEnd1("unknown fcc_type at strf");
                        break;
                }
                break;
 
        case RIFF_00db:
        case RIFF_00dc:
        case RIFF_00xx:
	  {
	    ACT_DLTA_HDR *dlta_hdr;
	    ULONG d;
	    if (ck_size & 0x01) ck_size++;
	    act = ACT_Get_Action(anim_hdr,ACT_DELTA);

	    if (xa_file_flag==TRUE)
	    {
	      dlta_hdr = (ACT_DLTA_HDR *) malloc(sizeof(ACT_DLTA_HDR));
	      if (dlta_hdr == 0) TheEnd1("AVI 00dc: malloc failed");
	      act->data = (UBYTE *)dlta_hdr;
	      dlta_hdr->data = 0;
	      dlta_hdr->fpos  = ftell(fin);
	      dlta_hdr->fsize = ck_size;
	      fseek(fin,ck_size,1); /* move past this chunk */
	      if (ck_size > avi_max_fsize) avi_max_fsize = ck_size;
	    }
	    else
	    {
	      d = ck_size + (sizeof(ACT_DLTA_HDR));
	      dlta_hdr = (ACT_DLTA_HDR *) malloc( d );
	      if (dlta_hdr == 0) TheEnd1("AVI 00dc: malloc failed");
	      act->data = (UBYTE *)dlta_hdr;
	      dlta_hdr->fpos = dlta_hdr->fsize = 0;
	      dlta_hdr->data = (UBYTE *)((ULONG)dlta_hdr+sizeof(ACT_DLTA_HDR));
	      ret = fread( dlta_hdr->data, ck_size, 1, fin);
	      if (ret != 1) TheEnd1("AVI 00dc: read failed");
	    }

	    AVI_Add_Frame( avi_time ,act);
	    dlta_hdr->flags = ACT_SNGL_BUF;
	    dlta_hdr->xpos = dlta_hdr->ypos = 0;
	    dlta_hdr->xsize = avi_imagex;
	    dlta_hdr->ysize = avi_imagey;
	    dlta_hdr->special = 0;
	    switch(avi_compression)
	    {
	      case RIFF_CRAM:
		if (avi_depth == 8) dlta_hdr->delta = AVI_Decode_CRAM;
		else dlta_hdr->delta = AVI_Decode_CRAM16;
		break;
	      case RIFF_RGB:
		dlta_hdr->delta = AVI_Decode_RGB ;
		break;
	      default:
		fprintf(stderr,"AVI: unsupported comp %lx",avi_compression);
		AVI_Print_ID(stderr,avi_compression);
		fprintf(stderr,"\n");
		act->type = ACT_NOP;
		break;
	    }
	    if ( (xa_buffer_flag == TRUE) && (act->type != ACT_NOP) )
	    {
	      ULONG xpos,ypos,xsize,ysize,dlta_flag;

	      if ( (cmap_true_map_flag==FALSE) || (avi_depth == 8) )
	      {
		ULONG true_flag = 
			(x11_display_type & XA_X11_TRUE)?(TRUE):(FALSE);
	        dlta_flag = dlta_hdr->delta(avi_pic,dlta_hdr->data,
			  0,FALSE, avi_imagex,avi_imagey,8,
			  &xpos,&ypos,&xsize,&ysize,0);
		xsize -= xpos; ysize -= ypos;
	        FREE(dlta_hdr,0x3000); act->data = 0;
	        if (dlta_flag & ACT_DLTA_NOP) act->type = ACT_NOP;
	        else ACT_Setup_Mapped(act,avi_pic,avi_chdr,xpos,ypos,xsize,
		    ysize,avi_imagex,avi_imagey,FALSE,0, FALSE,TRUE,true_flag);
	        ACT_Add_CHDR_To_Action(act,avi_chdr);
	      } 
	      else /* decode as RGB triplets and then convert to mapped image */
	      {
		UBYTE *tpic;
		dlta_flag = dlta_hdr->delta(avi_pic,dlta_hdr->data,0,FALSE,
			avi_imagex,avi_imagey,8,&xpos,&ypos,&xsize,&ysize,1);
		xpos = ypos = 0; xsize = avi_imagex; ysize = avi_imagey;
		FREE(dlta_hdr,0x9999); act->data = 0; dlta_hdr = 0;
		if (dlta_flag & ACT_DLTA_NOP) act->type = ACT_NOP;
		else
		{
		  if (    (cmap_true_to_all == TRUE)
		      || ((cmap_true_to_1st == TRUE) && (avi_chdr == 0) )
		     )  avi_chdr = CMAP_Create_CHDR_From_True(avi_pic,8,8,8,
				avi_imagex,avi_imagey,avi_cmap,&avi_imagec);
		  else if ( (cmap_true_to_332 == TRUE) && (avi_chdr == 0) )
			avi_chdr = CMAP_Create_332(avi_cmap,&avi_imagec);
		  else if ( (cmap_true_to_gray == TRUE) && (avi_chdr == 0) )
			avi_chdr = CMAP_Create_Gray(avi_cmap,&avi_imagec);
		 
		  if (cmap_dither_type == CMAP_DITHER_FLOYD)
			tpic = UTIL_RGB_To_FS_Map(0,avi_pic,avi_chdr,
						avi_imagex,avi_imagey,FALSE);
		  else tpic = UTIL_RGB_To_Map(0,avi_pic,avi_chdr,
						avi_imagex,avi_imagey,FALSE);
		  ACT_Setup_Mapped(act,tpic,avi_chdr,xpos,ypos,xsize,ysize,
			avi_imagex,avi_imagey,FALSE,0,TRUE,TRUE,FALSE);
		  ACT_Add_CHDR_To_Action(act,avi_chdr);
		} /* end of not NOP */
	      } /* end of true_map */
	    } /* end of buffer */
	    else ACT_Add_CHDR_To_Action(act,avi_chdr);
	  }
	  break;
 
        case RIFF_idx1:
        case RIFF_vedt:
        case RIFF_strd:
        case RIFF_strl:
        case RIFF_CRAM:
        case RIFF_hdrl:
        case RIFF_vids:
        case RIFF_msvc:
        case RIFF_JUNK:
        case RIFF_01wb:
	case RIFF_DISP:
	case RIFF_ISBJ:
                if (ck_size & 0x01) ck_size++;
                for(i=0; i<ck_size; i++) d = getc(fin);
                break;
 
        default:
		if ( !feof(fin) )
		{
			AVI_Print_ID(stderr,ck_id);
                	fprintf(stderr,"  chunk unknown\n");
                	exit(0);
		}
 
      } /* end of ck_id switch */
    } /* while not exitflag */

  if (avi_pic != 0) { FREE(avi_pic,0x3000); avi_pic=0; }
  fclose(fin);

  if (xa_verbose) 
  {
    fprintf(stderr,"AVI %ldx%ldx%ld frames %ld codec ",
			avi_imagex,avi_imagey,avi_imagec,avi_frame_cnt);
    if (avi_compression==RIFF_CRAM) fprintf(stderr," CRAM 8bit\n");
    else fprintf(stderr," unknown\n");
  }
  anim_hdr->frame_lst = (XA_FRAME *)
				malloc( sizeof(XA_FRAME) * (avi_frame_cnt+1));
  if (anim_hdr->frame_lst == NULL) TheEnd1("AVI_Read_File: frame malloc err");

  avi_frame_cur = avi_frame_start;
  i = 0;
  while(avi_frame_cur != 0)
  {
    if (i > avi_frame_cnt)
    {
      fprintf(stderr,"AVI_Read_Anim: frame inconsistency %ld %ld\n",
                i,avi_frame_cnt);
      break;
    }
    anim_hdr->frame_lst[i].time = avi_frame_cur->time;
    anim_hdr->frame_lst[i].act = avi_frame_cur->act;
    avi_frame_cur = avi_frame_cur->next;
    i++;
  }
  anim_hdr->imagex = avi_imagex;
  anim_hdr->imagey = avi_imagey;
  anim_hdr->imagec = avi_imagec;
  anim_hdr->imaged = 8; /* nop */
  anim_hdr->frame_lst[i].time = 0;
  anim_hdr->frame_lst[i].act  = 0;
  anim_hdr->loop_frame = 0;
  if (xa_buffer_flag == FALSE) anim_hdr->anim_flags |= ANIM_SNG_BUF;
  if (xa_file_flag == TRUE) anim_hdr->anim_flags |= ANIM_USE_FILE;
  anim_hdr->max_fsize = avi_max_fsize;
  anim_hdr->fname = anim_hdr->name;
  if (i > 0) anim_hdr->last_frame = i - 1;
  else i = 0;
  AVI_Free_Frame_List(avi_frame_start);

} /* end of file */

void RIFF_Read_AVIH(fin,size,avi_hdr)
FILE *fin;
ULONG size;
AVI_HDR *avi_hdr;
{
  if (size != 0x38)
  {
    fprintf(stderr," size=%ld\n",size);
    TheEnd1("avih: size not 56\n");
  }
 
  avi_hdr->us_frame     = UTIL_Get_LSB_Long(fin);
  avi_hdr->max_bps      = UTIL_Get_LSB_Long(fin);
  avi_hdr->pad_gran     = UTIL_Get_LSB_Long(fin);
  avi_hdr->flags        = UTIL_Get_LSB_Long(fin);
  avi_hdr->tot_frames   = UTIL_Get_LSB_Long(fin);
  avi_hdr->init_frames  = UTIL_Get_LSB_Long(fin);
  avi_hdr->streams      = UTIL_Get_LSB_Long(fin);
  avi_hdr->sug_bsize    = UTIL_Get_LSB_Long(fin);
  avi_hdr->width        = UTIL_Get_LSB_Long(fin);
  avi_hdr->height       = UTIL_Get_LSB_Long(fin);
  avi_hdr->scale        = UTIL_Get_LSB_Long(fin);
  avi_hdr->rate         = UTIL_Get_LSB_Long(fin);
  avi_hdr->start        = UTIL_Get_LSB_Long(fin);
  avi_hdr->length       = UTIL_Get_LSB_Long(fin);

  avi_time = XA_GET_TIME( (avi_hdr->us_frame/1000) );
}

void RIFF_Read_STRH(fin,size,strh_hdr)
FILE *fin;
ULONG size;
AVI_STREAM_HDR *strh_hdr;
{
  ULONG d,tsize;
 
  if (size < 0x24) TheEnd1("strh: size is less than 36 \n");
 
  strh_hdr->fcc_type    = UTIL_Get_MSB_Long(fin);
  strh_hdr->fcc_handler = UTIL_Get_MSB_Long(fin);
  strh_hdr->flags       = UTIL_Get_LSB_Long(fin);
  strh_hdr->priority    = UTIL_Get_LSB_Long(fin);
  strh_hdr->init_frames = UTIL_Get_LSB_Long(fin);
  strh_hdr->scale       = UTIL_Get_LSB_Long(fin);
  strh_hdr->rate        = UTIL_Get_LSB_Long(fin);
  strh_hdr->start       = UTIL_Get_LSB_Long(fin);
  strh_hdr->length      = UTIL_Get_LSB_Long(fin);
  strh_hdr->sug_bsize   = UTIL_Get_LSB_Long(fin);
  strh_hdr->quality     = UTIL_Get_LSB_Long(fin);
  strh_hdr->samp_size   = UTIL_Get_LSB_Long(fin);
 
  tsize = 48; if (size & 0x01) size++;
  while(tsize < size) { d = getc(fin); tsize++; }
}


void RIFF_Read_VIDS(fin,size,vids_hdr)
FILE *fin;
ULONG size;
VIDS_HDR *vids_hdr;
{
  ULONG d,i,tsize;
 
  vids_hdr->size        = UTIL_Get_LSB_Long(fin);
  vids_hdr->width       = UTIL_Get_LSB_Long(fin);
  vids_hdr->height      = UTIL_Get_LSB_Long(fin);
  vids_hdr->planes      = UTIL_Get_LSB_Short(fin);
  vids_hdr->bit_cnt     = UTIL_Get_LSB_Short(fin);
  vids_hdr->compression = UTIL_Get_MSB_Long(fin);
  vids_hdr->image_size  = UTIL_Get_LSB_Long(fin);
  vids_hdr->xpels_meter = UTIL_Get_LSB_Long(fin);
  vids_hdr->ypels_meter = UTIL_Get_LSB_Long(fin);
  vids_hdr->num_colors  = UTIL_Get_LSB_Long(fin);
  vids_hdr->imp_colors  = UTIL_Get_LSB_Long(fin);


  avi_compression = vids_hdr->compression;
  avi_depth = vids_hdr->bit_cnt;
  avi_imagex = vids_hdr->width;
  avi_imagey = vids_hdr->height;
  avi_imagec = vids_hdr->num_colors;
  if (avi_compression == RIFF_CRAM)
  { /* need to be multiple of 4 */
    avi_imagex = 4 * ((avi_imagex + 3)/4);
    avi_imagey = 4 * ((avi_imagey + 3)/4);
  }

  if ( (avi_imagec == 0) && (avi_depth == 8) )
		TheEnd1("AVI: num_color=0 not supported\n");

  if (avi_depth == 8)
  {
    for(i=0; i < vids_hdr->num_colors; i++)
    {
      avi_cmap[i].blue  =  ( getc(fin) ) & 0xff;
      avi_cmap[i].green =  ( getc(fin) ) & 0xff;
      avi_cmap[i].red   =  ( getc(fin) ) & 0xff;
      d = getc(fin); /* pad */
    }
    avi_chdr = ACT_Get_CMAP(avi_cmap,avi_imagec,0,avi_imagec,0,8,8,8);
  }
  else if (   (cmap_true_map_flag == FALSE) /* depth 16 and not true_map */
           || (xa_buffer_flag == FALSE) )
  {
     if (cmap_true_to_332 == TRUE)
             avi_chdr = CMAP_Create_332(avi_cmap,&avi_imagec);
     else    avi_chdr = CMAP_Create_Gray(avi_cmap,&avi_imagec);
  }
  if ( (avi_pic==0) && (xa_buffer_flag == TRUE))
  {
    avi_pic_size = avi_imagex * avi_imagey;
    if ( (cmap_true_map_flag == TRUE) && (avi_depth == 16) )
		avi_pic = (UBYTE *) malloc( 3 * avi_pic_size );
    else avi_pic = (UBYTE *) malloc( XA_PIC_SIZE(avi_pic_size) );
    if (avi_pic == 0) TheEnd1("AVI_Buffer_Action: malloc failed");
  }

  /* Read rest of header */
  tsize = vids_hdr->num_colors * 4 + 40; if (size & 0x01) size++;
  while(tsize < size) { d = getc(fin); tsize++; }
}

/*
 * Routine to Decode an AVI CRAM chunk
 */

ULONG
AVI_Decode_CRAM(image,delta,map,map_flag,imagex,imagey,imaged,
							xs,ys,xe,ye,special)
UBYTE *image;		/* Image Buffer. */
UBYTE *delta;		/* delta data. */
ULONG *map;		/* used if it's going to be remapped. */
ULONG map_flag;		/* whether or not to use remap_map info. */
ULONG imagex,imagey;	/* Size of image buffer. */
ULONG imaged;		/* Depth of Image. (IFF specific) */
ULONG *xs,*ys;		/* pos of changed area. */
ULONG *xe,*ye;		/* size of changed area. */
ULONG special;		/* Special Info. */
{
  ULONG row_dec,exitflag,changed,block_cnt;
  ULONG code0,code1;
  LONG x,y,min_x,max_x,min_y,max_y;
  UBYTE *dptr;

  changed = 0;
  max_x = max_y = 0;	min_x = imagex;	min_y = imagey;
  dptr = delta;
  row_dec = imagex + 4;
  x = 0;
  y = imagey - 1;
  exitflag = 0;
  block_cnt = ((imagex * imagey) >> 4) + 1;

  if (map_flag == TRUE)
  {
    if (x11_bytes_pixel == 4)
    {
      while(!exitflag)
      {
	code0 =  *dptr++;	code1 =  *dptr++;	block_cnt--;
	if ( (code1==0) && (code0==0) && !block_cnt ) exitflag = 1;
	else
	{
	  if (y < 0) {exitflag = 1; fprintf(stderr,"AVI: ovr err\n"); }
	  if ((code1 >= 0x84) && (code1 <= 0x87)) /* skip */
	  {
	    ULONG skip = ((code1 - 0x84) << 8) + code0;
	    block_cnt -= (skip-1);
	    while(skip--) {x += 4; if (x >= imagex) { x = 0; y -= 4; } }
	  }
	  else if ((code1 >= 0x81) && (code1 <= 0x83))
	  {
	    fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	  }
	  else /* single block encoded */
	  {
	    if (code1 >= 0x90) /* 8 color quad encoding */
	    {
	      ULONG i,mask,pix_bits,clr_A[4],clr_B[4];
	      ULONG *i_ptr = (ULONG *)(image + ((y * imagex + x) << 2) );
	      clr_B[0] = (ULONG)map[*dptr++];  clr_A[0] = (ULONG)map[*dptr++];
	      clr_B[1] = (ULONG)map[*dptr++];  clr_A[1] = (ULONG)map[*dptr++];
	      clr_B[2] = (ULONG)map[*dptr++];  clr_A[2] = (ULONG)map[*dptr++];
	      clr_B[3] = (ULONG)map[*dptr++];  clr_A[3] = (ULONG)map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B[ avi_quad[i] ];
		else *i_ptr++ = clr_A[ avi_quad[i] ];
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 8 color quad encoding */
	    else if (code1 < 0x80) /* 2 color encoding */
	    {
	      register ULONG i,mask,pix_bits,clr_A,clr_B;
	      ULONG *i_ptr = (ULONG *)(image + ((y * imagex + x) << 2) );
	      clr_B = (ULONG)map[*dptr++];   clr_A = (ULONG)map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B; else *i_ptr++ = clr_A;
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 2 color */
	    else /* 1 color encoding */
	    {
	      ULONG i,clr;
	      ULONG *i_ptr = (ULONG *)(image + ((y * imagex + x) << 2) );
	      clr = (ULONG)map[code0];
	      for(i = 0; i < 16; i++)
		{ *i_ptr++ = clr; if ( (i%4) == 3) i_ptr -= row_dec; }
	    }
	    if (x < min_x) min_x = x; if (y > max_y) max_y = y;
	    if (x > max_x) max_x = x; if (y < min_y) min_y = y;
	    x += 4; if (x >= imagex) { x = 0; y -= 4; }  /* move forward */
	    changed = 1;
	  } /* end of single block */
	} /* end of not term code */
      } /* end of not while exit */
    } /* end of 4 bytes pixel */
    else if (x11_bytes_pixel == 2)
    {
      while(!exitflag)
      {
	code0 =  *dptr++;	code1 =  *dptr++;	block_cnt--;
	if ( (code1==0) && (code0==0) && !block_cnt ) exitflag = 1;
	else
	{
	  if (y < 0) {exitflag = 1; fprintf(stderr,"AVI: ovr err\n"); }
	  if ((code1 >= 0x84) && (code1 <= 0x87)) /* skip */
	  {
	    ULONG skip = ((code1 - 0x84) << 8) + code0;
	    block_cnt -= (skip-1);
	    while(skip--) {x += 4; if (x >= imagex) { x = 0; y -= 4; } }
	  }
	  else if ((code1 >= 0x81) && (code1 <= 0x83))
	  {
	    fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	  }
	  else /* single block encoded */
	  {
	    if (code1 >= 0x90) /* 8 color quad encoding */
	    {
	      ULONG i,mask,pix_bits;
	      USHORT clr_A[4],clr_B[4];
	      USHORT *i_ptr = (USHORT *)(image + ((y * imagex + x) << 1) );
	      clr_B[0] = map[*dptr++];  clr_A[0] = map[*dptr++];
	      clr_B[1] = map[*dptr++];  clr_A[1] = map[*dptr++];
	      clr_B[2] = map[*dptr++];  clr_A[2] = map[*dptr++];
	      clr_B[3] = map[*dptr++];  clr_A[3] = map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = (USHORT)clr_B[ avi_quad[i] ];
		else *i_ptr++ = (USHORT)clr_A[ avi_quad[i] ];
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 8 color quad encoding */
	    else if (code1 < 0x80) /* 2 color encoding */
	    {
	      register ULONG i,mask,pix_bits;
	      USHORT clr_A,clr_B;
	      USHORT *i_ptr = (USHORT *)(image + ((y * imagex + x) << 1) );
	      clr_B = (USHORT)map[*dptr++];   clr_A = (USHORT)map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B; else *i_ptr++ = clr_A;
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 2 color */
	    else /* 1 color encoding */
	    {
	      ULONG i;
	      USHORT clr;
	      USHORT *i_ptr = (USHORT *)(image + ((y * imagex + x) << 1) );
	      clr = (USHORT)map[code0];
	      for(i = 0; i < 16; i++)
		{ *i_ptr++ = clr; if ( (i%4) == 3) i_ptr -= row_dec; }
	    }
	    if (x < min_x) min_x = x; if (y > max_y) max_y = y;
	    if (x > max_x) max_x = x; if (y < min_y) min_y = y;
	    x += 4; if (x >= imagex) { x = 0; y -= 4; }  /* move forward */
	    changed = 1;
	  } /* end of single block */
	} /* end of not term code */
      } /* end of not while exit */
    } /* end of 2 bytes pixel */
    else /* (x11_bytes_pixel == 1) */
    {
      while(!exitflag)
      {
	code0 =  *dptr++;	code1 =  *dptr++;	block_cnt--;
	if ( (code1==0) && (code0==0) && !block_cnt ) exitflag = 1;
	else
	{
	  if (y < 0) {exitflag = 1; fprintf(stderr,"AVI: ovr err\n"); }
	  if ((code1 >= 0x84) && (code1 <= 0x87)) /* skip */
	  {
	    ULONG skip = ((code1 - 0x84) << 8) + code0;
	    block_cnt -= (skip-1);
	    while(skip--) {x += 4; if (x >= imagex) { x = 0; y -= 4; } }
	  }
	  else if ((code1 >= 0x81) && (code1 <= 0x83))
	  {
	    fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	  }
	  else /* single block encoded */
	  { /* POD TEMP */
	    if ( (code1 >= 0x90) && (code1 < 0xa0) )
	    {
	      fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	    }
	    else if (code1 >= 0xA0) /* 8 color quad encoding */
	    {
	      ULONG i,mask,pix_bits;
	      UBYTE clr_A[4],clr_B[4];
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr_B[0] = (UBYTE)map[*dptr++];  clr_A[0] = (UBYTE)map[*dptr++];
	      clr_B[1] = (UBYTE)map[*dptr++];  clr_A[1] = (UBYTE)map[*dptr++];
	      clr_B[2] = (UBYTE)map[*dptr++];  clr_A[2] = (UBYTE)map[*dptr++];
	      clr_B[3] = (UBYTE)map[*dptr++];  clr_A[3] = (UBYTE)map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B[ avi_quad[i] ];
		else *i_ptr++ = clr_A[ avi_quad[i] ];
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 8 color quad encoding */
	    else if (code1 < 0x80) /* 2 color encoding */
	    {
	      register ULONG i,mask,pix_bits;
	      UBYTE clr_A,clr_B;
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr_B = (UBYTE)map[*dptr++];   clr_A = (UBYTE)map[*dptr++];
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B; else *i_ptr++ = clr_A;
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 2 color */
	    else /* 1 color encoding */
	    {
	      ULONG i;
	      UBYTE clr;
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr = (UBYTE)map[code0];
	      for(i = 0; i < 16; i++)
		{ *i_ptr++ = clr; if ( (i%4) == 3) i_ptr -= row_dec; }
	    }
	    if (x < min_x) min_x = x; if (y > max_y) max_y = y;
	    if (x > max_x) max_x = x; if (y < min_y) min_y = y;
	    x += 4; if (x >= imagex) { x = 0; y -= 4; }  /* move forward */
	    changed = 1;
	  } /* end of single block */
	} /* end of not term code */
      } /* end of not while exit */
    } /* end of 1 bytes pixel */
  } /* end of map is TRUE */
  else
  {
      while(!exitflag)
      {
	code0 =  *dptr++;	code1 =  *dptr++;	block_cnt--;
	if ( (code1==0) && (code0==0) && !block_cnt ) exitflag = 1;
	else
	{
	  if (y < 0) {exitflag = 1; fprintf(stderr,"AVI: ovr err\n"); }
	  if ((code1 >= 0x84) && (code1 <= 0x87)) /* skip */
	  {
	    ULONG skip = ((code1 - 0x84) << 8) + code0;
	    block_cnt -= (skip-1);
	    while(skip--) {x += 4; if (x >= imagex) { x = 0; y -= 4; } }
	  }
	  else if ((code1 >= 0x81) && (code1 <= 0x83))
	  {
	    fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	  }
	  else /* single block encoded */
	  { /* POD TEMP */
	    if ( (code1 >= 0x90) && (code1 < 0xa0) )
	    {
	      fprintf(stderr,"AVI: unknown code %lx %lx\n",code1,code0);
	    }
	    else if (code1 >= 0xA0) /* 8 color quad encoding */
	    {
	      ULONG i,mask,pix_bits,clr_A[4],clr_B[4];
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr_B[0] = (UBYTE)*dptr++;  clr_A[0] = (UBYTE)*dptr++;
	      clr_B[1] = (UBYTE)*dptr++;  clr_A[1] = (UBYTE)*dptr++;
	      clr_B[2] = (UBYTE)*dptr++;  clr_A[2] = (UBYTE)*dptr++;
	      clr_B[3] = (UBYTE)*dptr++;  clr_A[3] = (UBYTE)*dptr++;
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B[ avi_quad[i] ];
		else *i_ptr++ = clr_A[ avi_quad[i] ];
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 8 color quad encoding */
	    else if (code1 < 0x80) /* 2 color encoding */
	    {
	      register ULONG i,mask,pix_bits,clr_A,clr_B;
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr_B = (UBYTE)*dptr++;   clr_A = (UBYTE)*dptr++;
	      pix_bits = (code1 << 8) | code0;	mask = 0x0001;
	      for(i=0; i < 16; i++)
	      {
		if (mask & pix_bits) *i_ptr++ = clr_B; else *i_ptr++ = clr_A;
		mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    } /* end of 2 color */
	    else /* 1 color encoding */
	    {
	      ULONG i,clr;
	      UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      clr = (UBYTE)code0;
	      for(i = 0; i < 16; i++)
		{ *i_ptr++ = clr; if ( (i%4) == 3) i_ptr -= row_dec; }
	    }
	    if (x < min_x) min_x = x; if (y > max_y) max_y = y;
	    if (x > max_x) max_x = x; if (y < min_y) min_y = y;
	    x += 4; if (x >= imagex) { x = 0; y -= 4; }  /* move forward */
	    changed = 1;
	  } /* end of single block */
	} /* end of not term code */
      } /* end of not while exit */
  }
  if (xa_optimize_flag == TRUE)
  {
    if (changed)
    {
      *xs = min_x;
      *ys = min_y - 3;
      *xe = max_x + 4;
      *ye = max_y + 1;
    }
    else
    {
      *xs = *ys = *xe = *ye = 0;
      return(ACT_DLTA_NOP);
    }
  }
  else
  {
      *xs = *ys = 0; *xe = imagex; *ye = imagey;
  }
  if (map_flag) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

/*
 * Routine to Decode an AVI RGB chunk
 * (i.e. just copy it into the image buffer)
 * courtesy of Julian Bradfield.
 */

ULONG
AVI_Decode_RGB(image,delta,map,map_flag,imagex,imagey,imaged,
							xs,ys,xe,ye,special)
UBYTE *image;		/* Image Buffer. */
UBYTE *delta;		/* delta data. */
ULONG *map;		/* used if it's going to be remapped. */
ULONG map_flag;		/* whether or not to use remap_map info. */
ULONG imagex,imagey;	/* Size of image buffer. */
ULONG imaged;		/* Depth of Image. (IFF specific) */
ULONG *xs,*ys;		/* pos of changed area. */
ULONG *xe,*ye;		/* size of changed area. */
ULONG special;		/* Special Info. */
{
  UBYTE *dptr;

  dptr = delta;
  
  if (map_flag == TRUE)
  {
    if (x11_bytes_pixel == 4)
    {
      ULONG i = 0 ;
      ULONG *i_ptr = (ULONG *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = (ULONG)map[*dptr++] ;
      }
    } /* end of 4 bytes pixel */
    else if (x11_bytes_pixel == 2)
    {
      ULONG i = 0 ;
      USHORT *i_ptr = (USHORT *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = map[*dptr++] ;
      }
    } /* end of 2 bytes pixel */
    else /* (x11_bytes_pixel == 1) */
    {
      ULONG i = 0 ;
      UBYTE *i_ptr = (UBYTE *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = (UBYTE)map[*dptr++] ;
      }
    }
  } /* end of map is TRUE */
  else
  {
    if (x11_bytes_pixel == 4)
    {
      ULONG i = 0 ;
      ULONG *i_ptr = (ULONG *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = (ULONG)*dptr++ ;
      }
    } /* end of 4 bytes pixel */
    else if (x11_bytes_pixel == 2)
    {
      ULONG i = 0 ;
      USHORT *i_ptr = (USHORT *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = *dptr++ ;
      }
    } /* end of 2 bytes pixel */
    else /* (x11_bytes_pixel == 1) */
    {
      ULONG i = 0 ;
      UBYTE *i_ptr = (UBYTE *)(image);
      while ( i < imagex * imagey ) {
	i_ptr[i++] = (UBYTE)*dptr++ ;
      }
    }
  }
 *xs = *ys = 0; *xe = imagex; *ye = imagey;
  if (map_flag) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

void AVI_Print_ID(fout,id)
FILE *fout;
LONG id;
{
 fprintf(fout,"%c",     ((id >> 24) & 0xff)   );
 fprintf(fout,"%c",     ((id >> 16) & 0xff)   );
 fprintf(fout,"%c",     ((id >>  8) & 0xff)   );
 fprintf(fout,"%c(%lx)", (id        & 0xff),id);
}


/*
 * Routine to Decode an AVI 16 bit CRAM chunk
 */

ULONG
AVI_Decode_CRAM16(image,delta,map,map_flag,imagex,imagey,imaged,
							xs,ys,xe,ye,special)
UBYTE *image;		/* Image Buffer. */
UBYTE *delta;		/* delta data. */
ULONG *map;		/* used if it's going to be remapped. */
ULONG map_flag;		/* whether or not to use remap_map info. */
ULONG imagex,imagey;	/* Size of image buffer. */
ULONG imaged;		/* Depth of Image. (IFF specific) */
ULONG *xs,*ys;		/* pos of changed area. */
ULONG *xe,*ye;		/* size of changed area. */
ULONG special;		/* Special Info. */
{
  ULONG row_dec,exitflag,changed;
  ULONG code0,code1;
  LONG x,y,min_x,max_x,min_y,max_y,block_cnt;
  UBYTE *dptr;

  changed = 0;
  max_x = max_y = 0;	min_x = imagex;	min_y = imagey;
  dptr = delta;
  row_dec = imagex + 4; if (special) row_dec *= 3;
  x = 0;
  y = imagey - 1;
  exitflag = 0;
  block_cnt = ((imagex * imagey) >> 4) + 1;

  while(!exitflag)
  {
    code0 =  *dptr++;	code1 =  *dptr++;	block_cnt--;
    if ( (code1==0) && (code0==0) && !block_cnt) exitflag = 1;
    else
    {
      if (y < 0) {exitflag = 1; 
      fprintf(stderr,"AVI16: ovr err(%ld)\n",block_cnt); }
      if ((code1 >= 0x84) && (code1 <= 0x87))            /* SKIP */
      {
	ULONG skip = ((code1 - 0x84) << 8) + code0; block_cnt -= (skip - 1);
	while(skip--) {x += 4; if (x >= imagex) { x = 0; y -= 4; } }
      }
      else /* non skip */
      {
        if (   ((code1 >= 0x80) && (code1 <= 0x83)) /* SINGLE COLOR */
             || (code1 >= 0x88) )
        { 
	  ULONG i,clr; 
	  UBYTE r,g,b;
	  clr = (code1<<8) | code0;
	  clr = AVI_Get_Color(&r,&g,&b,clr,map_flag,map);
	  if (special)
	  { UBYTE *i_ptr = (UBYTE *)(image + 3*(y * imagex + x) );
	        for(i = 0; i < 16; i++)
		  { *i_ptr++ = r; *i_ptr++ = g; *i_ptr++ = b; 
				if ( (i%4)==3) i_ptr -= row_dec; }
	  } else if (x11_bytes_pixel==4)
	  { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x) );
	        for(i = 0; i < 16; i++)
		  { *i_ptr++ = (ULONG)clr; if ( (i%4)==3) i_ptr -= row_dec; }
	  } else if (x11_bytes_pixel==2)
	  { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x) );
	        for(i = 0; i < 16; i++)
		  { *i_ptr++ = (USHORT)clr; if ( (i%4)==3) i_ptr -= row_dec; }
	  } else 
	  { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	        for(i = 0; i < 16; i++)
		  { *i_ptr++ = (UBYTE)clr; if ( (i%4)==3) i_ptr -= row_dec; }
	  }
	} /* end of single color */
	else if (code1 < 0x80) /* 2 or 8 color encoding */
	{
	  ULONG cA,cB,pix_bits,mask;

	  pix_bits = (code1 << 8) | code0; mask = 0x0001;
          cB = *dptr++;  cB |= (*dptr++) << 8;
          cA = *dptr++;  cA |= (*dptr++) << 8;
	  if (cB & 0x8000)   /* EIGHT COLOR ENCODING */
	  {
	    ULONG i,d,clr_A[4],clr_B[4];
	    UBYTE rA[4],gA[4],bA[4],rB[4],gB[4],bB[4];
	    clr_B[0] = AVI_Get_Color(&rB[0],&gB[0],&bB[0],cB,map_flag,map);
	    clr_A[0] = AVI_Get_Color(&rA[0],&gA[0],&bA[0],cA,map_flag,map);
	    for(i=1;i<4;i++) /* read remaining colors */
	    {
	      d = *dptr++; d |= (*dptr++) << 8;
	      clr_B[i] =AVI_Get_Color(&rB[i],&gB[i],&bB[i],d,map_flag,map);
	      d = *dptr++; d |= (*dptr++) << 8;
	      clr_A[i] =AVI_Get_Color(&rA[i],&gA[i],&bA[i],d,map_flag,map);
	    }
	    if (special)
	    { UBYTE *i_ptr = (UBYTE *)(image + 3*(y * imagex + x) );
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) { *i_ptr++ = rB[avi_quad[i]]; 
		   *i_ptr++ = gB[avi_quad[i]]; *i_ptr++ = bB[avi_quad[i]]; }
	        else { *i_ptr++ = rA[avi_quad[i]]; 
		   *i_ptr++ = gA[avi_quad[i]]; *i_ptr++ = bA[avi_quad[i]]; }
	        mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    }
	    else if (x11_bytes_pixel==4)
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x) );
	          for(i=0; i < 16; i++)
	          { if (mask & pix_bits) *i_ptr++ = (ULONG)clr_B[avi_quad[i]];
		    else *i_ptr++ = (ULONG)clr_A[avi_quad[i]];
		    mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	          }
	    }
	    else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x) );
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) *i_ptr++ = (USHORT)clr_B[avi_quad[i]];
		else *i_ptr++ = (USHORT)clr_A[avi_quad[i]];
	        mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    }
	    else
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) *i_ptr++ = (UBYTE)clr_B[avi_quad[i]];
		    else *i_ptr++ = (UBYTE)clr_A[avi_quad[i]];
		    mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	       }
	    }
	  } /* end of 8 color */
	  else			/* TWO COLOR ENCODING */
	  {
	    ULONG i,clr_A,clr_B;
	    UBYTE r_A,g_A,b_A,r_B,g_B,b_B;
	    clr_B = AVI_Get_Color(&r_B,&g_B,&b_B,cB,map_flag,map);
	    clr_A = AVI_Get_Color(&r_A,&g_A,&b_A,cA,map_flag,map);
	    if (special)
	    { UBYTE *i_ptr = (UBYTE *)(image + 3*(y * imagex + x) );
	          for(i=0; i < 16; i++)
	          { if (mask & pix_bits) 
			 { *i_ptr++ = r_B; *i_ptr++ = g_B; *i_ptr++ = b_B; }
		    else { *i_ptr++ = r_A; *i_ptr++ = g_A; *i_ptr++ = b_A; }
		    mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	          }
	    }
	    else if (x11_bytes_pixel==4)
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x) );
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) *i_ptr++ = (ULONG)clr_B;
	        else *i_ptr++ = (ULONG)clr_A;
	        mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    }
	    else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x) );
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) *i_ptr++ = (USHORT)clr_B;
	        else *i_ptr++ = (USHORT)clr_A;
	        mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	      }
	    }
	    else
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      for(i=0; i < 16; i++)
	      { if (mask & pix_bits) *i_ptr++ = (UBYTE)clr_B;
	        else *i_ptr++ = (UBYTE)clr_A;
	        mask <<= 1; if ( (i%4) == 3) i_ptr -= row_dec;
	       }
	    }
	  } /* end of two color */
	} /* end of 2/8 color */
        if (x < min_x) min_x = x; if (y > max_y) max_y = y;
        if (x > max_x) max_x = x; if (y < min_y) min_y = y;
        x += 4; if (x >= imagex) { x = 0; y -= 4; }  /* move forward */
        changed = 1;
      } /* end of non_skip */
    } /* end of not term code */
  } /* end of not while exit */

  if (xa_optimize_flag == TRUE)
  {
    if (changed)
    {
      *xs = min_x;
      *ys = min_y - 3;
      *xe = max_x + 4;
      *ye = max_y + 1;
    }
    else
    {
      *xs = *ys = *xe = *ye = 0;
      return(ACT_DLTA_NOP);
    }
  }
  else
  {
      *xs = *ys = 0; *xe = imagex; *ye = imagey;
  }
  if (map_flag) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

ULONG AVI_Get_Color(r,g,b,color,map_flag,map)
UBYTE *r,*g,*b;
ULONG color,map_flag,*map;
{
  ULONG clr,ra,ga,ba;
 
  ra = (color >> 10) & 0x1f;    *r = 8 * ra;
  ga = (color >>  5) & 0x1f;    *g = 8 * ga;
  ba =  color & 0x1f;           *b = 8 * ba;
 
  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(ra,ga,ba,5);
  else { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(ra,ga,ba,CMAP_SCALE5);
         else   clr = CMAP_GET_GRAY(ra,ga,ba,CMAP_SCALE10);
         if (map_flag) clr = map[clr];
  }
  return(clr);
}

