--- /dev/null
+/*
+======================================================================
+clip.c
+
+Functions for LWO2 image references.
+
+Ernie Wright 17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwFreeClip()
+
+Free memory used by an lwClip.
+====================================================================== */
+
+void lwFreeClip( lwClip *clip )
+{
+ if ( clip ) {
+ lwListFree( clip->ifilter, (void *) lwFreePlugin );
+ lwListFree( clip->pfilter, (void *) lwFreePlugin );
+
+ switch ( clip->type ) {
+ case ID_STIL:
+ _pico_free( clip->source.still.name);
+ break;
+
+ case ID_ISEQ:
+ _pico_free( clip->source.seq.prefix );
+ _pico_free( clip->source.seq.suffix );
+ break;
+
+ case ID_ANIM:
+ _pico_free( clip->source.anim.name );
+ _pico_free( clip->source.anim.server );
+ _pico_free( clip->source.anim.data );
+ break;
+
+ case ID_XREF:
+ _pico_free( clip->source.xref.string );
+ break;
+
+ case ID_STCC:
+ _pico_free( clip->source.cycle.name );
+ break;
+
+ default:
+ break;
+ }
+
+ _pico_free( clip );
+ }
+}
+
+
+/*
+======================================================================
+lwGetClip()
+
+Read image references from a CLIP chunk in an LWO2 file.
+====================================================================== */
+
+lwClip *lwGetClip( picoMemStream_t *fp, int cksize )
+{
+ lwClip *clip;
+ lwPlugin *filt;
+ unsigned int id;
+ unsigned short sz;
+ int pos, rlen;
+
+
+ /* allocate the Clip structure */
+
+ clip = _pico_calloc( 1, sizeof( lwClip ));
+ if ( !clip ) goto Fail;
+
+ clip->contrast.val = 1.0f;
+ clip->brightness.val = 1.0f;
+ clip->saturation.val = 1.0f;
+ clip->gamma.val = 1.0f;
+
+ /* remember where we started */
+
+ set_flen( 0 );
+ pos = _pico_memstream_tell( fp );
+
+ /* index */
+
+ clip->index = getI4( fp );
+
+ /* first subchunk header */
+
+ clip->type = getU4( fp );
+ sz = getU2( fp );
+ if ( 0 > get_flen() ) goto Fail;
+
+ sz += sz & 1;
+ set_flen( 0 );
+
+ switch ( clip->type ) {
+ case ID_STIL:
+ clip->source.still.name = getS0( fp );
+ break;
+
+ case ID_ISEQ:
+ clip->source.seq.digits = getU1( fp );
+ clip->source.seq.flags = getU1( fp );
+ clip->source.seq.offset = getI2( fp );
+ getU2( fp ); /* not sure what this is yet */
+ clip->source.seq.start = getI2( fp );
+ clip->source.seq.end = getI2( fp );
+ clip->source.seq.prefix = getS0( fp );
+ clip->source.seq.suffix = getS0( fp );
+ break;
+
+ case ID_ANIM:
+ clip->source.anim.name = getS0( fp );
+ clip->source.anim.server = getS0( fp );
+ rlen = get_flen();
+ clip->source.anim.data = getbytes( fp, sz - rlen );
+ break;
+
+ case ID_XREF:
+ clip->source.xref.index = getI4( fp );
+ clip->source.xref.string = getS0( fp );
+ break;
+
+ case ID_STCC:
+ clip->source.cycle.lo = getI2( fp );
+ clip->source.cycle.hi = getI2( fp );
+ clip->source.cycle.name = getS0( fp );
+ break;
+
+ default:
+ break;
+ }
+
+ /* error while reading current subchunk? */
+
+ rlen = get_flen();
+ if ( rlen < 0 || rlen > sz ) goto Fail;
+
+ /* skip unread parts of the current subchunk */
+
+ if ( rlen < sz )
+ _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+ /* end of the CLIP chunk? */
+
+ rlen = _pico_memstream_tell( fp ) - pos;
+ if ( cksize < rlen ) goto Fail;
+ if ( cksize == rlen )
+ return clip;
+
+ /* process subchunks as they're encountered */
+
+ id = getU4( fp );
+ sz = getU2( fp );
+ if ( 0 > get_flen() ) goto Fail;
+
+ while ( 1 ) {
+ sz += sz & 1;
+ set_flen( 0 );
+
+ switch ( id ) {
+ case ID_TIME:
+ clip->start_time = getF4( fp );
+ clip->duration = getF4( fp );
+ clip->frame_rate = getF4( fp );
+ break;
+
+ case ID_CONT:
+ clip->contrast.val = getF4( fp );
+ clip->contrast.eindex = getVX( fp );
+ break;
+
+ case ID_BRIT:
+ clip->brightness.val = getF4( fp );
+ clip->brightness.eindex = getVX( fp );
+ break;
+
+ case ID_SATR:
+ clip->saturation.val = getF4( fp );
+ clip->saturation.eindex = getVX( fp );
+ break;
+
+ case ID_HUE:
+ clip->hue.val = getF4( fp );
+ clip->hue.eindex = getVX( fp );
+ break;
+
+ case ID_GAMM:
+ clip->gamma.val = getF4( fp );
+ clip->gamma.eindex = getVX( fp );
+ break;
+
+ case ID_NEGA:
+ clip->negative = getU2( fp );
+ break;
+
+ case ID_IFLT:
+ case ID_PFLT:
+ filt = _pico_calloc( 1, sizeof( lwPlugin ));
+ if ( !filt ) goto Fail;
+
+ filt->name = getS0( fp );
+ filt->flags = getU2( fp );
+ rlen = get_flen();
+ filt->data = getbytes( fp, sz - rlen );
+
+ if ( id == ID_IFLT ) {
+ lwListAdd( (void *) &clip->ifilter, filt );
+ clip->nifilters++;
+ }
+ else {
+ lwListAdd( (void *) &clip->pfilter, filt );
+ clip->npfilters++;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* error while reading current subchunk? */
+
+ rlen = get_flen();
+ if ( rlen < 0 || rlen > sz ) goto Fail;
+
+ /* skip unread parts of the current subchunk */
+
+ if ( rlen < sz )
+ _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+ /* end of the CLIP chunk? */
+
+ rlen = _pico_memstream_tell( fp ) - pos;
+ if ( cksize < rlen ) goto Fail;
+ if ( cksize == rlen ) break;
+
+ /* get the next chunk header */
+
+ set_flen( 0 );
+ id = getU4( fp );
+ sz = getU2( fp );
+ if ( 6 != get_flen() ) goto Fail;
+ }
+
+ return clip;
+
+Fail:
+ lwFreeClip( clip );
+ return NULL;
+}
+
+
+/*
+======================================================================
+lwFindClip()
+
+Returns an lwClip pointer, given a clip index.
+====================================================================== */
+
+lwClip *lwFindClip( lwClip *list, int index )
+{
+ lwClip *clip;
+
+ clip = list;
+ while ( clip ) {
+ if ( clip->index == index ) break;
+ clip = clip->next;
+ }
+ return clip;
+}