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