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.