1 | /****************************************************************************** |
---|
2 | * SAGE - Scalable Adaptive Graphics Environment |
---|
3 | * |
---|
4 | * Copyright (C) 2004 Electronic Visualization Laboratory, |
---|
5 | * University of Illinois at Chicago |
---|
6 | * |
---|
7 | * All rights reserved. |
---|
8 | * |
---|
9 | * Redistribution and use in source and binary forms, with or without |
---|
10 | * modification, are permitted provided that the following conditions are met: |
---|
11 | * |
---|
12 | * * Redistributions of source code must retain the above copyright |
---|
13 | * notice, this list of conditions and the following disclaimer. |
---|
14 | * * Redistributions in binary form must reproduce the above |
---|
15 | * copyright notice, this list of conditions and the following disclaimer |
---|
16 | * in the documentation and/or other materials provided with the distribution. |
---|
17 | * * Neither the name of the University of Illinois at Chicago nor |
---|
18 | * the names of its contributors may be used to endorse or promote |
---|
19 | * products derived from this software without specific prior written permission. |
---|
20 | * |
---|
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
---|
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
---|
25 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
26 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
27 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
---|
28 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
---|
29 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
---|
30 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
31 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
32 | * |
---|
33 | * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/ |
---|
34 | * |
---|
35 | *****************************************************************************/ |
---|
36 | |
---|
37 | #define _LARGEFILE64_SOURCE 1 |
---|
38 | #define _FILE_OFFSET_BITS 64 |
---|
39 | |
---|
40 | #include <stdio.h> |
---|
41 | #include <stdlib.h> |
---|
42 | #include <fcntl.h> |
---|
43 | #include <unistd.h> |
---|
44 | #include <errno.h> |
---|
45 | #include <string.h> |
---|
46 | |
---|
47 | #ifndef sun |
---|
48 | #include <endian.h> |
---|
49 | #endif |
---|
50 | |
---|
51 | #include "bpmovie.h" |
---|
52 | #include "imginfo.h" |
---|
53 | |
---|
54 | /* Macros for (A<<24) + (B<<16) + (G<<8) + R-format pixels as from getimgdata */ |
---|
55 | |
---|
56 | #if defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) |
---|
57 | # define ROFF 3 |
---|
58 | # define GOFF 2 |
---|
59 | # define BOFF 1 |
---|
60 | #else /* assume little-endian */ |
---|
61 | # define ROFF 0 |
---|
62 | # define GOFF 1 |
---|
63 | # define BOFF 2 |
---|
64 | #endif |
---|
65 | |
---|
66 | #define PR(p) (p)[ROFF] |
---|
67 | #define PG(p) (p)[GOFF] |
---|
68 | #define PB(p) (p)[BOFF] |
---|
69 | |
---|
70 | char Usage[] = "\ |
---|
71 | Usage: %s -o OUTFILE.bmv [-w XSIZExYSIZE] [-e OFFSET[m|k|f]@OUTDISK] [-p BPP] [-f rate] FROM-TO%%INCR LEFTPATTERN [RIGHTPATTERN]\n\ |
---|
72 | Encode a sequence of TIFF/SGI/JPEG/etc. files as a .bmv movie,\n\ |
---|
73 | optionally storing the image data in a separate file or disk partition.\n\ |
---|
74 | Options:\n\ |
---|
75 | -o outfile.bmv Write movie (or its header at least) to this file. Required.\n\ |
---|
76 | -e offset[m|k|f]@outdisk If given, store the movie data at the given\n\ |
---|
77 | offset on the given device or file. THe offset may be\n\ |
---|
78 | specified as a number with suffix 'm', 'k' or 'f'\n\ |
---|
79 | in which case it's in units of 2^20 (MB), 2^10 (KB),\n\ |
---|
80 | or the frame size, respectively.\n\ |
---|
81 | -p bytesperpixel\n\ |
---|
82 | Selects pixel format: 1: grayscale 2: 16-bit 5-6-5 RGB 3: 24-bit RGB\n\ |
---|
83 | -f rate preferred frame rate (if any), frames/sec\n\ |
---|
84 | \n\ |
---|
85 | from-to%%incr range of frame numbers to apply to left+righpattern\n\ |
---|
86 | leftpattern printf format string for image name, e.g. /some/where/left.%%04d.tif\n\ |
---|
87 | rightpattern similar for right-hand stereo image, or \"-\" to omit\n"; |
---|
88 | |
---|
89 | |
---|
90 | char *prog; |
---|
91 | |
---|
92 | static int bytesper[5] = { 0, 1, 2, 3, 4 }; /* indexed by enum pixeltype values */ |
---|
93 | |
---|
94 | int skipmissing = 1; |
---|
95 | int prefrate = 0; |
---|
96 | |
---|
97 | #define MAXALIGN 16384 /* largest credible page size */ |
---|
98 | |
---|
99 | /* Find head with both hands -- compute tile arrangement */ |
---|
100 | void findhead( bpmvhead_t *head, int xwin, int ywin, int xtile, int ytile, enum pixeltype format ) |
---|
101 | { |
---|
102 | head->magic = BPMV3_MAGIC; |
---|
103 | head->xsize = xwin; |
---|
104 | head->ysize = ywin; |
---|
105 | head->format = format; |
---|
106 | head->xtile = xtile; |
---|
107 | head->ytile = ytile; |
---|
108 | head->nxtile = (xwin + xtile - 1) / xtile; |
---|
109 | head->nytile = (ywin + ytile - 1) / ytile; |
---|
110 | |
---|
111 | /* Configure for fully packed tiles, which should be most |
---|
112 | * efficient for stuffing at graphics card |
---|
113 | */ |
---|
114 | |
---|
115 | head->tilerowstride = bytesper[format] * xtile; |
---|
116 | head->xtilestride = head->tilerowstride * ytile; |
---|
117 | head->ytilestride = head->xtilestride * head->nxtile; |
---|
118 | head->imagestride = (head->ytilestride * head->nytile + MAXALIGN-1) & ~(MAXALIGN-1); |
---|
119 | |
---|
120 | head->start = head->imagestride; |
---|
121 | } |
---|
122 | |
---|
123 | int writeheader( char *outfname, off_t foffset, bpmvhead_t *head ) |
---|
124 | { |
---|
125 | int outfd; |
---|
126 | |
---|
127 | outfd = outfname == NULL ? 1 : open(outfname, O_LARGEFILE|O_CREAT|O_TRUNC|O_WRONLY, 0666); |
---|
128 | |
---|
129 | if(outfd < 0) { |
---|
130 | fprintf(stderr, "%s: Can't create output: %s: %s\n", |
---|
131 | prog, outfname, strerror(errno)); |
---|
132 | exit(1); |
---|
133 | } |
---|
134 | |
---|
135 | if(head->extfname[0] == '\0') { |
---|
136 | /* All in one file. */ |
---|
137 | char *headbuf = (char *)malloc( head->start ); |
---|
138 | |
---|
139 | memset(headbuf, 0, head->start); |
---|
140 | memcpy( headbuf, head, sizeof(*head) ); |
---|
141 | if(write( outfd, headbuf, head->start ) != head->start) { |
---|
142 | fprintf(stderr, "%s: %s: can't write %lld-byte header: %s\n", |
---|
143 | prog, outfname, head->start, strerror(errno)); |
---|
144 | exit(1); |
---|
145 | } |
---|
146 | free(headbuf); |
---|
147 | return outfd; |
---|
148 | |
---|
149 | } else { |
---|
150 | int headsize = &head->cmd[ strlen(head->cmd) + 1 ] - (char *)head; |
---|
151 | if(write( outfd, head, headsize ) != headsize) { |
---|
152 | fprintf(stderr, "%s: %s: can't write %d-byte header: %s\n", |
---|
153 | prog, outfname, headsize, strerror(errno)); |
---|
154 | exit(1); |
---|
155 | } |
---|
156 | |
---|
157 | close(outfd); |
---|
158 | |
---|
159 | outfd = open( head->extfname, O_LARGEFILE|O_CREAT|O_WRONLY, 0666 ); |
---|
160 | if(outfd < 0) { |
---|
161 | fprintf(stderr, "%s: %s: Can't open external-data file for writing: %s\n", |
---|
162 | prog, head->extfname, strerror(errno)); |
---|
163 | exit(1); |
---|
164 | } |
---|
165 | |
---|
166 | if(lseek(outfd, head->start, SEEK_SET) < 0) { |
---|
167 | fprintf(stderr, "%s: %s: Can't seek to %lld on external-data file: %s\n", |
---|
168 | prog, head->extfname, (long long) head->start, strerror(errno)); |
---|
169 | exit(1); |
---|
170 | } |
---|
171 | |
---|
172 | return outfd; |
---|
173 | } |
---|
174 | } |
---|
175 | |
---|
176 | |
---|
177 | |
---|
178 | unsigned char dither3[8][8]; /* dither bias values as function of position mod 8 */ |
---|
179 | |
---|
180 | /* 3-bit (0..7) dither pattern */ |
---|
181 | static void initdither3( unsigned char dith3[8][8] ) |
---|
182 | { |
---|
183 | int i, j; |
---|
184 | |
---|
185 | for(i = 0; i < 8; i++) { |
---|
186 | for(j = 0; j < 8; j++) { |
---|
187 | int ij = i^j; |
---|
188 | |
---|
189 | /* Discard bottom 3 bits of 6-bit dither pattern */ |
---|
190 | dith3[i][j] = |
---|
191 | ( ((ij&4)<<3) | ((i&4)<<2) | ((ij&2)<<2) | ((i&2)<<1) | ((ij&1)<<1) | (i&1) |
---|
192 | ) >> 3; |
---|
193 | } |
---|
194 | } |
---|
195 | } |
---|
196 | |
---|
197 | static void encode( unsigned char *aus, bpmvhead_t *head, |
---|
198 | int aox0, int xwin, int ywin, |
---|
199 | unsigned char *data, struct imginfo *info ) |
---|
200 | { |
---|
201 | int xtile = head->xtile; |
---|
202 | int ytile = head->ytile; |
---|
203 | int xtilestride = head->xtilestride; |
---|
204 | int ytilestride = head->ytilestride; |
---|
205 | int tilerowstride = head->tilerowstride; |
---|
206 | enum pixeltype format = head->format; |
---|
207 | int obpp = bytesper[ format ]; |
---|
208 | |
---|
209 | int inx, iny; /* size of intersection between image and output */ |
---|
210 | int ix0, iy0; /* initial position within image */ |
---|
211 | int irowstride; /* row-stride in image */ |
---|
212 | int tox0, tox1, toy0, toy1; /* range of tiles in image-output intersection */ |
---|
213 | int tox, toy; /* current tile number */ |
---|
214 | unsigned int ox0, oy0; |
---|
215 | |
---|
216 | #define IBPP 4 /* bytes per input-image pixel, as provided by getimgdata() */ |
---|
217 | |
---|
218 | |
---|
219 | irowstride = IBPP * info->xsize; /* getimgdata() was told to make 4-byte-per-pixel format */ |
---|
220 | |
---|
221 | /* How does image fit within [xwin,ywin]? */ |
---|
222 | if(info->xsize <= xwin) { |
---|
223 | /* Just right or too small. Center image in output area */ |
---|
224 | ix0 = 0; |
---|
225 | inx = info->xsize; |
---|
226 | ox0 = aox0 + (xwin - info->xsize) / 2; |
---|
227 | } else { |
---|
228 | /* Too large. Center and crop image to fit. */ |
---|
229 | ix0 = (info->xsize - xwin) / 2; |
---|
230 | inx = xwin; |
---|
231 | ox0 = aox0; |
---|
232 | } |
---|
233 | if(info->ysize <= ywin) { |
---|
234 | /* Just right or too small. Center image in output area */ |
---|
235 | iy0 = 0; |
---|
236 | iny = info->ysize; |
---|
237 | oy0 = (ywin - info->ysize) / 2; |
---|
238 | } else { |
---|
239 | /* Too large. Center and crop image to fit. */ |
---|
240 | iy0 = (info->ysize - ywin) / 2; |
---|
241 | iny = ywin; |
---|
242 | oy0 = 0; |
---|
243 | } |
---|
244 | |
---|
245 | tox0 = ox0 / xtile; tox1 = (ox0 + inx-1) / xtile; |
---|
246 | toy0 = oy0 / ytile; toy1 = (oy0 + iny-1) / ytile; |
---|
247 | |
---|
248 | /* Loop over tiles */ |
---|
249 | for(toy = toy0; toy <= toy1; toy++) { |
---|
250 | int iytile = iy0 + ytile*(toy-toy0); |
---|
251 | int oytend = (iny - iytile >= ytile) ? ytile : iny - iytile; |
---|
252 | int oxstart = ox0 % xtile; |
---|
253 | |
---|
254 | for(tox = tox0; tox <= tox1; tox++, oxstart = 0) { |
---|
255 | /* Loop within this tile */ |
---|
256 | int ixtile = ix0 + xtile*(tox-tox0); |
---|
257 | int oxtend = (inx - ixtile >= xtile) ? xtile : inx - ixtile; |
---|
258 | unsigned char *ipstart = data + IBPP * ixtile + irowstride * iytile; |
---|
259 | unsigned char *opstart = aus |
---|
260 | + toy * ytilestride |
---|
261 | + tox * xtilestride |
---|
262 | + oxstart * obpp; |
---|
263 | int oxt, oyt; |
---|
264 | |
---|
265 | for(oyt = 0; oyt < oytend; oyt++) { |
---|
266 | unsigned char *ip = ipstart + oyt * irowstride; |
---|
267 | unsigned char *op = opstart + oyt * tilerowstride; |
---|
268 | switch( format ) { |
---|
269 | |
---|
270 | case GRAY8: |
---|
271 | /* Convert RGB to grayscale using NTSC weighting convention */ |
---|
272 | for(oxt = oxstart; oxt < oxtend; oxt++, ip += IBPP, op++) |
---|
273 | *op = (77*PR(ip) + 151*PG(ip) + 28*PB(ip)) >> 8; |
---|
274 | break; |
---|
275 | |
---|
276 | case RGB565: |
---|
277 | { |
---|
278 | unsigned char *dith3row = &dither3[oyt & 7][0]; |
---|
279 | for(oxt = oxstart; oxt < oxtend; oxt++, ip += IBPP, op += 2) { |
---|
280 | /* Apply ordered dither while packing into 5-6-5 format */ |
---|
281 | unsigned short r, g, b; |
---|
282 | unsigned char dith3 = dith3row[oxt & 7] >> 3; |
---|
283 | r = PR(ip) + dith3; if(r > 255) r = 255; |
---|
284 | g = PG(ip) + (dith3>>1); if(g > 255) g = 255; |
---|
285 | b = PB(ip) + dith3; if(b > 255) b = 255; |
---|
286 | *(unsigned short *)op = |
---|
287 | ((r & 0xF8) << 8) | |
---|
288 | ((g & 0xFC) << 3) | |
---|
289 | ((b >> 3) & 0x1F); |
---|
290 | } |
---|
291 | break; |
---|
292 | } |
---|
293 | |
---|
294 | case RGB888: |
---|
295 | for(oxt = oxstart; oxt < oxtend; oxt++, ip += IBPP, op += 3) { |
---|
296 | op[0] = PR(ip); |
---|
297 | op[1] = PG(ip); |
---|
298 | op[2] = PB(ip); |
---|
299 | } |
---|
300 | break; |
---|
301 | |
---|
302 | case ABGR8888: |
---|
303 | for(oxt = oxstart; oxt < oxtend; oxt++, ip += IBPP, op += 4) { |
---|
304 | op[0] = 255; |
---|
305 | op[1] = PB(ip); |
---|
306 | op[2] = PG(ip); |
---|
307 | op[3] = PR(ip); |
---|
308 | } |
---|
309 | break; |
---|
310 | } |
---|
311 | } |
---|
312 | } |
---|
313 | } |
---|
314 | } |
---|
315 | |
---|
316 | int main( int argc, char *argv[] ) |
---|
317 | { |
---|
318 | char *outname = NULL; |
---|
319 | char *extout = NULL; |
---|
320 | long long outoffset = 0; |
---|
321 | int offsetframes = 0; |
---|
322 | |
---|
323 | char *left, *right; |
---|
324 | int ffrom, fto, finc, frameno; |
---|
325 | int i, count; |
---|
326 | |
---|
327 | enum pixeltype pixelformat = RGB565; |
---|
328 | int xwin = 1920, ywin = 1080; |
---|
329 | int xtile = 512, ytile = 512; |
---|
330 | bpmvhead_t head; |
---|
331 | int outfd = -1; |
---|
332 | int relshift = 0; |
---|
333 | |
---|
334 | unsigned char *aus; |
---|
335 | |
---|
336 | memset( &head, 0, sizeof(head)); |
---|
337 | |
---|
338 | for(i = 0, count = 0; i < argc; i++) { |
---|
339 | int len = strlen(argv[i]); |
---|
340 | if(count + len > sizeof(head.cmd)-2) |
---|
341 | len = sizeof(head.cmd)-2 - count; |
---|
342 | memcpy(head.cmd+count, argv[i], len); |
---|
343 | count += len; |
---|
344 | head.cmd[count++] = ' '; |
---|
345 | } |
---|
346 | head.cmd[--count] = '\0'; |
---|
347 | |
---|
348 | prog = argv[0]; |
---|
349 | |
---|
350 | while(argc>2 && argv[1][0] == '-' && argv[1][1] != '\0') { |
---|
351 | switch(argv[1][1]) { |
---|
352 | case 'o': |
---|
353 | outname = argv[2]; |
---|
354 | argc -= 2, argv += 2; |
---|
355 | break; |
---|
356 | |
---|
357 | case 'f': /* preferred play rate */ |
---|
358 | prefrate = atoi(argv[2]); |
---|
359 | if(strchr(argv[2], 'm') != NULL) |
---|
360 | prefrate = -abs(prefrate); /* in ms/frame rather than frames/sec */ |
---|
361 | argc -= 2, argv += 2; |
---|
362 | break; |
---|
363 | |
---|
364 | case 'e': { |
---|
365 | char *cp = strchr(argv[2], '@'); |
---|
366 | if(cp) { |
---|
367 | char *ep; |
---|
368 | outoffset = strtoll(argv[2], &ep, 0); |
---|
369 | switch(*ep) { |
---|
370 | case 'k': case 'K': outoffset <<= 10; break; |
---|
371 | case 'm': case 'M': outoffset <<= 20; break; |
---|
372 | case 'f': case 'F': offsetframes = 1; break; |
---|
373 | } |
---|
374 | extout = cp+1; |
---|
375 | } else { |
---|
376 | extout = argv[2]; |
---|
377 | } |
---|
378 | argc -= 2, argv += 2; |
---|
379 | } |
---|
380 | break; |
---|
381 | |
---|
382 | case 'L': |
---|
383 | relshift = -atoi(argv[2]); argc -= 2, argv += 2; |
---|
384 | break; |
---|
385 | |
---|
386 | case 'R': |
---|
387 | relshift = atoi(argv[2]); argc -= 2, argv += 2; |
---|
388 | break; |
---|
389 | |
---|
390 | case 'p': |
---|
391 | pixelformat = (enum pixeltype) atoi(argv[2]); |
---|
392 | if(pixelformat < 1 || pixelformat > 4) { |
---|
393 | fprintf(stderr, "%s -p: expected pixel format 1 (gray), 2 (rgr565), 3 (rgb24), 4 (rgba), not %s\n", prog, argv[2]); |
---|
394 | exit(1); |
---|
395 | } |
---|
396 | argc -= 2, argv += 2; |
---|
397 | break; |
---|
398 | |
---|
399 | case 'w': |
---|
400 | sscanf(argv[2], "%d%*c%d", &xwin, &ywin); |
---|
401 | argc -= 2, argv += 2; |
---|
402 | break; |
---|
403 | |
---|
404 | default: |
---|
405 | argc = 0; |
---|
406 | } |
---|
407 | } |
---|
408 | |
---|
409 | if(argc < 3) { |
---|
410 | fprintf(stderr, Usage, prog); |
---|
411 | exit(1); |
---|
412 | } |
---|
413 | |
---|
414 | ffrom = 0; |
---|
415 | fto = -1; |
---|
416 | finc = 1; |
---|
417 | |
---|
418 | if(sscanf(argv[1], "%d-%d%%%d", &ffrom, &fto, &finc) <= 0) { |
---|
419 | fprintf(stderr, "%s: expected from-to%%incr, got %s\n", prog, argv[1]); |
---|
420 | exit(1); |
---|
421 | } |
---|
422 | |
---|
423 | left = argv[2]; |
---|
424 | right = argc>3 ? argv[3] : NULL; |
---|
425 | |
---|
426 | if(fto < 0) |
---|
427 | fto = ffrom; |
---|
428 | if(finc == 0) |
---|
429 | finc = 1; |
---|
430 | |
---|
431 | count = (fto - ffrom) / finc + 1; |
---|
432 | |
---|
433 | findhead( &head, right ? 2*xwin : xwin, ywin, xtile, ytile, pixelformat ); |
---|
434 | |
---|
435 | |
---|
436 | head.nframes = count; |
---|
437 | |
---|
438 | if(relshift != 0) { |
---|
439 | head.prefshift = relshift; |
---|
440 | head.flags |= BPF_PREFSHIFT; |
---|
441 | } |
---|
442 | |
---|
443 | if(prefrate != 0) { |
---|
444 | head.prefrate = prefrate; |
---|
445 | head.flags |= BPF_PREFRATE; |
---|
446 | } |
---|
447 | |
---|
448 | if(right != NULL) |
---|
449 | head.flags |= BPF_STEREO; |
---|
450 | |
---|
451 | if(extout != NULL) { |
---|
452 | if(offsetframes) |
---|
453 | outoffset *= head.imagestride; |
---|
454 | head.flags |= BPF_EXTDATA; |
---|
455 | head.start = outoffset; |
---|
456 | strncpy( head.extfname, extout, sizeof(head.extfname)-1 ); |
---|
457 | } |
---|
458 | |
---|
459 | aus = (unsigned char *) malloc( head.imagestride ); |
---|
460 | if(aus == NULL) { |
---|
461 | fprintf(stderr, "%s: Can't allocate %d bytes for image buffer\n", |
---|
462 | prog, head.imagestride); |
---|
463 | exit(1); |
---|
464 | } |
---|
465 | memset(aus, 0, head.imagestride); |
---|
466 | |
---|
467 | if(pixelformat == RGB565) |
---|
468 | initdither3( dither3 ); |
---|
469 | |
---|
470 | fprintf(stderr, "RIGHT [%s], XWIN %d YWIN %d XTILE %d YTILE %d\n", right, xwin, ywin, xtile, ytile); |
---|
471 | |
---|
472 | for(frameno = ffrom, i = 0; i < count; i++, frameno += finc) { |
---|
473 | struct imginfo lefti, righti; |
---|
474 | unsigned char *leftd = NULL, *rightd = NULL; |
---|
475 | char leftname[300], rightname[300]; |
---|
476 | |
---|
477 | /* Find names of images for this frame */ |
---|
478 | sprintf(leftname, left, frameno); |
---|
479 | |
---|
480 | /* Read images. Give up if left-hand is missing. */ |
---|
481 | leftd = getimgdata( leftname, NULL, &lefti, 1, 4, 1 ); |
---|
482 | if(leftd == NULL) { |
---|
483 | fprintf(stderr, "%s: can't open %s\n", prog, leftname); |
---|
484 | if(skipmissing) |
---|
485 | continue; |
---|
486 | else |
---|
487 | break; |
---|
488 | } |
---|
489 | |
---|
490 | /* Is this first time? Emit header if so. */ |
---|
491 | |
---|
492 | if(i == 0) { |
---|
493 | outfd = writeheader( outname, outoffset, &head ); |
---|
494 | } |
---|
495 | |
---|
496 | /* Re-encode left (or only) image into buffer */ |
---|
497 | |
---|
498 | encode( aus, &head, 0, xwin, ywin, leftd, &lefti ); |
---|
499 | |
---|
500 | if(right != NULL) { |
---|
501 | /* If there's a right-hand image, encode it too. */ |
---|
502 | sprintf(rightname, right, frameno); |
---|
503 | rightd = (0==strcmp(rightname, "-")) ? NULL |
---|
504 | : getimgdata( rightname, NULL, &righti, 1, 4, 1 ); |
---|
505 | if(rightd == NULL) { |
---|
506 | if(rightname[0] != '-') |
---|
507 | fprintf(stderr, "%s: can't open %s\n", prog, rightname); |
---|
508 | rightd = leftd; |
---|
509 | righti = lefti; |
---|
510 | } |
---|
511 | |
---|
512 | encode( aus, &head, xwin, xwin, ywin, rightd, &righti ); |
---|
513 | } |
---|
514 | |
---|
515 | /* DEBUG */ |
---|
516 | *(int *)( aus + head.imagestride-4 ) = frameno; |
---|
517 | |
---|
518 | errno = 0; |
---|
519 | if(write( outfd, aus, head.imagestride ) != head.imagestride ) { |
---|
520 | fprintf(stderr, "%s: %s: write error: %s\n", |
---|
521 | prog, outname ? outname : "stdout", strerror(errno)); |
---|
522 | exit(1); |
---|
523 | } |
---|
524 | free(leftd); |
---|
525 | if(rightd != leftd && rightd != NULL) |
---|
526 | free(rightd); |
---|
527 | } |
---|
528 | return 0; |
---|
529 | } |
---|