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.