1 /*===========================================================================*
2 * readframe.c *
3 * *
4 * procedures to read in frames *
5 * *
6 * EXPORTED PROCEDURES: *
7 * ReadFrame *
8 * SetFileType *
9 * SetFileFormat *
10 * *
11 *===========================================================================*/
12
13 /*
14 * Copyright (c) 1995 The Regents of the University of California.
15 * All rights reserved.
16 *
17 * Permission to use, copy, modify, and distribute this software and its
18 * documentation for any purpose, without fee, and without written agreement is
19 * hereby granted, provided that the above copyright notice and the following
20 * two paragraphs appear in all copies of this software.
21 *
22 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
23 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
24 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
25 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
28 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
30 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
31 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
32 */
33
34 /*
35 * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/readframe.c,v 1.27 1995/08/14 22:31:40 smoot Exp $
36 * $Log: readframe.c,v $
37 * Revision 1.27 1995/08/14 22:31:40 smoot
38 * reads training info from PPms now (needed for piping reads)
39 *
40 * Revision 1.26 1995/08/07 21:48:36 smoot
41 * better error reporting, JPG == JPEG now
42 *
43 * Revision 1.25 1995/06/12 20:30:12 smoot
44 * added popen for OS2
45 *
46 * Revision 1.24 1995/06/08 20:34:36 smoot
47 * added "b"'s to fopen calls to make MSDOS happy
48 *
49 * Revision 1.23 1995/05/03 10:16:01 smoot
50 * minor compile bug with static f
51 *
52 * Revision 1.22 1995/05/02 22:00:12 smoot
53 * added TUNEing, setting near-black values to black
54 *
55 * Revision 1.21 1995/03/27 21:00:01 eyhung
56 * fixed bug with some long jpeg names
57 *
58 * Revision 1.20 1995/02/02 01:05:54 eyhung
59 * Fixed aAdded error checking for stdin
60 *
61 * Revision 1.19 1995/02/01 05:01:12 eyhung
62 * Removed troubleshooting printf
63 *
64 * Revision 1.18 1995/01/31 21:08:16 eyhung
65 * Improved YUV_FORMAT strings with better algorithm
66 *
67 * Revision 1.17 1995/01/27 23:34:09 eyhung
68 * Removed temporary JPEG files created by JMOVIE input
69 *
70 * Revision 1.16 1995/01/27 21:57:43 eyhung
71 * Added case for reading original JMOVIES
72 *
73 * Revision 1.14 1995/01/24 23:47:51 eyhung
74 * Confusion with Abekas format fixed : all other YUV revisions are wrong
75 *
76 * Revision 1.13 1995/01/20 00:02:30 smoot
77 * added gamma correction
78 *
79 * Revision 1.12 1995/01/19 23:09:21 eyhung
80 * Changed copyrights
81 *
82 * Revision 1.11 1995/01/17 22:23:07 aswan
83 * AbekasYUV chrominance implementation fixed
84 *
85 * Revision 1.10 1995/01/17 21:26:25 smoot
86 * Tore our average on Abekus/Phillips reconstruct
87 *
88 * Revision 1.9 1995/01/17 08:22:34 eyhung
89 * Debugging of ReadAYUV
90 *
91 * Revision 1.8 1995/01/16 13:18:24 eyhung
92 * Interlaced YUV format (e.g. Abekas) support added (slightly buggy)
93 *
94 * Revision 1.7 1995/01/16 06:58:23 eyhung
95 * Added skeleton of ReadAYUV (for Abekas YUV files)
96 *
97 * Revision 1.6 1995/01/13 23:22:23 smoot
98 * Added ReadY, so we can make black&white movies (how artsy!)
99 *
100 * Revision 1.5 1994/12/16 00:20:40 smoot
101 * Now errors out on too small an input file
102 *
103 * Revision 1.4 1994/11/12 02:11:59 keving
104 * nothing
105 *
106 * Revision 1.3 1994/03/15 00:27:11 keving
107 * nothing
108 *
109 * Revision 1.2 1993/12/22 19:19:01 keving
110 * nothing
111 *
112 * Revision 1.1 1993/07/22 22:23:43 keving
113 * nothing
114 *
115 */
116
117
118 /*==============*
119 * HEADER FILES *
120 *==============*/
121
122 #include "all.h"
123 #include <time.h>
124 #include <errno.h>
125 #include <ctype.h>
126 #include <string.h>
127 //#include <unistd.h>
128 #include "mtypes.h"
129 #include "frames.h"
130 #include "prototypes.h"
131 #include "parallel.h"
132 #include "param.h"
133 #include "readframe.h"
134 #include "fsize.h"
135 #include "rgbtoycc.h"
136 #include "jpeg.h"
137 #include "opts.h"
138
139 #define PPM_READ_STATE_MAGIC 0
140 #define PPM_READ_STATE_WIDTH 1
141 #define PPM_READ_STATE_HEIGHT 2
142 #define PPM_READ_STATE_MAXVAL 3
143 #define PPM_READ_STATE_DONE 4
144
145
146 /*==================*
147 * STATIC VARIABLES *
148 *==================*/
149
150 static int fileType = BASE_FILE_TYPE;
151 struct YuvLine {
152 uint8 data[3072];
153 uint8 y[1024];
154 int8 cr[1024];
155 int8 cb[1024];
156 };
157
158
159 /*==================*
160 * Portability *
161 *==================*/
162 #ifdef __OS2__
163 #define popen _popen
164 #endif
165
166 #if defined(WIN32) && !defined(__CYGWIN__)
167 #define popen _popen
168 #define pclose _pclose
169 #endif
170
171 /*==================*
172 * Global VARIABLES *
173 *==================*/
174
175 extern boolean GammaCorrection;
176 extern float GammaValue;
177 extern int outputWidth,outputHeight;
178 boolean resizeFrame;
179 char *CurrFile;
180
181 /*===============================*
182 * INTERNAL PROCEDURE prototypes *
183 *===============================*/
184
185 static char *ScanNextString _ANSI_ARGS_((char *inputLine, char *string));
186 static void ReadPNM _ANSI_ARGS_((FILE * fp, MpegFrame * mf));
187 static boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
188 static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
189 int width, int height));
190 static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
191 int width, int height));
192 static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr,
193 int width));
194 static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
195 int width, int height));
196 static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
197 int width, int height));
198 static void DoGamma _ANSI_ARGS_((MpegFrame *mf, int width, int height));
199
200 static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h));
201
202 #define safe_fread(ptr,sz,len,fileptr) \
203 if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) { \
204 throw "Input file too small! (%s)"; \
205 } \
206
207 /*=====================*
208 * EXPORTED PROCEDURES *
209 *=====================*/
210
211
212
SetResize(boolean set)213 void SetResize( boolean set)
214 {
215 resizeFrame = set;
216 }
217
218
219
220 /*===========================================================================*
221 *
222 * ReadFrame
223 *
224 * reads the given frame, performing conversion as necessary
225 * if addPath = TRUE, then must add the current path before the
226 * file name
227 *
228 * RETURNS: frame modified
229 *
230 * SIDE EFFECTS: none
231 *
232 *===========================================================================*/
233 void
ReadFrame(MpegFrame * frame,char * fileName,char * conversion,boolean addPath)234 ReadFrame(MpegFrame *frame,
235 char *fileName,
236 char *conversion,
237 boolean addPath)
238 {
239 FILE *ifp;
240 char command[1024];
241 char fullFileName[1024];
242 MpegFrame tempFrame;
243 MpegFrame *framePtr;
244 #ifdef BLEAH
245 static int32 readDiskTime = 0;
246 int32 diskStartTime, diskEndTime;
247
248 time(&diskStartTime);
249 #endif
250
251 if ( resizeFrame ) {
252 tempFrame.inUse = FALSE;
253 tempFrame.ppm_data = NULL;
254 tempFrame.rgb_data = NULL;
255 tempFrame.orig_y = NULL;
256 tempFrame.y_blocks = NULL;
257 tempFrame.decoded_y = NULL;
258 tempFrame.halfX = NULL;
259 framePtr = &tempFrame;
260 } else {
261 framePtr = frame;
262 }
263
264 if ( addPath ) {
265 sprintf(fullFileName, "%s/%s", currentPath, fileName);
266 } else {
267 sprintf(fullFileName, "%s", fileName);
268 }
269
270 CurrFile = fullFileName;
271
272 #ifdef BLEAH
273 if ( ! childProcess ) {
274 fprintf(stdout, "+++++READING Frame %d (type %d): %s\n", framePtr->id,
275 framePtr->type, fullFileName);
276 }
277 #endif
278
279 if ( fileType == ANY_FILE_TYPE ) {
280 char *convertPtr, *commandPtr, *charPtr;
281
282 if ( stdinUsed ) {
283 throw "cannot use stdin with INPUT_CONVERT";
284 }
285
286 /* replace every occurrence of '*' with fullFileName */
287 convertPtr = conversion;
288 commandPtr = command;
289 while ( *convertPtr != '\0' ) {
290 while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
291 *commandPtr = *convertPtr;
292 commandPtr++;
293 convertPtr++;
294 }
295
296 if ( *convertPtr == '*' ) {
297 /* copy fullFileName */
298 charPtr = fullFileName;
299 while ( *charPtr != '\0' ) {
300 *commandPtr = *charPtr;
301 commandPtr++;
302 charPtr++;
303 }
304
305 convertPtr++; /* go past '*' */
306 }
307 }
308 *commandPtr = '\0';
309
310 if ( (ifp = popen(command, "r")) == NULL ) {
311 fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n");
312 fprintf(stderr, "\t%s\n", command);
313 fprintf(stderr, "errno = %d\n", errno);
314 if ( ioServer ) {
315 throw "IO SERVER: EXITING!";
316 } else {
317 throw "SLAVE EXITING!";
318 }
319 }
320 } else if (stdinUsed) {
321 ifp = stdin;
322 } else if ( (ifp = fopen(fullFileName, "rb")) == NULL ) {
323 throw "Couldn't open input file";
324 }
325
326 switch(baseFormat) {
327 case YUV_FILE_TYPE:
328
329 /* Encoder YUV */
330 if ((strncmp (yuvConversion, "EYUV", 4) == 0) ||
331 (strncmp (yuvConversion, "UCB", 3) == 0) )
332 {
333 ReadEYUV(framePtr, ifp, realWidth, realHeight);
334 }
335
336 /* Abekas-type (interlaced) YUV */
337 else {
338 ReadAYUV(framePtr, ifp, realWidth, realHeight);
339 }
340
341 break;
342 case Y_FILE_TYPE:
343 ReadY(framePtr, ifp, realWidth, realHeight);
344 break;
345 case PPM_FILE_TYPE:
346 if ( ! ReadPPM(framePtr, ifp) ) {
347 throw "Error reading PPM input file!";
348 }
349 PPMtoYUV(framePtr);
350 break;
351 case PNM_FILE_TYPE:
352 ReadPNM(ifp, framePtr);
353 PNMtoYUV(framePtr);
354 break;
355 case SUB4_FILE_TYPE:
356 ReadSub4(framePtr, ifp, yuvWidth, yuvHeight);
357 break;
358 case JPEG_FILE_TYPE:
359 case JMOVIE_FILE_TYPE:
360 ReadJPEG(framePtr, ifp);
361 break;
362 default:
363 break;
364 }
365
366 if (! stdinUsed) {
367 if ( fileType == ANY_FILE_TYPE ) {
368 int errorcode;
369 if ( (errorcode = pclose(ifp)) != 0) {
370 fprintf(stderr, "WARNING: Pclose reported error (%d)\n", errorcode);
371 }
372 } else {
373 fclose(ifp);
374 }
375 }
376
377 if ( baseFormat == JMOVIE_FILE_TYPE ) {
378 remove(fullFileName);
379 }
380
381 if ( resizeFrame ) {
382 Frame_Resize(frame, &tempFrame, Fsize_x, Fsize_y, outputWidth, outputHeight);
383 }
384
385 #ifdef BLEAH
386 time(&diskEndTime);
387
388 readDiskTime += (diskEndTime-diskStartTime);
389
390 fprintf(stdout, "cumulative disk read time: %d seconds\n", readDiskTime);
391 #endif
392
393 if ( GammaCorrection ) {
394 DoGamma(frame, Fsize_x, Fsize_y);
395 }
396
397 if ( kill_dim ) {
398 DoKillDim(frame, Fsize_x, Fsize_y);
399 }
400
401 MotionSearchPreComputation(frame);
402 }
403
404
405 /*===========================================================================*
406 *
407 * SetFileType
408 *
409 * set the file type to be either a base type (no conversion), or
410 * any type (conversion required)
411 *
412 * RETURNS: nothing
413 *
414 * SIDE EFFECTS: fileType
415 *
416 *===========================================================================*/
417 void
SetFileType(char * conversion)418 SetFileType(char *conversion)
419 {
420 if ( strcmp(conversion, "*") == 0 ) {
421 fileType = BASE_FILE_TYPE;
422 } else {
423 fileType = ANY_FILE_TYPE;
424 }
425 }
426
427
428 /*===========================================================================*
429 *
430 * SetFileFormat
431 *
432 * set the file format (PPM, PNM, YUV, JPEG)
433 *
434 * RETURNS: nothing
435 *
436 * SIDE EFFECTS: baseFormat
437 *
438 *===========================================================================*/
439 void
SetFileFormat(char * format)440 SetFileFormat(char *format)
441 {
442 if ( strcmp(format, "PPM") == 0 ) {
443 baseFormat = PPM_FILE_TYPE;
444 } else if ( strcmp(format, "YUV") == 0 ) {
445 baseFormat = YUV_FILE_TYPE;
446 } else if ( strcmp(format, "Y") == 0 ) {
447 baseFormat = Y_FILE_TYPE;
448 } else if ( strcmp(format, "PNM") == 0 ) {
449 baseFormat = PNM_FILE_TYPE;
450 } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) {
451 baseFormat = JPEG_FILE_TYPE;
452 } else if ( strcmp(format, "JMOVIE") == 0 ) {
453 baseFormat = JMOVIE_FILE_TYPE;
454 } else if ( strcmp(format, "SUB4") == 0 ) {
455 baseFormat = SUB4_FILE_TYPE;
456 } else {
457 throw "Invalid file format";
458 }
459 }
460
461
462 /*===========================================================================*
463 *
464 * ReadPNM
465 *
466 * read a PNM file
467 *
468 * RETURNS: mf modified
469 *
470 * SIDE EFFECTS: none
471 *
472 *===========================================================================*/
473 static void
ReadPNM(FILE * fp,MpegFrame * mf)474 ReadPNM(FILE *fp,
475 MpegFrame *mf)
476 {
477 int x, y;
478 xelval maxval;
479 int format;
480
481 if (mf->rgb_data) {
482 pnm_freearray(mf->rgb_data, Fsize_y);
483 }
484 mf->rgb_data = pnm_readpnm(fp, &x, &y, &maxval, &format);
485 ERRCHK(mf, "pnm_readpnm");
486
487 if (format != PPM_FORMAT) {
488 if (maxval < 255) {
489 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, PPM_FORMAT);
490 maxval = 255;
491 } else {
492 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, maxval, PPM_FORMAT);
493 }
494 }
495 if (maxval < 255) {
496 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, format);
497 maxval = 255;
498 }
499 /*
500 * if this is the first frame read, set the global frame size
501 */
502 Fsize_Note(mf->id, x, y);
503
504 mf->rgb_maxval = maxval;
505 mf->rgb_format = PPM_FORMAT;
506 }
507
508
509
510 /*===========================================================================*
511 *
512 * ReadIOConvert
513 *
514 * do conversion; return a pointer to the appropriate file
515 *
516 * RETURNS: pointer to the appropriate file
517 *
518 * SIDE EFFECTS: none
519 *
520 *===========================================================================*/
521 FILE *
ReadIOConvert(char * fileName)522 ReadIOConvert(char *fileName)
523 {
524 FILE *ifp;
525 char command[1024];
526 char fullFileName[1024];
527 char *convertPtr, *commandPtr, *charPtr;
528
529 sprintf(fullFileName, "%s/%s", currentPath, fileName);
530
531 #ifdef BLEAH
532 if ( ! childProcess ) {
533 fprintf(stdout, "+++++READING (IO CONVERT) Frame %d (type %d): %s\n", frame->id,
534 frame->type, fullFileName); }
535 #endif
536
537 if ( strcmp(ioConversion, "*") == 0 ) {
538 char buff[1024];
539 ifp = fopen(fullFileName, "rb");
540 sprintf(buff,"fopen \"%s\"",fullFileName);
541 ERRCHK(ifp, buff);
542 return ifp;
543 }
544
545 /* replace every occurrence of '*' with fullFileName */
546 convertPtr = ioConversion;
547 commandPtr = command;
548 while ( *convertPtr != '\0' ) {
549 while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
550 *commandPtr = *convertPtr;
551 commandPtr++;
552 convertPtr++;
553 }
554
555 if ( *convertPtr == '*' ) {
556 /* copy fullFileName */
557 charPtr = fullFileName;
558 while ( *charPtr != '\0' ) {
559 *commandPtr = *charPtr;
560 commandPtr++;
561 charPtr++;
562 }
563
564 convertPtr++; /* go past '*' */
565 }
566 }
567 *commandPtr = '\0';
568
569 if ( (ifp = popen(command, "r")) == NULL ) {
570 fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n");
571 fprintf(stderr, "\t%s\n", command);
572 fprintf(stderr, "errno = %d\n", errno);
573 if ( ioServer ) {
574 throw "IO SERVER: EXITING!";
575 } else {
576 throw "SLAVE EXITING!";
577 }
578 }
579
580 return ifp;
581 }
582
583
584
585 /*===========================================================================*
586 *
587 * ReadPPM
588 *
589 * read a PPM file
590 *
591 * RETURNS: TRUE if successful; FALSE otherwise; mf modified
592 *
593 * SIDE EFFECTS: none
594 *
595 *===========================================================================*/
596 static boolean
ReadPPM(MpegFrame * mf,FILE * fpointer)597 ReadPPM(MpegFrame *mf,
598 FILE *fpointer)
599 {
600 char inputBuffer[71];
601 char string[71];
602 char *inputLine;
603 int height = 0, width = 0, maxVal=255;
604 uint8 junk[4096];
605 register int y;
606 int state;
607 int safe_read_count;
608
609 state = PPM_READ_STATE_MAGIC;
610
611 while ( state != PPM_READ_STATE_DONE ) {
612 if ( fgets(inputBuffer, 71, fpointer) == NULL ) {
613 return FALSE;
614 }
615
616 inputLine = inputBuffer;
617
618 if ( inputLine[0] == '#' ) {
619 continue;
620 }
621
622 if ( inputLine[strlen(inputLine)-1] != '\n' ) {
623 return FALSE;
624 }
625
626 switch(state) {
627 case PPM_READ_STATE_MAGIC:
628 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
629 return FALSE;
630 }
631
632 if ( strcmp(string, "P6") != 0 ) {
633 return FALSE;
634 }
635 state = PPM_READ_STATE_WIDTH;
636 /* no break */
637 case PPM_READ_STATE_WIDTH:
638 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
639 if ( inputLine == inputBuffer ) {
640 return FALSE;
641 } else {
642 break;
643 }
644 }
645
646 width = atoi(string);
647
648 state = PPM_READ_STATE_HEIGHT;
649
650 /* no break */
651 case PPM_READ_STATE_HEIGHT:
652 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
653 if ( inputLine == inputBuffer ) {
654 return FALSE;
655 } else {
656 break;
657 }
658 }
659
660 height = atoi(string);
661
662 state = PPM_READ_STATE_MAXVAL;
663
664 /* no break */
665 case PPM_READ_STATE_MAXVAL:
666 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
667 if ( inputLine == inputBuffer ) {
668 return FALSE;
669 } else {
670 break;
671 }
672 }
673
674 maxVal = atoi(string);
675
676 state = PPM_READ_STATE_DONE;
677 break;
678 } /* end of switch */
679 }
680
681 Fsize_Note(mf->id, width, height);
682
683 mf->rgb_maxval = maxVal;
684
685 Frame_AllocPPM(mf);
686
687 for ( y = 0; y < Fsize_y; y++ ) {
688 safe_fread(mf->ppm_data[y], (int)sizeof(char), 3*Fsize_x, fpointer);
689
690 /* read the leftover stuff on the right side */
691 safe_fread(junk, (int)sizeof(char), 3*(width-Fsize_x), fpointer);
692 }
693
694 /* read the leftover stuff to prevent broken pipe */
695 for ( y=Fsize_y; y<height; ++y ) {
696 safe_fread(junk, (int)sizeof(char), 3*Fsize_x, fpointer);
697 }
698 return TRUE;
699 }
700
701
702 /*===========================================================================*
703 *
704 * ReadEYUV
705 *
706 * read a Encoder-YUV file (concatenated Y, U, and V)
707 *
708 * RETURNS: mf modified
709 *
710 * SIDE EFFECTS: none
711 *
712 *===========================================================================*/
713 static void
ReadEYUV(MpegFrame * mf,FILE * fpointer,int width,int height)714 ReadEYUV(MpegFrame *mf,
715 FILE *fpointer,
716 int width,
717 int height)
718 {
719 register int y;
720 uint8 junk[4096];
721 int safe_read_count;
722
723 Fsize_Note(mf->id, width, height);
724
725 Frame_AllocYCC(mf);
726
727 for (y = 0; y < Fsize_y; y++) { /* Y */
728 safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer);
729
730 /* read the leftover stuff on the right side */
731 if ( width != Fsize_x ) {
732 safe_fread(junk, 1, width-Fsize_x, fpointer);
733 }
734 }
735
736 /* read the leftover stuff on the bottom */
737 for (y = Fsize_y; y < height; y++) {
738 safe_fread(junk, 1, width, fpointer);
739 }
740
741 for (y = 0; y < (Fsize_y >> 1); y++) { /* U */
742 safe_fread(mf->orig_cb[y], 1, Fsize_x >> 1, fpointer);
743
744 /* read the leftover stuff on the right side */
745 if ( width != Fsize_x ) {
746 safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer);
747 }
748 }
749
750 /* read the leftover stuff on the bottom */
751 for (y = (Fsize_y >> 1); y < (height >> 1); y++) {
752 safe_fread(junk, 1, width>>1, fpointer);
753 }
754
755 for (y = 0; y < (Fsize_y >> 1); y++) { /* V */
756 safe_fread(mf->orig_cr[y], 1, Fsize_x >> 1, fpointer);
757
758 /* read the leftover stuff on the right side */
759 if ( width != Fsize_x ) {
760 safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer);
761 }
762 }
763
764 /* ignore leftover stuff on the bottom */
765 }
766
767 /*===========================================================================*
768 *
769 * ReadAYUV
770 *
771 * read an Abekas-YUV file
772 *
773 * RETURNS: mf modified
774 *
775 * SIDE EFFECTS: none
776 *
777 *===========================================================================*/
778 static void
ReadAYUV(MpegFrame * mf,FILE * fpointer,int width,int height)779 ReadAYUV(MpegFrame *mf,
780 FILE *fpointer,
781 int width,
782 int height)
783 {
784 register int x, y;
785 struct YuvLine line1, line2;
786 uint8 junk[4096];
787 int8 *cbptr, *crptr;
788 int safe_read_count;
789
790 Fsize_Note(mf->id, width, height);
791
792 Frame_AllocYCC(mf);
793
794 for (y = 0; y < Fsize_y; y += 2) {
795 SeparateLine(fpointer, &line1, width);
796 SeparateLine(fpointer, &line2, width);
797
798 /* Copy the Y values for each line to the frame */
799 for (x = 0; x < Fsize_x; x++) {
800 mf->orig_y[y][x] = line1.y[x];
801 mf->orig_y[y+1][x] = line2.y[x];
802 }
803
804 cbptr = (int8*)&(mf->orig_cb[y>>1][0]);
805 crptr = (int8*)&(mf->orig_cr[y>>1][0]);
806
807 /* One U and one V for each two pixels horizontal as well */
808 /* Toss the second line of Cr/Cb info, averaging was worse,
809 so just subsample */
810 for (x = 0; x < (Fsize_x >> 1); x ++) {
811 cbptr[x] = line1.cb[x];
812 crptr[x] = line1.cr[x];
813
814 }
815 }
816
817 /* read the leftover stuff on the bottom */
818 for (y = Fsize_y; y < height; y++) {
819 safe_fread(junk, 1, width<<1, fpointer);
820 }
821
822 }
823
824 /*===========================================================================*
825 *
826 * SeparateLine
827 *
828 * Separates one line of pixels into Y, U, and V components
829 *
830 * RETURNS: lineptr modified
831 *
832 * SIDE EFFECTS: none
833 *
834 *===========================================================================*/
835 static void
SeparateLine(FILE * fpointer,struct YuvLine * lineptr,int width)836 SeparateLine(FILE *fpointer,
837 struct YuvLine *lineptr,
838 int width)
839 {
840 uint8 junk[4096];
841 int8 *crptr, *cbptr;
842 uint8 *yptr;
843 int num, length;
844 int safe_read_count;
845
846
847 /* Sets the deinterlacing pattern */
848
849 /* shorthand for UYVY */
850 if (strncmp(yuvConversion, "ABEKAS", 6) == 0) {
851 strcpy(yuvConversion, "UYVY");
852
853 /* shorthand for YUYV */
854 } else if (strncmp(yuvConversion, "PHILLIPS", 8) == 0) {
855 strcpy(yuvConversion, "YUYV");
856 }
857
858 length = strlen (yuvConversion);
859
860 if ((length % 2) != 0) {
861 throw "YUV_FORMAT must represent two pixels, hence must be even in length";
862 }
863
864 /* each line in 4:2:2 chroma format takes 2X bytes to represent X pixels.
865 * each line in 4:4:4 chroma format takes 3X bytes to represent X pixels.
866 * Therefore, half of the length of the YUV_FORMAT represents 1 pixel.
867 */
868 safe_fread(lineptr->data, 1, Fsize_x*(length>>1), fpointer);
869
870 /* read the leftover stuff on the right side */
871 if ( width != Fsize_x ) {
872 safe_fread(junk, 1, (width-Fsize_x)*(length>>1), fpointer);
873 }
874
875 crptr = &(lineptr->cr[0]);
876 cbptr = &(lineptr->cb[0]);
877 yptr = &(lineptr->y[0]);
878
879 for (num = 0; num < (Fsize_x*(length>>1)); num++) {
880 switch (yuvConversion[num % length]) {
881 case 'U':
882 case 'u':
883 *(cbptr++) = (lineptr->data[num]);
884 break;
885 case 'V':
886 case 'v':
887 *(crptr++) = (lineptr->data[num]);
888 break;
889 case 'Y':
890 case 'y':
891 *(yptr++) = (lineptr->data[num]);
892 break;
893 default:
894 throw "bad YUV_FORMAT";
895 }
896
897 }
898
899 }
900
901
902 /*===========================================================================*
903 *
904 * ReadY
905 *
906 * read a Y file
907 *
908 * RETURNS: mf modified
909 *
910 * SIDE EFFECTS: none
911 *
912 *===========================================================================*/
913 static void
ReadY(MpegFrame * mf,FILE * fpointer,int width,int height)914 ReadY(MpegFrame *mf,
915 FILE *fpointer,
916 int width,
917 int height)
918 {
919 register int y;
920 uint8 junk[4096];
921 int safe_read_count;
922
923 Fsize_Note(mf->id, width, height);
924
925 Frame_AllocYCC(mf);
926
927 for (y = 0; y < Fsize_y; y++) { /* Y */
928 safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer);
929
930 /* read the leftover stuff on the right side */
931 if ( width != Fsize_x ) {
932 safe_fread(junk, 1, width-Fsize_x, fpointer);
933 }
934 }
935
936 /* read the leftover stuff on the bottom */
937 for (y = Fsize_y; y < height; y++) {
938 safe_fread(junk, 1, width, fpointer);
939 }
940
941 for (y = 0 ; y < (Fsize_y >> 1); y++) {
942 memset(mf->orig_cb[y], 128, (Fsize_x>>1));
943 memset(mf->orig_cr[y], 128, (Fsize_x>>1));
944 }
945 }
946
947
948 /*===========================================================================*
949 *
950 * ReadSub4
951 *
952 * read a YUV file (subsampled even further by 4:1 ratio)
953 *
954 * RETURNS: mf modified
955 *
956 * SIDE EFFECTS: none
957 *
958 *===========================================================================*/
959 static void
ReadSub4(MpegFrame * mf,FILE * fpointer,int width,int height)960 ReadSub4(MpegFrame *mf,
961 FILE *fpointer,
962 int width,
963 int height)
964 {
965 register int y;
966 register int x;
967 uint8 buffer[1024];
968 int safe_read_count;
969
970 Fsize_Note(mf->id, width, height);
971
972 Frame_AllocYCC(mf);
973
974 for (y = 0; y < (height>>1); y++) { /* Y */
975 safe_fread(buffer, 1, width>>1, fpointer);
976 for ( x = 0; x < (width>>1); x++ ) {
977 mf->orig_y[2*y][2*x] = buffer[x];
978 mf->orig_y[2*y][2*x+1] = buffer[x];
979 mf->orig_y[2*y+1][2*x] = buffer[x];
980 mf->orig_y[2*y+1][2*x+1] = buffer[x];
981 }
982 }
983
984 for (y = 0; y < (height >> 2); y++) { /* U */
985 safe_fread(buffer, 1, width>>2, fpointer);
986 for ( x = 0; x < (width>>2); x++ ) {
987 mf->orig_cb[2*y][2*x] = buffer[x];
988 mf->orig_cb[2*y][2*x+1] = buffer[x];
989 mf->orig_cb[2*y+1][2*x] = buffer[x];
990 mf->orig_cb[2*y+1][2*x+1] = buffer[x];
991 }
992 }
993
994 for (y = 0; y < (height >> 2); y++) { /* V */
995 safe_fread(buffer, 1, width>>2, fpointer);
996 for ( x = 0; x < (width>>2); x++ ) {
997 mf->orig_cr[2*y][2*x] = buffer[x];
998 mf->orig_cr[2*y][2*x+1] = buffer[x];
999 mf->orig_cr[2*y+1][2*x] = buffer[x];
1000 mf->orig_cr[2*y+1][2*x+1] = buffer[x];
1001 }
1002 }
1003 }
1004
1005
1006 /*=====================*
1007 * INTERNAL PROCEDURES *
1008 *=====================*/
1009
1010 /*===========================================================================*
1011 *
1012 * ScanNextString
1013 *
1014 * read a string from a input line, ignoring whitespace
1015 *
1016 * RETURNS: pointer to position in input line after string
1017 * NULL if all whitespace
1018 * puts string in 'string'
1019 *
1020 * SIDE EFFECTS: file stream munched a bit
1021 *
1022 *===========================================================================*/
1023 static char *
ScanNextString(char * inputLine,char * string)1024 ScanNextString(char *inputLine,
1025 char *string)
1026 {
1027 /* skip whitespace */
1028 while ( isspace(*inputLine) && (*inputLine != '\n') ) {
1029 inputLine++;
1030 }
1031
1032 if ( *inputLine == '\n' ) {
1033 return NULL;
1034 }
1035
1036 while ( (! isspace(*inputLine)) && (*inputLine != '\n') ) {
1037 *string = *inputLine;
1038 string++;
1039 inputLine++;
1040 }
1041
1042 *string = '\0';
1043
1044 return inputLine;
1045 }
1046
1047 /*===========================================================================*
1048 *
1049 * DoGamma
1050 *
1051 * Gamma Correct the Lum values
1052 *
1053 * RETURNS: nothing
1054 *
1055 * SIDE EFFECTS: Raises Y values to power gamma.
1056 *
1057 *===========================================================================*/
1058 static void
DoGamma(MpegFrame * mf,int w,int h)1059 DoGamma(MpegFrame *mf,
1060 int w, int h)
1061 {
1062 static int GammaVal[256];
1063 static boolean init_done=FALSE;
1064 int i,j;
1065
1066 if (!init_done) {
1067 for(i=0; i<256; i++)
1068 GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,(double)GammaValue)*255.0+0.5);
1069 init_done=TRUE;
1070 }
1071
1072 for (i=0; i< h; i++) { /* For each line */
1073 for (j=0; j<w; j++) { /* For each Y value */
1074 mf->orig_y[i][j] = GammaVal[mf->orig_y[i][j]];
1075 }}
1076 }
1077
1078
1079
1080
1081 /*===========================================================================*
1082 *
1083 * DoKillDim
1084 *
1085 * Applies an input filter to small Y values.
1086 *
1087 * RETURNS: nothing
1088 *
1089 * SIDE EFFECTS: Changes Y values:
1090 *
1091 * Output | /
1092 | /
1093 | /
1094 | !
1095 | /
1096 | !
1097 | /
1098 | -
1099 | /
1100 | --
1101 | /
1102 | --
1103 | /
1104 ------------------------
1105 ^ kill_dim_break
1106 ^kill_dim_end
1107 kill_dim_slope gives the slope (y = kill_dim_slope * x +0)
1108 from 0 to kill_dim_break
1109 *
1110 *===========================================================================*/
1111
1112 static void
DoKillDim(MpegFrame * mf,int w,int h)1113 DoKillDim(MpegFrame *mf,
1114 int w, int h)
1115 {
1116 static boolean init_done=FALSE;
1117 static unsigned char mapper[256];
1118 register int i,j;
1119 double slope, intercept;
1120
1121 slope = (kill_dim_end - kill_dim_break*kill_dim_slope)*1.0 /
1122 (kill_dim_end - kill_dim_break);
1123 intercept = kill_dim_end * (1.0-slope);
1124
1125 if (!init_done) {
1126 for(i=0; i<256; i++) {
1127 if (i >= kill_dim_end) {
1128 mapper[i] = (char) i;
1129 } else if (i >= kill_dim_break) {
1130 mapper[i] = (char) (slope*i + intercept);
1131 } else { /* i <= kill_dim_break */
1132 mapper[i] = (char) floor(i*kill_dim_slope + 0.49999);
1133 }
1134 }
1135 init_done = TRUE;
1136 }
1137
1138 for (i=0; i < h; i++) { /* For each line */
1139 for (j=0; j < w; j++) { /* For each Y value */
1140 mf->orig_y[i][j] = mapper[mf->orig_y[i][j]];
1141 }}
1142 }
1143