]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2enc/readpic.c
ENH: Revamp a bit the build process to make the exe more like a library...
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2enc / readpic.c
1 /* readpic.c, read source pictures                                          */
2
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
4
5 /*
6  * Disclaimer of Warranty
7  *
8  * These software programs are available to the user without any license fee or
9  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
10  * any and all warranties, whether express, implied, or statuary, including any
11  * implied warranties or merchantability or of fitness for a particular
12  * purpose.  In no event shall the copyright-holder be liable for any
13  * incidental, punitive, or consequential damages of any kind whatsoever
14  * arising from the use of these programs.
15  *
16  * This disclaimer of warranty extends to the user of these programs and user's
17  * customers, employees, agents, transferees, successors, and assigns.
18  *
19  * The MPEG Software Simulation Group does not represent or warrant that the
20  * programs furnished hereunder are free of infringement of any third-party
21  * patents.
22  *
23  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24  * are subject to royalty fees to patent holders.  Many of these patents are
25  * general enough such that they are unavoidable regardless of implementation
26  * design.
27  *
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include "config.h"
33 #include "global.h"
34
35 /* private prototypes */
36 static void read_y_u_v _ANSI_ARGS_((char *fname, unsigned char *frame[]));
37 static void read_yuv _ANSI_ARGS_((char *fname, unsigned char *frame[]));
38 static void read_ppm _ANSI_ARGS_((char *fname, unsigned char *frame[]));
39 static void border_extend _ANSI_ARGS_((unsigned char *frame, int w1, int h1,
40   int w2, int h2));
41 static void conv444to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
42 static void conv422to420 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
43
44 int pbm_getint(FILE *file); /*forward declaration */
45
46 void readframe(fname,frame)
47 char *fname;
48 unsigned char *frame[];
49 {
50   switch (inputtype)
51   {
52   case T_Y_U_V:
53     read_y_u_v(fname,frame);
54     break;
55   case T_YUV:
56     read_yuv(fname,frame);
57     break;
58   case T_PPM:
59     read_ppm(fname,frame);
60     break;
61   default:
62     break;
63   }
64 }
65
66 static void read_y_u_v(fname,frame)
67 char *fname;
68 unsigned char *frame[];
69 {
70   int i;
71   int chrom_hsize, chrom_vsize;
72   char name[128];
73   FILE *fd;
74
75   chrom_hsize = (chroma_format==CHROMA444) ? horizontal_size
76                                            : horizontal_size>>1;
77   chrom_vsize = (chroma_format!=CHROMA420) ? vertical_size
78                                            : vertical_size>>1;
79
80   sprintf(name,"%s.Y",fname);
81   if (!(fd = fopen(name,"rb")))
82   {
83     sprintf(errortext,"Couldn't open %s\n",name);
84     error(errortext);
85   }
86   for (i=0; i<vertical_size; i++)
87     fread(frame[0]+i*width,1,horizontal_size,fd);
88   fclose(fd);
89   border_extend(frame[0],horizontal_size,vertical_size,width,height);
90
91   sprintf(name,"%s.U",fname);
92   if (!(fd = fopen(name,"rb")))
93   {
94     sprintf(errortext,"Couldn't open %s\n",name);
95     error(errortext);
96   }
97   for (i=0; i<chrom_vsize; i++)
98     fread(frame[1]+i*chrom_width,1,chrom_hsize,fd);
99   fclose(fd);
100   border_extend(frame[1],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
101
102   sprintf(name,"%s.V",fname);
103   if (!(fd = fopen(name,"rb")))
104   {
105     sprintf(errortext,"Couldn't open %s\n",name);
106     error(errortext);
107   }
108   for (i=0; i<chrom_vsize; i++)
109     fread(frame[2]+i*chrom_width,1,chrom_hsize,fd);
110   fclose(fd);
111   border_extend(frame[2],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
112 }
113
114 static void read_yuv(fname,frame)
115 char *fname;
116 unsigned char *frame[];
117 {
118   int i;
119   int chrom_hsize, chrom_vsize;
120   char name[128];
121   FILE *fd;
122
123   chrom_hsize = (chroma_format==CHROMA444) ? horizontal_size
124                                            : horizontal_size>>1;
125   chrom_vsize = (chroma_format!=CHROMA420) ? vertical_size
126                                            : vertical_size>>1;
127
128   sprintf(name,"%s.yuv",fname);
129   if (!(fd = fopen(name,"rb")))
130   {
131     sprintf(errortext,"Couldn't open %s\n",name);
132     error(errortext);
133   }
134
135   /* Y */
136   for (i=0; i<vertical_size; i++)
137     fread(frame[0]+i*width,1,horizontal_size,fd);
138   border_extend(frame[0],horizontal_size,vertical_size,width,height);
139
140   /* Cb */
141   for (i=0; i<chrom_vsize; i++)
142     fread(frame[1]+i*chrom_width,1,chrom_hsize,fd);
143   border_extend(frame[1],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
144
145   /* Cr */
146   for (i=0; i<chrom_vsize; i++)
147     fread(frame[2]+i*chrom_width,1,chrom_hsize,fd);
148   border_extend(frame[2],chrom_hsize,chrom_vsize,chrom_width,chrom_height);
149
150   fclose(fd);
151 }
152
153 static void read_ppm(fname,frame)
154 char *fname;
155 unsigned char *frame[];
156 {
157   int i, j;
158   int r, g, b;
159   double y, u, v;
160   double cr, cg, cb, cu, cv;
161   char name[128];
162   FILE *fd;
163   unsigned char *yp, *up, *vp;
164   static unsigned char *u444, *v444, *u422, *v422;
165   static double coef[7][3] = {
166     {0.2125,0.7154,0.0721}, /* ITU-R Rec. 709 (1990) */
167     {0.299, 0.587, 0.114},  /* unspecified */
168     {0.299, 0.587, 0.114},  /* reserved */
169     {0.30,  0.59,  0.11},   /* FCC */
170     {0.299, 0.587, 0.114},  /* ITU-R Rec. 624-4 System B, G */
171     {0.299, 0.587, 0.114},  /* SMPTE 170M */
172     {0.212, 0.701, 0.087}}; /* SMPTE 240M (1987) */
173
174   i = matrix_coefficients;
175   if (i>8)
176     i = 3;
177
178   cr = coef[i-1][0];
179   cg = coef[i-1][1];
180   cb = coef[i-1][2];
181   cu = 0.5/(1.0-cb);
182   cv = 0.5/(1.0-cr);
183
184   if (chroma_format==CHROMA444)
185   {
186     u444 = frame[1];
187     v444 = frame[2];
188   }
189   else
190   {
191     if (!u444)
192     {
193       if (!(u444 = (unsigned char *)malloc(width*height)))
194         error("malloc failed");
195       if (!(v444 = (unsigned char *)malloc(width*height)))
196         error("malloc failed");
197       if (chroma_format==CHROMA420)
198       {
199         if (!(u422 = (unsigned char *)malloc((width>>1)*height)))
200           error("malloc failed");
201         if (!(v422 = (unsigned char *)malloc((width>>1)*height)))
202           error("malloc failed");
203       }
204     }
205   }
206
207   sprintf(name,"%s.ppm",fname);
208
209   if (!(fd = fopen(name,"rb")))
210   {
211     sprintf(errortext,"Couldn't open %s\n",name);
212     error(errortext);
213   }
214
215   /* skip header */
216   getc(fd); getc(fd); /* magic number (P6) */
217   pbm_getint(fd); pbm_getint(fd); pbm_getint(fd); /* width height maxcolors */
218
219   for (i=0; i<vertical_size; i++)
220   {
221     yp = frame[0] + i*width;
222     up = u444 + i*width;
223     vp = v444 + i*width;
224
225     for (j=0; j<horizontal_size; j++)
226     {
227       r=getc(fd); g=getc(fd); b=getc(fd);
228       /* convert to YUV */
229       y = cr*r + cg*g + cb*b;
230       u = cu*(b-y);
231       v = cv*(r-y);
232       yp[j] = (unsigned char)((219.0/256.0)*y + 16.5);  /* nominal range: 16..235 */
233       up[j] = (unsigned char)((224.0/256.0)*u + 128.5); /* 16..240 */
234       vp[j] = (unsigned char)((224.0/256.0)*v + 128.5); /* 16..240 */
235     }
236   }
237   fclose(fd);
238
239   border_extend(frame[0],horizontal_size,vertical_size,width,height);
240   border_extend(u444,horizontal_size,vertical_size,width,height);
241   border_extend(v444,horizontal_size,vertical_size,width,height);
242
243   if (chroma_format==CHROMA422)
244   {
245     conv444to422(u444,frame[1]);
246     conv444to422(v444,frame[2]);
247   }
248
249   if (chroma_format==CHROMA420)
250   {
251     conv444to422(u444,u422);
252     conv444to422(v444,v422);
253     conv422to420(u422,frame[1]);
254     conv422to420(v422,frame[2]);
255   }
256 }
257
258 static void border_extend(frame,w1,h1,w2,h2)
259 unsigned char *frame;
260 int w1,h1,w2,h2;
261 {
262   int i, j;
263   unsigned char *fp;
264
265   /* horizontal pixel replication (right border) */
266
267   for (j=0; j<h1; j++)
268   {
269     fp = frame + j*w2;
270     for (i=w1; i<w2; i++)
271       fp[i] = fp[i-1];
272   }
273
274   /* vertical pixel replication (bottom border) */
275
276   for (j=h1; j<h2; j++)
277   {
278     fp = frame + j*w2;
279     for (i=0; i<w2; i++)
280       fp[i] = fp[i-w2];
281   }
282 }
283
284 /* horizontal filter and 2:1 subsampling */
285 static void conv444to422(src,dst)
286 unsigned char *src, *dst;
287 {
288   int i, j, im5, im4, im3, im2, im1, ip1, ip2, ip3, ip4, ip5, ip6;
289
290   if (mpeg1)
291   {
292     for (j=0; j<height; j++)
293     {
294       for (i=0; i<width; i+=2)
295       {
296         im5 = (i<5) ? 0 : i-5;
297         im4 = (i<4) ? 0 : i-4;
298         im3 = (i<3) ? 0 : i-3;
299         im2 = (i<2) ? 0 : i-2;
300         im1 = (i<1) ? 0 : i-1;
301         ip1 = (i<width-1) ? i+1 : width-1;
302         ip2 = (i<width-2) ? i+2 : width-1;
303         ip3 = (i<width-3) ? i+3 : width-1;
304         ip4 = (i<width-4) ? i+4 : width-1;
305         ip5 = (i<width-5) ? i+5 : width-1;
306         ip6 = (i<width-5) ? i+6 : width-1;
307
308         /* FIR filter with 0.5 sample interval phase shift */
309         dst[i>>1] = clp[(int)(228*(src[i]+src[ip1])
310                          +70*(src[im1]+src[ip2])
311                          -37*(src[im2]+src[ip3])
312                          -21*(src[im3]+src[ip4])
313                          +11*(src[im4]+src[ip5])
314                          + 5*(src[im5]+src[ip6])+256)>>9];
315       }
316       src+= width;
317       dst+= width>>1;
318     }
319   }
320   else
321   {
322     /* MPEG-2 */
323     for (j=0; j<height; j++)
324     {
325       for (i=0; i<width; i+=2)
326       {
327         im5 = (i<5) ? 0 : i-5;
328         im3 = (i<3) ? 0 : i-3;
329         im1 = (i<1) ? 0 : i-1;
330         ip1 = (i<width-1) ? i+1 : width-1;
331         ip3 = (i<width-3) ? i+3 : width-1;
332         ip5 = (i<width-5) ? i+5 : width-1;
333
334         /* FIR filter coefficients (*512): 22 0 -52 0 159 256 159 0 -52 0 22 */
335         dst[i>>1] = clp[(int)(  22*(src[im5]+src[ip5])-52*(src[im3]+src[ip3])
336                          +159*(src[im1]+src[ip1])+256*src[i]+256)>>9];
337       }
338       src+= width;
339       dst+= width>>1;
340     }
341   }
342 }
343
344 /* vertical filter and 2:1 subsampling */
345 static void conv422to420(src,dst)
346 unsigned char *src, *dst;
347 {
348   int w, i, j, jm6, jm5, jm4, jm3, jm2, jm1;
349   int jp1, jp2, jp3, jp4, jp5, jp6;
350
351   w = width>>1;
352
353   if (prog_frame)
354   {
355     /* intra frame */
356     for (i=0; i<w; i++)
357     {
358       for (j=0; j<height; j+=2)
359       {
360         jm5 = (j<5) ? 0 : j-5;
361         jm4 = (j<4) ? 0 : j-4;
362         jm3 = (j<3) ? 0 : j-3;
363         jm2 = (j<2) ? 0 : j-2;
364         jm1 = (j<1) ? 0 : j-1;
365         jp1 = (j<height-1) ? j+1 : height-1;
366         jp2 = (j<height-2) ? j+2 : height-1;
367         jp3 = (j<height-3) ? j+3 : height-1;
368         jp4 = (j<height-4) ? j+4 : height-1;
369         jp5 = (j<height-5) ? j+5 : height-1;
370         jp6 = (j<height-5) ? j+6 : height-1;
371
372         /* FIR filter with 0.5 sample interval phase shift */
373         dst[w*(j>>1)] = clp[(int)(228*(src[w*j]+src[w*jp1])
374                              +70*(src[w*jm1]+src[w*jp2])
375                              -37*(src[w*jm2]+src[w*jp3])
376                              -21*(src[w*jm3]+src[w*jp4])
377                              +11*(src[w*jm4]+src[w*jp5])
378                              + 5*(src[w*jm5]+src[w*jp6])+256)>>9];
379       }
380       src++;
381       dst++;
382     }
383   }
384   else
385   {
386     /* intra field */
387     for (i=0; i<w; i++)
388     {
389       for (j=0; j<height; j+=4)
390       {
391         /* top field */
392         jm5 = (j<10) ? 0 : j-10;
393         jm4 = (j<8) ? 0 : j-8;
394         jm3 = (j<6) ? 0 : j-6;
395         jm2 = (j<4) ? 0 : j-4;
396         jm1 = (j<2) ? 0 : j-2;
397         jp1 = (j<height-2) ? j+2 : height-2;
398         jp2 = (j<height-4) ? j+4 : height-2;
399         jp3 = (j<height-6) ? j+6 : height-2;
400         jp4 = (j<height-8) ? j+8 : height-2;
401         jp5 = (j<height-10) ? j+10 : height-2;
402         jp6 = (j<height-12) ? j+12 : height-2;
403
404         /* FIR filter with 0.25 sample interval phase shift */
405         dst[w*(j>>1)] = clp[(int)(8*src[w*jm5]
406                             +5*src[w*jm4]
407                            -30*src[w*jm3]
408                            -18*src[w*jm2]
409                           +113*src[w*jm1]
410                           +242*src[w*j]
411                           +192*src[w*jp1]
412                            +35*src[w*jp2]
413                            -38*src[w*jp3]
414                            -10*src[w*jp4]
415                            +11*src[w*jp5]
416                             +2*src[w*jp6]+256)>>9];
417
418         /* bottom field */
419         jm6 = (j<9) ? 1 : j-9;
420         jm5 = (j<7) ? 1 : j-7;
421         jm4 = (j<5) ? 1 : j-5;
422         jm3 = (j<3) ? 1 : j-3;
423         jm2 = (j<1) ? 1 : j-1;
424         jm1 = (j<height-1) ? j+1 : height-1;
425         jp1 = (j<height-3) ? j+3 : height-1;
426         jp2 = (j<height-5) ? j+5 : height-1;
427         jp3 = (j<height-7) ? j+7 : height-1;
428         jp4 = (j<height-9) ? j+9 : height-1;
429         jp5 = (j<height-11) ? j+11 : height-1;
430         jp6 = (j<height-13) ? j+13 : height-1;
431
432         /* FIR filter with 0.25 sample interval phase shift */
433         dst[w*((j>>1)+1)] = clp[(int)(8*src[w*jp6]
434                                 +5*src[w*jp5]
435                                -30*src[w*jp4]
436                                -18*src[w*jp3]
437                               +113*src[w*jp2]
438                               +242*src[w*jp1]
439                               +192*src[w*jm1]
440                                +35*src[w*jm2]
441                                -38*src[w*jm3]
442                                -10*src[w*jm4]
443                                +11*src[w*jm5]
444                                 +2*src[w*jm6]+256)>>9];
445       }
446       src++;
447       dst++;
448     }
449   }
450 }
451
452 /* pbm_getc() and pbm_getint() are essentially taken from
453  * PBMPLUS (C) Jef Poskanzer
454  * but without error/EOF checking
455  */
456 char pbm_getc(file)
457 FILE* file;
458 {
459   char ch;
460
461   ch = getc(file);
462
463   if (ch=='#')
464   {
465     do
466     {
467       ch = getc(file);
468     }
469     while (ch!='\n' && ch!='\r');
470   }
471
472   return ch;
473 }
474
475 int pbm_getint(file)
476 FILE* file;
477 {
478   char ch;
479   int i;
480
481   do
482   {
483     ch = pbm_getc(file);
484   }
485   while (ch==' ' || ch=='\t' || ch=='\n' || ch=='\r');
486
487   i = 0;
488   do
489   {
490     i = i*10 + ch-'0';
491     ch = pbm_getc(file);
492   }
493   while (ch>='0' && ch<='9');
494
495   return i;
496 }