[4] | 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 | } |
---|