ftp.nice.ch/pub/next/graphics/movie/VideoStream.1.0.NIHS.bs.tar.gz#/VideoStreamV1.0/Source/aviDecodeSrc/xanim_avi.c

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

/*
 * xanim.h
 *
 * Copyright (C) 1990,1991,1992,1993 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.
 *
 */

/** WAR: Wildly hacked to stream AVI RGB data to stdout, 7/2/94 **/

/** WAR: global to buffer one frame of RGB interleaved data **/
unsigned char *frameData = (unsigned char *) 0;


#include "xanim_avi.h"

XA_ACTION *ACT_Get_Action(anim_hdr,type)
XA_ANIM_HDR *anim_hdr;
LONG type;
{
  XA_ACTION *act;

  act = (XA_ACTION *)malloc(sizeof(XA_ACTION));
  if (act == 0) TheEnd1("ACT_Get_Action: malloc err\n");

  act->type = type;
  act->cmap_rev = 0;
  act->data = 0;
  act->chdr = 0;
  act->h_cmap = 0;
  act->map = 0;
  act->next_same_chdr = 0;

  act->next = anim_hdr->acts;  /* insert at front of list */
  anim_hdr->acts = act;
  return(act);
}



XA_CHDR *ACT_Get_CHDR(rev,csize,coff,msize,moff,cmap_flag,map_flag)
ULONG rev,csize,coff,msize,moff;
ULONG cmap_flag,map_flag;
{
  XA_CHDR *chdr;

  chdr = (XA_CHDR *)malloc(sizeof(XA_CHDR));
  if (chdr == 0) TheEnd1("ACT_Get_CHDR: malloc err\n");

  chdr->rev    = rev;
  chdr->csize  = csize;
  chdr->coff   = coff;
  chdr->msize  = msize;
  chdr->moff   = moff;
  chdr->next   = 0;
  chdr->acts   = 0;
  chdr->new_chdr = 0;

  if ( (csize) && (cmap_flag) )
  {
    chdr->cmap = (ColorReg *)malloc(csize * sizeof(ColorReg));
    if (chdr->cmap == 0) TheEnd1("ACT_Get_CHDR: cmap malloc err\n");
  }
  else
  {
    chdr->cmap = 0;
    if ( (csize==0) && (cmap_flag) )
	 fprintf(stderr,"ACT_Get_CHDR: csize 0 err\n");
  }
  if ( (msize) && (map_flag) )
  {
    chdr->map = (ULONG *)malloc(msize * sizeof(ULONG));
    if (chdr->map == 0) TheEnd1("ACT_Get_CHDR: map malloc err\n");
  }
  else
  {
    chdr->map = 0;
    if ( (msize==0) && (map_flag) )
	 fprintf(stderr,"ACT_Get_CHDR: msize 0 err\n");
  }

  return(chdr);
}






XA_CHDR *ACT_Get_CMAP(new_map,csize,coff,msize,moff,rbits,gbits,bbits)
ColorReg *new_map;
ULONG csize,coff,msize,moff;
ULONG rbits,gbits,bbits;
{
  ULONG i;
  XA_CHDR *chdr;
  ULONG rscale,gscale,bscale;

  if (   (msize > csize) || (moff < coff) 
      || ( (msize+moff) > (csize+coff) )  )
	TheEnd1("ACT_Get_CMAP: map not in cmap err\n");

  chdr = ACT_Get_CHDR(0,csize,coff,msize,moff,TRUE,TRUE);

  rscale = 256;
  gscale = 256;
  bscale = 256;

  for(i = 0; i < csize; i++)
  {
    chdr->cmap[i].red   = ((rscale * new_map[i].red  ) >> 8);
    chdr->cmap[i].green = ((gscale * new_map[i].green) >> 8);
    chdr->cmap[i].blue  = ((bscale * new_map[i].blue ) >> 8);
  }
  rscale *= 11;
  gscale *= 16;
  bscale *=  5;
  for(i = 0; i < csize; i++)
  {
    register ULONG d = ( (   rscale * new_map[i].red
			   + gscale * new_map[i].green
			   + bscale * new_map[i].blue) >> 13 );
    chdr->cmap[i].gray = d ;
  }
  for(i = 0; i < csize; i++) 
	chdr->map[i] = i + moff;
  return(chdr);
}


void TheEnd1(char *message) {
	fprintf(stderr, message);
	exit(-1);
}


/* Routine to read a big endian long word. */
ULONG UTIL_Get_MSB_Long(fp)
	FILE *fp;
{
	ULONG ret;

	ret = fgetc(fp) << 24;
	ret |= fgetc(fp) << 16;
	ret |= fgetc(fp) << 8;
	ret |= fgetc(fp);
	return ret;
}




/* Routine to read a little endian long word. */
ULONG UTIL_Get_LSB_Long(fp)
	FILE *fp;
{
	ULONG ret;

	ret = fgetc(fp);
	ret |= fgetc(fp) << 8;
	ret |= fgetc(fp) << 16;
	ret |= fgetc(fp) << 24;
	return ret;
}




/* Routine to read a little endian half word. */
ULONG UTIL_Get_LSB_Short(fp)
	FILE *fp;
{
	ULONG ret;

	ret = fgetc(fp);
	ret |= fgetc(fp) << 8;
	return ret;
}




LONG x11_bytes_pixel;

#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_compression;

/* 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));
	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) {
		fprintf(stderr, "can't open %s\n", filename);
		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;
	UBYTE *pic;
	ULONG pic_size;

	if ((fin = fopen(fname, "r")) == 0) {
		fprintf(stderr, "can't open AVI File %s for reading\n", fname);
		TheEnd1("");
	}

	pic = 0;
	avi_chdr = 0;
	avi_frame_cnt = 0;
	avi_frame_start = 0;
	avi_frame_cur = 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);
			break;
		case RIFF_LIST:
			d = UTIL_Get_MSB_Long(fin);
			break;
		case RIFF_avih:
			RIFF_Read_AVIH(fin, ck_size, &avi_hdr);
			break;
		case RIFF_strh:
			RIFF_Read_STRH(fin, ck_size, &strh_hdr);
			break;
		case RIFF_strf:
			switch (strh_hdr.fcc_type) {
			case RIFF_vids:
				RIFF_Read_VIDS(fin, ck_size, &vids_hdr);
				if (pic == 0) {
					pic_size = avi_imagex * avi_imagey;
					pic = (UBYTE *) malloc(pic_size);
				}
				break;
			case RIFF_auds:
				if (ck_size & 0x01)
					ck_size++;
				for (i = 0; i < ck_size; i++)
					d = getc(fin);
				break;
			default:
				fprintf(stderr, "unknown fcc_type at strf, exiting...");
				exit(-1);
				break;
			}
			break;

		case RIFF_00dc:
			{
				ACT_DLTA_HDR *dlta_hdr;
				ULONG d;

				if (ck_size & 0x01)
					ck_size++;
				act = ACT_Get_Action(anim_hdr, ACT_DELTA);
				d = ck_size + (sizeof(ACT_DLTA_HDR));
				dlta_hdr = (ACT_DLTA_HDR *) malloc(d);
				act->data = (UBYTE *) dlta_hdr;
				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(17, 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:
					dlta_hdr->delta = AVI_Decode_CRAM;
					break;
				default:
					fprintf(stderr, "AVI: unsupported comp %lx\n", avi_compression);
					act->type = ACT_NOP;
					break;
				}
				if (act->type != ACT_NOP) {
					ULONG xpos, ypos, xsize, ysize, dlta_flag;

					dlta_flag = dlta_hdr->delta(pic, dlta_hdr->data,
					  avi_chdr->map, FALSE, avi_imagex, avi_imagey, 8,
					  &xpos, &ypos, &xsize, &ysize);
					  
	/*** WAR: Write the frame RGB data here***************/
	{
		unsigned char *framePtr=frameData, *picPtr=pic;
		int j;
		for(j=0; j<pic_size; j++) {
			*framePtr++ = avi_cmap[*picPtr].red;
			*framePtr++ = avi_cmap[*picPtr].green;
			*framePtr++ = avi_cmap[*picPtr++].blue;
		}
		fwrite(frameData, 3*pic_size, sizeof(unsigned char), stdout);
		fflush(stdout);
	}
	/******************************************************/
		
	
					FREE(dlta_hdr, 0x3000);
					act->data = 0;
					if (dlta_flag & ACT_DLTA_NOP)
						act->type = ACT_NOP;
					} /* end of buffer */
			}
			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)) {
				fprintf(stderr, " chunk unknown\n");
				exit(0);
			}

		} /* end of ck_id switch */
	} /* while not exitflag */

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

/********** WAR: don't print info in piped version
	if (FALSE) {	 
		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));

	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 (i > 0)
		anim_hdr->last_frame = i - 1;
	else
		i = 0;
	AVI_Free_Frame_List(avi_frame_start);
	
	/****** WAR: free frameData ********************/
	if(frameData) {
		free(frameData);
	}
	/***********************************************/

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






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);


	if (vids_hdr->bit_cnt != 8)
		TheEnd1("AVI: bit_cnt not 8 not supported\n");
	if (vids_hdr->num_colors == 0)
		TheEnd1("AVI: num_color=0 not supported\n");

	avi_compression = vids_hdr->compression;
	avi_imagex = vids_hdr->width;
	avi_imagey = vids_hdr->height;
	
	/******* WAR: write width and height to stdout, and allocate frameData ************/
	fwrite(&avi_imagex, 1, sizeof(int), stdout);
	fwrite(&avi_imagey, 1, sizeof(int), stdout);
	fflush(stdout);
	frameData = (unsigned char *) malloc(3 * avi_imagex * avi_imagey);
	/***********************************************************************************/
	
	if (vids_hdr->num_colors == 0)
		vids_hdr->num_colors = 256;
	avi_imagec = vids_hdr->num_colors;

	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 */
	}
	tsize = vids_hdr->num_colors * 4 + 40;
	if (size & 0x01)
		size++;
	while (tsize < size) {
		d = getc(fin);
		tsize++;
	}

	avi_chdr = ACT_Get_CMAP(avi_cmap, avi_imagec, 0, avi_imagec, 0, 8, 8, 8);
}








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

	if (map_flag == TRUE) {
		if (x11_bytes_pixel == 4) {
			while (!exitflag) {
				code0 = *dptr++;
				code1 = *dptr++;
				if ((code1 == 0) && (code0 == 0))
					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;

						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++;
				if ((code1 == 0) && (code0 == 0))
					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;

						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++;
				if ((code1 == 0) && (code0 == 0))
					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;

						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;
							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++;
			if ((code1 == 0) && (code0 == 0))
				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;

					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];
						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 (FALSE) /**WAR: was (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);
}


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