1 /*
2 ======================================================================
3 clip.c
4 
5 Functions for LWO2 image references.
6 
7 Ernie Wright  17 Sep 00
8 ====================================================================== */
9 
10 #include "../picointernal.h"
11 #include "lwo2.h"
12 
13 
14 /*
15 ======================================================================
16 lwFreeClip()
17 
18 Free memory used by an lwClip.
19 ====================================================================== */
20 
lwFreeClip(lwClip * clip)21 void lwFreeClip( lwClip *clip )
22 {
23    if ( clip ) {
24       lwListFree( clip->ifilter, (void *) lwFreePlugin );
25       lwListFree( clip->pfilter, (void *) lwFreePlugin );
26 
27       switch ( clip->type ) {
28           case ID_STIL:
29             _pico_free( clip->source.still.name);
30             break;
31 
32           case ID_ISEQ:
33             _pico_free( clip->source.seq.prefix );
34             _pico_free( clip->source.seq.suffix );
35             break;
36 
37           case ID_ANIM:
38             _pico_free( clip->source.anim.name );
39             _pico_free( clip->source.anim.server );
40             _pico_free( clip->source.anim.data );
41             break;
42 
43           case ID_XREF:
44             _pico_free( clip->source.xref.string );
45             break;
46 
47           case ID_STCC:
48             _pico_free( clip->source.cycle.name );
49             break;
50 
51           default:
52             break;
53       }
54 
55       _pico_free( clip );
56    }
57 }
58 
59 
60 /*
61 ======================================================================
62 lwGetClip()
63 
64 Read image references from a CLIP chunk in an LWO2 file.
65 ====================================================================== */
66 
lwGetClip(picoMemStream_t * fp,int cksize)67 lwClip *lwGetClip( picoMemStream_t *fp, int cksize )
68 {
69    lwClip *clip;
70    lwPlugin *filt;
71    unsigned int id;
72    unsigned short sz;
73    int pos, rlen;
74 
75 
76    /* allocate the Clip structure */
77 
78    clip = _pico_calloc( 1, sizeof( lwClip ));
79    if ( !clip ) goto Fail;
80 
81    clip->contrast.val = 1.0f;
82    clip->brightness.val = 1.0f;
83    clip->saturation.val = 1.0f;
84    clip->gamma.val = 1.0f;
85 
86    /* remember where we started */
87 
88    set_flen( 0 );
89    pos = _pico_memstream_tell( fp );
90 
91    /* index */
92 
93    clip->index = getI4( fp );
94 
95    /* first subchunk header */
96 
97    clip->type = getU4( fp );
98    sz = getU2( fp );
99    if ( 0 > get_flen() ) goto Fail;
100 
101    sz += sz & 1;
102    set_flen( 0 );
103 
104    switch ( clip->type ) {
105       case ID_STIL:
106          clip->source.still.name = getS0( fp );
107          break;
108 
109       case ID_ISEQ:
110          clip->source.seq.digits  = getU1( fp );
111          clip->source.seq.flags   = getU1( fp );
112          clip->source.seq.offset  = getI2( fp );
113          getU2( fp );  /* not sure what this is yet */
114          clip->source.seq.start   = getI2( fp );
115          clip->source.seq.end     = getI2( fp );
116          clip->source.seq.prefix  = getS0( fp );
117          clip->source.seq.suffix  = getS0( fp );
118          break;
119 
120       case ID_ANIM:
121          clip->source.anim.name   = getS0( fp );
122          clip->source.anim.server = getS0( fp );
123          rlen = get_flen();
124          clip->source.anim.data   = getbytes( fp, sz - rlen );
125          break;
126 
127       case ID_XREF:
128          clip->source.xref.index  = getI4( fp );
129          clip->source.xref.string = getS0( fp );
130          break;
131 
132       case ID_STCC:
133          clip->source.cycle.lo   = getI2( fp );
134          clip->source.cycle.hi   = getI2( fp );
135          clip->source.cycle.name = getS0( fp );
136          break;
137 
138       default:
139          break;
140    }
141 
142    /* error while reading current subchunk? */
143 
144    rlen = get_flen();
145    if ( rlen < 0 || rlen > sz ) goto Fail;
146 
147    /* skip unread parts of the current subchunk */
148 
149    if ( rlen < sz )
150       _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
151 
152    /* end of the CLIP chunk? */
153 
154    rlen = _pico_memstream_tell( fp ) - pos;
155    if ( cksize < rlen ) goto Fail;
156    if ( cksize == rlen )
157       return clip;
158 
159    /* process subchunks as they're encountered */
160 
161    id = getU4( fp );
162    sz = getU2( fp );
163    if ( 0 > get_flen() ) goto Fail;
164 
165    while ( 1 ) {
166       sz += sz & 1;
167       set_flen( 0 );
168 
169       switch ( id ) {
170          case ID_TIME:
171             clip->start_time = getF4( fp );
172             clip->duration = getF4( fp );
173             clip->frame_rate = getF4( fp );
174             break;
175 
176          case ID_CONT:
177             clip->contrast.val = getF4( fp );
178             clip->contrast.eindex = getVX( fp );
179             break;
180 
181          case ID_BRIT:
182             clip->brightness.val = getF4( fp );
183             clip->brightness.eindex = getVX( fp );
184             break;
185 
186          case ID_SATR:
187             clip->saturation.val = getF4( fp );
188             clip->saturation.eindex = getVX( fp );
189             break;
190 
191          case ID_HUE:
192             clip->hue.val = getF4( fp );
193             clip->hue.eindex = getVX( fp );
194             break;
195 
196          case ID_GAMM:
197             clip->gamma.val = getF4( fp );
198             clip->gamma.eindex = getVX( fp );
199             break;
200 
201          case ID_NEGA:
202             clip->negative = getU2( fp );
203             break;
204 
205          case ID_IFLT:
206          case ID_PFLT:
207             filt = _pico_calloc( 1, sizeof( lwPlugin ));
208             if ( !filt ) goto Fail;
209 
210             filt->name = getS0( fp );
211             filt->flags = getU2( fp );
212             rlen = get_flen();
213             filt->data = getbytes( fp, sz - rlen );
214 
215             if ( id == ID_IFLT ) {
216                lwListAdd( (void *) &clip->ifilter, filt );
217                clip->nifilters++;
218             }
219             else {
220                lwListAdd( (void *) &clip->pfilter, filt );
221                clip->npfilters++;
222             }
223             break;
224 
225          default:
226             break;
227       }
228 
229       /* error while reading current subchunk? */
230 
231       rlen = get_flen();
232       if ( rlen < 0 || rlen > sz ) goto Fail;
233 
234       /* skip unread parts of the current subchunk */
235 
236       if ( rlen < sz )
237          _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
238 
239       /* end of the CLIP chunk? */
240 
241       rlen = _pico_memstream_tell( fp ) - pos;
242       if ( cksize < rlen ) goto Fail;
243       if ( cksize == rlen ) break;
244 
245       /* get the next chunk header */
246 
247       set_flen( 0 );
248       id = getU4( fp );
249       sz = getU2( fp );
250       if ( 6 != get_flen() ) goto Fail;
251    }
252 
253    return clip;
254 
255 Fail:
256    lwFreeClip( clip );
257    return NULL;
258 }
259 
260 
261 /*
262 ======================================================================
263 lwFindClip()
264 
265 Returns an lwClip pointer, given a clip index.
266 ====================================================================== */
267 
lwFindClip(lwClip * list,int index)268 lwClip *lwFindClip( lwClip *list, int index )
269 {
270    lwClip *clip;
271 
272    clip = list;
273    while ( clip ) {
274       if ( clip->index == index ) break;
275       clip = clip->next;
276    }
277    return clip;
278 }
279