1 /************************************************************************
2 *
3 * store.c, picture output routines for tmndecode (H.263 decoder)
4 * Copyright (C) 1995, 1996 Telenor R&D, Norway
5 *
6 * Contacts:
7 * Robert Danielsen <Robert.Danielsen@nta.no>
8 *
9 * Telenor Research and Development http://www.nta.no/brukere/DVC/
10 * P.O.Box 83 tel.: +47 63 84 84 00
11 * N-2007 Kjeller, Norway fax.: +47 63 81 00 76
12 *
13 * Copyright (C) 1997 University of BC, Canada
14 * Modified by: Michael Gallant <mikeg@ee.ubc.ca>
15 * Guy Cote <guyc@ee.ubc.ca>
16 * Berna Erol <bernae@ee.ubc.ca>
17 *
18 * Contacts:
19 * Michael Gallant <mikeg@ee.ubc.ca>
20 *
21 * UBC Image Processing Laboratory http://www.ee.ubc.ca/image
22 * 2356 Main Mall tel.: +1 604 822 4051
23 * Vancouver BC Canada V6T1Z4 fax.: +1 604 822 5949
24 *
25 ************************************************************************/
26
27 /* Disclaimer of Warranty
28 *
29 * These software programs are available to the user without any license fee
30 * or royalty on an "as is" basis. The University of British Columbia
31 * disclaims any and all warranties, whether express, implied, or
32 * statuary, including any implied warranties or merchantability or of
33 * fitness for a particular purpose. In no event shall the
34 * copyright-holder be liable for any incidental, punitive, or
35 * consequential damages of any kind whatsoever arising from the use of
36 * these programs.
37 *
38 * This disclaimer of warranty extends to the user of these programs and
39 * user's customers, employees, agents, transferees, successors, and
40 * assigns.
41 *
42 * The University of British Columbia does not represent or warrant that the
43 * programs furnished hereunder are free of infringement of any
44 * third-party patents.
45 *
46 * Commercial implementations of H.263, including shareware, are subject to
47 * royalty fees to patent holders. Many of these patents are general
48 * enough such that they are unavoidable regardless of implementation
49 * design.
50 *
51 */
52
53
54
55 /* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group and
56 * mpeg2play, (C) 1994 Stefan Eckart <stefan@lis.e-technik.tu-muenchen.de>
57 *
58 */
59
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <fcntl.h>
65 #ifdef WIN32
66 #include <io.h>
67 #endif
68
69 #include "config.h"
70 #include "tmndec.h"
71 #include "global.h"
72 #ifdef WINDOWS
73 int displayImage (unsigned char *lum, unsigned char *Cr, unsigned char *Cb);
74 #endif
75
76 /* private prototypes */
77 static void store_yuv _ANSI_ARGS_ ((char *outname, unsigned char *src[],
78 int offset, int incr, int height));
79 static void store_yuv_append _ANSI_ARGS_ ((char *outname, unsigned char *src[],
80 int offset, int incr, int height));
81 static void store_sif _ANSI_ARGS_ ((char *outname, unsigned char *src[],
82 int offset, int incr, int height));
83 static void store_ppm_tga _ANSI_ARGS_ ((char *outname, unsigned char *src[],
84 int offset, int incr, int height, int tgaflag));
85 static void store_yuv1 _ANSI_ARGS_ ((char *name, unsigned char *src,
86 int offset, int incr, int width, int height, int append));
87 static void putbyte _ANSI_ARGS_ ((int c));
88 static void putword _ANSI_ARGS_ ((int w));
89 static void conv422to444 _ANSI_ARGS_ ((unsigned char *src, unsigned char *dst));
90 static void conv420to422 _ANSI_ARGS_ ((unsigned char *src, unsigned char *dst));
91
92 #define OBFRSIZE 4096
93 static unsigned char obfr[OBFRSIZE];
94 static unsigned char *optr;
95 static int outfile;
96
97 /* store a picture as either one frame or two fields */
98 void storeframe (unsigned char *src[], int frame)
99 {
100 char outname[32];
101
102 /* progressive */
103 sprintf (outname, outputname, frame, 'f');
104 store_one (outname, src, 0, coded_picture_width, vertical_size);
105 }
106
107 /* store one frame or one field */
108 void store_one (char *outname, unsigned char *src[], int offset, int incr, int height)
109 {
110 switch (outtype)
111 {
112 case T_YUV:
113 store_yuv (outname, src, offset, incr, height);
114 break;
115 case T_YUV_CONC:
116 store_yuv_append (outname, src, offset, incr, height);
117 break;
118 case T_SIF:
119 store_sif (outname, src, offset, incr, height);
120 break;
121 case T_TGA:
122 store_ppm_tga (outname, src, offset, incr, height, 1);
123 break;
124 case T_PPM:
125 store_ppm_tga (outname, src, offset, incr, height, 0);
126 break;
127 #ifdef DISPLAY
128 case T_X11:
129 if (enhancement_layer_num == 1)
130 dither (src);
131 break;
132 #endif
133 #ifdef WINDOWS
134 case T_WIN:
135 if (enhancement_layer_num == 1)
136 displayImage (src[0], src[2], src[1]);
137 break;
138 #endif
139 default:
140 break;
141 }
142 }
143
144 /* separate headerless files for y, u and v */
145 static void store_yuv (char *outname, unsigned char *src[], int offset, int incr, int height)
146 {
147 int hsize;
148 char tmpname[32];
149
150 hsize = horizontal_size;
151
152 sprintf (tmpname, "%s.Y", outname);
153 store_yuv1 (tmpname, src[0], offset, incr, hsize, height, 0);
154
155 offset >>= 1;
156 incr >>= 1;
157 hsize >>= 1;
158 height >>= 1;
159
160 sprintf (tmpname, "%s.U", outname);
161 store_yuv1 (tmpname, src[1], offset, incr, hsize, height, 0);
162
163 sprintf (tmpname, "%s.V", outname);
164 store_yuv1 (tmpname, src[2], offset, incr, hsize, height, 0);
165 }
166
167 /* concatenated headerless file for y, u and v */
168 static void store_yuv_append (outname, src, offset, incr, height)
169 char *outname;
170 unsigned char *src[];
171 int offset, incr, height;
172 {
173 int hsize;
174 hsize = horizontal_size;
175
176 store_yuv1 (outname, src[0], offset, incr, hsize, height, 1);
177
178 offset >>= 1;
179 incr >>= 1;
180 hsize >>= 1;
181 height >>= 1;
182
183 store_yuv1 (outname, src[1], offset, incr, hsize, height, 1);
184 store_yuv1 (outname, src[2], offset, incr, hsize, height, 1);
185 }
186
187 /* auxiliary routine */
188 static void store_yuv1 (char *name, unsigned char *src, int offset,
189 int incr, int width, int height, int append)
190 {
191 int i, j;
192 unsigned char *p;
193
194 if (append)
195 {
196 if ((outfile = open (name, O_APPEND | O_WRONLY | O_BINARY, 0666)) == -1)
197 {
198 sprintf (errortext, "Couldn't append to %s\n", name);
199 error (errortext);
200 }
201 } else
202 {
203 if ((outfile = open (name, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) == -1)
204 {
205 sprintf (errortext, "Couldn't create %s\n", name);
206 error (errortext);
207 }
208 }
209 #if 0
210 if (!quiet)
211 fprintf (stderr, "saving %s\n", name);
212 #endif
213
214 optr = obfr;
215
216 for (i = 0; i < height; i++)
217 {
218 p = src + offset + incr * i;
219 for (j = 0; j < width; j++)
220 putbyte (*p++);
221 }
222
223 if (optr != obfr)
224 write (outfile, obfr, optr - obfr);
225
226 close (outfile);
227 }
228
229 /* store as headerless file in U,Y,V,Y format */
230 static void store_sif (char *outname, unsigned char *src[], int offset, int incr, int height)
231 {
232 int i, j;
233 unsigned char *py, *pu, *pv;
234 static unsigned char *u422, *v422;
235
236 if (!u422)
237 {
238 if (!(u422 = (unsigned char *) malloc ((coded_picture_width >> 1)
239 * coded_picture_height)))
240 error ("malloc failed");
241 if (!(v422 = (unsigned char *) malloc ((coded_picture_width >> 1)
242 * coded_picture_height)))
243 error ("malloc failed");
244 }
245 conv420to422 (src[1], u422);
246 conv420to422 (src[2], v422);
247
248 strcat (outname, ".SIF");
249
250 if (!quiet)
251 fprintf (stderr, "saving %s\n", outname);
252
253 if ((outfile = open (outname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) == -1)
254 {
255 sprintf (errortext, "Couldn't create %s\n", outname);
256 error (errortext);
257 }
258 optr = obfr;
259
260 for (i = 0; i < height; i++)
261 {
262 py = src[0] + offset + incr * i;
263 pu = u422 + (offset >> 1) + (incr >> 1) * i;
264 pv = v422 + (offset >> 1) + (incr >> 1) * i;
265
266 for (j = 0; j < horizontal_size; j += 2)
267 {
268 putbyte (*pu++);
269 putbyte (*py++);
270 putbyte (*pv++);
271 putbyte (*py++);
272 }
273 }
274
275 if (optr != obfr)
276 write (outfile, obfr, optr - obfr);
277
278 close (outfile);
279 }
280
281 /* store as PPM (PBMPLUS) or uncompressed Truevision TGA ('Targa') file */
282 static void store_ppm_tga (char *outname, unsigned char *src[], int offset, int incr,
283 int height, int tgaflag)
284 {
285 int i, j;
286 int y, u, v, r, g, b;
287 int crv, cbu, cgu, cgv;
288 unsigned char *py, *pu, *pv;
289 static unsigned char tga24[14] = {0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 32};
290 char header[32];
291 static unsigned char *u422, *v422, *u444, *v444;
292
293 if (!u444)
294 {
295 if (!(u422 = (unsigned char *) malloc ((coded_picture_width >> 1)
296 * coded_picture_height)))
297 error ("malloc failed");
298 if (!(v422 = (unsigned char *) malloc ((coded_picture_width >> 1)
299 * coded_picture_height)))
300 error ("malloc failed");
301
302 if (!(u444 = (unsigned char *) malloc (coded_picture_width
303 * coded_picture_height)))
304 error ("malloc failed");
305
306 if (!(v444 = (unsigned char *) malloc (coded_picture_width
307 * coded_picture_height)))
308 error ("malloc failed");
309 }
310 conv420to422 (src[1], u422);
311 conv420to422 (src[2], v422);
312 conv422to444 (u422, u444);
313 conv422to444 (v422, v444);
314
315 strcat (outname, tgaflag ? ".tga" : ".ppm");
316
317 if (!quiet)
318 fprintf (stderr, "saving %s\n", outname);
319
320 if ((outfile = open (outname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) == -1)
321 {
322 sprintf (errortext, "Couldn't create %s\n", outname);
323 error (errortext);
324 }
325 optr = obfr;
326
327 if (tgaflag)
328 {
329 /* TGA header */
330 for (i = 0; i < 12; i++)
331 putbyte (tga24[i]);
332
333 putword (horizontal_size);
334 putword (height);
335 putbyte (tga24[12]);
336 putbyte (tga24[13]);
337 } else
338 {
339 /* PPM header */
340 sprintf (header, "P6\n%d %d\n255\n", horizontal_size, height);
341
342 for (i = 0; header[i] != 0; i++)
343 putbyte (header[i]);
344 }
345
346 /* matrix coefficients */
347 crv = convmat[matrix_coefficients][0];
348 cbu = convmat[matrix_coefficients][1];
349 cgu = convmat[matrix_coefficients][2];
350 cgv = convmat[matrix_coefficients][3];
351
352 for (i = 0; i < height; i++)
353 {
354 py = src[0] + offset + incr * i;
355 pu = u444 + offset + incr * i;
356 pv = v444 + offset + incr * i;
357
358 for (j = 0; j < horizontal_size; j++)
359 {
360 u = *pu++ - 128;
361 v = *pv++ - 128;
362 y = 76309 * (*py++ - 16); /* (255/219)*65536 */
363 r = clp[(y + crv * v + 32768) >> 16];
364 g = clp[(y - cgu * u - cgv * v + 32768) >> 16];
365 b = clp[(y + cbu * u + 32786) >> 16];
366
367 if (tgaflag)
368 {
369 putbyte (b);
370 putbyte (g);
371 putbyte (r);
372 } else
373 {
374 putbyte (r);
375 putbyte (g);
376 putbyte (b);
377 }
378 }
379 }
380
381 if (optr != obfr)
382 write (outfile, obfr, optr - obfr);
383
384 close (outfile);
385 }
386
387 static void putbyte (int c)
388 {
389 *optr++ = c;
390
391 if (optr == obfr + OBFRSIZE)
392 {
393 write (outfile, obfr, OBFRSIZE);
394 optr = obfr;
395 }
396 }
397
398 static void putword (int w)
399 {
400 putbyte (w);
401 putbyte (w >> 8);
402 }
403
404 /* horizontal 1:2 interpolation filter */
405 static void conv422to444 (unsigned char *src, unsigned char *dst)
406 {
407 int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3;
408
409 w = coded_picture_width >> 1;
410
411 for (j = 0; j < coded_picture_height; j++)
412 {
413 for (i = 0; i < w; i++)
414 {
415
416 i2 = i << 1;
417 im3 = (i < 3) ? 0 : i - 3;
418 im2 = (i < 2) ? 0 : i - 2;
419 im1 = (i < 1) ? 0 : i - 1;
420 ip1 = (i < w - 1) ? i + 1 : w - 1;
421 ip2 = (i < w - 2) ? i + 2 : w - 1;
422 ip3 = (i < w - 3) ? i + 3 : w - 1;
423
424 /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
425 dst[i2] = clp[(int) (5 * src[im3]
426 - 21 * src[im2]
427 + 70 * src[im1]
428 + 228 * src[i]
429 - 37 * src[ip1]
430 + 11 * src[ip2] + 128) >> 8];
431
432 dst[i2 + 1] = clp[(int) (5 * src[ip3]
433 - 21 * src[ip2]
434 + 70 * src[ip1]
435 + 228 * src[i]
436 - 37 * src[im1]
437 + 11 * src[im2] + 128) >> 8];
438 }
439 src += w;
440 dst += coded_picture_width;
441 }
442 }
443
444 /* vertical 1:2 interpolation filter */
445 static void conv420to422 (unsigned char *src, unsigned char *dst)
446 {
447 int w, h, i, j, j2;
448 int jm3, jm2, jm1, jp1, jp2, jp3;
449
450 w = coded_picture_width >> 1;
451 h = coded_picture_height >> 1;
452
453 /* intra frame */
454 for (i = 0; i < w; i++)
455 {
456 for (j = 0; j < h; j++)
457 {
458 j2 = j << 1;
459 jm3 = (j < 3) ? 0 : j - 3;
460 jm2 = (j < 2) ? 0 : j - 2;
461 jm1 = (j < 1) ? 0 : j - 1;
462 jp1 = (j < h - 1) ? j + 1 : h - 1;
463 jp2 = (j < h - 2) ? j + 2 : h - 1;
464 jp3 = (j < h - 3) ? j + 3 : h - 1;
465
466 /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
467 /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */
468 dst[w * j2] = clp[(int) (3 * src[w * jm3]
469 - 16 * src[w * jm2]
470 + 67 * src[w * jm1]
471 + 227 * src[w * j]
472 - 32 * src[w * jp1]
473 + 7 * src[w * jp2] + 128) >> 8];
474
475 dst[w * (j2 + 1)] = clp[(int) (3 * src[w * jp3]
476 - 16 * src[w * jp2]
477 + 67 * src[w * jp1]
478 + 227 * src[w * j]
479 - 32 * src[w * jm1]
480 + 7 * src[w * jm2] + 128) >> 8];
481 }
482 src++;
483 dst++;
484 }
485 }
486
487 /* Stores 1 frame to a file in a raw format */
488
489 void save_frame (unsigned char *src[], int framenum, FILE *file)
490 {
491 unsigned char *lum;
492 unsigned char *Cr;
493 unsigned char *Cb;
494
495 lum = src[0];
496 Cb = src[1];
497 Cr = src[2];
498
499 if ((int) fwrite (lum, sizeof (unsigned char), coded_picture_height * coded_picture_width,
500 file) != coded_picture_height * coded_picture_width)
501 {
502 fprintf (stdout, "Error occured when writing reconstructed data\n");
503 exit (-1);
504 }
505 if ((int) fwrite (Cb, sizeof (unsigned char), coded_picture_height * coded_picture_width / 4,
506 file) != coded_picture_height * coded_picture_width / 4)
507 {
508 fprintf (stdout, "Error occured when writing reconstructed data\n");
509 exit (-1);
510 }
511 if ((int) fwrite (Cr, sizeof (unsigned char), coded_picture_height * coded_picture_width / 4,
512 file) != coded_picture_height * coded_picture_width / 4)
513 {
514 fprintf (stdout, "Error occured when writing reconstructed data\n");
515 exit (-1);
516 }
517 }
518
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.