ftp.nice.ch/pub/next/graphics/movie/Movie.3.0.NIHS.bs.tar.gz#/Movie3.0/Source/xanim/xanim_rle.c

This is xanim_rle.c in view mode; [Download] [Up]

/*
 * xanim_rle.c
 *
 * Copyright (C) 1993,1994 by Mark Podlipec. 
 * All rights reserved.
 *
 * This software may be freely copied, modified and redistributed without
 * fee for non-commerical purposes 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_rle.h"

LONG Is_RLE_File();
ULONG RLE_Read_File();
ULONG RLE_Read_Header();
ULONG RLE_Get_Image();
void RLE_Read_Row();

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

ULONG rle_imagex, rle_imagey, rle_imagec;
ULONG rle_max_imagex, rle_max_imagey;
ULONG rle_xpos,rle_ypos;
ULONG rle_image_size;
ColorReg rle_cmap[256];
UBYTE bg_color[3];
UBYTE rle_chan_map[3][256];
XA_CHDR *rle_chdr;
UBYTE *rle_pic;

static RLE_FRAME *rle_frame_start,*rle_frame_cur;
static ULONG rle_frame_cnt;
static RLE_HDR rle_hdr;
static LONG priv_vert_skip;
static LONG priv_scan_y;
static LONG priv_is_eof;
static UBYTE *rle_row_buf,*rle_rows[3];

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

  if ( (fin=fopen(filename,XA_OPEN_MODE)) == 0) return(XA_NOFILE);
  data = UTIL_Get_LSB_Short(fin);  /* read past size */
  fclose(fin);
  if (data == RLE_MAGIC) return(TRUE);
  return(FALSE);
}


RLE_FRAME *RLE_Add_Frame(time,act)
ULONG time;
XA_ACTION *act;
{
  RLE_FRAME *rframe;

  rframe = (RLE_FRAME *) malloc(sizeof(RLE_FRAME));
  if (rframe == 0) TheEnd1("RLE_Add_Frame: malloc err");

  rframe->time = time;
  rframe->act = act;
  rframe->next = 0;

  if (rle_frame_start == 0) rle_frame_start = rframe;
  else rle_frame_cur->next = rframe;

  rle_frame_cur = rframe;
  rle_frame_cnt++;
  return(rframe);
}

void
RLE_Free_Frame_List(rframes)
RLE_FRAME *rframes;
{
  RLE_FRAME *rtmp;
  while(rframes != 0)
  {
    rtmp = rframes;
    rframes = rframes->next;
    FREE(rtmp,0x9999);
  }
}


ULONG RLE_Read_File(fname,anim_hdr)
char *fname;
XA_ANIM_HDR *anim_hdr;
{
  int i;
  RLE_FRAME *rtmp;


  rle_frame_start = 0;
  rle_frame_cur = 0;
  rle_frame_cnt = 0;
  rle_imagex = rle_imagey = 0;
  rle_max_imagex = rle_max_imagey = 0;
  rle_imagec = 0;

  rle_chdr = 0;

  if (RLE_Get_Image(fname,anim_hdr)==FALSE) return(FALSE);

    anim_hdr->frame_lst = (XA_FRAME *)
		malloc(sizeof(XA_FRAME) * (rle_frame_cnt + 1));
  if (anim_hdr->frame_lst == NULL)
       TheEnd1("RLE_Read_Anim: malloc err");

  rtmp = rle_frame_start;
  i = 0;
  while(rtmp != 0)
  {
    if (i >= rle_frame_cnt)
    {
      fprintf(stderr,"RLE_Read_Anim: frame inconsistency %ld %ld\n",
                i,rle_frame_cnt);
      break;
    }
    anim_hdr->frame_lst[i].time = rtmp->time;
    anim_hdr->frame_lst[i].act = rtmp->act;
    rtmp = rtmp->next;
    i++;
  }
  anim_hdr->frame_lst[i].time = 0;
  anim_hdr->frame_lst[i].act  = 0;
  anim_hdr->loop_frame = 0;
  if (i > 0) anim_hdr->last_frame = i - 1;
  else i = 0;
  anim_hdr->imagex = rle_max_imagex;
  anim_hdr->imagey = rle_max_imagey;
  anim_hdr->imagec = rle_imagec;
  anim_hdr->imaged = 8;

  RLE_Free_Frame_List(rle_frame_start);
  return(TRUE);
} 

ULONG 
RLE_Read_Header(fp,rle_hdr)
FILE *fp;
RLE_HDR *rle_hdr;
{
  rle_hdr->magic  = UTIL_Get_LSB_Short(fp);
  if (rle_hdr->magic != RLE_MAGIC) return(FALSE);

  rle_hdr->xpos  = UTIL_Get_LSB_Short(fp);
  rle_hdr->ypos  = UTIL_Get_LSB_Short(fp);
  rle_hdr->xsize = UTIL_Get_LSB_Short(fp);
  rle_hdr->ysize = UTIL_Get_LSB_Short(fp);

  rle_hdr->flags     = (ULONG)getc(fp) & 0xff;
  rle_hdr->chan_num  = (ULONG)getc(fp) & 0xff;
  rle_hdr->pbits     = (ULONG)getc(fp) & 0xff;
  rle_hdr->cmap_num  = (ULONG)getc(fp) & 0xff;
  rle_hdr->cbits     = getc(fp) & 0xff;
  if (rle_hdr->cbits > 8) TheEnd1("RLE_Read_Header: csize > 256\n");
  if (rle_hdr->cbits == 0) rle_hdr->cbits = rle_hdr->pbits; /*PODGUESS*/
  rle_hdr->csize     =  0x01 << rle_hdr->cbits;

  DEBUG_LEVEL1
  {
    fprintf(stderr,"RLE_Read_Header: pos %ld %ld size %ld %ld csize %ld\n",
		rle_hdr->xpos,rle_hdr->ypos,rle_hdr->xsize,rle_hdr->ysize,
		rle_hdr->csize);
    fprintf(stderr,"                 flags %lx chans %ld pbits %ld maps %ld\n",
	rle_hdr->flags,rle_hdr->chan_num,rle_hdr->pbits,rle_hdr->cmap_num);
  }

  /* read background colors - only save 1st three */
  if ( !(rle_hdr->flags & RLEH_NO_BACKGROUND) )
  {
    register ULONG i,j;
    j = 1 + (rle_hdr->chan_num / 2) * 2;
    for(i=0; i < j; i++)
    { 
      if (i < 3) bg_color[i] = getc(fp) & 0xff;
      else (void)getc(fp);
    }
  }
  else 
  {
    bg_color[0] = bg_color[1] = bg_color[2] = 0; 
    (void)getc(fp);
  }

  /* read all of the color maps - only store 1st three */
  if (rle_hdr->cmap_num)
  {
    register ULONG i,j,d;
    for(i=0; i < rle_hdr->cmap_num; i++)
    {
      for(j=0; j < rle_hdr->csize; j++)
      {
        d = UTIL_Get_LSB_Short(fp);
        if (i < 3) rle_chan_map[i][j] = d >> 8;
      }
    }
    if (rle_hdr->cmap_num == 1) /* singlemap? copy to others */
    {
      for(j=0; j < rle_hdr->csize; j++)
        rle_chan_map[1][j] = rle_chan_map[2][j] = rle_chan_map[0][j];
    } 
  }
  else  /* no maps? then create linear maps */
  { register ULONG i;
    for(i=0;i<rle_hdr->csize;i++) 
	rle_chan_map[0][i] = rle_chan_map[1][i] = rle_chan_map[2][i] = i;
  }
  /* GAMMA adjust map */
  if (   (rle_hdr->chan_num == 3) && (cmap_true_map_flag == TRUE)
      && (xa_gamma_flag==TRUE) )  
  { register ULONG i,j;
    for(j=0;j<3;j++)
      for(i=0;i<rle_hdr->csize;i++)
	rle_chan_map[j][i] = xa_gamma_adj[ rle_chan_map[j][i] ] >> 8;
  }

  /* skip comments */
  if (rle_hdr->flags & RLEH_COMMENT)  /* see rle_retrow.c for more details */
  {
    register ULONG d,i,len;
    len = UTIL_Get_LSB_Short(fp);
    for(i=0; i<len; i++)
    {
      d = getc(fp) & 0xff;
	/* if (xa_verbose) fprintf(stderr,"%c",d); */
    }
    if (len & 0x01) getc(fp); /* pad */
  }

  /*  if not end of file return ok */
  if ( !feof(fp) )
  {
    rle_imagec = rle_hdr->csize;
    rle_imagex = rle_hdr->xsize;
    rle_imagey = rle_hdr->ysize;
    if (rle_imagex > rle_max_imagex) rle_max_imagex = rle_imagex;
    if (rle_imagey > rle_max_imagey) rle_max_imagey = rle_imagey;
    rle_xpos   = rle_hdr->xpos;
    rle_ypos   = rle_max_imagey - (rle_hdr->ypos + rle_hdr->ysize);
    rle_image_size = rle_imagex * rle_imagey;
     /* POD need to check for initial image having non zero pos and need to
      * check for subsequent images fitting in initial images
      * maybe keep initial positions around to shift subsequent.
      */
    priv_scan_y = rle_hdr->ypos;
    priv_vert_skip = 0;
    priv_is_eof = FALSE;

    return(TRUE);
  } else return(False);
}


ULONG RLE_Get_Image(filename,anim_hdr)
char *filename;
XA_ANIM_HDR *anim_hdr;
{
  XA_ACTION *act;
  FILE *fin;
  int x,y;
  int rle_cnt;
  UBYTE *im_ptr;

  if ( (fin=fopen(filename,XA_OPEN_MODE)) == 0)
  {
    fprintf(stderr,"can't open RLE File %s for reading\n",filename);
    return(FALSE);
  }

  rle_cnt = 0;
  while ( RLE_Read_Header(fin,&rle_hdr) == TRUE )
  {
    rle_cnt++;

    if ( (rle_hdr.chan_num != 1) && (rle_hdr.chan_num != 3) )
    		TheEnd1("RLE_Get_Image: only 1 and 3 channels supported");
    /* currently must do this here to init xa_r_mask, etc TBD*/
    if (  (rle_hdr.chan_num == 3) && (cmap_true_map_flag != TRUE)
	&& (rle_chdr == 0) )
    {
	if (cmap_true_to_332 == TRUE)
		rle_chdr = CMAP_Create_332(rle_cmap,&rle_imagec);
	else	rle_chdr = CMAP_Create_Gray(rle_cmap,&rle_imagec);
    }

    if (xa_verbose) fprintf(stderr,"%ld) pos %ld %ld  size %ld %ld chans %ld\n",
	  rle_cnt,rle_xpos,rle_ypos,rle_imagex,rle_imagey,rle_hdr.chan_num);

    /* Allocate memory for the input image. */
    if (rle_cnt == 1) 
    {
      ULONG i,num_to_alloc;
      UBYTE *p;
      if (x11_display_type & XA_X11_TRUE) num_to_alloc = 3;
      else num_to_alloc = rle_hdr.chan_num;
      p = rle_row_buf = (UBYTE *)malloc( num_to_alloc * rle_imagex );
      if (rle_row_buf == 0) TheEnd1("RLE rowbuf malloc err");
      for(i=0; i<num_to_alloc; i++) { rle_rows[i] = p; p += rle_imagex; };
    }
    if (    (cmap_true_map_flag == TRUE) && (rle_hdr.chan_num == 3)
        && !(x11_display_type & XA_X11_TRUE) )
		rle_pic = (UBYTE *)malloc( 3 * rle_image_size );
    else	rle_pic = (UBYTE *)malloc( XA_PIC_SIZE(rle_image_size) );
    if (rle_pic == 0) TheEnd1("RLE_Get_Image: malloc err\n");

    im_ptr = rle_pic;
    y = rle_imagey; while(y--)
    {
      RLE_Read_Row(fin,&rle_hdr);

      /* if three channel image then remap data with rle_chan_map */
      if (rle_hdr.chan_num == 3)
      {
	register int i; register UBYTE *p0,*p1,*p2;
	i = rle_imagex; p0 = rle_rows[0]; p1 = rle_rows[1]; p2 = rle_rows[2];
	while(i--) 
	{ 
	  *p0++ = rle_chan_map[RLE_RED][(ULONG)(*p0)];
	  *p1++ = rle_chan_map[RLE_GREEN][(ULONG)(*p1)]; 
	  *p2++ = rle_chan_map[RLE_BLUE][(ULONG)(*p2)]; 
	}
      }

      if (x11_display_type & XA_X11_TRUE)
      {
	register int i; register UBYTE *p0,*p1,*p2;

	/* expand to rgb if color mapped image */
	if (rle_hdr.chan_num == 1)
	{
	  i = rle_imagex; p0 = rle_rows[0]; p1 = rle_rows[1]; p2 = rle_rows[2];
	  while(i--)
	  { register ULONG d = (ULONG)(*p0);
	    *p0++ = rle_chan_map[RLE_RED][d];
	    *p1++ = rle_chan_map[RLE_GREEN][d];
	    *p2++ = rle_chan_map[RLE_BLUE][d];
	  }
	}

	i = rle_imagex; p0 = rle_rows[0]; p1 = rle_rows[1]; p2 = rle_rows[2];
        if (x11_bytes_pixel == 1)
        {
          UBYTE *iptr = (UBYTE *)(rle_pic + (y * rle_imagex));
	  while(i--) *iptr++ = (UBYTE)
	    X11_Get_True_Color((ULONG)(*p0++),(ULONG)(*p1++),(ULONG)(*p2++),8);
	}
        else if (x11_bytes_pixel == 2)
        {
          USHORT *iptr = (USHORT *)(rle_pic + (2 * y * rle_imagex));
	  while(i--) *iptr++ = (USHORT)
	    X11_Get_True_Color((ULONG)(*p0++),(ULONG)(*p1++),(ULONG)(*p2++),8);
	}
        else
        {
          ULONG *iptr = (ULONG *)(rle_pic + (4 * y * rle_imagex));
	  while(i--) *iptr++ = (ULONG)
	    X11_Get_True_Color((ULONG)(*p0++),(ULONG)(*p1++),(ULONG)(*p2++),8);
	}
      }
      else if (rle_hdr.chan_num == 1) /* color mapped image */
      {
        im_ptr = (UBYTE *)(rle_pic + y * rle_imagex);
        for(x=0; x < rle_imagex; x++) *im_ptr++ = (UBYTE)rle_rows[0][x];
      }
      else if (cmap_true_map_flag == TRUE) /* 3 channels */
      {
        im_ptr = (UBYTE *)(rle_pic + (3 * y * rle_imagex));
        for(x=0; x < rle_imagex; x++)
	{
	  *im_ptr++ = (UBYTE)rle_rows[0][x];
	  *im_ptr++ = (UBYTE)rle_rows[1][x];
	  *im_ptr++ = (UBYTE)rle_rows[2][x];
	}
      }
      else
      {
        im_ptr =  (UBYTE *)( rle_pic + (y * rle_imagex));
        if (cmap_true_to_332 == TRUE)
	{
          for(x=0; x < rle_imagex; x++)
	  {
	    *im_ptr++ = CMAP_GET_332( (ULONG)(rle_rows[0][x]),
		(ULONG)(rle_rows[1][x]), (ULONG)(rle_rows[2][x]), CMAP_SCALE8 );
	  }
	}
        else 
	{
          for(x=0; x < rle_imagex; x++)
	  {
	    *im_ptr++ = CMAP_GET_GRAY( (ULONG)(rle_rows[0][x]),
		(ULONG)(rle_rows[1][x]), (ULONG)(rle_rows[2][x]), CMAP_SCALE13 );
	  }
	}
      }
    }

    act = ACT_Get_Action(anim_hdr);

    /* Create Color Maps */
    if (rle_hdr.chan_num == 1) /* images with color maps */
    { register ULONG i;
      for(i=0; i<rle_imagec; i++)
      {
	rle_cmap[i].red   = rle_chan_map[RLE_RED][i];
	rle_cmap[i].green = rle_chan_map[RLE_GREEN][i];
	rle_cmap[i].blue  = rle_chan_map[RLE_BLUE][i];
      }
      rle_chdr = ACT_Get_CMAP(rle_cmap,rle_imagec,0,rle_imagec,0,8,8,8);
    }
    else if (cmap_true_map_flag == TRUE)  /* 3 channels */
    {
      UBYTE *tpic;

      if (    (cmap_true_to_all == TRUE)
          || ((cmap_true_to_1st == TRUE) && (rle_chdr == 0) )
         )		rle_chdr = CMAP_Create_CHDR_From_True(rle_pic,8,8,8,
				rle_imagex,rle_imagey,rle_cmap,&rle_imagec);
      else if ( (cmap_true_to_332 == TRUE) && (rle_chdr == 0) )
			rle_chdr = CMAP_Create_332(rle_cmap,&rle_imagec);
      else if ( (cmap_true_to_gray == TRUE) && (rle_chdr == 0) )
			rle_chdr = CMAP_Create_Gray(rle_cmap,&rle_imagec);

      if (cmap_dither_type == CMAP_DITHER_FLOYD)
        tpic = UTIL_RGB_To_FS_Map(0,rle_pic,rle_chdr,
				rle_imagex,rle_imagey,TRUE);
      else
        tpic = UTIL_RGB_To_Map(0,rle_pic,rle_chdr,rle_imagex,rle_imagey,TRUE);
      FREE(rle_pic,0x9999);
      rle_pic = tpic;
    } /* NOTE: 332 and Gray Cases are done much earlier */
    else  /* 3 channels to either gray or 332 */
    {
      if (rle_chdr == 0)  /* error, this should have happened earlier */
	TheEnd1("RLE_Read_File: 332/gray error");
    }

    if (x11_display_type & XA_X11_TRUE)
    { 
      ACT_Setup_Mapped(act,rle_pic, 0,
                     rle_xpos,rle_ypos,rle_imagex,rle_imagey,
                     rle_imagex,rle_imagey,FALSE,0,TRUE,TRUE,TRUE);
    }
    else
    { 
      ACT_Setup_Mapped(act,rle_pic, rle_chdr,
                     rle_xpos,rle_ypos,rle_imagex,rle_imagey,
                     rle_imagex,rle_imagey,FALSE,0,TRUE,TRUE,FALSE);
      ACT_Add_CHDR_To_Action(act,rle_chdr);
    }
    RLE_Add_Frame(17,act);

  }
  if (rle_row_buf) { FREE(rle_row_buf,0x999); rle_row_buf=0; }
  fclose(fin);
  return(TRUE);
}


void RLE_Read_Row(fp,rle_hdr)
FILE *fp;
RLE_HDR *rle_hdr;
{
  ULONG posx,opcode,opdata,data;
  ULONG ymax,channel,exit_flag;
 
  ymax = rle_ypos + rle_imagey;
  posx = 0;
  exit_flag = 0;

  /* clear to background if necessary */
  if ( !(rle_hdr->flags & RLEH_NO_BACKGROUND) ) 
  { register ULONG i;
    for(i=0; i < rle_hdr->chan_num; i++)
		memset( (char *)rle_rows[i], bg_color[i], rle_hdr->xsize);
  }

  if (priv_vert_skip) 
  {
    priv_vert_skip--; 
    DEBUG_LEVEL3 fprintf(stderr,"  Prev Skip %ld\n",priv_vert_skip);
    return;
  }
  if ( priv_is_eof ) return;  /* EOF already encountered */

  while(!exit_flag)
  {
    opcode = getc(fp) & 0xff;
    opdata = getc(fp) & 0xff;
    switch( RLE_OPCODE(opcode) )
    {
      case RLE_SkipLinesOp:
	if (RLE_LONGP(opcode))  priv_vert_skip = UTIL_Get_LSB_Short(fp); 
        else priv_vert_skip = opdata;
	priv_vert_skip--;  /* count this line */
	posx = 0;
        exit_flag = 1; 
	break;
      case RLE_SetColorOp:
	channel = opdata; posx = 0;
	break;
      case RLE_SkipPixelsOp:
	if (RLE_LONGP(opcode))  posx += UTIL_Get_LSB_Short(fp); 
        else posx += opdata;
	break;
      case RLE_ByteDataOp:
	{ register ULONG i;
	if (RLE_LONGP(opcode))  opdata = UTIL_Get_LSB_Short(fp); 
	opdata++; i = opdata;
        if (channel < 3)
		  while(i--) {rle_rows[channel][posx] = getc(fp); posx++;}
	else	{ posx += opdata; while(i--) (void)getc(fp); }
	if (opdata & 0x01) (void)getc(fp);  /* pad to SHORT */
	}
	break;
      case RLE_RunDataOp:
	if (RLE_LONGP(opcode))  opdata = UTIL_Get_LSB_Short(fp); 
	opdata++;
	data = getc(fp) & 0xff;  (void)getc(fp);
        if (channel < 3)
		while(opdata--) {rle_rows[channel][posx] = data; posx++;}
	else	posx += opdata;
	break;
      case RLE_EOFOp:
	priv_is_eof = TRUE;
	exit_flag = 1;
	break;
      default:
	fprintf(stderr,"RLE unknown opcode %lx\n",RLE_OPCODE(opcode));
	exit_flag = 1;
    } /* end of opcode switch */
  } /* end of while */
}
       

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.