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.