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