]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2dec/store.c
ENH: Start working again on the MPEG2 stuff. Gather the stdio mess in a single place
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2dec / store.c
1 /* store.c, picture output routines                                         */
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 <stdlib.h> /* for malloc */
31 #include <fcntl.h>
32 #include <string.h> /* for strcat */
33
34 #include "config.h"
35 #include "global.h"
36
37 /* private prototypes */
38 static void store_one _ANSI_ARGS_((char *outname, unsigned char *src[],
39   int offset, int incr, int height));
40 static void store_yuv _ANSI_ARGS_((char *outname, unsigned char *src[],
41   int offset, int incr, int height));
42 static void store_sif _ANSI_ARGS_((char *outname, unsigned char *src[],
43   int offset, int incr, int height));
44 static void store_ppm_tga _ANSI_ARGS_((char *outname, unsigned char *src[],
45   int offset, int incr, int height, int tgaflag));
46 static void store_yuv1 _ANSI_ARGS_((char *name, unsigned char *src,
47   int offset, int incr, int width, int height));
48 static void putbyte _ANSI_ARGS_((int c));
49 static void putword _ANSI_ARGS_((int w));
50 static void conv422to444 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
51 static void conv420to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
52
53 #define OBFRSIZE 4096
54 static unsigned char obfr[OBFRSIZE];
55 static unsigned char *optr;
56 static int outfile;
57
58 /*
59  * store a picture as either one frame or two fields
60  */
61 void Write_Frame(src,frame)
62 unsigned char *src[];
63 int frame;
64 {
65   char outname[FILENAME_LENGTH];
66
67   if (progressive_sequence || progressive_frame || Frame_Store_Flag)
68   {
69     /* progressive */
70     my_sprintf(outname,Output_Picture_Filename,frame,'f');
71     store_one(outname,src,0,Coded_Picture_Width,vertical_size);
72   }
73   else
74   {
75     /* interlaced */
76     my_sprintf(outname,Output_Picture_Filename,frame,'a');
77     store_one(outname,src,0,Coded_Picture_Width<<1,vertical_size>>1);
78
79     my_sprintf(outname,Output_Picture_Filename,frame,'b');
80     store_one(outname,src,
81       Coded_Picture_Width,Coded_Picture_Width<<1,vertical_size>>1);
82   }
83 }
84
85 /*
86  * store one frame or one field
87  */
88 static void store_one(outname,src,offset,incr,height)
89 char *outname;
90 unsigned char *src[];
91 int offset, incr, height;
92 {
93   switch (Output_Type)
94   {
95   case T_YUV:
96     store_yuv(outname,src,offset,incr,height);
97     break;
98   case T_SIF:
99     store_sif(outname,src,offset,incr,height);
100     break;
101   case T_TGA:
102     store_ppm_tga(outname,src,offset,incr,height,1);
103     break;
104   case T_PPM:
105     store_ppm_tga(outname,src,offset,incr,height,0);
106     break;
107 #ifdef DISPLAY
108   case T_X11:
109     dither(src);
110     break;
111 #endif
112   default:
113     break;
114   }
115 }
116
117 /* separate headerless files for y, u and v */
118 static void store_yuv(outname,src,offset,incr,height)
119 char *outname;
120 unsigned char *src[];
121 int offset,incr,height;
122 {
123   int hsize;
124   char tmpname[FILENAME_LENGTH];
125
126   hsize = horizontal_size;
127
128   my_sprintf(tmpname,"%s.Y",outname);
129   store_yuv1(tmpname,src[0],offset,incr,hsize,height);
130
131   if (chroma_format!=CHROMA444)
132   {
133     offset>>=1; incr>>=1; hsize>>=1;
134   }
135
136   if (chroma_format==CHROMA420)
137   {
138     height>>=1;
139   }
140
141   my_sprintf(tmpname,"%s.U",outname);
142   store_yuv1(tmpname,src[1],offset,incr,hsize,height);
143
144   my_sprintf(tmpname,"%s.V",outname);
145   store_yuv1(tmpname,src[2],offset,incr,hsize,height);
146 }
147
148 /* auxiliary routine */
149 static void store_yuv1(name,src,offset,incr,width,height)
150 char *name;
151 unsigned char *src;
152 int offset,incr,width,height;
153 {
154   int i, j;
155   unsigned char *p;
156
157   if (!Quiet_Flag)
158     my_fprintf("saving %s\n",name);
159
160   if ((outfile = open(name,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
161   {
162     my_sprintf(Error_Text,"Couldn't create %s\n",name);
163     Error(Error_Text);
164   }
165
166   optr=obfr;
167
168   for (i=0; i<height; i++)
169   {
170     p = src + offset + incr*i;
171     for (j=0; j<width; j++)
172       putbyte(*p++);
173   }
174
175   if (optr!=obfr)
176     write(outfile,obfr,optr-obfr);
177
178   close(outfile);
179 }
180
181 /*
182  * store as headerless file in U,Y,V,Y format
183  */
184 static void store_sif (outname,src,offset,incr,height)
185 char *outname;
186 unsigned char *src[];
187 int offset, incr, height;
188 {
189   int i,j;
190   unsigned char *py, *pu, *pv;
191   static unsigned char *u422, *v422;
192
193   if (chroma_format==CHROMA444)
194     Error("4:4:4 not supported for SIF format");
195
196   if (chroma_format==CHROMA422)
197   {
198     u422 = src[1];
199     v422 = src[2];
200   }
201   else
202   {
203     if (!u422)
204     {
205       if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
206                                            *Coded_Picture_Height)))
207         Error("malloc failed");
208       if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
209                                            *Coded_Picture_Height)))
210         Error("malloc failed");
211     }
212   
213     conv420to422(src[1],u422);
214     conv420to422(src[2],v422);
215   }
216
217   strcat(outname,".SIF");
218
219   if (!Quiet_Flag)
220     my_fprintf("saving %s\n",outname);
221
222   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
223   {
224     my_sprintf(Error_Text,"Couldn't create %s\n",outname);
225     Error(Error_Text);
226   }
227
228   optr = obfr;
229
230   for (i=0; i<height; i++)
231   {
232     py = src[0] + offset + incr*i;
233     pu = u422 + (offset>>1) + (incr>>1)*i;
234     pv = v422 + (offset>>1) + (incr>>1)*i;
235
236     for (j=0; j<horizontal_size; j+=2)
237     {
238       putbyte(*pu++);
239       putbyte(*py++);
240       putbyte(*pv++);
241       putbyte(*py++);
242     }
243   }
244
245   if (optr!=obfr)
246     write(outfile,obfr,optr-obfr);
247
248   close(outfile);
249 }
250
251 /*
252  * store as PPM (PBMPLUS) or uncompressed Truevision TGA ('Targa') file
253  */
254 static void store_ppm_tga(outname,src,offset,incr,height,tgaflag)
255 char *outname;
256 unsigned char *src[];
257 int offset, incr, height;
258 int tgaflag;
259 {
260   int i, j;
261   int y, u, v, r, g, b;
262   int crv, cbu, cgu, cgv;
263   unsigned char *py, *pu, *pv;
264   static unsigned char tga24[14] = {0,0,2,0,0,0,0, 0,0,0,0,0,24,32};
265   char header[FILENAME_LENGTH];
266   static unsigned char *u422, *v422, *u444, *v444;
267
268   if (chroma_format==CHROMA444)
269   {
270     u444 = src[1];
271     v444 = src[2];
272   }
273   else
274   {
275     if (!u444)
276     {
277       if (chroma_format==CHROMA420)
278       {
279         if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
280                                              *Coded_Picture_Height)))
281           Error("malloc failed");
282         if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
283                                              *Coded_Picture_Height)))
284           Error("malloc failed");
285       }
286
287       if (!(u444 = (unsigned char *)malloc(Coded_Picture_Width
288                                            *Coded_Picture_Height)))
289         Error("malloc failed");
290
291       if (!(v444 = (unsigned char *)malloc(Coded_Picture_Width
292                                            *Coded_Picture_Height)))
293         Error("malloc failed");
294     }
295
296     if (chroma_format==CHROMA420)
297     {
298       conv420to422(src[1],u422);
299       conv420to422(src[2],v422);
300       conv422to444(u422,u444);
301       conv422to444(v422,v444);
302     }
303     else
304     {
305       conv422to444(src[1],u444);
306       conv422to444(src[2],v444);
307     }
308   }
309
310   strcat(outname,tgaflag ? ".tga" : ".ppm");
311
312   if (!Quiet_Flag)
313     my_fprintf("saving %s\n",outname);
314
315   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
316   {
317     my_sprintf(Error_Text,"Couldn't create %s\n",outname);
318     Error(Error_Text);
319   }
320
321   optr = obfr;
322
323   if (tgaflag)
324   {
325     /* TGA header */
326     for (i=0; i<12; i++)
327       putbyte(tga24[i]);
328
329     putword(horizontal_size); putword(height);
330     putbyte(tga24[12]); putbyte(tga24[13]);
331   }
332   else
333   {
334     /* PPM header */
335     my_sprintf(header,"P6\n%d %d\n255\n",horizontal_size,height);
336
337     for (i=0; header[i]!=0; i++)
338       putbyte(header[i]);
339   }
340
341   /* matrix coefficients */
342   crv = Inverse_Table_6_9[matrix_coefficients][0];
343   cbu = Inverse_Table_6_9[matrix_coefficients][1];
344   cgu = Inverse_Table_6_9[matrix_coefficients][2];
345   cgv = Inverse_Table_6_9[matrix_coefficients][3];
346   
347   for (i=0; i<height; i++)
348   {
349     py = src[0] + offset + incr*i;
350     pu = u444 + offset + incr*i;
351     pv = v444 + offset + incr*i;
352
353     for (j=0; j<horizontal_size; j++)
354     {
355       u = *pu++ - 128;
356       v = *pv++ - 128;
357       y = 76309 * (*py++ - 16); /* (255/219)*65536 */
358       r = Clip[(y + crv*v + 32768)>>16];
359       g = Clip[(y - cgu*u - cgv*v + 32768)>>16];
360       b = Clip[(y + cbu*u + 32786)>>16];
361
362       if (tgaflag)
363       {
364         putbyte(b); putbyte(g); putbyte(r);
365       }
366       else
367       {
368         putbyte(r); putbyte(g); putbyte(b);
369       }
370     }
371   }
372
373   if (optr!=obfr)
374     write(outfile,obfr,optr-obfr);
375
376   close(outfile);
377 }
378
379 static void putbyte(c)
380 int c;
381 {
382   *optr++ = c;
383
384   if (optr == obfr+OBFRSIZE)
385   {
386     write(outfile,obfr,OBFRSIZE);
387     optr = obfr;
388   }
389 }
390
391 static void putword(w)
392 int w;
393 {
394   putbyte(w); putbyte(w>>8);
395 }
396
397 /* horizontal 1:2 interpolation filter */
398 static void conv422to444(src,dst)
399 unsigned char *src,*dst;
400 {
401   int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3;
402
403   w = Coded_Picture_Width>>1;
404
405   if (base.MPEG2_Flag)
406   {
407     for (j=0; j<Coded_Picture_Height; j++)
408     {
409       for (i=0; i<w; i++)
410       {
411         i2 = i<<1;
412         im2 = (i<2) ? 0 : i-2;
413         im1 = (i<1) ? 0 : i-1;
414         ip1 = (i<w-1) ? i+1 : w-1;
415         ip2 = (i<w-2) ? i+2 : w-1;
416         ip3 = (i<w-3) ? i+3 : w-1;
417
418         /* FIR filter coefficients (*256): 21 0 -52 0 159 256 159 0 -52 0 21 */
419         /* even samples (0 0 256 0 0) */
420         dst[i2] = src[i];
421
422         /* odd samples (21 -52 159 159 -52 21) */
423         dst[i2+1] = Clip[(int)(21*(src[im2]+src[ip3])
424                         -52*(src[im1]+src[ip2]) 
425                        +159*(src[i]+src[ip1])+128)>>8];
426       }
427       src+= w;
428       dst+= Coded_Picture_Width;
429     }
430   }
431   else
432   {
433     for (j=0; j<Coded_Picture_Height; j++)
434     {
435       for (i=0; i<w; i++)
436       {
437
438         i2 = i<<1;
439         im3 = (i<3) ? 0 : i-3;
440         im2 = (i<2) ? 0 : i-2;
441         im1 = (i<1) ? 0 : i-1;
442         ip1 = (i<w-1) ? i+1 : w-1;
443         ip2 = (i<w-2) ? i+2 : w-1;
444         ip3 = (i<w-3) ? i+3 : w-1;
445
446         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
447         dst[i2] =   Clip[(int)(  5*src[im3]
448                          -21*src[im2]
449                          +70*src[im1]
450                         +228*src[i]
451                          -37*src[ip1]
452                          +11*src[ip2]+128)>>8];
453
454        dst[i2+1] = Clip[(int)(  5*src[ip3]
455                          -21*src[ip2]
456                          +70*src[ip1]
457                         +228*src[i]
458                          -37*src[im1]
459                          +11*src[im2]+128)>>8];
460       }
461       src+= w;
462       dst+= Coded_Picture_Width;
463     }
464   }
465 }
466
467 /* vertical 1:2 interpolation filter */
468 static void conv420to422(src,dst)
469 unsigned char *src,*dst;
470 {
471   int w, h, i, j, j2;
472   int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7;
473
474   w = Coded_Picture_Width>>1;
475   h = Coded_Picture_Height>>1;
476
477   if (progressive_frame)
478   {
479     /* intra frame */
480     for (i=0; i<w; i++)
481     {
482       for (j=0; j<h; j++)
483       {
484         j2 = j<<1;
485         jm3 = (j<3) ? 0 : j-3;
486         jm2 = (j<2) ? 0 : j-2;
487         jm1 = (j<1) ? 0 : j-1;
488         jp1 = (j<h-1) ? j+1 : h-1;
489         jp2 = (j<h-2) ? j+2 : h-1;
490         jp3 = (j<h-3) ? j+3 : h-1;
491
492         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
493         /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */
494         dst[w*j2] =     Clip[(int)(  3*src[w*jm3]
495                              -16*src[w*jm2]
496                              +67*src[w*jm1]
497                             +227*src[w*j]
498                              -32*src[w*jp1]
499                              +7*src[w*jp2]+128)>>8];
500
501         dst[w*(j2+1)] = Clip[(int)(  3*src[w*jp3]
502                              -16*src[w*jp2]
503                              +67*src[w*jp1]
504                             +227*src[w*j]
505                              -32*src[w*jm1]
506                              +7*src[w*jm2]+128)>>8];
507       }
508       src++;
509       dst++;
510     }
511   }
512   else
513   {
514     /* intra field */
515     for (i=0; i<w; i++)
516     {
517       for (j=0; j<h; j+=2)
518       {
519         j2 = j<<1;
520
521         /* top field */
522         jm6 = (j<6) ? 0 : j-6;
523         jm4 = (j<4) ? 0 : j-4;
524         jm2 = (j<2) ? 0 : j-2;
525         jp2 = (j<h-2) ? j+2 : h-2;
526         jp4 = (j<h-4) ? j+4 : h-2;
527         jp6 = (j<h-6) ? j+6 : h-2;
528
529         /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */
530         /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */
531         dst[w*j2] = Clip[(int)(  1*src[w*jm6]
532                          -7*src[w*jm4]
533                          +30*src[w*jm2]
534                         +248*src[w*j]
535                          -21*src[w*jp2]
536                           +5*src[w*jp4]+128)>>8];
537
538         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
539         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
540         dst[w*(j2+2)] = Clip[(int)( 7*src[w*jm4]
541                              -35*src[w*jm2]
542                             +194*src[w*j]
543                             +110*src[w*jp2]
544                              -24*src[w*jp4]
545                               +4*src[w*jp6]+128)>>8];
546
547         /* bottom field */
548         jm5 = (j<5) ? 1 : j-5;
549         jm3 = (j<3) ? 1 : j-3;
550         jm1 = (j<1) ? 1 : j-1;
551         jp1 = (j<h-1) ? j+1 : h-1;
552         jp3 = (j<h-3) ? j+3 : h-1;
553         jp5 = (j<h-5) ? j+5 : h-1;
554         jp7 = (j<h-7) ? j+7 : h-1;
555
556         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
557         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
558         dst[w*(j2+1)] = Clip[(int)( 7*src[w*jp5]
559                              -35*src[w*jp3]
560                             +194*src[w*jp1]
561                             +110*src[w*jm1]
562                              -24*src[w*jm3]
563                               +4*src[w*jm5]+128)>>8];
564
565         dst[w*(j2+3)] = Clip[(int)(  1*src[w*jp7]
566                              -7*src[w*jp5]
567                              +30*src[w*jp3]
568                             +248*src[w*jp1]
569                              -21*src[w*jm1]
570                               +5*src[w*jm3]+128)>>8];
571       }
572       src++;
573       dst++;
574     }
575   }
576 }