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