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

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

/*
 * xanim_qt.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_qt.h"

ULONG QT_Decode_RLE();
ULONG QT_Decode_RLE16();
ULONG QT_Decode_RLE24();
ULONG QT_Decode_RLE33();
ULONG QT_Decode_RAW();
ULONG QT_Decode_RPZA();
ULONG QT_Decode_SMC();
ULONG QT_Decode_CVID();
ULONG QT_Decode_YUV2();
ULONG QT_Decode_SPIG();
ULONG QT_Read_Video_Codec_HDR();
ULONG QT_Read_Audio_Codec_HDR();
void QT_Audio_Type();
ULONG QT_Read_File();
void QT_Gen_YUV_Tabs();
void QT_CVID_C1();
void QT_CVID_C4();
void QT_Create_Default_Cmap();
char *XA_rindex();

ULONG qt_cmap_cnt,qt_cmap_flag;
void CMAP_Cache_Clear();
void CMAP_Cache_Init();

#define SMC_MAX_CNT 256
static ULONG smc_8cnt,smc_Acnt,smc_Ccnt;
static ULONG smc_8[ (2 * SMC_MAX_CNT) ];
static ULONG smc_A[ (4 * SMC_MAX_CNT) ];
static ULONG smc_C[ (8 * SMC_MAX_CNT) ];

QTV_CODEC_HDR *qtv_codecs;
QTS_CODEC_HDR *qts_codecs;
ULONG qtv_codec_num,qts_codec_num;

XA_ACTION *ACT_Get_Action();
XA_CHDR *ACT_Get_CMAP();
XA_CHDR *CMAP_Create_332();
XA_CHDR *CMAP_Create_422();
XA_CHDR *CMAP_Create_Gray();
void ACT_Add_CHDR_To_Action();
void ACT_Setup_Mapped();
XA_CHDR *CMAP_Create_CHDR_From_True();
UBYTE *UTIL_RGB_To_FS_Map();
UBYTE *UTIL_RGB_To_Map();
ULONG CMAP_Find_Closest();
 
ULONG UTIL_Get_MSB_Long();
LONG UTIL_Get_MSB_Short();
ULONG UTIL_Get_MSB_UShort();

FILE *QT_Open_File();
void  QT_Parse_Chunks();
ULONG QT_Parse_Bin();
void  QT_Read_Video_Data();
void  QT_Read_Audio_Data();

void yuv_to_rgb();
void QT_Print_ID();
void QT_Read_MVHD();
void QT_Read_TKHD();
void QT_Read_ELST();
void QT_Read_MDHD();
void QT_Read_HDLR();
void QT_Read_Video_STSD();
void QT_Read_Audio_STSD();
void QT_Read_Name();
void QT_Read_STTS();
void QT_Read_STSS();
void QT_Read_STCO();
void QT_Read_STSZ();
void QT_Read_STSC();
void QT_Read_STGS();
void QT_Codec_List();
ULONG QT_Get_Color();
void QT_Get_RGBColor();
void QT_Get_AV_Colors();
void QT_Get_AV_RGBColors();
ULONG QT_Get_Color24();


QT_MVHDR qt_mvhdr;
QT_TKHDR qt_tkhdr;
QT_MDHDR qt_mdhdr;
QT_HDLR_HDR qt_hdlr_hdr;

char qt_rfilename[256];
char qt_dfilename[256];
ULONG qt_video_flag;
ULONG qt_data_flag;
ULONG qt_v_flag,qt_s_flag;


#define QT_MAX_COLORS  256
ColorReg qt_cmap[QT_MAX_COLORS];
XA_CHDR *qt_chdr;
USHORT qt_gamma_adj[32];

ULONG qt_frame_cnt;
ULONG qt_imagex,qt_imagey,qt_imagec;
ULONG qt_max_imagex,qt_max_imagey;
ULONG qt_compression,qt_depth;
ULONG qt_max_fsize;
ULONG qt_time,qt_timelo;
ULONG qt_timescale,qt_mv_timescale,qt_tk_timescale,qt_md_timescale;

#define QT_CODEC_UNK   0x000
#define QT_CODEC_RLE   0x001
#define QT_CODEC_RLE16 0x002
#define QT_CODEC_RLE24 0x003
#define QT_CODEC_RLE33 0x004
#define QT_CODEC_RAW   0x008
#define QT_CODEC_SMC   0x010
#define QT_CODEC_RPZA  0x020
#define QT_CODEC_CVID  0x030
#define QT_CODEC_YUV2  0x040
#define QT_CODEC_SPIG  0x050

/* YUV cache tables for CVID */
static LONG *QT_UB_tab=0;
static LONG *QT_VR_tab=0;
static LONG *QT_UG_tab=0;
static LONG *QT_VG_tab=0;

/*** SOUND SUPPORT ****/
ULONG qt_audio_attempt;
ULONG qt_audio_type;
ULONG qt_audio_freq;
ULONG qt_audio_chans;
ULONG qt_audio_bps;
ULONG qt_audio_end;
#ifdef POD_AUDIO_BETA
void XA_Add_Sound();
#endif



QT_FRAME *qt_frame_start,*qt_frame_cur;
 
QT_FRAME *QT_Add_Frame(time,timelo,act)
ULONG time,timelo;
XA_ACTION *act;
{
  QT_FRAME *fframe;
 
  fframe = (QT_FRAME *) malloc(sizeof(QT_FRAME));
  if (fframe == 0) TheEnd1("QT_Add_Frame: malloc err");
 
  fframe->time = time;
  fframe->timelo = timelo;
  fframe->act = act;
  fframe->next = 0;
 
  if (qt_frame_start == 0) qt_frame_start = fframe;
  else qt_frame_cur->next = fframe;
 
  qt_frame_cur = fframe;
  qt_frame_cnt++;
  return(fframe);
}
 
void QT_Free_Frame_List(fframes)
QT_FRAME *fframes;
{
  QT_FRAME *ftmp;
  while(fframes != 0)
  {
    ftmp = fframes;
    fframes = fframes->next;
    FREE(ftmp,0x9000);
  }
}


LONG Is_QT_File(filename)
char *filename;
{
  FILE *fin;
  ULONG ret;

  if ( (fin=QT_Open_File(filename,qt_rfilename,qt_dfilename)) == 0)
				return(XA_NOFILE);
  ret = QT_Parse_Bin(fin);
  fclose(fin);
  if ( ret != 0 ) return(TRUE);
  return(FALSE);
}

/* FOR PARSING Quicktime Files */
ULONG *qtv_samp_sizes,*qts_samp_sizes;
ULONG qtv_samp_num,qts_samp_num;
ULONG qts_init_duration;

QT_S2CHUNK_HDR *qtv_s2chunks,*qts_s2chunks;
ULONG qtv_s2chunk_num,qts_s2chunk_num;

QT_T2SAMP_HDR *qtv_t2samps,*qts_t2samps;
ULONG qtv_t2samp_num,qts_t2samp_num;
 
ULONG qtv_chunkoff_num,qts_chunkoff_num;
ULONG *qtv_chunkoffs,*qts_chunkoffs;
UBYTE *qt_pic;
ULONG qt_pic_size;

ULONG qtv_codec_lstnum,qts_codec_lstnum;
ULONG qtv_chunkoff_lstnum,qts_chunkoff_lstnum;
ULONG qtv_samp_lstnum,qts_samp_lstnum;
ULONG qtv_s2chunk_lstnum,qts_s2chunk_lstnum;
ULONG qt_stgs_num;

/* main() */
ULONG QT_Read_File(fname,anim_hdr)
char *fname;
XA_ANIM_HDR *anim_hdr;
{
  FILE *fin;
  LONG i;

  qt_stgs_num = 0;
  qt_cmap_flag = 0;
  qt_cmap_cnt = 0;
  qtv_codec_lstnum	= qts_codec_lstnum = 0;
  qtv_chunkoff_lstnum	= qts_chunkoff_lstnum = 0;
  qtv_samp_lstnum	= qts_samp_lstnum = 0;
  qtv_codecs = 0;
  qts_codecs = 0;
  qtv_codec_num 	= qts_codec_num = 0;
  qt_data_flag = FALSE;
  qt_video_flag		= 0;
  qt_v_flag		= qt_s_flag = 0;
  qt_compression	= QT_CODEC_UNK;
  qt_depth = 0;
  qt_pic = 0;
  qt_pic_size = 0;

  qt_chdr = 0;
  qt_frame_cnt = 0;
  qt_frame_start = 0;
  qt_frame_cur = 0;
  qt_time = XA_GET_TIME( 100 ); /* default 10 frames per second */
  qt_timelo = 0;
  qt_timescale		= 1000;
  qt_mv_timescale = qt_tk_timescale = qt_md_timescale = 1000;
  qtv_chunkoff_num	= qts_chunkoff_num = 0;
  qtv_chunkoffs		= qts_chunkoffs = 0;
  qtv_s2chunk_num	= qts_s2chunk_lstnum = 0;
  qtv_s2chunks		= qts_s2chunks = 0;
  qtv_s2chunk_num	= qts_s2chunk_lstnum = 0;
  qtv_t2samp_num	= qts_t2samp_num = 0;
  qtv_t2samps		= qts_t2samps = 0;
  qtv_samp_sizes	= qts_samp_sizes = 0;
  qtv_samp_num		= qts_samp_num = 0;
  qts_init_duration	= 0;
  qt_imagex = qt_imagey = qt_imagec = 0;
  qt_max_fsize = 0;
  qt_max_imagex = qt_max_imagey = 0;

  qt_audio_attempt = FALSE;

  for(i=0;i<32;i++) qt_gamma_adj[i] = xa_gamma_adj[ ((i<<3)|(i>>2)) ];

  if ( (fin=QT_Open_File(fname,qt_rfilename,qt_dfilename)) == 0)
  {
    fprintf(stderr,"QT_Read: can't open %s\n",qt_rfilename);
    return(FALSE);
  }

  if ( QT_Parse_Bin(fin) == 0 )
  {
    fprintf(stderr,"Not quicktime file\n");
    return(FALSE);
  }

DEBUG_LEVEL1 fprintf(stderr,"parsing chunks\n");
  QT_Parse_Chunks(fin);

  if (qt_data_flag == FALSE) 
  { /* mdat was not in .rscr file need to open .data file */
    fclose(fin); /* close .rscr file */
    if (qt_dfilename[0] == 0)
    {
       fprintf(stderr,"QT_Data: No data in %s file. Can't find .data file.\n",
		qt_rfilename);
       return(FALSE);
    }
    if ( (fin=fopen(qt_dfilename,XA_OPEN_MODE)) == 0) 
    {
      fprintf(stderr,"QT_Data: can't open %s file.\n",qt_dfilename);
      return(FALSE);
    }
  } else strcpy(qt_dfilename,qt_rfilename); /* r file is d file */
DEBUG_LEVEL1 fprintf(stderr,"reading data\n");
  QT_Read_Video_Data(fin,anim_hdr);
  QT_Read_Audio_Data(fin,anim_hdr);
  fclose(fin);

  if (xa_verbose) fprintf(stderr,"    Frames %ld\n", qt_frame_cnt);

  anim_hdr->frame_lst = (XA_FRAME *)
                                malloc( sizeof(XA_FRAME) * (qt_frame_cnt+1));
  if (anim_hdr->frame_lst == NULL) TheEnd1("QT_Read_File: frame malloc err");
 
  qt_frame_cur = qt_frame_start;
  i = 0;
  while(qt_frame_cur != 0)
  {
    if (i >= qt_frame_cnt)
    {
      fprintf(stderr,"QT_Read_Anim: frame inconsistency %ld %ld\n",
                i,qt_frame_cnt);
      break;
    }
    anim_hdr->frame_lst[i].time = qt_frame_cur->time;
    anim_hdr->frame_lst[i].timelo = qt_frame_cur->timelo;
    anim_hdr->frame_lst[i].act = qt_frame_cur->act;
    qt_frame_cur = qt_frame_cur->next;
    i++;
  }
  anim_hdr->imagex = qt_max_imagex;
  anim_hdr->imagey = qt_max_imagey;
  anim_hdr->imagec = qt_imagec;
  anim_hdr->imaged = 8; /* nop */
  anim_hdr->frame_lst[i].time = 0;
  anim_hdr->frame_lst[i].timelo = 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;
  anim_hdr->max_fsize = qt_max_fsize;
  if (xa_file_flag == TRUE) 
  {
    ULONG len;
    anim_hdr->anim_flags |= ANIM_USE_FILE;
    len = strlen(qt_dfilename) + 1;
    anim_hdr->fname = (char *)malloc(len);
    if (anim_hdr->fname==0) TheEnd1("QT: malloc fname err");
    strcpy(anim_hdr->fname,qt_dfilename);
  }
  if (i > 0) anim_hdr->last_frame = i - 1;
  else i = 0;
  QT_Free_Frame_List(qt_frame_start);
  if (qtv_samp_sizes) free(qtv_samp_sizes);
  if (qts_samp_sizes) free(qts_samp_sizes);
  if (qtv_codecs) free(qtv_codecs);
  if (qts_codecs) free(qts_codecs);
  if (qtv_t2samps) free(qtv_t2samps);
  if (qts_t2samps) free(qts_t2samps);
  if (qtv_s2chunks) free(qtv_s2chunks);
  if (qts_s2chunks) free(qts_s2chunks);
  if (qtv_chunkoffs) free(qtv_chunkoffs);
  if (qts_chunkoffs) free(qts_chunkoffs);
  return(TRUE);
}

FILE *QT_Open_File(fname,r_file,d_file)
char *fname,*r_file,*d_file;
{
  FILE *fin;

  /* check to see if fname exists? */
  if ( (fin=fopen(fname,XA_OPEN_MODE)) != 0)  /* filename is as give */
  { /*three choices - with or without .rsrc ending, or using .resource subdir*/
    LONG len;
    FILE *ftst;
    /* path/fname exits. */

    /* check for  path/.resource/fname */
    {
      char *lastdirsep;
      strcpy(r_file,fname);			/* copy path/fname to r */
      lastdirsep = XA_rindex(r_file, '/');	/* find sep if any */
      if ( lastdirsep != (char *)(NULL) )
      {
        strcpy(d_file,lastdirsep);		/* save fname to d*/
	lastdirsep++; *lastdirsep = 0;		/* cut of fname off r*/
        strcat(lastdirsep, ".resource/"); 	/* add .resource to r*/
        strcat(r_file, d_file); 		/* add fname to r */
      }
      else /* no path */
      {
	strcpy(r_file,".resource/");
	strcat(r_file,fname);
      }
      if ( (ftst=fopen(r_file,"r")) != 0)
      {
	/* path/fname and path/.resource/fname exist - wrap it up */
	strcpy(d_file,fname);			/* setup .data name */
	fclose(fin);				/* close .data fork */
        return(ftst);		/* return .rsrc fork (in .resource) */
      }
    }
     
    /* Now check for .rsrc or .data endings */
    strcpy(r_file,fname);
    strcpy(d_file,fname);
    len = strlen(r_file) - 5;
    if (len > 0)
    { char *tmp;
      tmp = XA_rindex(d_file, '.');	/* get last "." */
      if ( tmp == (char *)(NULL) ) { *d_file = 0; return(fin); }
      else if (strcmp(tmp,".rsrc")==0)  /* fname has .rsrc ending */
      {
        strcpy(tmp,".data"); /* overwrite .rsrc with .data in d*/
	return(fin);
      }
      else if (strcmp(tmp,".data")==0)  /* fname has .data ending */
      {
        strcpy(tmp,".rsrc"); /* overwrite .rsrc with .data in d*/
        if ( (ftst=fopen(d_file,"r")) != 0) /* see if .rsrc exists */
	{
	  char t_file[256];  /* swap r and d files */
	  strcpy(t_file,r_file); strcpy(r_file,d_file); strcpy(d_file,t_file);
	  fclose(fin);		/* close .data file */
	  return(ftst);		/* return .rsrc file */
	}
	/* hopefully .data is flattened. find out later */
	else { *d_file = 0; return(fin); }
      }
      else { *d_file = 0; return(fin); }
    }
    else { *d_file = 0; return(fin); }
  }

  /* does fname.rsrc exist? */
  strcpy(r_file,fname);
  strcat(r_file,".rsrc");
  if ( (fin=fopen(r_file,XA_OPEN_MODE)) != 0)  /* fname.rsrc */
  { FILE *ftst;
    /* if so, check .data existence */
    strcpy(d_file,fname);
    strcat(d_file,".data");
    if ( (ftst=fopen(d_file,XA_OPEN_MODE)) != 0)	fclose(ftst);
    else *d_file = 0;
    return(fin);
  } else *d_file = 0;
  return(0);
}

void QT_Parse_Chunks(fin)
FILE *fin;
{
  LONG file_len;
  ULONG id,len;

  file_len = 1;
  while(file_len > 0)
  {
    len = UTIL_Get_MSB_Long(fin);
    id  = UTIL_Get_MSB_Long(fin);

    if ( (len == 0) && (id == QT_mdat) )
	TheEnd1("QT: mdat len is 0. You also need a .rsrc file.\n");
    if (len < 8) { file_len = 0; continue; } /* just bad - finish this */
    if (file_len == 1)
    {
      if (id == QT_moov) file_len = len;
      else file_len = len + 1;
    }
    DEBUG_LEVEL2 fprintf(stderr,"%c%c%c%c %04lx len = %lx file_len =  %lx\n",
	(id >> 24),((id>>16)&0xff),((id>>8)&0xff),(id&0xff),id,len,file_len);

    switch(id)
    {
    /*--------------ATOMS------------------*/
      case QT_trak:
	qt_v_flag = qt_s_flag = 0;
	qtv_codec_lstnum = qtv_codec_num;
	qts_codec_lstnum = qts_codec_num;
	qtv_chunkoff_lstnum = qtv_chunkoff_num;
	qts_chunkoff_lstnum = qts_chunkoff_num;
	qtv_samp_lstnum = qtv_samp_num;
	qts_samp_lstnum = qts_samp_num;
	qtv_s2chunk_lstnum = qtv_s2chunk_num;
	qts_s2chunk_lstnum = qts_s2chunk_num;
      case QT_moov:
      case QT_mdia:
      case QT_minf:
      case QT_stbl:
      case QT_edts:
	file_len -= 8;
	break;
    /*---------------STUFF------------------*/
      case QT_mvhd:
	QT_Read_MVHD(fin,&qt_mvhdr);
	file_len -= len;
	break;
      case QT_tkhd:
	QT_Read_TKHD(fin,&qt_tkhdr);
	file_len -= len;
	break;
      case QT_elst:
	QT_Read_ELST(fin);
	file_len -= len;
	break;
      case QT_mdhd:
	QT_Read_MDHD(fin,&qt_mdhdr);
	file_len -= len;
	break;
      case QT_hdlr:
	QT_Read_HDLR(fin,len,&qt_hdlr_hdr);
	file_len -= len;
	break;
    /*--------------DATA CHUNKS-------------*/
      case QT_mdat:  /* data is included in .rsrc - assumed flatness */
	fseek(fin,(len-8),1); /* skip over it for now */
	qt_data_flag = TRUE;
	break;
      case QT_stsd:
	qt_video_flag = 0;
	if (qt_v_flag) QT_Read_Video_STSD(fin);
	else if (qt_s_flag) QT_Read_Audio_STSD(fin);
        else fseek(fin,(len-8),1);
	file_len -= len;
	break;
      case QT_stts:
	if (qt_v_flag) 
		QT_Read_STTS(fin,(len-8),&qtv_t2samp_num,&qtv_t2samps);
/*POD NOTE: AUDIO don't need? probably, just haven't been bit by it yet.
	else if (qt_s_flag) 
		QT_Read_STTS(fin,(len-8),&qts_t2samp_num,&qts_t2samps);
*/
        else	fseek(fin,(len-8),1);
	file_len -= len;
	break;
      case QT_stss:
	QT_Read_STSS(fin);
	file_len -= len;
	break;
      case QT_stco:
	if (qt_v_flag) QT_Read_STCO(fin,&qtv_chunkoff_num,&qtv_chunkoffs);
	else if (qt_s_flag) QT_Read_STCO(fin,&qts_chunkoff_num,&qts_chunkoffs);
	else fseek(fin,(len-8),1);
	file_len -= len;
	break;
      case QT_stsz:
	if (qt_v_flag) QT_Read_STSZ(fin,len,&qtv_samp_num,&qtv_samp_sizes);
	else if (qt_s_flag) 
		QT_Read_STSZ(fin,len,&qts_samp_num,&qts_samp_sizes);
	else fseek(fin,(len-8),1);
	file_len -= len;
	break;
      case QT_stsc:
	if (qt_v_flag) QT_Read_STSC(fin,len,&qtv_s2chunk_num,&qtv_s2chunks,
			qtv_chunkoff_lstnum,qtv_codec_num,qtv_codec_lstnum);
	else if (qt_s_flag) QT_Read_STSC(fin,len,&qts_s2chunk_num,&qts_s2chunks,
			qts_chunkoff_lstnum,qts_codec_num,qts_codec_lstnum);
	else fseek(fin,(len-8),1);
	file_len -= len;
	break;
      case QT_stgs:
	QT_Read_STGS(fin,len);
	file_len -= len;
	break;
    /*-----------Sound Codec Headers--------------*/
      case QT_raw00:
    /*-----------Video/Sound Codec Headers--------------*/
      case QT_raw:
    /*-----------Video Codec Headers--------------*/
      case QT_smc:
      case QT_rpza:
      case QT_rle:
      case QT_cvid:
	fprintf(stderr,"QT: Warning %08lx\n",id);
        fseek(fin,(len-8),1);  /* skip over */
	file_len -= len;
	break;
    /*-----------TYPE OF TRAK---------------*/
      case QT_vmhd:
        fseek(fin,(len-8),1);
	file_len -= len; qt_v_flag = 1;
	qt_timescale = qt_md_timescale;
	break;
      case QT_smhd:
        fseek(fin,(len-8),1);
	file_len -= len; qt_s_flag = 1;
	break;
    /*--------------IGNORED FOR NOW---------*/
      case QT_gmhd:
      case QT_text:
      case QT_skip:
      case QT_udta:
      case QT_dinf:
        fseek(fin,(len-8),1);  /* skip over */
	file_len -= len;
	break;
    /*--------------UNKNOWN-----------------*/
      default:
	if ( !feof(fin) && (len <= file_len) )
	{
	  LONG i;
	  QT_Print_ID(stderr,id,1);
	  fprintf(stderr," len = %lx\n",len);
	  i = (LONG)(len) - 8;
	  while(i > 0) { i--; getc(fin); if (feof(fin)) i = 0; }
	}
	file_len -= len;
	break;
    } /* end of switch */
    if ( feof(fin) ) file_len = 0;
  } /* end of while */
}

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


void QT_Read_MVHD(fin,qt_mvhdr)
FILE *fin;
QT_MVHDR *qt_mvhdr;
{
  ULONG i,j;

  qt_mvhdr->version =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->creation =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->modtime =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->timescale =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->duration =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->rate =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->volume =	UTIL_Get_MSB_UShort(fin);
  qt_mvhdr->r1  =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->r2  =	UTIL_Get_MSB_Long(fin);
  for(i=0;i<3;i++) for(j=0;j<3;j++) 
	qt_mvhdr->matrix[i][j]=UTIL_Get_MSB_Long(fin);
  qt_mvhdr->r3  =	UTIL_Get_MSB_UShort(fin);
  qt_mvhdr->r4  =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->pv_time =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->post_time =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->sel_time =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->sel_durat =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->cur_time =	UTIL_Get_MSB_Long(fin);
  qt_mvhdr->nxt_tk_id =	UTIL_Get_MSB_Long(fin);

  if (qt_mvhdr->timescale) qt_mv_timescale = qt_mvhdr->timescale;
  else qt_mv_timescale = 1000;
  qt_timescale = qt_mv_timescale;
  
  DEBUG_LEVEL2
  {
    fprintf(stderr,"mv   ver = %lx  timescale = %lx  duration = %lx\n",
	qt_mvhdr->version,qt_mvhdr->timescale, qt_mvhdr->duration);
    fprintf(stderr,"     rate = %lx volumne = %lx  nxt_tk = %lx\n",
	qt_mvhdr->rate,qt_mvhdr->volume,qt_mvhdr->nxt_tk_id);
  }
}

void QT_Read_TKHD(fin,qt_tkhdr)
FILE *fin;
QT_TKHDR *qt_tkhdr;
{
  ULONG i,j;

  qt_tkhdr->version =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->creation =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->modtime =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->trackid =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->timescale =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->duration =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->time_off =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->priority  =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->layer  =	UTIL_Get_MSB_UShort(fin);
  qt_tkhdr->alt_group = UTIL_Get_MSB_UShort(fin);
  qt_tkhdr->volume  =	UTIL_Get_MSB_UShort(fin);
  for(i=0;i<3;i++) for(j=0;j<3;j++) 
			qt_tkhdr->matrix[i][j]=UTIL_Get_MSB_Long(fin);
  qt_tkhdr->tk_width =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->tk_height =	UTIL_Get_MSB_Long(fin);
  qt_tkhdr->pad  =	UTIL_Get_MSB_UShort(fin);

  if (qt_tkhdr->timescale) qt_tk_timescale = qt_tkhdr->timescale;
  else qt_tk_timescale = qt_mv_timescale;

  DEBUG_LEVEL2
  {
    fprintf(stderr,"tk   ver = %lx  tk_id = %lx  timescale = %lx\n",
	qt_tkhdr->version,qt_tkhdr->trackid,qt_tkhdr->timescale);
    fprintf(stderr,"     dur= %lx timoff= %lx tk_width= %lx  tk_height= %lx\n",
	qt_tkhdr->duration,qt_tkhdr->time_off,qt_tkhdr->tk_width,qt_tkhdr->tk_height);
  }
}


void QT_Read_ELST(fin)
FILE *fin;
{
 ULONG num,version;

 if (qts_samp_num==0) qts_init_duration = 0;
 version = UTIL_Get_MSB_Long(fin);
 num = UTIL_Get_MSB_Long(fin);
 DEBUG_LEVEL2 fprintf(stderr,"    ELST ver %lx num %lx\n",version,num);
 while(num--)
 {
   ULONG duration,time,rate,pad;
   duration = UTIL_Get_MSB_Long(fin); 
   time = UTIL_Get_MSB_Long(fin); 
   rate = UTIL_Get_MSB_UShort(fin); 
   pad  = UTIL_Get_MSB_UShort(fin); 
   /* if 1st audio doesn't start at time 0 */
   /* NOTE: this still won't work if there's a middle trak with no audio */
   if ((qts_samp_num==0) && (time == 0xffffffff)) qts_init_duration += duration;

   DEBUG_LEVEL2 fprintf(stderr,"    -) dur %lx tim %lx rate %lx\n",
		duration,time,rate);
 }
}

void QT_Read_MDHD(fin,qt_mdhdr)
FILE *fin;
QT_MDHDR *qt_mdhdr;
{
  qt_mdhdr->version =	UTIL_Get_MSB_Long(fin);
  qt_mdhdr->creation =	UTIL_Get_MSB_Long(fin);
  qt_mdhdr->modtime =	UTIL_Get_MSB_Long(fin);
  qt_mdhdr->timescale =	UTIL_Get_MSB_Long(fin);
  qt_mdhdr->duration =	UTIL_Get_MSB_Long(fin);
  qt_mdhdr->language =	UTIL_Get_MSB_UShort(fin);
  qt_mdhdr->quality =	UTIL_Get_MSB_UShort(fin);

  if (qt_mdhdr->timescale) qt_md_timescale = qt_mdhdr->timescale;
  else qt_md_timescale = qt_tk_timescale;

  DEBUG_LEVEL2
  {
    fprintf(stderr,"md   ver = %lx  timescale = %lx  duration = %lx\n",
	qt_mdhdr->version,qt_mdhdr->timescale,qt_mdhdr->duration);
    fprintf(stderr,"     lang= %lx quality= %lx\n", 
	qt_mdhdr->language,qt_mdhdr->quality);
  }
}


void QT_Read_HDLR(fin,len,qt_hdlr_hdr)
FILE *fin;
LONG len;
QT_HDLR_HDR *qt_hdlr_hdr;
{
  qt_hdlr_hdr->version =	UTIL_Get_MSB_Long(fin);
  qt_hdlr_hdr->type =	UTIL_Get_MSB_Long(fin);
  qt_hdlr_hdr->subtype =	UTIL_Get_MSB_Long(fin);
  qt_hdlr_hdr->vendor =	UTIL_Get_MSB_Long(fin);
  qt_hdlr_hdr->flags =	UTIL_Get_MSB_Long(fin);
  qt_hdlr_hdr->mask =	UTIL_Get_MSB_Long(fin);

  DEBUG_LEVEL2
  {
    fprintf(stderr,"     ver = %lx  ",qt_hdlr_hdr->version);
    QT_Print_ID(stderr,qt_hdlr_hdr->type,1);
    QT_Print_ID(stderr,qt_hdlr_hdr->subtype,1);
    QT_Print_ID(stderr,qt_hdlr_hdr->vendor,0);
    fprintf(stderr,"\n     flags= %lx mask= %lx\n",
	qt_hdlr_hdr->flags,qt_hdlr_hdr->mask);
  }
  /* Read Handler Name if Present */
  if (len > 32)
  {
    len -= 32;
    QT_Read_Name(fin,len);
  }
}


/*********************************************
 * Read and Parse Video Codecs
 *
 **********/
void QT_Read_Video_STSD(fin)
FILE *fin;
{ ULONG i,version,num,cur,sup;
  version = UTIL_Get_MSB_Long(fin);
  num = UTIL_Get_MSB_Long(fin);
  DEBUG_LEVEL2 fprintf(stderr,"     ver = %lx  num = %lx\n", version,num);
  if (qtv_codecs == 0)
  { qtv_codec_num = num;
    qtv_codecs = (QTV_CODEC_HDR *)malloc(qtv_codec_num * sizeof(QTV_CODEC_HDR));
    if (qtv_codecs==0) TheEnd1("QT STSD: malloc err");
    cur = 0;
  }
  else
  { QTV_CODEC_HDR *tcodecs;
    tcodecs = (QTV_CODEC_HDR *)malloc((qtv_codec_num+num) * sizeof(QTV_CODEC_HDR));
    if (tcodecs==0) TheEnd1("QT STSD: malloc err");
    for(i=0;i<qtv_codec_num;i++) tcodecs[i] = qtv_codecs[i];
    cur = qtv_codec_num;
    qtv_codec_num += num;
    free(qtv_codecs);
    qtv_codecs = tcodecs;
  }
  sup = 0;
  for(i=0; i < num; i++)
  {
    sup |= QT_Read_Video_Codec_HDR( &qtv_codecs[cur], fin ); 
    cur++;
  }
  /*POD NOTE: eventually make flag this back and return 0 */
  if (sup == 0) TheEnd1("    QT codecs not supported - exiting.");
  qt_video_flag = 1; 
  if ( (qt_pic==0) && (xa_buffer_flag == TRUE))
  {
    qt_pic_size = qt_max_imagex * qt_max_imagey;
    if ( (cmap_true_map_flag == TRUE) && (qt_depth > 8) )
		qt_pic = (UBYTE *) malloc(3 * qt_pic_size);
    else	qt_pic = (UBYTE *) malloc( XA_PIC_SIZE(qt_pic_size) );
    if (qt_pic == 0) TheEnd1("QT_Buffer_Action: malloc failed");
  }
}


ULONG QT_Read_Video_Codec_HDR(c_hdr,fin)
QTV_CODEC_HDR *c_hdr;
FILE *fin;
{
  ULONG id;
  LONG len,i;
  ULONG unk_0,unk_1,unk_2,unk_3,unk_4,unk_5,unk_6,unk_7,flag;
  ULONG vendor,temp_qual,spat_qual,h_res,v_res;
  
  c_hdr->compression = 0;  /* used as support flag later */
  len		= UTIL_Get_MSB_Long(fin);
  id 		= UTIL_Get_MSB_Long(fin);
  unk_0		= UTIL_Get_MSB_Long(fin);
  unk_1		= UTIL_Get_MSB_Long(fin);
  unk_2		= UTIL_Get_MSB_UShort(fin);
  unk_3		= UTIL_Get_MSB_UShort(fin);
  vendor	= UTIL_Get_MSB_Long(fin);
  temp_qual	= UTIL_Get_MSB_Long(fin);
  spat_qual	= UTIL_Get_MSB_Long(fin);
  qt_imagex	= UTIL_Get_MSB_UShort(fin);
  qt_imagey	= UTIL_Get_MSB_UShort(fin);
  h_res		= UTIL_Get_MSB_UShort(fin);
  unk_4		= UTIL_Get_MSB_UShort(fin);
  v_res		= UTIL_Get_MSB_UShort(fin);
  unk_5		= UTIL_Get_MSB_UShort(fin);
  unk_6		= UTIL_Get_MSB_Long(fin);
  unk_7		= UTIL_Get_MSB_UShort(fin);
  QT_Read_Name(fin,32);
  qt_depth	= UTIL_Get_MSB_UShort(fin);
  flag		= UTIL_Get_MSB_UShort(fin);
  len -= 0x56;

  if (qt_depth == 8) /* generate colormap */
  {
    qt_imagec = 256;
    QT_Create_Default_Cmap(qt_cmap);
    if (!(flag & 0x08)) /* colormap isn't default */
    {
      ULONG start,end,p,r,g,b;
      start = UTIL_Get_MSB_Long(fin); /* is this start or something else? */
      end   = UTIL_Get_MSB_Long(fin); /* is this end or total number? */
      len -= 8;
      for(i = start; i <= end; i++)
      {
        p = UTIL_Get_MSB_UShort(fin); 
        r = UTIL_Get_MSB_UShort(fin); 
        g = UTIL_Get_MSB_UShort(fin); 
        b = UTIL_Get_MSB_UShort(fin);  len -= 8;
        if (p<qt_imagec)
        {
	  qt_cmap[p].red   = r;
	  qt_cmap[p].green = g;
	  qt_cmap[p].blue  = b;
        }
        if (len <= 0) break;
      }
    } 
  }

  while(len > 0) {fgetc(fin); len--; }

  if (xa_verbose) fprintf(stderr,"    Size %ldx%ld  Codec ",
						qt_imagex,qt_imagey);
  switch(id)
  {
    case QT_rle:
	if (xa_verbose) fprintf(stderr,"RLE depth %ld\n",qt_depth);
	if (qt_depth == 8)
	{
	  qt_compression = QT_CODEC_RLE;
	  qt_imagex = 4 * ((qt_imagex + 3)/4);
	}
	else if (qt_depth == 16) qt_compression = QT_CODEC_RLE16;
	else if (qt_depth == 24) qt_compression = QT_CODEC_RLE24;
	else if ( (qt_depth == 33) || (qt_depth == 1) )
	{
	  qt_compression = QT_CODEC_RLE33;
	  qt_imagex = 16 * ((qt_imagex + 15)/16);
	  qt_depth = 1;
	}
	else { fprintf(stderr,"      unsupported\n"); return(0); }
	break;
    case QT_smc:
	if (xa_verbose) fprintf(stderr,"SMC depth %ld\n",qt_depth);
	if (qt_depth == 8)
	{
	  qt_compression = QT_CODEC_SMC;
	  qt_imagex = 4 * ((qt_imagex + 3)/4);
	  qt_imagey = 4 * ((qt_imagey + 3)/4);
	}
	else { fprintf(stderr,"      unsupported\n"); return(0); }
	break;
    case QT_raw:
	if (xa_verbose) fprintf(stderr,"RAW depth %ld\n",qt_depth);
	if (qt_depth == 8) qt_compression = QT_CODEC_RAW;
	else { fprintf(stderr,"      unsupported\n"); return(0); }
	break;
    case QT_rpza:
	if (xa_verbose) fprintf(stderr,"RPZA depth %ld\n",qt_depth);
	if (qt_depth == 16)
	{
	  qt_compression = QT_CODEC_RPZA;
	  qt_imagex = 4 * ((qt_imagex + 3)/4);
	  qt_imagey = 4 * ((qt_imagey + 3)/4);
	}
	else { fprintf(stderr,"      unsupported\n"); return(0); }
	break;
    case QT_cvid:
	if (xa_verbose) fprintf(stderr,"CVID depth %ld\n",qt_depth);
	if ((qt_depth == 24) || (qt_depth == 32) )
	{
	  QT_Gen_YUV_Tabs();
	  qt_compression = QT_CODEC_CVID;
	  qt_imagex = 4 * ((qt_imagex + 3)/4);
	  qt_imagey = 4 * ((qt_imagey + 3)/4);
	}
	else { fprintf(stderr,"      unsupported\n"); return(0); }
	break;
    case QT_jpeg:
       fprintf(stderr,"JPEG unsupported\n",id); return(0); break;
    case QT_SPIG:
	if (xa_verbose) fprintf(stderr,"SPIG depth %ld\n",qt_depth);
	goto QT_UNSUPPORTED;
/*
	QT_Gen_YUV_Tabs();
	qt_compression = QT_CODEC_SPIG;
	qt_imagex = 2 * ((qt_imagex + 1)/2);
	qt_imagey = 2 * ((qt_imagey + 1)/2);
*/
	break;
    case QT_yuv2:
	if (xa_verbose) fprintf(stderr,"YUV2 depth %ld\n",qt_depth);
	QT_Gen_YUV_Tabs();
	qt_compression = QT_CODEC_YUV2;
	qt_imagex = 2 * ((qt_imagex + 1)/2);
	qt_imagey = 2 * ((qt_imagey + 1)/2);
	break;
    default:
	QT_UNSUPPORTED:
	fprintf(stderr,"%08lx unknown\n",id);
	return(0);
	break;
  }
 
  if (qt_depth == 1)
  {
    qt_imagec = 2;
    qt_cmap[0].red = qt_cmap[0].green = qt_cmap[0].blue = 0; 
    qt_cmap[1].red = qt_cmap[1].green = qt_cmap[1].blue = 0xff; 
    qt_chdr = ACT_Get_CMAP(qt_cmap,qt_imagec,0,qt_imagec,0,8,8,8);
  }
  else if (qt_depth == 8)
  {
    qt_chdr = ACT_Get_CMAP(qt_cmap,qt_imagec,0,qt_imagec,0,16,16,16);
  }
  else if (qt_depth >= 16)
  {
    if (   (cmap_true_map_flag == FALSE) /* depth 16 and not true_map */
           || (xa_buffer_flag == FALSE) )
    {
      if (cmap_true_to_332 == TRUE)
		qt_chdr = CMAP_Create_332(qt_cmap,&qt_imagec);
      else	qt_chdr = CMAP_Create_Gray(qt_cmap,&qt_imagec);
    }
    else { qt_imagec = 0; qt_chdr = 0; }
  }
  c_hdr->width	= qt_imagex;
  c_hdr->height	= qt_imagey;
  c_hdr->depth	= qt_depth;
  c_hdr->compression = qt_compression;
  c_hdr->chdr	= qt_chdr;
  if (qt_imagex > qt_max_imagex) qt_max_imagex = qt_imagex;
  if (qt_imagey > qt_max_imagey) qt_max_imagey = qt_imagey;
  return(1);
}

void QT_Read_Name(fin,r_len)
FILE *fin;
LONG r_len;
{
  ULONG len,d,i;

  len = fgetc(fin); r_len--;
  if (r_len == 0) r_len = len;
  if (len > r_len) fprintf(stderr,"QT_Name: len(%ld) > r_len(%ld)\n",len,r_len);
  DEBUG_LEVEL2 fprintf(stderr,"      (%ld/%ld) ",len,r_len);
  for(i=0;i<r_len;i++)
  {
    d = fgetc(fin);
    if (i < len) DEBUG_LEVEL2 fputc(d,stderr);
  }
  DEBUG_LEVEL2 fputc('\n',stderr);
}

/* Time To Sample */
void QT_Read_STTS(fin,len,qt_t2samp_num,qt_t2samps)
FILE *fin;
LONG len;
ULONG *qt_t2samp_num;
QT_T2SAMP_HDR **qt_t2samps;
{
  ULONG version,num,i,samp_cnt,duration,cur; 
  ULONG t2samp_num = *qt_t2samp_num;
  QT_T2SAMP_HDR *t2samps = *qt_t2samps;

  version	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin);  len -= 8;
  DEBUG_LEVEL2 fprintf(stderr,"    ver=%lx num of entries = %lx\n",version,num);
/* POD TEST chunk len/num mismatch - deal with it - ignore given num??*/
  num = len >> 3;
  if (t2samps==0)
  {
    t2samp_num = num;
    t2samps = (QT_T2SAMP_HDR *)malloc(num * sizeof(QT_T2SAMP_HDR));
    if (t2samps==0) TheEnd1("QT_Read_STTS: malloc err");
    cur = 0;
  }
  else
  { QT_T2SAMP_HDR *t_t2samp;
    t_t2samp = (QT_T2SAMP_HDR *)
			malloc((t2samp_num + num) * sizeof(QT_T2SAMP_HDR));
    if (t_t2samp==0) TheEnd1("QT_Read_STTS: malloc err");
    for(i=0;i<t2samp_num;i++) t_t2samp[i] = t2samps[i];
    cur = t2samp_num;
    t2samp_num += num;
    free(t2samps);
    t2samps = t_t2samp;
  }
  for(i=0;i<num;i++)
  { double ftime;
    samp_cnt	= UTIL_Get_MSB_Long(fin);
    duration	= UTIL_Get_MSB_Long(fin);  len -= 8;
    if (duration == 0) duration = 1;
    /* NOTE: convert to 1000ms per second */
    t2samps[cur].cnt = samp_cnt;
    ftime = (1000.0 * (double)(duration)) / (double)(qt_timescale);
    t2samps[cur].time = (ULONG)(ftime);
    ftime -= (double)(t2samps[cur].time);
    t2samps[cur].timelo = (ULONG)(ftime * (double)(1<<24));
    DEBUG_LEVEL2 fprintf(stderr,"      %ld) samp_cnt=%lx duration = %lx time %ld timelo %ld ftime %lf\n",
	i,samp_cnt,duration,t2samps[cur].time,t2samps[cur].timelo,ftime);
    cur++;
  }
  *qt_t2samp_num = t2samp_num;
  *qt_t2samps = t2samps;
  while(len > 0) {len--; getc(fin); }
}


/* Sync Sample */
void QT_Read_STSS(fin)
FILE *fin;
{
  ULONG version,num,i,j;
  version	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin);
  DEBUG_LEVEL2 
  {
    fprintf(stderr,"    ver=%lx num of entries = %lx\n",version,num);
    j = 0;
    fprintf(stderr,"      ");
  }
  for(i=0;i<num;i++)
  {
    ULONG samp_num;
    samp_num	= UTIL_Get_MSB_Long(fin);
    DEBUG_LEVEL2
    {
      fprintf(stderr,"%lx ",samp_num); j++;
      if (j >= 8) {fprintf(stderr,"\n      "); j=0; }
    }
  }
  DEBUG_LEVEL2 fprintf(stderr,"\n");
}


/* Sample to Chunk */
void QT_Read_STSC(fin,len,qt_s2chunk_num,qt_s2chunks,
		chunkoff_lstnum,codec_num,codec_lstnum)
FILE *fin;
LONG len;
ULONG *qt_s2chunk_num;
QT_S2CHUNK_HDR **qt_s2chunks;
ULONG chunkoff_lstnum,codec_num,codec_lstnum;
{
  ULONG version,num,i,cur,stsc_type,last;
  ULONG s2chunk_num = *qt_s2chunk_num;
  QT_S2CHUNK_HDR *s2chunks = *qt_s2chunks;

  version	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin);	len -= 16;
  i = (num)?(len/num):(0);
  if (i == 16) 
  { 
    DEBUG_LEVEL2 fprintf(stderr,"STSC: OLD STYLE\n");
    len -= num * 16; stsc_type = 0;
  }
  else 
  { 
    DEBUG_LEVEL2 fprintf(stderr,"STSC: NEW STYLE\n");
    len -= num * 12; stsc_type = 1;
  }

  DEBUG_LEVEL2 fprintf(stderr,"    ver=%lx num of entries = %lx\n",version,num);
  if (s2chunks == 0)
  {
    s2chunk_num = num;
    s2chunks = (QT_S2CHUNK_HDR *)malloc((num+1) * sizeof(QT_S2CHUNK_HDR));
    cur = 0;
  }
  else
  { QT_S2CHUNK_HDR *ts2c;
    ts2c = (QT_S2CHUNK_HDR *)
	malloc( (s2chunk_num + num + 1) * sizeof(QT_S2CHUNK_HDR));
    for(i=0;i<s2chunk_num;i++) ts2c[i] = s2chunks[i];
    cur = s2chunk_num;
    s2chunk_num += num;
    free(s2chunks);
    s2chunks = ts2c;
  }
  last = 0;
  for(i=0;i<num;i++)
  {
    ULONG first_chk,samp_per,chunk_tag;
    if (stsc_type == 0)  /* 4 entries */
    { ULONG tmp;
      first_chk	= UTIL_Get_MSB_Long(fin);
      tmp	= UTIL_Get_MSB_Long(fin);
      samp_per	= UTIL_Get_MSB_Long(fin);
      chunk_tag	= UTIL_Get_MSB_Long(fin);
      if (i > 0) s2chunks[cur-1].num   = first_chk - last;
      last = first_chk;
      if (i==(num-1))
      {
	if (qt_stgs_num)
	{
	  s2chunks[cur].num   = (qt_stgs_num - first_chk) + 1;
	  qt_stgs_num = 0;
        }
	else 
	{
	  fprintf(stderr,"STSC: old style but not stgs chunk warning\n");
	  s2chunks[cur].num = 100000;
	}
      }
    }
    else		/* 3 entries */
    {
      first_chk	= UTIL_Get_MSB_Long(fin);
      samp_per	= UTIL_Get_MSB_Long(fin);
      chunk_tag	= UTIL_Get_MSB_Long(fin);
      s2chunks[cur].num   = samp_per;
    }
    DEBUG_LEVEL2 
     fprintf(stderr,"      %ld-%ld) first_chunk=%lx samp_per_chk=%lx chk_tag=%lx\n",
					i,cur,first_chk,samp_per,chunk_tag);
        /* start at 0 not 1  and account for previous chunks */
    s2chunks[cur].first = first_chk - 1 + chunkoff_lstnum;
    if (chunk_tag > (codec_num - codec_lstnum)) 
	{ samp_per = chunk_tag = 1; }
    s2chunks[cur].tag   = chunk_tag - 1 + codec_lstnum;
    cur++;
  }
  s2chunks[cur].first = 0;
  s2chunks[cur].num   = 0;
  s2chunks[cur].tag   = 0;
  DEBUG_LEVEL2 fprintf(stderr,"    STSC left over %ld\n",len);
  while (len > 0) { fgetc(fin); len--; }
  *qt_s2chunk_num = s2chunk_num;
  *qt_s2chunks = s2chunks;
}

/* Sample Size */
void QT_Read_STSZ(fin,len,qt_samp_num,qt_samp_sizes)
FILE *fin;
LONG len;
ULONG *qt_samp_num,**qt_samp_sizes;
{
  ULONG version,samp_size,num,i,cur;
  ULONG samp_num   = *qt_samp_num;
  ULONG *samp_sizes = *qt_samp_sizes;

  version	= UTIL_Get_MSB_Long(fin);
  samp_size	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin);
  len = (len - 20) / 4;   /* number of stored samples */
  DEBUG_LEVEL2 fprintf(stderr,"    ver=%lx samp_size=%lx entries= %lx stored entries=%lx\n",version,samp_size,num,len);

  if (samp_size == 1) num = 1; /* for AUDIO PODNOTE: rethink this */
  if (samp_sizes == 0)
  {
    samp_num = num;
    samp_sizes = (ULONG *)malloc(num * sizeof(ULONG));
    if (samp_sizes == 0) {fprintf(stderr,"malloc err 0\n"); exit(0);}
    cur = 0;
  }
  else /*TRAK*/
  {
    ULONG *tsamps;
    tsamps = (ULONG *)malloc((samp_num + num) * sizeof(ULONG));
    if (tsamps == 0) {fprintf(stderr,"malloc err 0\n"); exit(0);}
    for(i=0; i<samp_num; i++) tsamps[i] = samp_sizes[i];
    cur = samp_num;
    samp_num += num;
    free(samp_sizes);
    samp_sizes = tsamps;
  }
  for(i=0;i<num;i++) 
  {
    if (i < len) samp_sizes[cur] = UTIL_Get_MSB_Long(fin);
    else if (i==0) samp_sizes[cur] = samp_size;
           else samp_sizes[cur] = samp_sizes[cur-1];
    cur++;
  }
  *qt_samp_num = samp_num;
  *qt_samp_sizes = samp_sizes;
}

/* Chunk Offset */
void QT_Read_STCO(fin,qt_chunkoff_num,qt_chunkoffs)
FILE *fin;
ULONG *qt_chunkoff_num;
ULONG **qt_chunkoffs;
{
  ULONG version,num,i,cur;
  ULONG chunkoff_num = *qt_chunkoff_num;
  ULONG *chunkoffs = *qt_chunkoffs;

  version	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin);
  DEBUG_LEVEL2 fprintf(stderr,"    ver=%lx entries= %lx\n",version,num);
  if (chunkoffs == 0)
  {
    chunkoff_num = num;
    chunkoffs = (ULONG *)malloc(num * sizeof(ULONG) );
    cur = 0;
  }
  else
  {
    ULONG *tchunks;
    tchunks = (ULONG *)malloc((chunkoff_num + num) * sizeof(ULONG));
    if (tchunks == 0) {fprintf(stderr,"malloc err 0\n"); exit(0);}
    for(i=0; i<chunkoff_num; i++) tchunks[i] = chunkoffs[i];
    cur = chunkoff_num;
    chunkoff_num += num;
    free(chunkoffs);
    chunkoffs = tchunks;
  }
  for(i=0;i<num;i++) {chunkoffs[cur] = UTIL_Get_MSB_Long(fin); cur++; }
  *qt_chunkoff_num = chunkoff_num;
  *qt_chunkoffs = chunkoffs;
}



void QT_Read_Video_Data(fin,anim_hdr)
FILE *fin;
XA_ANIM_HDR *anim_hdr;
{
  ULONG d,ret,base_offset,i;
  ULONG cur_samp,cur_s2chunk,nxt_s2chunk;
  ULONG cur_t2samp,nxt_t2samp;
  ULONG tag;
  ULONG olast;
  ULONG cmap_frame_num;
  XA_ACTION *act;

  if (qtv_samp_sizes == 0) {fprintf(stderr,"no samples\n"); return; } 
  base_offset = 0;

  cmap_frame_num = qtv_chunkoff_num / cmap_sample_cnt;

  nxt_t2samp = cur_t2samp = 0;
  if (qtv_t2samps)
  {
    if (xa_jiffy_flag) { qt_time = xa_jiffy_flag; qt_timelo = 0; }
    else
    { 
      qt_time   = qtv_t2samps[cur_t2samp].time;
      qt_timelo = qtv_t2samps[cur_t2samp].timelo;
    }
    nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
  } else { qt_time = XA_GET_TIME(100); qt_timelo = 0; }

  olast=0;
  cur_samp = 0;
  cur_s2chunk = 0;
  nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
  tag =  qtv_s2chunks[cur_s2chunk].tag;
  qt_imagex = qtv_codecs[tag].width;
  qt_imagey = qtv_codecs[tag].height;
  qt_depth  = qtv_codecs[tag].depth;
  qt_compression  = qtv_codecs[tag].compression;
  qt_chdr   = qtv_codecs[tag].chdr;
  /* KLUDGE FOR Lem_Separation */
/*
  if (qtv_samp_num == qtv_chunkoff_num) nxt_s2chunk = qtv_chunkoff_num + 1;
*/
  /* Loop through chunk offsets */
  for(i=0; i < qtv_chunkoff_num; i++)
  {
    ULONG size,off,num_samps;
    ACT_DLTA_HDR *dlta_hdr;

    off =  base_offset + qtv_chunkoffs[i];
    	/* survive RPZA despite corruption(offsets commonly corrupted).*/
    if (qt_compression == QT_CODEC_RPZA)
    { ULONG check;
      fseek(fin,off,0); check = UTIL_Get_MSB_Long(fin) & 0x00ffffff;
      if (check != qtv_samp_sizes[cur_samp])
      {
        fseek(fin,olast,0); check = UTIL_Get_MSB_Long(fin) & 0x00ffffff;
        if (check == qtv_samp_sizes[cur_samp]) off = olast;
      }
    }
    olast = off;
    fseek(fin,off,0);  /* move to start of chunk data */

DEBUG_LEVEL2 fprintf(stderr,"T2S: cur-t2 %ld cur-smp %ld nxt-t2 %ld tot t2 %ld\n", cur_t2samp,cur_samp,nxt_t2samp,qtv_t2samp_num);
    if ( (cur_samp >= nxt_t2samp) && (cur_t2samp < qtv_t2samp_num) )
    {
      cur_t2samp++;
      if (xa_jiffy_flag) { qt_time = xa_jiffy_flag; qt_timelo = 0; }
      else
      { 
	qt_time   = qtv_t2samps[cur_t2samp].time;
	qt_timelo = qtv_t2samps[cur_t2samp].timelo;
      }
      nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
    }

    if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qtv_s2chunk_num) )
    {
      cur_s2chunk++;
      nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
    }
    num_samps = qtv_s2chunks[cur_s2chunk].num;

    /* Check tags and possibly move to new codec */
    if (qtv_s2chunks[cur_s2chunk].tag >= qtv_codec_num) 
    {
      fprintf(stderr,"QT Data: Warning stsc chunk invalid %ld tag %ld\n",
		cur_s2chunk,qtv_s2chunks[cur_s2chunk].tag);
    } 
    else if (qtv_s2chunks[cur_s2chunk].tag != tag)
    {
      tag =  qtv_s2chunks[cur_s2chunk].tag;
      qt_imagex = qtv_codecs[tag].width;
      qt_imagey = qtv_codecs[tag].height;
      qt_depth  = qtv_codecs[tag].depth;
      qt_compression  = qtv_codecs[tag].compression;
      qt_chdr   = qtv_codecs[tag].chdr;
    }

    /* Read number of samples in each chunk */
    while(num_samps--)
    {
      size = qtv_samp_sizes[cur_samp];
      olast += size;

      /* QT_Codec_List(fin,size);  for decoding only */
      DEBUG_LEVEL2 fprintf(stderr,"CODEC %lx) size = %lx offset = %lx\n",
		i,size,off);
/*
fprintf(stderr,"CODEC %lx %ld) size = %lx offset = %lx samp %ld\n",
		i,cur_samp,size,off,num_samps);
*/

      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("QT rle: malloc failed");
	act->data = (UBYTE *)dlta_hdr;
	dlta_hdr->flags = ACT_SNGL_BUF;
	dlta_hdr->fsize = size;
	dlta_hdr->fpos  = ftell(fin);
	fseek(fin,size,1); /* move past this chunk */
	if (size > qt_max_fsize) qt_max_fsize = size;
      }
      else
      {
	d = size + (sizeof(ACT_DLTA_HDR));
	dlta_hdr = (ACT_DLTA_HDR *) malloc( d );
	if (dlta_hdr == 0) TheEnd1("QT rle: malloc failed");
	act->data = (UBYTE *)dlta_hdr;
	dlta_hdr->flags = ACT_SNGL_BUF | DLTA_DATA;
	dlta_hdr->fpos = 0; dlta_hdr->fsize = size;
	ret = fread( dlta_hdr->data, size, 1, fin);
	if (ret != 1) TheEnd1("QT codec: read failed");
      }

      QT_Add_Frame(qt_time,qt_timelo,act);
      dlta_hdr->xpos = dlta_hdr->ypos = 0;
      dlta_hdr->xsize = qt_imagex;
      dlta_hdr->ysize = qt_imagey;
      dlta_hdr->special = 0;
      dlta_hdr->extra = 0;
      switch(qt_compression)
      {
        case QT_CODEC_SPIG:  dlta_hdr->delta = QT_Decode_SPIG; break;
        case QT_CODEC_YUV2:  dlta_hdr->delta = QT_Decode_YUV2; break;
        case QT_CODEC_RLE:   dlta_hdr->delta = QT_Decode_RLE; break;
        case QT_CODEC_RLE16: dlta_hdr->delta = QT_Decode_RLE16; break;
        case QT_CODEC_RLE24: dlta_hdr->delta = QT_Decode_RLE24; break;
        case QT_CODEC_RLE33: dlta_hdr->delta = QT_Decode_RLE33; break;
        case QT_CODEC_RAW:   dlta_hdr->delta = QT_Decode_RAW; break;
        case QT_CODEC_RPZA:  dlta_hdr->delta = QT_Decode_RPZA; break;
        case QT_CODEC_CVID:  dlta_hdr->delta = QT_Decode_CVID; break;
        case QT_CODEC_SMC:   dlta_hdr->delta = QT_Decode_SMC; break;
        default:
          fprintf(stderr,"QT: unsupported comp ");
          QT_Print_ID(stderr,qt_compression,1); 
	  fprintf(stderr,"depth=%ld\n",qt_depth);
          act->type = ACT_NOP;
          break;
      } /* end of compression types */

      if ( (xa_buffer_flag == TRUE) && (act->type != ACT_NOP) )
      {
	ULONG xpos,ypos,xsize,ysize,dlta_flag;
        if ( (cmap_true_map_flag==FALSE) || (qt_depth <= 8) )
	{
	  ULONG map_flag = (x11_display_type & XA_X11_TRUE)?(TRUE):(FALSE);
	  dlta_flag = dlta_hdr->delta(qt_pic,dlta_hdr->data,dlta_hdr->fsize,
		0,qt_chdr->map,map_flag, qt_imagex,qt_imagey,8,
		&xpos,&ypos,&xsize,&ysize,0,0);
	  if (!(dlta_flag & ACT_DLTA_MAPD)) map_flag = FALSE;
	  xsize -= xpos; ysize -= ypos;
	  FREE(dlta_hdr,0x9001); act->data = 0; dlta_hdr = 0;
	  if (dlta_flag & ACT_DLTA_NOP) act->type = ACT_NOP;
	  else ACT_Setup_Mapped(act,qt_pic,qt_chdr,xpos,ypos,xsize,ysize,
		qt_imagex,qt_imagey,FALSE,0, FALSE,TRUE,map_flag);
          ACT_Add_CHDR_To_Action(act,qt_chdr);
	}
	else /* decode as RGB triplets and then convert to mapped image */
	{
          UBYTE *tpic;
	  dlta_flag = dlta_hdr->delta(qt_pic,dlta_hdr->data,dlta_hdr->fsize,
		0,0,FALSE,qt_imagex,qt_imagey,8,&xpos,&ypos,&xsize,&ysize,1,0);
/*POD NOTE: need to add subimage support to RGB conversion utils */
	  FREE(dlta_hdr,0x9002); act->data = 0; dlta_hdr = 0;
	  if (dlta_flag & ACT_DLTA_NOP) act->type = ACT_NOP;
	  else
	  {
	    xpos = ypos = 0; xsize = qt_imagex; ysize = qt_imagey;
	    /* xsize -= xpos; ysize -= ypos; */
	    if (    (cmap_true_to_all == TRUE)
	        || ((cmap_true_to_1st == TRUE) && (qt_chdr == 0) )
	       )	qt_chdr = CMAP_Create_CHDR_From_True(qt_pic,8,8,8,
				qt_imagex,qt_imagey,qt_cmap,&qt_imagec);
	    else if ( (cmap_true_to_332 == TRUE) && (qt_chdr == 0) )
			qt_chdr = CMAP_Create_332(qt_cmap,&qt_imagec);
	    else if ( (cmap_true_to_gray == TRUE) && (qt_chdr == 0) )
			qt_chdr = CMAP_Create_Gray(qt_cmap,&qt_imagec);

	    if (cmap_dither_type == CMAP_DITHER_FLOYD)
		tpic = UTIL_RGB_To_FS_Map(0,qt_pic,qt_chdr,
					qt_imagex,qt_imagey,FALSE);
	    else
		tpic = UTIL_RGB_To_Map(0,qt_pic,qt_chdr,
					qt_imagex,qt_imagey,FALSE);
	    ACT_Setup_Mapped(act,tpic,qt_chdr,xpos,ypos,xsize,ysize,
		qt_imagex,qt_imagey,FALSE,0,TRUE,TRUE,FALSE);
            ACT_Add_CHDR_To_Action(act,qt_chdr);
	  } /* end of not NOP */
	} /* end of true_map */
      } /* end of buffer */
      else  /* not buffered */
      {
        /* Also make sure not TRUE, is 332 and special case file_flag */
        if ( (cmap_color_func != 0)
            && (qt_depth > 8) && (!(x11_display_type & XA_X11_TRUE)) )
        { 
        if (qt_cmap_flag == 0)
        {
	  ULONG xpos,ypos,xsize,ysize,dlta_flag,psize;
	  UBYTE *cbuf,*data;

	  psize = qt_imagex * qt_imagey;
	  cbuf = (UBYTE *) malloc(3 * psize);
          if (cbuf == 0) TheEnd1("colorfunc1 malloc err0\n");
	  memset((char *)(cbuf),0x00,(3 * psize) );

	  if (xa_file_flag == TRUE)
	  { ULONG pos;
	    data = (UBYTE *)malloc(dlta_hdr->fsize);
	    if (data==0) TheEnd1("colorfunc1 malloc err1\n");
	    pos = ftell(fin); 
	    fseek(fin,dlta_hdr->fpos,0); /* save file pos */
	    fread(data,dlta_hdr->fsize,1,fin); /* read data*/
	    fseek(fin,pos,0); /* restore file pos */
	  } else data = dlta_hdr->data;
          dlta_flag = dlta_hdr->delta(cbuf,data,dlta_hdr->fsize,
                0,0,FALSE,qt_imagex,qt_imagey,8,&xpos,&ypos,&xsize,&ysize,1,0);
	  if (xa_file_flag == TRUE) { free(data); data = 0; }

	 switch(cmap_color_func)
	 {
	  case 4:
	  {
            qt_chdr = CMAP_Create_CHDR_From_True(cbuf,8,8,8,
                              qt_imagex,qt_imagey,qt_cmap,&qt_imagec);
            DEBUG_LEVEL1 fprintf(stderr,"CF4: csize = %ld\n",qt_chdr->csize);
            if (qt_chdr->csize > 128) qt_cmap_flag = 1;
            if (cbuf) free(cbuf); cbuf = 0;
	  }
	  break;
         } /* end of switch */
        } /* first time through */
        else  /* else cnt til next time */
        {
          qt_cmap_cnt++;
          if (cmap_sample_cnt && (qt_cmap_cnt >= cmap_frame_num))
			{ qt_cmap_flag = 0; qt_cmap_cnt = 0; }
        }
        } /* color func, true color anim and not True Display  */
        ACT_Add_CHDR_To_Action(act,qt_chdr);
      }
      cur_samp++;
      if (cur_samp >= qtv_samp_num) break;
    } /* end of sample number */
    if (cur_samp >= qtv_samp_num) break;
  } /* end of chunk_offset loop */
}


ULONG
QT_Decode_RLE(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG y,lines,d; /* LONG min_x,max_x,min_y,max_y;  */
  UBYTE *dptr;

  dptr = delta;
  dptr += 4;    /* skip codec size */
  d = (*dptr++) << 8;  d |= *dptr++;   /* read code either 0008 or 0000 */
  if (d == 0x0000) /* NOP frame? */
  { /* There is one more byte 0x00 that I don't read in this case */
    *xs = *ys = *xe = *ye = 0;
    return(ACT_DLTA_NOP);
  }
  y = (*dptr++) << 8; y |= *dptr++;		/* start line */
  dptr += 2;					/* unknown */
  lines = (*dptr++) << 8; lines |= *dptr++;	/* number of lines */
  dptr += 2;					/* unknown */
  while(lines--)
  {
    ULONG xskip,cnt;
    xskip = *dptr++;				/* skip x pixels */
    cnt = *dptr++;				/* RLE code */
    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
    { UBYTE *iptr = (UBYTE *)(image + (y * imagex) + (4 * (xskip-1)) );
      while(cnt != 0xff)
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += 4 * (xskip-1); }
        else if (cnt < 0x80)			/* run of data */
        {
          cnt *= 4; if (map_flag==FALSE) while(cnt--) *iptr++ = (UBYTE)*dptr++;
          else while(cnt--) *iptr++ = (UBYTE)map[*dptr++];
        } else					/* repeat data */
        { UBYTE d1,d2,d3,d4;	cnt = 0x100 - cnt;
          if (map_flag==TRUE) { d1=(UBYTE)map[*dptr++]; d2=(UBYTE)map[*dptr++];
			      d3=(UBYTE)map[*dptr++]; d4=(UBYTE)map[*dptr++]; }
	  else	{ d1 = (UBYTE)*dptr++; d2 = (UBYTE)*dptr++;
		  d3 = (UBYTE)*dptr++; d4 = (UBYTE)*dptr++; }
          while(cnt--) { *iptr++ =d1; *iptr++ =d2; *iptr++ =d3; *iptr++ =d4; }
        } /* end of  >= 0x80 */
        cnt = *dptr++;
      } /* end while cnt */
    } else if (x11_bytes_pixel==2)
    { USHORT *iptr = (USHORT *)(image + 2 *((y * imagex) + (4 * (xskip-1))) );
      while(cnt != 0xff)
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += 4 * (xskip-1); }
        else if (cnt < 0x80)			/* run of data */
        {
          cnt *= 4; while(cnt--) *iptr++ = (USHORT)map[*dptr++];
        } else					/* repeat data */
        { USHORT d1,d2,d3,d4;	cnt = 0x100 - cnt;
	  { d1 = (USHORT)map[*dptr++]; d2 = (USHORT)map[*dptr++];
	    d3 = (USHORT)map[*dptr++]; d4 = (USHORT)map[*dptr++]; }
          while(cnt--) { *iptr++ =d1; *iptr++ =d2; *iptr++ =d3; *iptr++ =d4; }
        } /* end of  >= 0x80 */
        cnt = *dptr++;
      } /* end while cnt */
    } else /* bytes == 4 */
    { ULONG *iptr = (ULONG *)(image + 4 * ((y * imagex) + (4 * (xskip-1))) );
      while(cnt != 0xff)
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += 4 * (xskip-1); }
        else if (cnt < 0x80)			/* run of data */
        {
          cnt *= 4; while(cnt--) *iptr++ = (ULONG)map[*dptr++];
        } else					/* repeat data */
        { ULONG d1,d2,d3,d4; cnt = 0x100 - cnt;
	  { d1 = (ULONG)map[*dptr++]; d2 = (ULONG)map[*dptr++]; 
	    d3 = (ULONG)map[*dptr++]; d4 = (ULONG)map[*dptr++]; }
          while(cnt--) { *iptr++ =d1; *iptr++ =d2; *iptr++ =d3; *iptr++ =d4; }
        } /* end of  >= 0x80 */
        cnt = *dptr++;
      } /* end while cnt */
    }
    y++;
  } /* end of lines */
 /* one more zero byte */
 *xs = *ys = 0; *xe = imagex; *ye = imagey;
 if (map_flag==TRUE) return(ACT_DLTA_MAPD);
 else return(ACT_DLTA_NORM);
}

ULONG QT_Parse_Bin(fin)
FILE *fin;
{
  ULONG pos,len,csize,cid,total;
 
  fseek(fin,0,2);
  total = ftell(fin);
 
/* Read over Header */
  fseek(fin,0,0);
  pos = len = UTIL_Get_MSB_Long(fin);
  cid = UTIL_Get_MSB_Long(fin);
  if (cid == QT_mdat)
  {
    fseek(fin,0,0);
    if (len == 0)
    {
      fprintf(stderr,"QT: This is only .data fork. Need .rsrc fork\n");
      return(0);
    }
    else return(1);
  }
 
DEBUG_LEVEL1 fprintf(stderr,"QT_Parse_Bin: %lx\n",pos);
 
  while( pos < total )
  {
    fseek(fin,pos,0);
 
    len = UTIL_Get_MSB_Long(fin);
    pos += 4;        /* binary size is 4 bytes */
    csize = UTIL_Get_MSB_Long(fin);
    cid   = UTIL_Get_MSB_Long(fin);
    if (cid == QT_moov)
    {
      fseek(fin,pos,0);
      return(1);
    }
    if (len == 0) return(0);
    pos += len;
  }
  return(0);
}

#define QT_BLOCK_INC(x,y,imagex) { x += 4; if (x>=imagex) { x=0; y += 4; }}

#define QT_MIN_MAX_CHECK(x,y,min_x,min_y,max_x,max_y) {	\
  if (x > max_x) max_x=x; if (y > max_y) max_y=y;	\
  if (x < min_x) min_x=x; if (y < min_y) min_y=y;  }

#define QT_RPZA_C1(ip,c,CAST,rinc) { \
 *ip++=(CAST)c; *ip++ =(CAST)c; *ip++ =(CAST)c; *ip = (CAST)c; ip +=rinc; \
 *ip++=(CAST)c; *ip++ =(CAST)c; *ip++ =(CAST)c; *ip = (CAST)c; ip +=rinc; \
 *ip++=(CAST)c; *ip++ =(CAST)c; *ip++ =(CAST)c; *ip = (CAST)c; ip +=rinc; \
 *ip++=(CAST)c; *ip++ =(CAST)c; *ip++ =(CAST)c; *ip = (CAST)c; }

#define QT_RPZA_C4(ip,c,mask,CAST); { \
 *ip++ =(CAST)(c[((mask>>6)&0x03)]); *ip++ =(CAST)(c[((mask>>4)&0x03)]); \
 *ip++ =(CAST)(c[((mask>>2)&0x03)]); *ip   =(CAST)(c[ (mask & 0x03)]); }

#define QT_RPZA_C16(ip,c,CAST,rinc) { \
 *ip++=(CAST)(*c++); *ip++=(CAST)(*c++); \
 *ip++=(CAST)(*c++); *ip  =(CAST)(*c++); ip +=rinc; \
 *ip++=(CAST)(*c++); *ip++=(CAST)(*c++); \
 *ip++=(CAST)(*c++); *ip  =(CAST)(*c++); ip +=rinc; \
 *ip++=(CAST)(*c++); *ip++=(CAST)(*c++); \
 *ip++=(CAST)(*c++); *ip  =(CAST)(*c++); ip +=rinc; \
 *ip++=(CAST)(*c++); *ip++=(CAST)(*c++); \
 *ip++=(CAST)(*c++); *ip  =(CAST)(*c  ); }

#define QT_RPZA_rgbC1(ip,r,g,b) { \
 *ip++=r; *ip++=g; *ip++=b; *ip++=r; *ip++=g; *ip++=b; \
 *ip++=r; *ip++=g; *ip++=b; *ip++=r; *ip++=g; *ip  =b; }

#define QT_RPZA_rgbC4(ip,r,g,b,mask); { ULONG _idx; \
 _idx = (mask>>6)&0x03; *ip++ = r[_idx]; *ip++ = g[_idx]; *ip++ = b[_idx]; \
 _idx = (mask>>4)&0x03; *ip++ = r[_idx]; *ip++ = g[_idx]; *ip++ = b[_idx]; \
 _idx = (mask>>2)&0x03; *ip++ = r[_idx]; *ip++ = g[_idx]; *ip++ = b[_idx]; \
 _idx =  mask    &0x03; *ip++ = r[_idx]; *ip++ = g[_idx]; *ip   = b[_idx]; }

#define QT_RPZA_rgbC16(ip,r,g,b) { \
 *ip++= *r++; *ip++= *g++; *ip++= *b++; *ip++= *r++; *ip++= *g++; *ip++= *b++; \
 *ip++= *r++; *ip++= *g++; *ip++= *b++; *ip++= *r++; *ip++= *g++; *ip  = *b++; }

ULONG
QT_Decode_RPZA(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG x,y,len,row_inc, min_x,max_x,min_y,max_y;
  UBYTE *dptr;
  ULONG code,changed;
  XA_CHDR *chdr;

  if (tchdr) {chdr=(tchdr->new_chdr)?(tchdr->new_chdr):(tchdr);} else chdr=0;
  *xs = *ys = 0; *xe = imagex; *ye = imagey;
  max_x = max_y = 0; min_x = imagex; min_y = imagey; changed = 0;
  dptr = delta;
  x = y = 0;
  if (special) row_inc = (3 * imagex) - 11 ;
  else row_inc = imagex - 3;

  dptr++;			/* for 0xe1 */
  len =(*dptr++)<<16; len |= (*dptr++)<< 8; len |= (*dptr++); /* Read Len */
  if (len != dsize) /* CHECK FOR CORRUPTION - FAIRLY COMMON */
  {
    if (xa_verbose==TRUE) 
	fprintf(stderr,"QT corruption-skipping this frame %lx %lx\n",dsize,len);
    return(ACT_DLTA_NOP);
  }
  len -= 4;				/* read 4 already */
  while(len > 0)
  {
    code = *dptr++; len--;

    if ( (code >= 0xa0) && (code <= 0xbf) )			/* SINGLE */
    {
      ULONG color,skip;
      changed = 1;
      color = (*dptr++) << 8; color |= *dptr++; len -= 2;
      skip = (code-0x9f);
      if (special)
      { UBYTE r,g,b;
        QT_Get_RGBColor(&r,&g,&b,color); 
        while(skip--)
        { UBYTE *i_ptr = (UBYTE *)(image + 3 * (y * imagex + x) );
	  QT_RPZA_rgbC1(i_ptr,r,g,b); i_ptr += row_inc;
	  QT_RPZA_rgbC1(i_ptr,r,g,b); i_ptr += row_inc;
	  QT_RPZA_rgbC1(i_ptr,r,g,b); i_ptr += row_inc;
	  QT_RPZA_rgbC1(i_ptr,r,g,b); 
	  QT_MIN_MAX_CHECK(x,y,min_x,min_y,max_x,max_y);
	  QT_BLOCK_INC(x,y,imagex);
	}
      }
      else /* not special */
      {
        color = QT_Get_Color(color,map_flag,map,chdr); 
        while(skip--)
        {
          if ( (x11_bytes_pixel==1) || (map_flag == FALSE) )
          { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	    QT_RPZA_C1(i_ptr,color,UBYTE,row_inc);
	  }
          else if (x11_bytes_pixel==4)
          { ULONG *i_ptr = (ULONG *)(image + 4 * (y * imagex + x) );
	    QT_RPZA_C1(i_ptr,color,ULONG,row_inc);
	  }
          else /* if (x11_bytes_pixel==2) */
          { USHORT *i_ptr = (USHORT *)(image + 2 * (y * imagex + x) );
	    QT_RPZA_C1(i_ptr,color,USHORT,row_inc);
	  }
	  QT_MIN_MAX_CHECK(x,y,min_x,min_y,max_x,max_y);
	  QT_BLOCK_INC(x,y,imagex);
        } /* end of skip-- */
      } /* end not special */
    }
    else if ( (code >= 0x80) && (code <= 0x9f) )		/* SKIP */
    {
      ULONG skip = (code-0x7f);
      while(skip--) QT_BLOCK_INC(x,y,imagex);
    }
    else if ( (code < 0x80) 				/* FOUR/SIXTEEN */ 
	     || ((code >= 0xc0) && (code <= 0xdf)) )
    { ULONG cA,cB;
      changed = 1;
      /* Get 1st two colors */
      if (code >= 0xc0) { cA = (*dptr++) << 8; cA |= *dptr++; len -= 2; }
      else {cA = (code << 8) | *dptr++; len -= 1;}
      cB = (*dptr++) << 8; cB |= *dptr++; len -= 2;

      /****** SIXTEEN COLOR *******/
      if ( (code < 0x80) && ((cB & 0x8000)==0) ) /* 16 color */
      {
        ULONG i,d,*clr,c[16];
        UBYTE r[16],g[16],b[16];
	if (special)
	{
          QT_Get_RGBColor(&r[0],&g[0],&b[0],cA);
          QT_Get_RGBColor(&r[1],&g[1],&b[1],cB);
          for(i=2; i<16; i++)
          {
            d = (*dptr++) << 8; d |= *dptr++; len -= 2;
            QT_Get_RGBColor(&r[i],&g[i],&b[i],d);
          }
	}
	else
	{
	  clr = c;
          *clr++ = QT_Get_Color(cA,map_flag,map,chdr);
          *clr++ = QT_Get_Color(cB,map_flag,map,chdr);
          for(i=2; i<16; i++)
          {
            d = (*dptr++) << 8; d |= *dptr++; len -= 2;
            *clr++ = QT_Get_Color(d,map_flag,map,chdr);
          }
	}
	clr = c;
	if (special)
	{ UBYTE *i_ptr = (UBYTE *)(image + 3 * (y * imagex + x) );
	  UBYTE *tr,*tg,*tb; tr=r; tg=g; tb=b;
	  QT_RPZA_rgbC16(i_ptr,tr,tg,tb); *i_ptr += row_inc;
	  QT_RPZA_rgbC16(i_ptr,tr,tg,tb); *i_ptr += row_inc;
	  QT_RPZA_rgbC16(i_ptr,tr,tg,tb); *i_ptr += row_inc;
	  QT_RPZA_rgbC16(i_ptr,tr,tg,tb);
	}
	else if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
        { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	  QT_RPZA_C16(i_ptr,clr,UBYTE,row_inc);
	}
	else if (x11_bytes_pixel==4)
	{ ULONG *i_ptr = (ULONG *)(image + 4 * (y * imagex + x) );
	  QT_RPZA_C16(i_ptr,clr,ULONG,row_inc);
	}
	else /* if (x11_bytes_pixel==2) */
	{ USHORT *i_ptr = (USHORT *)(image + 2 * (y * imagex + x) );
	  QT_RPZA_C16(i_ptr,clr,USHORT,row_inc);
	}
	QT_MIN_MAX_CHECK(x,y,min_x,min_y,max_x,max_y);
	QT_BLOCK_INC(x,y,imagex);
      } /*** END of SIXTEEN COLOR */
      else					/****** FOUR COLOR *******/
      {
        ULONG m_cnt,msk0,msk1,msk2,msk3,c[4];
	UBYTE r[4],g[4],b[4];

        if (code < 0x80) m_cnt = 1; 
	else m_cnt = code - 0xbf; 

	if (special) QT_Get_AV_RGBColors(c,r,g,b,cA,cB);
	else QT_Get_AV_Colors(c,cA,cB,map_flag,map,chdr);

        while(m_cnt--)
        {
	  msk0 = *dptr++; msk1 = *dptr++;
	  msk2 = *dptr++; msk3 = *dptr++; len -= 4;
	  if (special)
	  { UBYTE *i_ptr = (UBYTE *)(image + 3 * (y * imagex + x) );
	    QT_RPZA_rgbC4(i_ptr,r,g,b,msk0); *i_ptr += row_inc;
	    QT_RPZA_rgbC4(i_ptr,r,g,b,msk1); *i_ptr += row_inc;
	    QT_RPZA_rgbC4(i_ptr,r,g,b,msk2); *i_ptr += row_inc;
	    QT_RPZA_rgbC4(i_ptr,r,g,b,msk3);
	  }
	  else if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
          { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	    QT_RPZA_C4(i_ptr,c,msk0,UBYTE); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk1,UBYTE); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk2,UBYTE); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk3,UBYTE);
	  }
	  else if (x11_bytes_pixel==4)
	  { ULONG *i_ptr = (ULONG *)(image + 4 * (y * imagex + x) );
	    QT_RPZA_C4(i_ptr,c,msk0,ULONG); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk1,ULONG); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk2,ULONG); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk3,ULONG);
	  }
	  else /* if (x11_bytes_pixel==2) */
	  { USHORT *i_ptr = (USHORT *)(image + 2 * (y * imagex + x) );
	    QT_RPZA_C4(i_ptr,c,msk0,USHORT); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk1,USHORT); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk2,USHORT); i_ptr += row_inc;
	    QT_RPZA_C4(i_ptr,c,msk3,USHORT);
	  }
	  QT_MIN_MAX_CHECK(x,y,min_x,min_y,max_x,max_y);
	  QT_BLOCK_INC(x,y,imagex);
        }  
      } /*** END of FOUR COLOR *******/
    } /*** END of 4/16 COLOR BLOCKS ****/
    else /* UNKNOWN */
    {
      fprintf(stderr,"QT RPZA: Unknown %lx\n",code);
      return(ACT_DLTA_NOP);
    }
  }
  if (xa_optimize_flag == TRUE)
  {
    if (changed) { *xs=min_x; *ys=min_y; *xe=max_x + 4; *ye=max_y + 4; }
    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);
}

void QT_Get_RGBColor(r,g,b,color)
UBYTE *r,*g,*b;
ULONG color;
{ ULONG ra,ga,ba;
  ra = (color >> 10) & 0x1f;	ra = (ra << 3) | (ra >> 2);
  ga = (color >>  5) & 0x1f;	ga = (ga << 3) | (ga >> 2);
  ba =  color & 0x1f;		ba = (ba << 3) | (ba >> 2);
  *r = ra; *g = ga; *b = ba;
}

ULONG QT_Get_Color(color,map_flag,map,chdr)
ULONG color,map_flag,*map;
XA_CHDR *chdr;
{
  register ULONG clr,ra,ga,ba,ra5,ga5,ba5;

  ra5 = (color >> 10) & 0x1f;
  ga5 = (color >>  5) & 0x1f;
  ba5 =  color & 0x1f;
  ra = qt_gamma_adj[ra5]; ga = qt_gamma_adj[ga5]; ba = qt_gamma_adj[ba5];

  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(ra,ga,ba,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i = color & 0x7fff;
      if (cmap_cache == 0) CMAP_Cache_Init();
      if (chdr != cmap_cache_chdr)
      {
        CMAP_Cache_Clear();
        cmap_cache_chdr = chdr;
      }
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,ra,ga,ba,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else
    {
      if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(ra5,ga5,ba5,CMAP_SCALE5);
      else			  clr = CMAP_GET_GRAY(ra5,ga5,ba5,CMAP_SCALE10);
      if (map_flag) clr = map[clr];
    }
  }
  return(clr);
}

ULONG QT_Get_Color24(r,g,b,map_flag,map,chdr)
register ULONG r,g,b;
ULONG map_flag,*map;
XA_CHDR *chdr;
{
  ULONG clr,ra,ga,ba;

  ra = xa_gamma_adj[r]; ga = xa_gamma_adj[g]; ba = xa_gamma_adj[b];

  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(ra,ga,ba,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i;
      if (cmap_cache == 0) CMAP_Cache_Init();
      if (chdr != cmap_cache_chdr)
      {
        CMAP_Cache_Clear();
        cmap_cache_chdr = chdr;
      }
      cache_i  = ((r>>3)<<10) | ((g>>3)<<5) | (b>>3);
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,ra,ga,ba,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else 
    { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(r,g,b,CMAP_SCALE8);
      else			  clr = CMAP_GET_GRAY(r,g,b,CMAP_SCALE13);
      if (map_flag) clr = map[clr];
    }
  }
  return(clr);
}

void QT_Get_AV_RGBColors(c,r,g,b,cA,cB)
ULONG *c;
UBYTE *r,*g,*b;
ULONG cA,cB;
{ ULONG rA,gA,bA,rB,gB,bB,ra,ga,ba;
/**color 3 ***/
  rA = (cA >> 10) & 0x1f;	r[3] = (rA << 3) | (rA >> 2);
  gA = (cA >>  5) & 0x1f;	g[3] = (gA << 3) | (gA >> 2);
  bA =  cA & 0x1f;		b[3] = (bA << 3) | (bA >> 2);
/**color 0 ***/
  rB = (cB >> 10) & 0x1f;	r[0] = (rB << 3) | (rB >> 2);
  gB = (cB >>  5) & 0x1f;	g[0] = (gB << 3) | (gB >> 2);
  bB =  cB & 0x1f;		b[0] = (bB << 3) | (bB >> 2);
/**color 2 ***/
  ra = (21*rA + 11*rB) >> 5;	r[2] = (ra << 3) | (ra >> 2);
  ga = (21*gA + 11*gB) >> 5;	g[2] = (ga << 3) | (ga >> 2);
  ba = (21*bA + 11*bB) >> 5;	b[2] = (ba << 3) | (ba >> 2);
/**color 1 ***/
  ra = (11*rA + 21*rB) >> 5;	r[1] = (ra << 3) | (ra >> 2);
  ga = (11*gA + 21*gB) >> 5;	g[1] = (ga << 3) | (ga >> 2);
  ba = (11*bA + 21*bB) >> 5;	b[1] = (ba << 3) | (ba >> 2);
}

void QT_Get_AV_Colors(c,cA,cB,map_flag,map,chdr)
ULONG *c;
ULONG cA,cB,map_flag,*map;
XA_CHDR *chdr;
{
  ULONG clr,rA,gA,bA,rB,gB,bB,r0,g0,b0,r1,g1,b1;
  ULONG rA5,gA5,bA5,rB5,gB5,bB5;
  ULONG r05,g05,b05,r15,g15,b15;

/*color 3*/
  rA5 = (cA >> 10) & 0x1f;
  gA5 = (cA >>  5) & 0x1f;
  bA5 =  cA & 0x1f;
/*color 0*/
  rB5 = (cB >> 10) & 0x1f;
  gB5 = (cB >>  5) & 0x1f;
  bB5 =  cB & 0x1f;
/*color 2*/
  r05 = (21*rA5 + 11*rB5) >> 5;
  g05 = (21*gA5 + 11*gB5) >> 5;
  b05 = (21*bA5 + 11*bB5) >> 5;
/*color 1*/
  r15 = (11*rA5 + 21*rB5) >> 5;
  g15 = (11*gA5 + 21*gB5) >> 5;
  b15 = (11*bA5 + 21*bB5) >> 5;
/*adj and scale to 16 bits */
  rA=qt_gamma_adj[rA5]; gA=qt_gamma_adj[gA5]; bA=qt_gamma_adj[bA5];
  rB=qt_gamma_adj[rB5]; gB=qt_gamma_adj[gB5]; bB=qt_gamma_adj[bB5];
  r0=qt_gamma_adj[r05]; g0=qt_gamma_adj[g05]; b0=qt_gamma_adj[b05];
  r1=qt_gamma_adj[r15]; g1=qt_gamma_adj[g15]; b1=qt_gamma_adj[b15];

  /*** 1st Color **/
  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(rA,gA,bA,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i = cA & 0x7fff;
      if (cmap_cache == 0) CMAP_Cache_Init();
      if (chdr != cmap_cache_chdr)
      {
        CMAP_Cache_Clear();
        cmap_cache_chdr = chdr;
      }
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,rA,gA,bA,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else
    { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(rA5,gA5,bA5,CMAP_SCALE5);
      else	clr = CMAP_GET_GRAY(rA5,gA5,bA5,CMAP_SCALE10);
      if (map_flag) clr = map[clr];
    }
  }
  c[3] = clr;

  /*** 2nd Color **/
  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(rB,gB,bB,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i = cB & 0x7fff;
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,rB,gB,bB,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else
    { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(rB5,gB5,bB5,CMAP_SCALE5);
      else	clr = CMAP_GET_GRAY(rB5,gB5,bB5,CMAP_SCALE10);
      if (map_flag) clr = map[clr];
    }
  }
  c[0] = clr;

  /*** 1st Av ****/
  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(r0,g0,b0,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i;
      cache_i = (ULONG)(r05 << 10) | (g05 << 5) | b05;
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,r0,g0,b0,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else
    { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(r05,g05,b05,CMAP_SCALE5);
      else	clr = CMAP_GET_GRAY(r05,g05,b05,CMAP_SCALE10);
      if (map_flag) clr = map[clr];
    }
  }
  c[2] = clr;

  /*** 2nd Av ****/
  if (x11_display_type & XA_X11_TRUE) clr = X11_Get_True_Color(r1,g1,b1,16);
  else 
  { 
    if ((cmap_color_func == 4) && (chdr))
    { register ULONG cache_i;
      cache_i = (ULONG)(r15 << 10) | (g15 << 5) | b15;
      if (cmap_cache[cache_i] == 0xffff)
      {
        clr = chdr->coff +
           CMAP_Find_Closest(chdr->cmap,chdr->csize,r1,g1,b1,16,16,16,TRUE);
        cmap_cache[cache_i] = (USHORT)clr;
      }
      else clr = (ULONG)cmap_cache[cache_i];
    }
    else
    { if (cmap_true_to_332 == TRUE) clr = CMAP_GET_332(r15,g15,b15,CMAP_SCALE5);
      else	clr = CMAP_GET_GRAY(r15,g15,b15,CMAP_SCALE10);
      if (map_flag) clr = map[clr];
    }
  }
  c[1] = clr;
}


ULONG
QT_Decode_RLE16(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG y,d,lines; /* LONG min_x,max_x,min_y,max_y; */
  ULONG special_flag;
  UBYTE r,g,b,*dptr;
  XA_CHDR *chdr;

  if (tchdr) {chdr=(tchdr->new_chdr)?(tchdr->new_chdr):(tchdr);} else chdr=0;

  special_flag = special & 0x0001;

  dptr = delta;
  dptr += 4;    /* skip codec size */
  d = (*dptr++) << 8;  d |= *dptr++;   /* read code either 0008 or 0000 */
  if (d == 0x0000) /* NOP */
  { /* There is one more byte 0x00 that I don't read in this case */
    *xs = *ys = *xe = *ye = 0;
    return(ACT_DLTA_NOP);
  }
  y = (*dptr++) << 8; y |= *dptr++;		/* start line */
  dptr += 2;					/* unknown */
  lines = (*dptr++) << 8; lines |= *dptr++;	/* number of lines */
  dptr += 2;					/* unknown */
  while(lines--)				/* loop thru lines */
  {
    ULONG d,xskip,cnt;
    xskip = *dptr++;				/* skip x pixels */
    cnt = *dptr++;				/* RLE code */

    if (special_flag)
    { UBYTE *iptr = (UBYTE *)(image + 3*((y * imagex) + (xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += 3*(xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { d = (*dptr++ << 8); d |= *dptr++;
			 QT_Get_RGBColor(&r,&g,&b,d);
			*iptr++ = r; *iptr++ = g; *iptr++ = b; }
        else						/* repeat data */
        { cnt = 0x100 - cnt; d = (*dptr++ << 8); d |= *dptr++;
          QT_Get_RGBColor(&r,&g,&b,d);
          while(cnt--) { *iptr++ = r; *iptr++ = g; *iptr++ = b; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
    { UBYTE *iptr = (UBYTE *)(image + (y * imagex) + (xskip-1) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { d = (*dptr++ << 8); d |= *dptr++;
		*iptr++ = (UBYTE)QT_Get_Color(d,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; d = (*dptr++ << 8); d |= *dptr++;
          d = QT_Get_Color(d,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (UBYTE)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else if (x11_bytes_pixel==4)
    { ULONG *iptr = (ULONG *)(image + 4*((y * imagex)+(xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { d = (*dptr++ << 8); d |= *dptr++;
		*iptr++ = (ULONG)QT_Get_Color(d,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; d = (*dptr++ << 8); d |= *dptr++;
          d = QT_Get_Color(d,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (ULONG)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else /* if (x11_bytes_pixel==2) */
    { USHORT *iptr = (USHORT *)(image + 2*((y * imagex)+(xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { d = (*dptr++ << 8); d |= *dptr++;
		*iptr++ = (USHORT)QT_Get_Color(d,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; d = (*dptr++ << 8); d |= *dptr++;
          d = QT_Get_Color(d,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (USHORT)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    y++;
  } /* end of lines */
 /* one more zero byte */
 *xs = *ys = 0; *xe = imagex; *ye = imagey;
 if (map_flag==TRUE) return(ACT_DLTA_MAPD);
 else return(ACT_DLTA_NORM);
}


ULONG
QT_Decode_RLE33(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG x,y,d,lines; /* LONG min_x,max_x,min_y,max_y; */
  UBYTE *dptr;

  dptr = delta;
  dptr += 4;    /* skip codec size */
  d = (*dptr++) << 8;  d |= *dptr++;   /* read code either 0008 or 0000 */
  if (d == 0x0000) /* NOP */
  { /* There is one more byte 0x00 that I don't read in this case */
    *xs = *ys = *xe = *ye = 0;
    return(ACT_DLTA_NOP);
  }
  y = (*dptr++) << 8; y |= *dptr++;		/* start line */
  dptr += 2;					/* unknown */
  lines = (*dptr++) << 8; lines |= *dptr++;	/* number of lines */
  dptr += 2;					/* unknown */
  x = 0; y--; lines++;
  while(lines)				/* loop thru lines */
  {
    ULONG d,xskip,cnt;
    xskip = *dptr++;				/* skip x pixels */
    cnt = *dptr++;				/* RLE code */
    
    if ((xskip == 0x80) && (cnt == 0x00))  /* end of codec */
	{lines = 0; y++; x = 0; }
    else if ((xskip == 0x80) && (cnt == 0xff)) /* skip line */
	{lines--; y++; x = 0; }
    else
    {
      if (xskip & 0x80) {lines--; y++; x = xskip & 0x7f;}
      else x += xskip;

      if (cnt < 0x80)				/* run of data */
      { 
        UBYTE *bptr; USHORT *sptr; ULONG *lptr;
	if ((x11_bytes_pixel==1) || (map_flag==FALSE) )
		bptr = (UBYTE *)(image + (y * imagex) + (x << 4) );
	else if (x11_bytes_pixel==2)
		sptr = (USHORT *)(image + 2*(y * imagex) + (x << 5) );
        else lptr = (ULONG *)(image + 4*(y * imagex) + (x << 6) );
        x += cnt;
        while(cnt--) 
        { ULONG i,mask;
          d = (*dptr++ << 8); d |= *dptr++;
          mask = 0x8000;
          for(i=0;i<16;i++)
          {
            if (map_flag==FALSE) 
		{ if (d & mask) *bptr++ = 0;  else *bptr++ = 1; }
            else if (x11_bytes_pixel==1) {if (d & mask) *bptr++=(UBYTE)map[0];
					else *bptr++=(UBYTE)map[1];}
            else if (x11_bytes_pixel==2) {if (d & mask) *sptr++ =(USHORT)map[0];
					else *sptr++ =(USHORT)map[1]; }
            else { if (d & mask) *lptr++ = (ULONG)map[0]; 
					else *lptr++ = (ULONG)map[1]; }
            mask >>= 1;
          }
        }
      } /* end run */ 
      else				/* repeat data */
      { 
        UBYTE *bptr; USHORT *sptr; ULONG *lptr;
	if ((x11_bytes_pixel==1) || (map_flag==FALSE) )
		bptr = (UBYTE *)(image + (y * imagex) + (x << 4) );
	else if (x11_bytes_pixel==2)
		sptr = (USHORT *)(image + 2*(y * imagex) + (x << 5) );
        else lptr = (ULONG *)(image + 4*(y * imagex) + (x << 6) );
        cnt = 0x100 - cnt;
        x += cnt;
        d = (*dptr++ << 8); d |= *dptr++;
        while(cnt--) 
        { ULONG i,mask;
          mask = 0x8000;
          for(i=0;i<16;i++)
          {
            if (map_flag==FALSE) 
		{ if (d & mask) *bptr++ = 0;  else *bptr++ = 1; }
            else if (x11_bytes_pixel==1) {if (d & mask) *bptr++=(UBYTE)map[0];
					else *bptr++=(UBYTE)map[1];}
            else if (x11_bytes_pixel==2) {if (d & mask) *sptr++ =(USHORT)map[0];
					else *sptr++ =(USHORT)map[1]; }
            else { if (d & mask) *lptr++ = (ULONG)map[0]; 
					else *lptr++ = (ULONG)map[1]; }
            mask >>= 1;
          }
        }
      } /* end repeat */
    } /* end of code */
  } /* end of lines */
 *xs = *ys = 0; *xe = imagex; *ye = imagey;
 if (map_flag==TRUE) return(ACT_DLTA_MAPD);
 else return(ACT_DLTA_NORM);
}

ULONG
QT_Decode_RAW(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  UBYTE *dptr = delta;
  LONG i = imagex * imagey;
  
  if (map_flag==FALSE) { UBYTE *iptr = (UBYTE *)image; 
				while(i--) *iptr++ = (UBYTE)*dptr++; }
  else if (x11_bytes_pixel==1) { UBYTE *iptr = (UBYTE *)image; 
				while(i--) *iptr++ = (UBYTE)map[*dptr++]; }
  else if (x11_bytes_pixel==2) { USHORT *iptr = (USHORT *)image; 
				while(i--) *iptr++ = (USHORT)map[*dptr++]; }
  else { ULONG *iptr = (ULONG *)image; 
				while(i--) *iptr++ = (ULONG)map[*dptr++]; }

  *xs = *ys = 0; *xe = imagex; *ye = imagey;
  if (map_flag==TRUE) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}


#define QT_SMC_O2I(i,o,rinc) { \
*i++ = *o++; *i++ = *o++; *i++ = *o++; *i++ = *o++; i += rinc; o += rinc; \
*i++ = *o++; *i++ = *o++; *i++ = *o++; *i++ = *o++; i += rinc; o += rinc; \
*i++ = *o++; *i++ = *o++; *i++ = *o++; *i++ = *o++; i += rinc; o += rinc; \
*i++ = *o++; *i++ = *o++; *i++ = *o++; *i++ = *o++;  } 

#define QT_SMC_C1(i,c,rinc) { \
*i++ = c; *i++ = c; *i++ = c; *i++ = c;  i += rinc; \
*i++ = c; *i++ = c; *i++ = c; *i++ = c;  i += rinc; \
*i++ = c; *i++ = c; *i++ = c; *i++ = c;  i += rinc; \
*i++ = c; *i++ = c; *i++ = c; *i++ = c;  i += rinc; }

#define QT_SMC_C2(i,c0,c1,msk,rinc) { \
*i++ =(msk&0x80)?c1:c0; *i++ =(msk&0x40)?c1:c0; \
*i++ =(msk&0x20)?c1:c0; *i++ =(msk&0x10)?c1:c0; i += rinc; \
*i++ =(msk&0x08)?c1:c0; *i++ =(msk&0x04)?c1:c0; \
*i++ =(msk&0x02)?c1:c0; *i++ =(msk&0x01)?c1:c0; }

#define QT_SMC_C4(i,CST,c,mska,mskb,rinc) { \
*i++ = (CST)(c[(mska>>6) & 0x03]); *i++ = (CST)(c[(mska>>4) & 0x03]); \
*i++ = (CST)(c[(mska>>2) & 0x03]); *i++ = (CST)(c[mska & 0x03]); i+=rinc; \
*i++ = (CST)(c[(mskb>>6) & 0x03]); *i++ = (CST)(c[(mskb>>4) & 0x03]); \
*i++ = (CST)(c[(mskb>>2) & 0x03]); *i++ = (CST)(c[mskb & 0x03]); }

#define QT_SMC_C8(i,CST,c,msk,rinc) { \
*i++ = (CST)(c[(msk>>21) & 0x07]); *i++ = (CST)(c[(msk>>18) & 0x07]); \
*i++ = (CST)(c[(msk>>15) & 0x07]); *i++ = (CST)(c[(msk>>12) & 0x07]); i+=rinc; \
*i++ = (CST)(c[(msk>> 9) & 0x07]); *i++ = (CST)(c[(msk>> 6) & 0x07]); \
*i++ = (CST)(c[(msk>> 3) & 0x07]); *i++ = (CST)(c[msk & 0x07]); }

#define QT_SMC_C16m(i,dp,CST,map,rinc) { \
*i++ =(CST)map[*dp++]; *i++ =(CST)map[*dp++]; \
*i++ =(CST)map[*dp++]; *i++ =(CST)map[*dp++]; i += rinc; \
*i++ =(CST)map[*dp++]; *i++ =(CST)map[*dp++]; \
*i++ =(CST)map[*dp++]; *i++ =(CST)map[*dp++]; }

#define QT_SMC_C16(i,dp,CST) { \
*i++ =(CST)(*dp++); *i++ =(CST)(*dp++); \
*i++ =(CST)(*dp++); *i++ =(CST)(*dp++); }

ULONG
QT_Decode_SMC(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG x,y,len,row_inc; /* LONG min_x,max_x,min_y,max_y; */
  UBYTE *dptr;
  ULONG i,cnt,hicode,code;
  ULONG *c;

  smc_8cnt = smc_Acnt = smc_Ccnt = 0;

  *xs = *ys = 0; *xe = imagex; *ye = imagey;
  dptr = delta;
  x = y = 0;
  row_inc = imagex - 4;

  dptr++;				/* skip over 0xe1 */
  len =(*dptr++)<<16; len |= (*dptr++)<< 8; len |= (*dptr++); /* Read Len */
  len -= 4;				/* read 4 already */
  while(len > 0)
  {
    code = *dptr++; len--; hicode = code & 0xf0;
    switch(hicode)
    {
      case 0x00: /* SKIPs */
      case 0x10:
	if (hicode == 0x10) {cnt = 1 + *dptr++; len -= 1;}
	else cnt = 1 + (code & 0x0f);
        while(cnt--) {x += 4; if (x >= imagex) { x = 0; y += 4; } }
	break;
      case 0x20: /* Repeat Last Block */
      case 0x30:
	{ LONG tx,ty;
	  if (hicode == 0x30) {cnt = 1 + *dptr++; len--;}
	  else cnt = 1 + (code & 0x0f);
	  if (x==0) {ty = y-4; tx = imagex-4;} else {ty=y; tx = x-4;}

	  while(cnt--)
	  { 
	    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      UBYTE *o_ptr = (UBYTE *)(image + ty * imagex + tx);
	      QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x) );
	      USHORT *o_ptr = (USHORT *)(image + 2*(ty * imagex + tx) );
	      QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	    } else /* if (x11_bytes_pixel==4) */
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x) );
	      ULONG *o_ptr = (ULONG *)(image + 4*(ty * imagex + tx) );
	      QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	    }
	    x += 4; if (x >= imagex) { x = 0; y += 4; }
	  }
	}
	break;
      case 0x40: /* */
      case 0x50:
	{ ULONG cnt,cnt1;
	  ULONG m_cnt,m_cnt1;
	  LONG m_tx,m_ty;
          LONG tx,ty;
	  if (hicode == 0x50) 
	  {  
	     m_cnt1 = 1 + *dptr++; len--; 
	     m_cnt = 2;
	  }
          else 
	  {
	    m_cnt1 = (1 + (code & 0x0f));
	    m_cnt = 2;
	  }
          m_tx = x-(LONG)(4 * m_cnt); m_ty = y; 
	  if (m_tx < 0) {m_tx += imagex; m_ty -= 4;}
	  cnt1 = m_cnt1;
	  while(cnt1--)
	  {
	    cnt = m_cnt; tx = m_tx; ty = m_ty;
	    while(cnt--)
	    { 
	      if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	      { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
		UBYTE *o_ptr = (UBYTE *)(image + ty * imagex + tx);
		QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	      } else if (x11_bytes_pixel==2)
	      { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
		USHORT *o_ptr = (USHORT *)(image + 2*(ty * imagex + tx));
		QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	      } else 
	      { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
		ULONG *o_ptr = (ULONG *)(image + 4*(ty * imagex + tx));
		QT_SMC_O2I(i_ptr,o_ptr,row_inc);
	      }
	      x += 4; if (x >= imagex) { x = 0; y += 4; }
	      tx += 4; if (tx >= imagex) { tx = 0; ty += 4; }
	    } /* end of cnt */
	  } /* end of cnt1 */
	}
	break;

      case 0x60: /* Repeat Data */
      case 0x70:
	{ ULONG ct,cnt;
	  if (hicode == 0x70) {cnt = 1 + *dptr++; len--;}
	  else cnt = 1 + (code & 0x0f);
	  ct = (map_flag)?(map[*dptr++]):(ULONG)(*dptr++); len--;
	  while(cnt--)
	  {
	    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      UBYTE d = (UBYTE)(ct);
	      QT_SMC_C1(i_ptr,d,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
	      USHORT d = (UBYTE)(ct);
	      QT_SMC_C1(i_ptr,d,row_inc);
	    } else
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
	      QT_SMC_C1(i_ptr,ct,row_inc);
	    }
	    x += 4; if (x >= imagex) { x = 0; y += 4; }
	  }
	}
	break;

      case 0x80: /* 2 colors plus 16 mbits per */
      case 0x90:
        { ULONG cnt = 1 + (code & 0x0f);
	  if (hicode == 0x80)
	  {
            c = (ULONG *)&smc_8[ (smc_8cnt * 2) ];  len -= 2;
	    smc_8cnt++; if (smc_8cnt >= SMC_MAX_CNT) smc_8cnt -= SMC_MAX_CNT;
	    for(i=0;i<2;i++) {c[i]=(map_flag)?map[*dptr++]:(ULONG)(*dptr++);}
	  }
          else { c = (ULONG *)&smc_8[ ((ULONG)(*dptr++) << 1) ]; len--; }
	  while(cnt--)
	  { ULONG msk1,msk0;
	    msk0 = *dptr++; msk1 = *dptr++;  len-= 2;
	    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      UBYTE c0=(UBYTE)c[0];	UBYTE c1=(UBYTE)c[1];
	      QT_SMC_C2(i_ptr,c0,c1,msk0,row_inc); i_ptr += row_inc;
	      QT_SMC_C2(i_ptr,c0,c1,msk1,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
	      USHORT c0=(USHORT)c[0];	USHORT c1=(USHORT)c[1];
	      QT_SMC_C2(i_ptr,c0,c1,msk0,row_inc); i_ptr += row_inc;
	      QT_SMC_C2(i_ptr,c0,c1,msk1,row_inc);
	    } else
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
	      ULONG c0=(ULONG)c[0];	ULONG c1=(ULONG)c[1];
	      QT_SMC_C2(i_ptr,c0,c1,msk0,row_inc); i_ptr += row_inc;
	      QT_SMC_C2(i_ptr,c0,c1,msk1,row_inc);
	    }
	    x += 4; if (x >= imagex) { x = 0; y += 4; }
          } 
        } 
	break;

      case 0xA0: /* 4 color + 32 mbits */
      case 0xB0:
        { ULONG cnt = 1 + (code & 0xf);
          if (hicode == 0xA0)
          {
            c = (ULONG *)&smc_A[ (smc_Acnt << 2) ]; len -= 4;
            smc_Acnt++; if (smc_Acnt >= SMC_MAX_CNT) smc_Acnt -= SMC_MAX_CNT;
            for(i=0;i<4;i++) {c[i]=(map_flag)?map[*dptr++]:(ULONG)(*dptr++);}
          }
          else { c = (ULONG *)&smc_A[ ((ULONG)(*dptr++) << 2) ]; len--; }
	  while(cnt--)
	  { UBYTE msk0,msk1,msk2,msk3; 
	    msk0 = *dptr++;	msk1 = *dptr++; 
	    msk2 = *dptr++;	msk3 = *dptr++;		len -= 4;
	    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      QT_SMC_C4(i_ptr,UBYTE,c,msk0,msk1,row_inc); i_ptr += row_inc;
	      QT_SMC_C4(i_ptr,UBYTE,c,msk2,msk3,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
	      QT_SMC_C4(i_ptr,USHORT,c,msk0,msk1,row_inc); i_ptr += row_inc;
	      QT_SMC_C4(i_ptr,USHORT,c,msk2,msk3,row_inc);
	    } else
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
	      QT_SMC_C4(i_ptr,ULONG,c,msk0,msk1,row_inc); i_ptr += row_inc;
	      QT_SMC_C4(i_ptr,ULONG,c,msk2,msk3,row_inc);
	    }
	    x += 4; if (x >= imagex) { x = 0; y += 4; }
          } 
        } 
	break;

      case 0xC0: /* 8 colors + 48 mbits */
      case 0xD0:
        { ULONG cnt = 1 + (code & 0xf);
          if (hicode == 0xC0)
          {
            c = (ULONG *)&smc_C[ (smc_Ccnt << 3) ];   len -= 8;
            smc_Ccnt++; if (smc_Ccnt >= SMC_MAX_CNT) smc_Ccnt -= SMC_MAX_CNT;
            for(i=0;i<8;i++) {c[i]=(map_flag)?map[*dptr++]:(ULONG)(*dptr++);}
          }
          else { c = (ULONG *)&smc_C[ ((ULONG)(*dptr++) << 3) ]; len--; }

	  while(cnt--)
	  { ULONG t,mbits0,mbits1;
	    t = (*dptr++) << 8; t |= *dptr++;
	    mbits0  = (t & 0xfff0) << 8;  mbits1  = (t & 0x000f) << 8;
	    t = (*dptr++) << 8; t |= *dptr++;
	    mbits0 |= (t & 0xfff0) >> 4;  mbits1 |= (t & 0x000f) << 4;
	    t = (*dptr++) << 8; t |= *dptr++;
	    mbits1 |= (t & 0xfff0) << 8;  mbits1 |= (t & 0x000f);
	    len -= 6;
	    if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      QT_SMC_C8(i_ptr,UBYTE,c,mbits0,row_inc); i_ptr += row_inc;
	      QT_SMC_C8(i_ptr,UBYTE,c,mbits1,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
	      QT_SMC_C8(i_ptr,USHORT,c,mbits0,row_inc); i_ptr += row_inc;
	      QT_SMC_C8(i_ptr,USHORT,c,mbits1,row_inc);
	    } else
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
	      QT_SMC_C8(i_ptr,ULONG,c,mbits0,row_inc); i_ptr += row_inc;
	      QT_SMC_C8(i_ptr,ULONG,c,mbits1,row_inc);
	    }
	    x += 4; if (x >= imagex) { x = 0; y += 4; }
          } 
        } 
	break;

      case 0xE0: /* 16 colors */
        { ULONG cnt = 1 + (code & 0x0f);
	  while(cnt--)
	  { 
	    if (map_flag==FALSE)
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      QT_SMC_C16(i_ptr,dptr,UBYTE); i_ptr += row_inc;
	      QT_SMC_C16(i_ptr,dptr,UBYTE); i_ptr += row_inc;
	      QT_SMC_C16(i_ptr,dptr,UBYTE); i_ptr += row_inc;
	      QT_SMC_C16(i_ptr,dptr,UBYTE);
	    } else if (x11_bytes_pixel==1)
	    { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
	      QT_SMC_C16m(i_ptr,dptr,UBYTE,map,row_inc); i_ptr += row_inc;
	      QT_SMC_C16m(i_ptr,dptr,UBYTE,map,row_inc);
	    } else if (x11_bytes_pixel==2)
	    { USHORT *i_ptr = (USHORT *)(image + 2*(y * imagex + x));
	      QT_SMC_C16m(i_ptr,dptr,USHORT,map,row_inc); i_ptr += row_inc;
	      QT_SMC_C16m(i_ptr,dptr,USHORT,map,row_inc);
	    } else
	    { ULONG *i_ptr = (ULONG *)(image + 4*(y * imagex + x));
	      QT_SMC_C16m(i_ptr,dptr,ULONG,map,row_inc); i_ptr += row_inc;
	      QT_SMC_C16m(i_ptr,dptr,ULONG,map,row_inc);
	    }
	    len -= 16; x += 4; if (x >= imagex) { x = 0; y += 4; }
	  }
	}
	break;

      case 0xF0: /* ??? */
	fprintf(stderr,"SMC opcode %lx is unknown\n",code);
	TheEnd();
	break;
    }
  }
  if (map_flag) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

ULONG
QT_Decode_RLE24(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG y,d,lines; /* ULONG min_x,max_x,min_y,max_y; */
  ULONG special_flag,r,g,b;
  UBYTE *dptr;
  XA_CHDR *chdr;

  if (tchdr) {chdr=(tchdr->new_chdr)?(tchdr->new_chdr):(tchdr);} else chdr=0;

  special_flag = special & 0x0001;

  dptr = delta;
  dptr += 4;    /* skip codec size */
  d = (*dptr++) << 8;  d |= *dptr++;   /* read code either 0008 or 0000 */
  if (d == 0x0000) /* NOP */
  { /* There is one more byte 0x00 that I don't read in this case */
    *xs = *ys = *xe = *ye = 0;
    return(ACT_DLTA_NOP);
  }
  y = (*dptr++) << 8; y |= *dptr++;		/* start line */
  dptr += 2;					/* unknown */
  lines = (*dptr++) << 8; lines |= *dptr++;	/* number of lines */
  dptr += 2;					/* unknown */
  while(lines--)				/* loop thru lines */
  {
    ULONG d,xskip,cnt;
    xskip = *dptr++;				/* skip x pixels */
    cnt = *dptr++;				/* RLE code */

    if (special_flag)
    { UBYTE *iptr = (UBYTE *)(image + 3*((y * imagex) + (xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += 3*(xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { r = *dptr++; g = *dptr++; b = *dptr++;
			*iptr++ = (UBYTE)r; *iptr++ = (UBYTE)g; 
					    *iptr++ = (UBYTE)b; }
        else						/* repeat data */
        { cnt = 0x100 - cnt; r = *dptr++; g = *dptr++; b = *dptr++;
          while(cnt--) { *iptr++ = (UBYTE)r; *iptr++ = (UBYTE)g; 
					     *iptr++ = (UBYTE)b; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
    { UBYTE *iptr = (UBYTE *)(image + (y * imagex) + (xskip-1) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { r = *dptr++; g = *dptr++; b = *dptr++;
		*iptr++ = (UBYTE)QT_Get_Color24(r,g,b,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; r = *dptr++; g = *dptr++; b = *dptr++;
          d = QT_Get_Color24(r,g,b,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (UBYTE)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else if (x11_bytes_pixel==4)
    { ULONG *iptr = (ULONG *)(image + 4*((y * imagex)+(xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { r = *dptr++; g = *dptr++; b = *dptr++;
		*iptr++ = (ULONG)QT_Get_Color24(r,g,b,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; r = *dptr++; g = *dptr++; b = *dptr++;
          d = QT_Get_Color24(r,g,b,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (ULONG)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    else /* if (x11_bytes_pixel==2) */
    { USHORT *iptr = (USHORT *)(image + 2*((y * imagex)+(xskip-1)) );
      while(cnt != 0xff)				/* while not EOL */
      {
        if (cnt == 0x00) { xskip = *dptr++; iptr += (xskip-1); }
        else if (cnt < 0x80)				/* run of data */
          while(cnt--) { r = *dptr++; g = *dptr++; b = *dptr++;
		*iptr++ = (USHORT)QT_Get_Color24(r,g,b,map_flag,map,chdr); }
        else						/* repeat data */
        { cnt = 0x100 - cnt; r = *dptr++; g = *dptr++; b = *dptr++;
          d = QT_Get_Color24(r,g,b,map_flag,map,chdr);
          while(cnt--) { *iptr++ = (USHORT)d; }
        }
        cnt = *dptr++;				/* get new RLE code */
      } /* end of line */
    }
    y++;
  } /* end of lines */
 /* one more zero byte */
 *xs = *ys = 0; *xe = imagex; *ye = imagey;
 if (map_flag==TRUE) return(ACT_DLTA_MAPD);
 else return(ACT_DLTA_NORM);
}

typedef struct
{
  UBYTE r,g,b,pad;
  ULONG clr;
  ULONG g0,g1,g2,g3,v0,v1;
} CVID_Color;

#define QT_CVID_MAX_STRIPS 16
CVID_Color *qt_cvid_maps0[QT_CVID_MAX_STRIPS];
CVID_Color *qt_cvid_maps1[QT_CVID_MAX_STRIPS];
int qt_cvid_vmap0[QT_CVID_MAX_STRIPS];
int qt_cvid_vmap1[QT_CVID_MAX_STRIPS];
int qt_cvid_map_num = 0;



/* POD Move this internal Later */
CVID_Color *qt_cvid_cmap0,*qt_cvid_cmap1;

ULONG
QT_Decode_CVID(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG len,x,y,row_inc;
  UBYTE *dptr;
  ULONG kk,strips,cnum,xsz,ysz;
  ULONG copy_flag;
  ULONG y_top;
  XA_CHDR *chdr;

  *xs = *ys = 0; *xe = imagex; *ye = imagey;
  dptr = delta;
  x = y = 0;
  y_top = 0;
  row_inc = imagex - 4; if (special) row_inc *= 3;
  if (tchdr) {chdr=(tchdr->new_chdr)?(tchdr->new_chdr):(tchdr);} else chdr=0;

  len = *dptr++;
  copy_flag = (len & 0x01)?(FALSE):(TRUE);
  len =(*dptr++)<<16; len |= (*dptr++)<< 8; len |= (*dptr++); /* Read Len */
  if (len != dsize) /* CHECK FOR CORRUPTION - FAIRLY COMMON */
  {
    if (len & 0x01) len++; /* AVIs tend to have a size mismatch */
    if (len != dsize)
    {
     if (xa_verbose==TRUE) 
	 fprintf(stderr,"QT CVID corruption-skipping this frame %lx %lx\n",
								dsize,len);
     return(ACT_DLTA_NOP);
    }
  }
  xsz    = (*dptr++) << 8;  xsz    |= *dptr++;  /* xsize */
  ysz    = (*dptr++) << 8;  ysz    |= *dptr++;  /* ysize */
  strips = (*dptr++) << 8;  strips |= *dptr++;

  if (strips > qt_cvid_map_num)
  { int i;
    if (strips >= QT_CVID_MAX_STRIPS) 
		TheEnd1("CVID: strip ovrflow - contact Author");
    for(i=qt_cvid_map_num; i<strips; i++)
    {
      CVID_Color *cvmap;
      cvmap = (CVID_Color *)malloc( 1040 * sizeof(CVID_Color) );
      if (cvmap==0) TheEnd1("CVID: cvmap0 alloc err");
      qt_cvid_maps0[i] = cvmap;
      cvmap = (CVID_Color *)malloc( 1040 * sizeof(CVID_Color) );
      if (cvmap==0) TheEnd1("CVID: cvmap1 alloc err");
      qt_cvid_maps1[i] = cvmap;
      qt_cvid_vmap0[i] = qt_cvid_vmap1[i] = FALSE;
    }
  }
  qt_cvid_map_num = strips;

  DEBUG_LEVEL1 fprintf(stderr,"CVID <%lx %lx> strips %lx\n",xsz,ysz,strips);

  for(kk=0;kk<strips;kk++)
  {
    ULONG i,top_cid,cid,x0,y0,x1,y1; 
    LONG top_size, csize;

/* POD QUESTION: TREAT 20 and 22 separately or together???? */

    qt_cvid_cmap0 = qt_cvid_maps0[kk];
    qt_cvid_cmap1 = qt_cvid_maps1[kk];
/* OLD WAY
    if (qt_cvid_vmap0[kk]==FALSE) 
    { ULONG idx;
      CVID_Color *src,*dst;
      idx = (kk==0)?(strips-1):(kk-1);
      src = qt_cvid_maps0[idx]; dst = qt_cvid_maps0[kk];
      qt_cvid_vmap0[kk] = TRUE;
      for(i=0;i<1024;i++) dst[i]=src[i];
    }
    if (qt_cvid_vmap1[kk]==FALSE) 
    { ULONG idx;
      CVID_Color *src,*dst;
      idx = (kk==0)?(strips-1):(kk-1);
      src = qt_cvid_maps1[idx]; dst = qt_cvid_maps1[kk];
      qt_cvid_vmap1[kk] = TRUE;
      for(i=0;i<1024;i++) dst[i]=src[i];
    }
*/
/* NEW WAY gardiner*/
    qt_cvid_vmap0[kk] = TRUE;
    qt_cvid_vmap1[kk] = TRUE;
    if ( kk && (copy_flag==TRUE))
    { CVID_Color *src,*dst;
      src = qt_cvid_maps0[kk-1]; dst = qt_cvid_maps0[kk];
      for(i=0;i<1024;i++) dst[i]=src[i];
      src = qt_cvid_maps1[kk-1]; dst = qt_cvid_maps1[kk];
      for(i=0;i<1024;i++) dst[i]=src[i];
    }

    top_cid  = (*dptr++) << 8;   top_cid  |= *dptr++;
    top_size = (*dptr++) << 8;   top_size |= *dptr++;
    y0       = (*dptr++) << 8;   y0       |= *dptr++;
    x0       = (*dptr++) << 8;   x0       |= *dptr++;
    y1       = (*dptr++) << 8;   y1       |= *dptr++;
    x1       = (*dptr++) << 8;   x1       |= *dptr++;

    y_top += y1;
    top_size -= 12;
    x = 0;
    if (x1 != imagex) 
	fprintf(stderr,"CVID Warning x1(%lx) != imagex(%lx)\n",x1,imagex);
    DEBUG_LEVEL2
    {
      fprintf(stderr,"   %ld) %04lx %04lx <%lx,%lx> <%lx,%lx> yt %lx\n",
	    kk,top_cid,top_size,x0,y0,x1,y1,y_top);
    }
    while(top_size > 0)
    {
      cid   = (*dptr++) << 8;  cid   |= *dptr++;
      csize = (*dptr++) << 8;  csize |= *dptr++;
      /* DEBUG_LEVEL1 fprintf(stderr,"        %04lx %04lx\n",cid,csize); */
      top_size -= csize;
      csize -= 4;
      switch(cid)
      {
	case 0x2000: 
	case 0x2200: 
	  { ULONG i;
	    CVID_Color *cvid_map;

	    if (cid == 0x2200)
	    {
  	      cvid_map = qt_cvid_cmap1;
	      for(i=0;i<qt_cvid_map_num;i++) qt_cvid_vmap1[i] = FALSE;
	      qt_cvid_vmap1[kk] = TRUE;
	    }
	    else if (cid == 0x2000) 
	    { 
  	      cvid_map = qt_cvid_cmap0;
	      for(i=0;i<qt_cvid_map_num;i++) qt_cvid_vmap0[i] = FALSE;
	      qt_cvid_vmap0[kk] = TRUE;
	    }

	    cnum = csize / 6;  
	    for(i=0; i<cnum; i++) 
	    { ULONG Y0,Y1,Y2,Y3,U,V;
	      ULONG r0,r1,r2,r3,g0,g1,g2,g3,b0,b1,b2,b3;
	      Y0 = (ULONG)*dptr++; Y1 = (ULONG)*dptr++;  /* luma */
	      Y2 = (ULONG)*dptr++; Y3 = (ULONG)*dptr++;
	      U = (ULONG)(*dptr++); /* chroma */
	      V = (ULONG)(*dptr++);

	      yuv_to_rgb(Y0,U,V,&r0,&g0,&b0);
	      yuv_to_rgb(Y1,U,V,&r1,&g1,&b1);
	      yuv_to_rgb(Y2,U,V,&r2,&g2,&b2);
	      yuv_to_rgb(Y3,U,V,&r3,&g3,&b3);

	      if (special)
	      { register ULONG off;
	        cvid_map[  i].r=r0; cvid_map[  i].g=g0; cvid_map[  i].b=b0; 
	        off=i+256;
	        cvid_map[off].r=r1; cvid_map[off].g=g1; cvid_map[off].b=b1;
	        off+=256;
	        cvid_map[off].r=r2; cvid_map[off].g=g2; cvid_map[off].b=b2;
	        off+=256;
	        cvid_map[off].r=r3; cvid_map[off].g=g3; cvid_map[off].b=b3;
	      }
	      else
	      {
	        cvid_map[i].clr = QT_Get_Color24(r0,g0,b0,map_flag,map,chdr);
	        cvid_map[i+256].clr =QT_Get_Color24(r1,g1,b1,map_flag,map,chdr);
	        cvid_map[i+512].clr =QT_Get_Color24(r2,g2,b2,map_flag,map,chdr);
	        cvid_map[i+768].clr =QT_Get_Color24(r3,g3,b3,map_flag,map,chdr);
	      }
	    } /* end of cnum loop */
	  } /* end of case */
	  break;
	case 0x2100: 
	case 0x2300: 
	  { ULONG k,flag,mask,ci;
	    CVID_Color *cvid_map;

	    if (cid == 0x2300) cvid_map = qt_cvid_cmap1; 
	    else cvid_map = qt_cvid_cmap0;

	    ci = 0;
	    while(csize > 0)
	    {
	      flag  = (*dptr++) << 24;  flag |= (*dptr++) << 16;
	      flag |= (*dptr++) <<  8;  flag |= *dptr++; csize -= 4;

	      mask = 0x80000000;
	      for(k=0;k<32;k++)
	      {
	        if (mask & flag)
		{ ULONG Y0,Y1,Y2,Y3,U,V;
		  ULONG r0,r1,r2,r3,g0,g1,g2,g3,b0,b1,b2,b3;
		  Y0 = (ULONG)*dptr++; Y1 = (ULONG)*dptr++; /* luma */
		  Y2 = (ULONG)*dptr++; Y3 = (ULONG)*dptr++;
		  U = (ULONG)(*dptr++);
		  V = (ULONG)(*dptr++);
		  csize -= 6;
 
		  yuv_to_rgb(Y0,U,V,&r0,&g0,&b0);
		  yuv_to_rgb(Y1,U,V,&r1,&g1,&b1);
		  yuv_to_rgb(Y2,U,V,&r2,&g2,&b2);
		  yuv_to_rgb(Y3,U,V,&r3,&g3,&b3);

		  if (special)
		  { register ULONG off;
		    cvid_map[ ci].r=r0; cvid_map[ ci].g=g0; cvid_map[ ci].b=b0; 
		    off = ci+256;
		    cvid_map[off].r=r1; cvid_map[off].g=g1; cvid_map[off].b=b1;
		    off += 256;
		    cvid_map[off].r=r2; cvid_map[off].g=g2; cvid_map[off].b=b2;
		    off += 256;
		    cvid_map[off].r=r3; cvid_map[off].g=g3; cvid_map[off].b=b3;
		  }
		  else
		  {
		    cvid_map[ci].clr = 
				QT_Get_Color24(r0,g0,b0,map_flag,map,chdr);
		    cvid_map[ci+256].clr =
				QT_Get_Color24(r1,g1,b1,map_flag,map,chdr);
		    cvid_map[ci+512].clr =
				QT_Get_Color24(r2,g2,b2,map_flag,map,chdr);
		    cvid_map[ci+768].clr =
				QT_Get_Color24(r3,g3,b3,map_flag,map,chdr);
		  }
		} /* end of if update */
	        ci++; mask >>= 1;
	      } /* loop thru flag */
	    } /* while csize > 0 */
	    if (csize != 0) fprintf(stderr,"CVID_21 err sz %04lx\n",csize);
	  } /* end of case */
	  break;
	case 0x3000: 
	{ ULONG flag;

	  while( (csize > 0) && (y < y_top) )
	  { ULONG mask;
	    LONG j;
	    flag  = (*dptr++) << 24;  flag |= (*dptr++) << 16;
	    flag |= (*dptr++) <<  8;  flag |= *dptr++; csize -= 4;

	    mask = 0x80000000; j = 32;
	    for(j=0; j<32; j++)
	    { 
	      if (y >= y_top) break;
	      if (mask & flag) /* update blocks 4 bytes map 0*/
	      { ULONG d0,d1,d2,d3;
	        d0 = *dptr++; d1 = *dptr++; 
		d2 = *dptr++; d3 = *dptr++; csize -= 4;
		QT_CVID_C4(image,x,y,imagex,special,map_flag,
						d0,d1,d2,d3,qt_cvid_cmap0);
	      }
	      else /* 1 byte map 1 */
	      { ULONG d;
		d = *dptr++; csize--;
		QT_CVID_C1(image,x,y,imagex,special,map_flag,d,qt_cvid_cmap1);
	      }
              x += 4; if (x >= imagex) {x = 0; y += 4;}
	      mask >>= 1;
            } /* end of loop through flags */
	    if (csize < 4) { dptr += csize;  csize = 0; } /* POD still ness?? */
	  } /* end of csize loop */
	  if (csize) dptr += csize;
	} /* end of case 3000 */
	break;
	case 0x3200: /* Every Byte is <C1> */ 
	{
	  while( (csize > 0) && (y < y_top) )
	  { ULONG d;
	    d = *dptr++; csize--;
	    QT_CVID_C1(image,x,y,imagex,special,map_flag,d,qt_cvid_cmap1);
            x += 4; if (x >= imagex) {x = 0; y += 4;}
	  }
	  if (csize) dptr += csize;
	} /* end of case 3200 */
	break;
/***********
 Used to have a funky combination of flags and 2 bits codes(00 01 10 11), but
 someone pointed out it was actually a combinations of 1 and 2 bit codes.
 Slightly slower this way, but easier to understand.

  0   SKIP
  10  C1
  11  C4

if(nextbit)
{
  if(nextbit)
    C4
  else
    C1
}
***********/
	case 0x3100: 
	{ ULONG mcode;

	  while( (csize > 0) && (y < y_top) )
	  { ULONG mcode,mask;
	    LONG j;
	    mcode  = (*dptr++) << 24;  mcode |= (*dptr++) << 16;
	    mcode |= (*dptr++) <<  8;  mcode |= *dptr++; csize -= 4;
	    mask = 0x80000000;
	    while( (mask) && (y < y_top) )
	    {
	      if (mcode & mask)
	      {
		if (mask == 1)
		{
		  if (csize < 0) break;
		  mcode  = (*dptr++) << 24;  mcode |= (*dptr++) << 16;
		  mcode |= (*dptr++) <<  8;  mcode |= *dptr++; csize -= 4;
		  mask = 0x80000000;
		} else mask >>= 1;

		if (mcode & mask)  /* C4 */
		{ ULONG d0,d1,d2,d3;
		  d0 = *dptr++; d1 = *dptr++;
		  d2 = *dptr++; d3 = *dptr++; csize -= 4;
		  QT_CVID_C4(image,x,y,imagex,special,map_flag,
						d0,d1,d2,d3,qt_cvid_cmap0);
		}
		else /* C1 */
		{ ULONG d = *dptr++; csize--;
		  QT_CVID_C1(image,x,y,imagex,special,map_flag,
							d,qt_cvid_cmap1);
		}
	      } /* else SKIP */
	      mask >>= 1;
	      x += 4; if (x >= imagex) {x = 0; y += 4;}
	    } /* end of loop through mask */
	  } /* end of csize loop */
	  if (csize) dptr += csize; /* better way of doing this */
	} /* end of case 3000 */
	break;

	default:
	  fprintf(stderr,"CVID unknown cid %08lx\n",cid);
	  TheEnd();
	  break;
      } /* end of switch */
    } /* end of top_size */
  } /* end of strips */
  if (map_flag) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

#define QT_CVID_C1_BLK(ip,CAST,d,cv_map,rinc) { register CAST d0,d1; \
 *ip++ = d0 = (CAST)(cv_map[d].clr); *ip++ = d0; d += 256;	\
 *ip++ = d1 = (CAST)(cv_map[d].clr); *ip   = d1; d += 256;	\
  ip += rinc; \
 *ip++ = d0; *ip++ = d0; *ip++ = d1; *ip = d1; ip += rinc;	\
 *ip++ = d0 = (CAST)(cv_map[ d ].clr); *ip++ = d0; d += 256;	\
 *ip++ = d1 = (CAST)(cv_map[ d ].clr); *ip   = d1;		\
  ip += rinc; *ip++ = d0; *ip++ = d0; *ip++ = d1; *ip = d1; }

#define QT_CVID_C4_BLK(ip,CAST,d0,d1,cv_map,rinc) { \
 *ip++ = (CAST)(cv_map[d0].clr); d0 += 256;  \
 *ip++ = (CAST)(cv_map[d0].clr); d0 += 256;  \
 *ip++ = (CAST)(cv_map[d1].clr); d1 += 256;  \
 *ip   = (CAST)(cv_map[d1].clr); d1 += 256; ip += rinc; \
 *ip++ = (CAST)(cv_map[d0].clr); d0 += 256;  \
 *ip++ = (CAST)(cv_map[d0].clr); 		  \
 *ip++ = (CAST)(cv_map[d1].clr); d1 += 256;  \
 *ip   = (CAST)(cv_map[d1].clr); }

void QT_CVID_C1(image,x,y,imagex,special,map_flag,d,cvid_map)
UBYTE *image;
ULONG x,y,imagex,special,map_flag,d;
CVID_Color *cvid_map;
{ ULONG row_inc;
  row_inc = imagex - 3;
  if (special)
  { UBYTE *i_ptr = (UBYTE *)(image + 3*(y * imagex + x) );
    register UBYTE r0,r1,b0,b1,g0,g1;
    row_inc *= 3; row_inc -= 2;
    *i_ptr++ = r0 = (UBYTE)(cvid_map[ d ].r);  
    *i_ptr++ = g0 = (UBYTE)(cvid_map[ d ].g);  
    *i_ptr++ = b0 = (UBYTE)(cvid_map[ d ].b);  
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;  d += 256;
    *i_ptr++ = r1 = (UBYTE)(cvid_map[ d ].r);  
    *i_ptr++ = g1 = (UBYTE)(cvid_map[ d ].g);  
    *i_ptr++ = b1 = (UBYTE)(cvid_map[ d ].b);  
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr = b1;  d += 256;
     i_ptr += row_inc;
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr++ = b1;
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr   = b1;
     i_ptr += row_inc;
    *i_ptr++ = r0 = (UBYTE)(cvid_map[ d ].r);  
    *i_ptr++ = g0 = (UBYTE)(cvid_map[ d ].g);  
    *i_ptr++ = b0 = (UBYTE)(cvid_map[ d ].b);  
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;  d += 256;
    *i_ptr++ = r1 = (UBYTE)(cvid_map[ d ].r);  
    *i_ptr++ = g1 = (UBYTE)(cvid_map[ d ].g);  
    *i_ptr++ = b1 = (UBYTE)(cvid_map[ d ].b);  
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr = b1;
     i_ptr += row_inc;
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;
    *i_ptr++ = r0; *i_ptr++ = g0; *i_ptr++ = b0;
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr++ = b1;
    *i_ptr++ = r1; *i_ptr++ = g1; *i_ptr   = b1;
    return;
  }
  if ( (x11_bytes_pixel==1) || (map_flag == FALSE) )
  { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
    QT_CVID_C1_BLK(i_ptr,UBYTE,d,cvid_map,row_inc);
  }
  else if (x11_bytes_pixel==2)
  { USHORT *i_ptr = (USHORT *)(image + ((y*imagex+x)<<1) );
    QT_CVID_C1_BLK(i_ptr,USHORT,d,cvid_map,row_inc);
  }
  else /* if (x11_bytes_pixel==4) */
  { ULONG *i_ptr = (ULONG *)(image + ((y*imagex+x)<<2) );
    QT_CVID_C1_BLK(i_ptr,ULONG,d,cvid_map,row_inc);
  }
}

void QT_CVID_C4(image,x,y,imagex,special,map_flag,d0,d1,d2,d3,cvid_map)
UBYTE *image;
ULONG x,y,imagex,special,map_flag;
ULONG d0,d1,d2,d3;
CVID_Color *cvid_map;
{ ULONG row_inc;
  row_inc = imagex - 3;
  if (special)
  { UBYTE *i_ptr = (UBYTE *)(image + 3*(y * imagex + x) );
    row_inc *= 3; row_inc -= 2;
    *i_ptr++ = (UBYTE)(cvid_map[d0].r);  *i_ptr++ = (UBYTE)(cvid_map[d0].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d0].b); d0 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d0].r);  *i_ptr++ = (UBYTE)(cvid_map[d0].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d0].b); d0 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d1].r);  *i_ptr++ = (UBYTE)(cvid_map[d1].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d1].b); d1 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d1].r);  *i_ptr++ = (UBYTE)(cvid_map[d1].g);  
    *i_ptr   = (UBYTE)(cvid_map[d1].b); d1 += 256;  i_ptr += row_inc;
    *i_ptr++ = (UBYTE)(cvid_map[d0].r);  *i_ptr++ = (UBYTE)(cvid_map[d0].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d0].b); d0 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d0].r);  *i_ptr++ = (UBYTE)(cvid_map[d0].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d0].b);
    *i_ptr++ = (UBYTE)(cvid_map[d1].r);  *i_ptr++ = (UBYTE)(cvid_map[d1].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d1].b); d1 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d1].r);  *i_ptr++ = (UBYTE)(cvid_map[d1].g);  
    *i_ptr   = (UBYTE)(cvid_map[d1].b); i_ptr += row_inc;
    *i_ptr++ = (UBYTE)(cvid_map[d2].r);  *i_ptr++ = (UBYTE)(cvid_map[d2].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d2].b); d2 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d2].r);  *i_ptr++ = (UBYTE)(cvid_map[d2].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d2].b); d2 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d3].r);  *i_ptr++ = (UBYTE)(cvid_map[d3].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d3].b); d3 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d3].r);  *i_ptr++ = (UBYTE)(cvid_map[d3].g);  
    *i_ptr   = (UBYTE)(cvid_map[d3].b); d3 += 256;  i_ptr += row_inc;
    *i_ptr++ = (UBYTE)(cvid_map[d2].r);  *i_ptr++ = (UBYTE)(cvid_map[d2].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d2].b); d2 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d2].r);  *i_ptr++ = (UBYTE)(cvid_map[d2].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d2].b);
    *i_ptr++ = (UBYTE)(cvid_map[d3].r);  *i_ptr++ = (UBYTE)(cvid_map[d3].g);  
    *i_ptr++ = (UBYTE)(cvid_map[d3].b); d3 += 256;  
    *i_ptr++ = (UBYTE)(cvid_map[d3].r);  *i_ptr++ = (UBYTE)(cvid_map[d3].g);  
    *i_ptr   = (UBYTE)(cvid_map[d3].b);
    return;
  }
  if ( (x11_bytes_pixel==1) || (map_flag == FALSE) )
  { UBYTE *i_ptr = (UBYTE *)(image + y * imagex + x);
    QT_CVID_C4_BLK(i_ptr,UBYTE,d0,d1,cvid_map,row_inc);
    i_ptr += row_inc;
    QT_CVID_C4_BLK(i_ptr,UBYTE,d2,d3,cvid_map,row_inc);
  }
  else if (x11_bytes_pixel==2)
  { USHORT *i_ptr = (USHORT *)(image + ((y*imagex+x)<<1) );
    QT_CVID_C4_BLK(i_ptr,USHORT,d0,d1,cvid_map,row_inc);
    i_ptr += row_inc;
    QT_CVID_C4_BLK(i_ptr,USHORT,d2,d3,cvid_map,row_inc);
  }
  else /* if (x11_bytes_pixel==4) */
  { ULONG *i_ptr = (ULONG *)(image + ((y*imagex+x)<<2) );
    QT_CVID_C4_BLK(i_ptr,ULONG,d0,d1,cvid_map,row_inc);
    i_ptr += row_inc;
    QT_CVID_C4_BLK(i_ptr,ULONG,d2,d3,cvid_map,row_inc);
  }
}

void yuv_to_rgb(y,u,v,ir,ig,ib)
ULONG y,u,v,*ir,*ig,*ib;
{
  LONG r,g,b;
  y <<= 14;
  r = ( (LONG)(y) + QT_VR_tab[v]);
  g = ( (LONG)(y) + QT_UG_tab[u] + QT_VG_tab[v]);
  b = ( (LONG)(y) + QT_UB_tab[u]);
  if (r<0) r = 0; if (g<0) g = 0; if (b<0) b = 0;
  r >>= 14; g >>= 14; b >>= 14;
  if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255;
  *ir = (ULONG)r; *ig = (ULONG)g; *ib = (ULONG)b;
}
  

/*
 *      R = Y               + 1.40200 * V
 *      G = Y - 0.34414 * U - 0.71414 * V
 *      B = Y + 1.77200 * U
 */
void QT_Gen_YUV_Tabs()
{
  LONG i;

  if (QT_UB_tab==0)
  {
    QT_UB_tab = (LONG *)malloc( 256 * sizeof(LONG) );
    QT_VR_tab = (LONG *)malloc( 256 * sizeof(LONG) );
    QT_UG_tab = (LONG *)malloc( 256 * sizeof(LONG) );
    QT_VG_tab = (LONG *)malloc( 256 * sizeof(LONG) );
    if (  (QT_UB_tab==0) || (QT_VR_tab==0)
	||(QT_UG_tab==0)||(QT_VG_tab==0) ) TheEnd1("CVID: yuv tab malloc err");
  }

  for(i=0;i<256;i++)
  {
    float x = (float)(i);
    if (i & 0x80) x -= 256.0;
    x *= 16384.0; /* 1<<14) */
    QT_UB_tab[i] = (LONG)( 1.77200 * x);
    QT_VR_tab[i] = (LONG)( 1.40200 * x);
    QT_UG_tab[i] = (LONG)(-0.34414 * x);
    QT_VG_tab[i] = (LONG)(-0.71414 * x);
  }
}

char *XA_rindex(s,c)
char *s,c;
{
  int len = strlen(s);
  char *p = s + len;
  while(len >= 0)
  {
    if (*p == c) return(p);
    else {p--; len--;}
  }
  return( (char *)(NULL) );
}

/*********************************************
 * Read and Parse Audio Codecs
 *
 **********/
void QT_Read_Audio_STSD(fin)
{ ULONG i,version,num,cur,sup;
  version = UTIL_Get_MSB_Long(fin);
  num = UTIL_Get_MSB_Long(fin);
  DEBUG_LEVEL2 fprintf(stderr,"     ver = %lx  num = %lx\n", version,num);
  if (qts_codecs == 0)
  { qts_codec_num = num;
    qts_codecs = (QTS_CODEC_HDR *)malloc(qts_codec_num * sizeof(QTS_CODEC_HDR));
    if (qts_codecs==0) TheEnd1("QT STSD: malloc err");
    cur = 0;
  }
  else
  { QTS_CODEC_HDR *tcodecs;
    tcodecs = (QTS_CODEC_HDR *)malloc((qts_codec_num+num) * sizeof(QTS_CODEC_HDR))
;
    if (tcodecs==0) TheEnd1("QT STSD: malloc err");
    for(i=0;i<qts_codec_num;i++) tcodecs[i] = qts_codecs[i];
    cur = qts_codec_num;
    qts_codec_num += num;
    free(qts_codecs);
    qts_codecs = tcodecs;
  }
  sup = 0;
  for(i=0; i < num; i++)
  {
    sup |= QT_Read_Audio_Codec_HDR( &qts_codecs[cur], fin );
    cur++;
  }
#ifdef POD_AUDIO_BETA
  if (xa_audio_enable && sup) qt_audio_attempt = TRUE;
  else 
#endif
     qt_audio_attempt = FALSE;
}


ULONG QT_Read_Audio_Codec_HDR(c_hdr,fin)
QTS_CODEC_HDR *c_hdr;
FILE *fin;
{ ULONG len;
  ULONG ret = 1;
  len			= UTIL_Get_MSB_Long(fin);
  c_hdr->compression	= UTIL_Get_MSB_Long(fin);
  c_hdr->dref_id	= UTIL_Get_MSB_Long(fin);
  c_hdr->version	= UTIL_Get_MSB_Long(fin);
  c_hdr->codec_rev	= UTIL_Get_MSB_Long(fin);
  c_hdr->vendor		= UTIL_Get_MSB_Long(fin);
  c_hdr->chan_num	= UTIL_Get_MSB_UShort(fin);
  c_hdr->bits_samp	= UTIL_Get_MSB_UShort(fin);
  c_hdr->comp_id	= UTIL_Get_MSB_UShort(fin);
  c_hdr->pack_size	= UTIL_Get_MSB_UShort(fin);
  c_hdr->samp_rate	= UTIL_Get_MSB_UShort(fin);
  c_hdr->pad		= UTIL_Get_MSB_UShort(fin);

#ifdef POD_AUDIO_BETA
  if (xa_verbose)
  {
    fprintf(stderr,"  Audio: "); QT_Audio_Type(c_hdr->compression);
    fprintf(stderr," Rate %ld Chans %ld Bps %ld cmp_id %lx\n",
	c_hdr->samp_rate,c_hdr->chan_num,c_hdr->bits_samp,c_hdr->comp_id);
/*PODTEMP */
    fprintf(stderr,"          v %ld crev %ld drefid %lx pk_sz %ld\n",c_hdr->version,c_hdr->codec_rev,c_hdr->dref_id,c_hdr->pack_size);
  }
#endif

  if (c_hdr->compression == QT_twos) c_hdr->compression =XA_AUDIO_SIGNED;
  else if (c_hdr->compression == QT_raw) c_hdr->compression =XA_AUDIO_LINEAR;
  else if (c_hdr->compression == QT_raw00) c_hdr->compression =XA_AUDIO_LINEAR;
  else
  {
    ret = 0;
    c_hdr->compression = XA_AUDIO_INVALID;
  }
  if (c_hdr->bits_samp==8) c_hdr->bps = 1;
  else if (c_hdr->bits_samp==16) c_hdr->bps = 2;
  else if (c_hdr->bits_samp==32) c_hdr->bps = 4;
  else c_hdr->bps = 100 + c_hdr->bits_samp;

  if (c_hdr->bps > 2) ret = 0;
  if (c_hdr->chan_num > 2) ret = 0;

  if (c_hdr->bps==2)		
  {
    c_hdr->compression |= XA_AUDIO_BPS_2_MSK;
    c_hdr->compression |= XA_AUDIO_BIGEND_MSK; /* only has meaning >= 2 bps */
  }
  if (c_hdr->chan_num==2)	c_hdr->compression |= XA_AUDIO_STEREO_MSK;

  return(ret);
}

void QT_Audio_Type(type)
ULONG type;
{
  switch(type)
  {
    case QT_raw:	fprintf(stderr,"PCM"); break;
    case QT_raw00:	fprintf(stderr,"PCM0"); break;
    case QT_twos:	fprintf(stderr,"TWOS"); break;
    case QT_MAC6:	fprintf(stderr,"MAC6"); break;
    default:		fprintf(stderr,"%08lx",type); break;
  }
}

/**************
 *
 * 
 *******/
void QT_Read_Audio_Data(fin,anim_hdr)
FILE *fin;
XA_ANIM_HDR *anim_hdr;
{
  ULONG ret,base_offset,i;
  ULONG cur_s2chunk,nxt_s2chunk;
  ULONG tag;

DEBUG_LEVEL1 fprintf(stderr,"QT_Read_Audio: attempt %lx co# %ld\n",
				qt_audio_attempt,qts_chunkoff_num);
  if (qt_audio_attempt==FALSE) return;
  if (qts_samp_sizes == 0) {fprintf(stderr,"no samples\n"); return; } 
  base_offset = 0;


  cur_s2chunk = 0;
  nxt_s2chunk = qts_s2chunks[cur_s2chunk + 1].first;
  tag =  qts_s2chunks[cur_s2chunk].tag;
  qt_audio_freq  = qts_codecs[tag].samp_rate;
  qt_audio_chans = qts_codecs[tag].chan_num;
  qt_audio_bps   = qts_codecs[tag].bps;
  qt_audio_type  = qts_codecs[tag].compression;
  qt_audio_end   = 1;

#ifdef POD_AUDIO_BETA
  if (qts_init_duration)
  { ULONG num,snd_size,d;
    UBYTE *snd_data;
    num  = (qt_audio_freq * qts_init_duration) / qt_tk_timescale;
    snd_size = num * qt_audio_bps;
    if ((qt_audio_type & XA_AUDIO_TYPE_MASK)==XA_AUDIO_LINEAR) d = 0x80;
    else d = 0x00;
    snd_data = (UBYTE *)malloc(snd_size);
    if (snd_data==0) TheEnd1("QT aud_dat: malloc err0");
    memset((char *)(snd_data),d,snd_size); 
    XA_Add_Sound(anim_hdr,snd_data,qt_audio_type, 0, qt_audio_freq,snd_size);
  }
#endif


  /* Loop through chunk offsets */
  for(i=0; i < qts_chunkoff_num; i++)
  { UBYTE *snd_data;
    ULONG size,off,num_samps,snd_size;
    ACT_DLTA_HDR *dlta_hdr;

    off =  base_offset + qts_chunkoffs[i];
    fseek(fin,off,0);  /* move to start of chunk data */

DEBUG_LEVEL2 fprintf(stderr,"Audio: co %ld) curS2 %ld nxtS2 %ld totS2 %ld\n",
	i,cur_s2chunk,nxt_s2chunk,qts_s2chunk_num);

    if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qts_s2chunk_num) )
    {
      cur_s2chunk++;
      nxt_s2chunk = qts_s2chunks[cur_s2chunk+1].first;
    }
    num_samps = qts_s2chunks[cur_s2chunk].num; /* * sttz */
DEBUG_LEVEL2 fprintf(stderr,"Audio:       curS2 %ld nxtS2 %ld num_samps %ld\n",
	cur_s2chunk,nxt_s2chunk,num_samps);

    /* Check tags and possibly move to new codec */
    if (qts_s2chunks[cur_s2chunk].tag >= qts_codec_num) 
    {
      fprintf(stderr,"QT Data: Warning stsc chunk invalid %ld tag %ld\n",
		cur_s2chunk,qts_s2chunks[cur_s2chunk].tag);
    } 
    else if (qts_s2chunks[cur_s2chunk].tag != tag)
    {
      tag =  qts_s2chunks[cur_s2chunk].tag;
      qt_audio_freq  = qts_codecs[tag].samp_rate;
      qt_audio_chans = qts_codecs[tag].chan_num;
      qt_audio_bps   = qts_codecs[tag].bps;
      qt_audio_type  = qts_codecs[tag].compression;
      qt_audio_end   = 1;
    }

/*PODNOTE: this'll only work if STSZ num is 1 or matches chunk offset size */
/* STSZ needs to same # of entries as well. */
    if (i < qts_samp_num) size = qts_samp_sizes[i];

#ifdef POD_AUDIO_BETA
    snd_size = num_samps * size;
    snd_data = (UBYTE *)malloc(snd_size);
    if (snd_data==0) TheEnd1("QT aud_dat: malloc err");
    ret = fread(snd_data, snd_size, 1, fin);
    if (ret != 1) { fprintf(stderr,"QT: snd rd err\n"); return; }
    XA_Add_Sound(anim_hdr,snd_data,qt_audio_type, 0, qt_audio_freq,snd_size);
#endif
  } /* end of chunk_offset loop */
}


/********
 * Have No Clue
 *
 ****/
void QT_Read_STGS(fin,len)
FILE *fin;
LONG len;
{
  ULONG i,version,num;
  ULONG samps,pad;

  version	= UTIL_Get_MSB_Long(fin);
  num		= UTIL_Get_MSB_Long(fin); len -= 16;
  qt_stgs_num = 0;
  for(i=0; i<num; i++)
  {
    samps	= UTIL_Get_MSB_Long(fin);
    pad		= UTIL_Get_MSB_Long(fin);	len -= 8;
    qt_stgs_num += samps;
  }
  while(len > 0) {len--; getc(fin); }
}


ULONG
QT_Decode_YUV2(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG size;
  UBYTE *dptr;
  UBYTE *iptr;
  XA_CHDR *chdr;

  dptr = delta;

  if (tchdr)	{ chdr = (tchdr->new_chdr)?(tchdr->new_chdr):(tchdr); } 
  else		chdr=0;
  size = imagex * imagey;
/* Y0 U Y1 V  encodes two pixel Y0/U/V and Y1/U/V */
  if (special)
  { UBYTE *iptr = image;
    while(size > 0)
    { ULONG y0,y1,u,v,chroma,r,g,b;
      y0 = *dptr++; u = *dptr++;  y1 = *dptr++; v = *dptr++;  size -= 2;
      yuv_to_rgb(y0,u,v,&r,&g,&b);
      *iptr++ = r; *iptr++ = g; *iptr++ = b;
      yuv_to_rgb(y1,u,v,&r,&g,&b);
      *iptr++ = r; *iptr++ = g; *iptr++ = b;
    }
  }
  else if ( (x11_bytes_pixel==1) || (map_flag==FALSE) )
  { UBYTE *iptr = image;
    while(size > 0)
    { ULONG y0,y1,u,v,chroma,r,g,b;
      y0 = *dptr++; u = *dptr++;  y1 = *dptr++; v = *dptr++;  size -= 2;
      yuv_to_rgb(y0,u,v,&r,&g,&b);
      *iptr++  = (UBYTE)QT_Get_Color24(r,g,b,map_flag,map,chdr);
      yuv_to_rgb(y1,u,v,&r,&g,&b);
      *iptr++  = (UBYTE)QT_Get_Color24(r,g,b,map_flag,map,chdr);
    }
  }
  else if (x11_bytes_pixel==4)
  { ULONG *iptr = (ULONG *)image;
    while(size > 0)
    { ULONG y0,y1,u,v,chroma,r,g,b;
      y0 = *dptr++; u = *dptr++;  y1 = *dptr++; v = *dptr++;  size -= 2;
      yuv_to_rgb(y0,u,v,&r,&g,&b);
      *iptr++  = (ULONG)QT_Get_Color24(r,g,b,map_flag,map,chdr);
      yuv_to_rgb(y1,u,v,&r,&g,&b);
      *iptr++  = (ULONG)QT_Get_Color24(r,g,b,map_flag,map,chdr);
    }
  }
  else /* if (x11_bytes_pixel==2) */
  { USHORT *iptr = (USHORT *)image;
    while(size > 0)
    { ULONG y0,y1,u,v,chroma,r,g,b;
      y0 = *dptr++; u = *dptr++;  y1 = *dptr++; v = *dptr++;  size -= 2;
      yuv_to_rgb(y0,u,v,&r,&g,&b);
      *iptr++  = (USHORT)QT_Get_Color24(r,g,b,map_flag,map,chdr);
      yuv_to_rgb(y1,u,v,&r,&g,&b);
      *iptr++  = (USHORT)QT_Get_Color24(r,g,b,map_flag,map,chdr);
    }
  }
  *xs = *ys = 0; *xe = imagex; *ye = imagey;
  if (map_flag==TRUE) return(ACT_DLTA_MAPD);
  else return(ACT_DLTA_NORM);
}

ULONG
QT_Decode_SPIG(image,delta,dsize,tchdr,map,map_flag,imagex,imagey,imaged,
					xs,ys,xe,ye,special,extra)
UBYTE *image;           /* Image Buffer. */
UBYTE *delta;           /* delta data. */
ULONG dsize;            /* delta size */
XA_CHDR *tchdr;		/* color map info */
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 extra;		/* extra info needed to decode delta */
{
  LONG size,x,y,row_inc;
  UBYTE *dptr;
  UBYTE *iptr;
  XA_CHDR *chdr;

  dptr = delta;

 *xs = *ys = 0; *xe = imagex; *ye = imagey;
 return(ACT_DLTA_NOP);
}


/**************************************
 * QT_Create_Default_Cmap
 *
 * This routine recreates the Default Apple colormap.
 * It is an educated quess after looking at two quicktime animations
 * and may not be totally correct, but seems to work okay.
 */
void QT_Create_Default_Cmap(cmap)
ColorReg *cmap;
{
  static UBYTE pat[10] = {0xee,0xdd,0xbb,0xaa,0x88,0x77,0x55,0x44,0x22,0x11};
  LONG r,g,b,i;

  r = g = b = 0xff;
  for(i=0;i<215;i++)
  {
    cmap[i].red   = 0x101 * r;
    cmap[i].green = 0x101 * g;
    cmap[i].blue  = 0x101 * b;
    b -= 0x33;
    if (b < 0) { b = 0xff; g -= 0x33; if (g < 0) { g = 0xff; r -= 0x33; } }
  }
  for(i=0;i<10;i++)
  { ULONG d = 0x101 * pat[i];
    ULONG ip = 215 + i; 
    cmap[ip].red   = d; cmap[ip].green = cmap[ip].blue  = 0; ip += 10;
    cmap[ip].green = d; cmap[ip].red   = cmap[ip].blue  = 0; ip += 10;
    cmap[ip].blue  = d; cmap[ip].red   = cmap[ip].green = 0; ip += 10;
    cmap[ip].red   = cmap[ip].green = cmap[ip].blue  = d;
  }
  qt_cmap[255].red = qt_cmap[255].green = qt_cmap[255].blue  = 0x00;
}
   
   

 




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