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
167 /*==================*
168 * Global VARIABLES *
169 *==================*/
170
171 extern boolean GammaCorrection;
172 extern float GammaValue;
173 extern int outputWidth,outputHeight;
174 boolean resizeFrame;
175 char *CurrFile;
176
177 /*===============================*
178 * INTERNAL PROCEDURE prototypes *
179 *===============================*/
180
181 static char *ScanNextString _ANSI_ARGS_((char *inputLine, char *string));
182 static void ReadPNM _ANSI_ARGS_((FILE * fp, MpegFrame * mf));
183 static boolean ReadPPM _ANSI_ARGS_((MpegFrame *mf, FILE *fpointer));
184 static void ReadEYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
185 int width, int height));
186 static void ReadAYUV _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
187 int width, int height));
188 static void SeparateLine _ANSI_ARGS_((FILE *fpointer, struct YuvLine *lineptr,
189 int width));
190 static void ReadY _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
191 int width, int height));
192 static void ReadSub4 _ANSI_ARGS_((MpegFrame * mf, FILE *fpointer,
193 int width, int height));
194 static void DoGamma _ANSI_ARGS_((MpegFrame *mf, int width, int height));
195
196 static void DoKillDim _ANSI_ARGS_((MpegFrame *mf, int w, int h));
197
198 #define safe_fread(ptr,sz,len,fileptr) \
199 if ((safe_read_count=fread(ptr,sz,len,fileptr))!=sz*len) { \
200 fprintf(stderr,"Input file too small! (%s)\n",CurrFile); \
201 exit(1);} \
202
203 /*=====================*
204 * EXPORTED PROCEDURES *
205 *=====================*/
206
207
208
SetResize(set)209 void SetResize(set)
210 boolean set;
211 {
212 resizeFrame = set;
213 }
214
215
216
217 /*===========================================================================*
218 *
219 * ReadFrame
220 *
221 * reads the given frame, performing conversion as necessary
222 * if addPath = TRUE, then must add the current path before the
223 * file name
224 *
225 * RETURNS: frame modified
226 *
227 * SIDE EFFECTS: none
228 *
229 *===========================================================================*/
230 void
ReadFrame(frame,fileName,conversion,addPath)231 ReadFrame(frame, fileName, conversion, addPath)
232 MpegFrame *frame;
233 char *fileName;
234 char *conversion;
235 boolean addPath;
236 {
237 FILE *ifp;
238 char command[1024];
239 char fullFileName[1024];
240 MpegFrame tempFrame;
241 MpegFrame *framePtr;
242 #ifdef BLEAH
243 static int32 readDiskTime = 0;
244 int32 diskStartTime, diskEndTime;
245
246 time(&diskStartTime);
247 #endif
248
249 if ( resizeFrame ) {
250 tempFrame.inUse = FALSE;
251 tempFrame.ppm_data = NULL;
252 tempFrame.rgb_data = NULL;
253 tempFrame.orig_y = NULL;
254 tempFrame.y_blocks = NULL;
255 tempFrame.decoded_y = NULL;
256 tempFrame.halfX = NULL;
257 framePtr = &tempFrame;
258 } else {
259 framePtr = frame;
260 }
261
262 if ( addPath ) {
263 sprintf(fullFileName, "%s/%s", currentPath, fileName);
264 } else {
265 sprintf(fullFileName, "%s", fileName);
266 }
267
268 CurrFile = fullFileName;
269
270 #ifdef BLEAH
271 if ( ! childProcess ) {
272 fprintf(stdout, "+++++READING Frame %d (type %d): %s\n", framePtr->id,
273 framePtr->type, fullFileName);
274 }
275 #endif
276
277 if ( fileType == ANY_FILE_TYPE ) {
278 char *convertPtr, *commandPtr, *charPtr;
279
280 if ( stdinUsed ) {
281 fprintf(stderr, "ERROR : cannot use stdin with INPUT_CONVERT.\n");
282 exit(1);
283 }
284
285 /* replace every occurrence of '*' with fullFileName */
286 convertPtr = conversion;
287 commandPtr = command;
288 while ( *convertPtr != '\0' ) {
289 while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
290 *commandPtr = *convertPtr;
291 commandPtr++;
292 convertPtr++;
293 }
294
295 if ( *convertPtr == '*' ) {
296 /* copy fullFileName */
297 charPtr = fullFileName;
298 while ( *charPtr != '\0' ) {
299 *commandPtr = *charPtr;
300 commandPtr++;
301 charPtr++;
302 }
303
304 convertPtr++; /* go past '*' */
305 }
306 }
307 *commandPtr = '\0';
308
309 if ( (ifp = popen(command, "r")) == NULL ) {
310 fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n");
311 fprintf(stderr, "\t%s\n", command);
312 fprintf(stderr, "errno = %d\n", errno);
313 if ( ioServer ) {
314 fprintf(stderr, "IO SERVER: EXITING!!!\n");
315 } else {
316 fprintf(stderr, "SLAVE EXITING!!!\n");
317 }
318 exit(1);
319 }
320 } else if (stdinUsed) {
321 ifp = stdin;
322 } else if ( (ifp = fopen(fullFileName, "rb")) == NULL ) {
323 fprintf(stderr, "ERROR: Couldn't open input file %s\n",
324 fullFileName);
325 exit(1);
326 }
327
328 switch(baseFormat) {
329 case YUV_FILE_TYPE:
330
331 /* Encoder YUV */
332 if ((strncmp (yuvConversion, "EYUV", 4) == 0) ||
333 (strncmp (yuvConversion, "UCB", 3) == 0) )
334 {
335 ReadEYUV(framePtr, ifp, realWidth, realHeight);
336 }
337
338 /* Abekas-type (interlaced) YUV */
339 else {
340 ReadAYUV(framePtr, ifp, realWidth, realHeight);
341 }
342
343 break;
344 case Y_FILE_TYPE:
345 ReadY(framePtr, ifp, realWidth, realHeight);
346 break;
347 case PPM_FILE_TYPE:
348 if ( ! ReadPPM(framePtr, ifp) ) {
349 fprintf(stderr, "Error reading PPM input file!!! (%s)\n", CurrFile);
350 exit(1);
351 }
352 PPMtoYUV(framePtr);
353 break;
354 case PNM_FILE_TYPE:
355 ReadPNM(ifp, framePtr);
356 PNMtoYUV(framePtr);
357 break;
358 case SUB4_FILE_TYPE:
359 ReadSub4(framePtr, ifp, yuvWidth, yuvHeight);
360 break;
361 case JPEG_FILE_TYPE:
362 case JMOVIE_FILE_TYPE:
363 ReadJPEG(framePtr, ifp);
364 break;
365 default:
366 break;
367 }
368
369 if (! stdinUsed) {
370 if ( fileType == ANY_FILE_TYPE ) {
371 int errorcode;
372 if ( (errorcode = pclose(ifp)) != 0) {
373 fprintf(stderr, "WARNING: Pclose reported error (%d)\n", errorcode);
374 }
375 } else {
376 fclose(ifp);
377 }
378 }
379
380 if ( baseFormat == JMOVIE_FILE_TYPE ) {
381 remove(fullFileName);
382 }
383
384 if ( resizeFrame ) {
385 Frame_Resize(frame, &tempFrame, Fsize_x, Fsize_y, outputWidth, outputHeight);
386 }
387
388 #ifdef BLEAH
389 time(&diskEndTime);
390
391 readDiskTime += (diskEndTime-diskStartTime);
392
393 fprintf(stdout, "cumulative disk read time: %d seconds\n", readDiskTime);
394 #endif
395
396 if ( GammaCorrection ) {
397 DoGamma(frame, Fsize_x, Fsize_y);
398 }
399
400 if ( kill_dim ) {
401 DoKillDim(frame, Fsize_x, Fsize_y);
402 }
403
404 MotionSearchPreComputation(frame);
405 }
406
407
408 /*===========================================================================*
409 *
410 * SetFileType
411 *
412 * set the file type to be either a base type (no conversion), or
413 * any type (conversion required)
414 *
415 * RETURNS: nothing
416 *
417 * SIDE EFFECTS: fileType
418 *
419 *===========================================================================*/
420 void
SetFileType(conversion)421 SetFileType(conversion)
422 char *conversion;
423 {
424 if ( strcmp(conversion, "*") == 0 ) {
425 fileType = BASE_FILE_TYPE;
426 } else {
427 fileType = ANY_FILE_TYPE;
428 }
429 }
430
431
432 /*===========================================================================*
433 *
434 * SetFileFormat
435 *
436 * set the file format (PPM, PNM, YUV, JPEG)
437 *
438 * RETURNS: nothing
439 *
440 * SIDE EFFECTS: baseFormat
441 *
442 *===========================================================================*/
443 void
SetFileFormat(format)444 SetFileFormat(format)
445 char *format;
446 {
447 if ( strcmp(format, "PPM") == 0 ) {
448 baseFormat = PPM_FILE_TYPE;
449 } else if ( strcmp(format, "YUV") == 0 ) {
450 baseFormat = YUV_FILE_TYPE;
451 } else if ( strcmp(format, "Y") == 0 ) {
452 baseFormat = Y_FILE_TYPE;
453 } else if ( strcmp(format, "PNM") == 0 ) {
454 baseFormat = PNM_FILE_TYPE;
455 } else if (( strcmp(format, "JPEG") == 0 ) || ( strcmp(format, "JPG") == 0 )) {
456 baseFormat = JPEG_FILE_TYPE;
457 } else if ( strcmp(format, "JMOVIE") == 0 ) {
458 baseFormat = JMOVIE_FILE_TYPE;
459 } else if ( strcmp(format, "SUB4") == 0 ) {
460 baseFormat = SUB4_FILE_TYPE;
461 } else {
462 fprintf(stderr, "ERROR: Invalid file format: %s\n", format);
463 exit(1);
464 }
465 }
466
467
468 /*===========================================================================*
469 *
470 * ReadPNM
471 *
472 * read a PNM file
473 *
474 * RETURNS: mf modified
475 *
476 * SIDE EFFECTS: none
477 *
478 *===========================================================================*/
479 static void
ReadPNM(fp,mf)480 ReadPNM(fp, mf)
481 FILE *fp;
482 MpegFrame *mf;
483 {
484 int x, y;
485 xelval maxval;
486 int format;
487
488 if (mf->rgb_data) {
489 pnm_freearray(mf->rgb_data, Fsize_y);
490 }
491 mf->rgb_data = pnm_readpnm(fp, &x, &y, &maxval, &format);
492 ERRCHK(mf, "pnm_readpnm");
493
494 if (format != PPM_FORMAT) {
495 if (maxval < 255) {
496 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, PPM_FORMAT);
497 maxval = 255;
498 } else {
499 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, maxval, PPM_FORMAT);
500 }
501 }
502 if (maxval < 255) {
503 pnm_promoteformat(mf->rgb_data, x, y, maxval, format, 255, format);
504 maxval = 255;
505 }
506 /*
507 * if this is the first frame read, set the global frame size
508 */
509 Fsize_Note(mf->id, x, y);
510
511 mf->rgb_maxval = maxval;
512 mf->rgb_format = PPM_FORMAT;
513 }
514
515
516
517 /*===========================================================================*
518 *
519 * ReadIOConvert
520 *
521 * do conversion; return a pointer to the appropriate file
522 *
523 * RETURNS: pointer to the appropriate file
524 *
525 * SIDE EFFECTS: none
526 *
527 *===========================================================================*/
528 FILE *
ReadIOConvert(fileName)529 ReadIOConvert(fileName)
530 char *fileName;
531 {
532 FILE *ifp;
533 char command[1024];
534 char fullFileName[1024];
535 char *convertPtr, *commandPtr, *charPtr;
536
537 sprintf(fullFileName, "%s/%s", currentPath, fileName);
538
539 #ifdef BLEAH
540 if ( ! childProcess ) {
541 fprintf(stdout, "+++++READING (IO CONVERT) Frame %d (type %d): %s\n", frame->id,
542 frame->type, fullFileName); }
543 #endif
544
545 if ( strcmp(ioConversion, "*") == 0 ) {
546 char buff[1024];
547 ifp = fopen(fullFileName, "rb");
548 sprintf(buff,"fopen \"%s\"",fullFileName);
549 ERRCHK(ifp, buff);
550 return ifp;
551 }
552
553 /* replace every occurrence of '*' with fullFileName */
554 convertPtr = ioConversion;
555 commandPtr = command;
556 while ( *convertPtr != '\0' ) {
557 while ( (*convertPtr != '\0') && (*convertPtr != '*') ) {
558 *commandPtr = *convertPtr;
559 commandPtr++;
560 convertPtr++;
561 }
562
563 if ( *convertPtr == '*' ) {
564 /* copy fullFileName */
565 charPtr = fullFileName;
566 while ( *charPtr != '\0' ) {
567 *commandPtr = *charPtr;
568 commandPtr++;
569 charPtr++;
570 }
571
572 convertPtr++; /* go past '*' */
573 }
574 }
575 *commandPtr = '\0';
576
577 if ( (ifp = popen(command, "r")) == NULL ) {
578 fprintf(stderr, "ERROR: Couldn't execute input conversion command:\n");
579 fprintf(stderr, "\t%s\n", command);
580 fprintf(stderr, "errno = %d\n", errno);
581 if ( ioServer ) {
582 fprintf(stderr, "IO SERVER: EXITING!!!\n");
583 } else {
584 fprintf(stderr, "SLAVE EXITING!!!\n");
585 }
586 exit(1);
587 }
588
589 return ifp;
590 }
591
592
593
594 /*===========================================================================*
595 *
596 * ReadPPM
597 *
598 * read a PPM file
599 *
600 * RETURNS: TRUE if successful; FALSE otherwise; mf modified
601 *
602 * SIDE EFFECTS: none
603 *
604 *===========================================================================*/
605 static boolean
ReadPPM(mf,fpointer)606 ReadPPM(mf, fpointer)
607 MpegFrame *mf;
608 FILE *fpointer;
609 {
610 char inputBuffer[71];
611 char string[71];
612 char *inputLine;
613 int height = 0, width = 0, maxVal=255;
614 uint8 junk[4096];
615 register int y;
616 int state;
617 int safe_read_count;
618
619 state = PPM_READ_STATE_MAGIC;
620
621 while ( state != PPM_READ_STATE_DONE ) {
622 if ( fgets(inputBuffer, 71, fpointer) == NULL ) {
623 return FALSE;
624 }
625
626 inputLine = inputBuffer;
627
628 if ( inputLine[0] == '#' ) {
629 continue;
630 }
631
632 if ( inputLine[strlen(inputLine)-1] != '\n' ) {
633 return FALSE;
634 }
635
636 switch(state) {
637 case PPM_READ_STATE_MAGIC:
638 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
639 return FALSE;
640 }
641
642 if ( strcmp(string, "P6") != 0 ) {
643 return FALSE;
644 }
645 state = PPM_READ_STATE_WIDTH;
646 /* no break */
647 case PPM_READ_STATE_WIDTH:
648 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
649 if ( inputLine == inputBuffer ) {
650 return FALSE;
651 } else {
652 break;
653 }
654 }
655
656 width = atoi(string);
657
658 state = PPM_READ_STATE_HEIGHT;
659
660 /* no break */
661 case PPM_READ_STATE_HEIGHT:
662 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
663 if ( inputLine == inputBuffer ) {
664 return FALSE;
665 } else {
666 break;
667 }
668 }
669
670 height = atoi(string);
671
672 state = PPM_READ_STATE_MAXVAL;
673
674 /* no break */
675 case PPM_READ_STATE_MAXVAL:
676 if ( (inputLine = ScanNextString(inputLine, string)) == NULL ) {
677 if ( inputLine == inputBuffer ) {
678 return FALSE;
679 } else {
680 break;
681 }
682 }
683
684 maxVal = atoi(string);
685
686 state = PPM_READ_STATE_DONE;
687 break;
688 } /* end of switch */
689 }
690
691 Fsize_Note(mf->id, width, height);
692
693 mf->rgb_maxval = maxVal;
694
695 Frame_AllocPPM(mf);
696
697 for ( y = 0; y < Fsize_y; y++ ) {
698 safe_fread(mf->ppm_data[y], sizeof(char), 3*Fsize_x, fpointer);
699
700 /* read the leftover stuff on the right side */
701 safe_fread(junk, sizeof(char), 3*(width-Fsize_x), fpointer);
702 }
703
704 /* read the leftover stuff to prevent broken pipe */
705 for ( y=Fsize_y; y<height; ++y ) {
706 safe_fread(junk, sizeof(char), 3*Fsize_x, fpointer);
707 }
708 return TRUE;
709 }
710
711
712 /*===========================================================================*
713 *
714 * ReadEYUV
715 *
716 * read a Encoder-YUV file (concatenated Y, U, and V)
717 *
718 * RETURNS: mf modified
719 *
720 * SIDE EFFECTS: none
721 *
722 *===========================================================================*/
723 static void
ReadEYUV(mf,fpointer,width,height)724 ReadEYUV(mf, fpointer, width, height)
725 MpegFrame *mf;
726 FILE *fpointer;
727 int width;
728 int height;
729 {
730 register int y;
731 uint8 junk[4096];
732 int safe_read_count;
733
734 Fsize_Note(mf->id, width, height);
735
736 Frame_AllocYCC(mf);
737
738 for (y = 0; y < Fsize_y; y++) { /* Y */
739 safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer);
740
741 /* read the leftover stuff on the right side */
742 if ( width != Fsize_x ) {
743 safe_fread(junk, 1, width-Fsize_x, fpointer);
744 }
745 }
746
747 /* read the leftover stuff on the bottom */
748 for (y = Fsize_y; y < height; y++) {
749 safe_fread(junk, 1, width, fpointer);
750 }
751
752 for (y = 0; y < (Fsize_y >> 1); y++) { /* U */
753 safe_fread(mf->orig_cb[y], 1, Fsize_x >> 1, fpointer);
754
755 /* read the leftover stuff on the right side */
756 if ( width != Fsize_x ) {
757 safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer);
758 }
759 }
760
761 /* read the leftover stuff on the bottom */
762 for (y = (Fsize_y >> 1); y < (height >> 1); y++) {
763 safe_fread(junk, 1, width>>1, fpointer);
764 }
765
766 for (y = 0; y < (Fsize_y >> 1); y++) { /* V */
767 safe_fread(mf->orig_cr[y], 1, Fsize_x >> 1, fpointer);
768
769 /* read the leftover stuff on the right side */
770 if ( width != Fsize_x ) {
771 safe_fread(junk, 1, (width-Fsize_x)>>1, fpointer);
772 }
773 }
774
775 /* ignore leftover stuff on the bottom */
776 }
777
778 /*===========================================================================*
779 *
780 * ReadAYUV
781 *
782 * read an Abekas-YUV file
783 *
784 * RETURNS: mf modified
785 *
786 * SIDE EFFECTS: none
787 *
788 *===========================================================================*/
789 static void
ReadAYUV(mf,fpointer,width,height)790 ReadAYUV(mf, fpointer, width, height)
791 MpegFrame *mf;
792 FILE *fpointer;
793 int width;
794 int height;
795 {
796 register int x, y;
797 struct YuvLine line1, line2;
798 uint8 junk[4096];
799 int8 *cbptr, *crptr;
800 int safe_read_count;
801
802 Fsize_Note(mf->id, width, height);
803
804 Frame_AllocYCC(mf);
805
806 for (y = 0; y < Fsize_y; y += 2) {
807 SeparateLine(fpointer, &line1, width);
808 SeparateLine(fpointer, &line2, width);
809
810 /* Copy the Y values for each line to the frame */
811 for (x = 0; x < Fsize_x; x++) {
812 mf->orig_y[y][x] = line1.y[x];
813 mf->orig_y[y+1][x] = line2.y[x];
814 }
815
816 cbptr = &(mf->orig_cb[y>>1][0]);
817 crptr = &(mf->orig_cr[y>>1][0]);
818
819 /* One U and one V for each two pixels horizontal as well */
820 /* Toss the second line of Cr/Cb info, averaging was worse,
821 so just subsample */
822 for (x = 0; x < (Fsize_x >> 1); x ++) {
823 cbptr[x] = line1.cb[x];
824 crptr[x] = line1.cr[x];
825
826 }
827 }
828
829 /* read the leftover stuff on the bottom */
830 for (y = Fsize_y; y < height; y++) {
831 safe_fread(junk, 1, width<<1, fpointer);
832 }
833
834 }
835
836 /*===========================================================================*
837 *
838 * SeparateLine
839 *
840 * Separates one line of pixels into Y, U, and V components
841 *
842 * RETURNS: lineptr modified
843 *
844 * SIDE EFFECTS: none
845 *
846 *===========================================================================*/
847 static void
SeparateLine(fpointer,lineptr,width)848 SeparateLine(fpointer, lineptr, width)
849 FILE *fpointer;
850 struct YuvLine *lineptr;
851 int width;
852 {
853 uint8 junk[4096];
854 int8 *crptr, *cbptr;
855 uint8 *yptr;
856 int num, length;
857 int safe_read_count;
858
859
860 /* Sets the deinterlacing pattern */
861
862 /* shorthand for UYVY */
863 if (strncmp(yuvConversion, "ABEKAS", 6) == 0) {
864 strcpy(yuvConversion, "UYVY");
865
866 /* shorthand for YUYV */
867 } else if (strncmp(yuvConversion, "PHILLIPS", 8) == 0) {
868 strcpy(yuvConversion, "YUYV");
869 }
870
871 length = strlen (yuvConversion);
872
873 if ((length % 2) != 0) {
874 fprintf (stderr, "ERROR : YUV_FORMAT must represent two pixels, hence must be even in length.\n");
875 exit(1);
876 }
877
878 /* each line in 4:2:2 chroma format takes 2X bytes to represent X pixels.
879 * each line in 4:4:4 chroma format takes 3X bytes to represent X pixels.
880 * Therefore, half of the length of the YUV_FORMAT represents 1 pixel.
881 */
882 safe_fread(lineptr->data, 1, Fsize_x*(length>>1), fpointer);
883
884 /* read the leftover stuff on the right side */
885 if ( width != Fsize_x ) {
886 safe_fread(junk, 1, (width-Fsize_x)*(length>>1), fpointer);
887 }
888
889 crptr = &(lineptr->cr[0]);
890 cbptr = &(lineptr->cb[0]);
891 yptr = &(lineptr->y[0]);
892
893 for (num = 0; num < (Fsize_x*(length>>1)); num++) {
894 switch (yuvConversion[num % length]) {
895 case 'U':
896 case 'u':
897 *(cbptr++) = (lineptr->data[num]);
898 break;
899 case 'V':
900 case 'v':
901 *(crptr++) = (lineptr->data[num]);
902 break;
903 case 'Y':
904 case 'y':
905 *(yptr++) = (lineptr->data[num]);
906 break;
907 default:
908 fprintf(stderr, "ERROR: YUV_FORMAT must be one of the following:\n");
909 fprintf(stderr, " ABEKAS\n");
910 fprintf(stderr, " EYUV\n");
911 fprintf(stderr, " PHILLIPS\n");
912 fprintf(stderr, " UCB\n");
913 fprintf(stderr, " or any even-length string consisting of the letters U, V, and Y.\n");
914 exit(1);
915 }
916
917 }
918
919 }
920
921
922 /*===========================================================================*
923 *
924 * ReadY
925 *
926 * read a Y file
927 *
928 * RETURNS: mf modified
929 *
930 * SIDE EFFECTS: none
931 *
932 *===========================================================================*/
933 static void
ReadY(mf,fpointer,width,height)934 ReadY(mf, fpointer, width, height)
935 MpegFrame *mf;
936 FILE *fpointer;
937 int width;
938 int height;
939 {
940 register int y;
941 uint8 junk[4096];
942 int safe_read_count;
943
944 Fsize_Note(mf->id, width, height);
945
946 Frame_AllocYCC(mf);
947
948 for (y = 0; y < Fsize_y; y++) { /* Y */
949 safe_fread(mf->orig_y[y], 1, Fsize_x, fpointer);
950
951 /* read the leftover stuff on the right side */
952 if ( width != Fsize_x ) {
953 safe_fread(junk, 1, width-Fsize_x, fpointer);
954 }
955 }
956
957 /* read the leftover stuff on the bottom */
958 for (y = Fsize_y; y < height; y++) {
959 safe_fread(junk, 1, width, fpointer);
960 }
961
962 for (y = 0 ; y < (Fsize_y >> 1); y++) {
963 memset(mf->orig_cb[y], 128, (Fsize_x>>1));
964 memset(mf->orig_cr[y], 128, (Fsize_x>>1));
965 }
966 }
967
968
969 /*===========================================================================*
970 *
971 * ReadSub4
972 *
973 * read a YUV file (subsampled even further by 4:1 ratio)
974 *
975 * RETURNS: mf modified
976 *
977 * SIDE EFFECTS: none
978 *
979 *===========================================================================*/
980 static void
ReadSub4(mf,fpointer,width,height)981 ReadSub4(mf, fpointer, width, height)
982 MpegFrame *mf;
983 FILE *fpointer;
984 int width;
985 int height;
986 {
987 register int y;
988 register int x;
989 uint8 buffer[1024];
990 int safe_read_count;
991
992 Fsize_Note(mf->id, width, height);
993
994 Frame_AllocYCC(mf);
995
996 for (y = 0; y < (height>>1); y++) { /* Y */
997 safe_fread(buffer, 1, width>>1, fpointer);
998 for ( x = 0; x < (width>>1); x++ ) {
999 mf->orig_y[2*y][2*x] = buffer[x];
1000 mf->orig_y[2*y][2*x+1] = buffer[x];
1001 mf->orig_y[2*y+1][2*x] = buffer[x];
1002 mf->orig_y[2*y+1][2*x+1] = buffer[x];
1003 }
1004 }
1005
1006 for (y = 0; y < (height >> 2); y++) { /* U */
1007 safe_fread(buffer, 1, width>>2, fpointer);
1008 for ( x = 0; x < (width>>2); x++ ) {
1009 mf->orig_cb[2*y][2*x] = buffer[x];
1010 mf->orig_cb[2*y][2*x+1] = buffer[x];
1011 mf->orig_cb[2*y+1][2*x] = buffer[x];
1012 mf->orig_cb[2*y+1][2*x+1] = buffer[x];
1013 }
1014 }
1015
1016 for (y = 0; y < (height >> 2); y++) { /* V */
1017 safe_fread(buffer, 1, width>>2, fpointer);
1018 for ( x = 0; x < (width>>2); x++ ) {
1019 mf->orig_cr[2*y][2*x] = buffer[x];
1020 mf->orig_cr[2*y][2*x+1] = buffer[x];
1021 mf->orig_cr[2*y+1][2*x] = buffer[x];
1022 mf->orig_cr[2*y+1][2*x+1] = buffer[x];
1023 }
1024 }
1025 }
1026
1027
1028 /*=====================*
1029 * INTERNAL PROCEDURES *
1030 *=====================*/
1031
1032 /*===========================================================================*
1033 *
1034 * ScanNextString
1035 *
1036 * read a string from a input line, ignoring whitespace
1037 *
1038 * RETURNS: pointer to position in input line after string
1039 * NULL if all whitespace
1040 * puts string in 'string'
1041 *
1042 * SIDE EFFECTS: file stream munched a bit
1043 *
1044 *===========================================================================*/
1045 static char *
ScanNextString(inputLine,string)1046 ScanNextString(inputLine, string)
1047 char *inputLine;
1048 char *string;
1049 {
1050 /* skip whitespace */
1051 while ( isspace(*inputLine) && (*inputLine != '\n') ) {
1052 inputLine++;
1053 }
1054
1055 if ( *inputLine == '\n' ) {
1056 return NULL;
1057 }
1058
1059 while ( (! isspace(*inputLine)) && (*inputLine != '\n') ) {
1060 *string = *inputLine;
1061 string++;
1062 inputLine++;
1063 }
1064
1065 *string = '\0';
1066
1067 return inputLine;
1068 }
1069
1070 /*===========================================================================*
1071 *
1072 * DoGamma
1073 *
1074 * Gamma Correct the Lum values
1075 *
1076 * RETURNS: nothing
1077 *
1078 * SIDE EFFECTS: Raises Y values to power gamma.
1079 *
1080 *===========================================================================*/
1081 static void
DoGamma(mf,w,h)1082 DoGamma(mf, w, h)
1083 MpegFrame *mf;
1084 int w,h;
1085 {
1086 static int GammaVal[256];
1087 static boolean init_done=FALSE;
1088 int i,j;
1089
1090 if (!init_done) {
1091 for(i=0; i<256; i++)
1092 GammaVal[i]=(unsigned char) (pow(((double) i)/255.0,GammaValue)*255.0+0.5);
1093 init_done=TRUE;
1094 }
1095
1096 for (i=0; i< h; i++) { /* For each line */
1097 for (j=0; j<w; j++) { /* For each Y value */
1098 mf->orig_y[i][j] = GammaVal[mf->orig_y[i][j]];
1099 }}
1100 }
1101
1102
1103
1104
1105 /*===========================================================================*
1106 *
1107 * DoKillDim
1108 *
1109 * Applies an input filter to small Y values.
1110 *
1111 * RETURNS: nothing
1112 *
1113 * SIDE EFFECTS: Changes Y values:
1114 *
1115 * Output | /
1116 | /
1117 | /
1118 | !
1119 | /
1120 | !
1121 | /
1122 | -
1123 | /
1124 | --
1125 | /
1126 | --
1127 | /
1128 ------------------------
1129 ^ kill_dim_break
1130 ^kill_dim_end
1131 kill_dim_slope gives the slope (y = kill_dim_slope * x +0)
1132 from 0 to kill_dim_break
1133 *
1134 *===========================================================================*/
1135
1136 static void
DoKillDim(mf,w,h)1137 DoKillDim(mf, w, h)
1138 MpegFrame *mf;
1139 int w,h;
1140 {
1141 static boolean init_done=FALSE;
1142 static unsigned char mapper[256];
1143 register int i,j;
1144 double slope, intercept;
1145
1146 slope = (kill_dim_end - kill_dim_break*kill_dim_slope)*1.0 /
1147 (kill_dim_end - kill_dim_break);
1148 intercept = kill_dim_end * (1.0-slope);
1149
1150 if (!init_done) {
1151 for(i=0; i<256; i++) {
1152 if (i >= kill_dim_end) {
1153 mapper[i] = (char) i;
1154 } else if (i >= kill_dim_break) {
1155 mapper[i] = (char) (slope*i + intercept);
1156 } else { /* i <= kill_dim_break */
1157 mapper[i] = (char) floor(i*kill_dim_slope + 0.49999);
1158 }
1159 }
1160 init_done = TRUE;
1161 }
1162
1163 for (i=0; i < h; i++) { /* For each line */
1164 for (j=0; j < w; j++) { /* For each Y value */
1165 mf->orig_y[i][j] = mapper[mf->orig_y[i][j]];
1166 }}
1167 }
1168