about summary refs log tree commit diff
path: root/converter/ppm/ppmtoyuv.c
blob: 7d843cc02b829dc6f8b35852923a177ec2338984 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* ppmtoyuv.c - convert a portable pixmap into an Abekas YUV file
**
** by Marc Boucher
** Internet: marc@PostImage.COM
** 
** Based on Example Conversion Program, A60/A64 Digital Video Interface
** Manual, page 69.
**
** Copyright (C) 1991 by DHD PostImage Inc.
** Copyright (C) 1987 by Abekas Video Systems Inc.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include "ppm.h"

int
main(argc, argv)
char **argv;
{
	FILE *ifp;
	pixel          *pixelrow;
	register pixel *pP;
	int             rows, cols, format, row;
	register int    col;
	pixval          maxval;
	unsigned long   y1, y2=0, u=0, v=0, u0=0, u1, u2, v0=0, v1, v2;
	unsigned char  *yuvbuf;


	ppm_init(&argc, argv);

	if (argc > 2) pm_usage("[ppmfile]");

	if (argc == 2) ifp = pm_openr(argv[1]);
	else ifp = stdin;

	ppm_readppminit(ifp, &cols, &rows, &maxval, &format);

    if (cols % 2 != 0)
        pm_error("Image must have even number of columns.\n"
                 "This image is %d columns wide.  Try Pnmcut.", cols);

	pixelrow = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
	yuvbuf = (unsigned char *) pm_allocrow( cols, 2 );

	for (row = 0; row < rows; ++row) {
		unsigned char *yuvptr;

		ppm_readppmrow(ifp, pixelrow, cols, maxval, format);

		for (col = 0, pP = pixelrow, yuvptr=yuvbuf; col < cols; col += 2, ++pP) {
			pixval r, g, b;

			/* first pixel gives Y and 0.5 of chroma */
			r = PPM_GETR(*pP);
			g = PPM_GETG(*pP);
			b = PPM_GETB(*pP);

			y1 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y2);
			u1 = -4853 * r - 9530 * g + 14383 * b;
			v1 = 14386 * r - 12046 * g - 2340 * b;

			pP++;
			/* second pixel just yields a Y and 0.25 U, 0.25 V */
			r = PPM_GETR(*pP);
			g = PPM_GETG(*pP);
			b = PPM_GETB(*pP);

			y2 = 16829 * r + 33039 * g + 6416 * b + (0xffff & y1);
			u2 = -2426 * r - 4765 * g + 7191 * b;
			v2 = 7193 * r - 6023 * g - 1170 * b;

			/* filter the chroma */
			u = u0 + u1 + u2 + (0xffff & u);
			v = v0 + v1 + v2 + (0xffff & v);

			u0 = u2;
			v0 = v2;

			*yuvptr++ = (u >> 16) + 128;
			*yuvptr++ = (y1 >> 16) + 16;
			*yuvptr++ = (v >> 16) + 128;
			*yuvptr++ = (y2 >> 16) + 16;
		}
		fwrite(yuvbuf, cols*2, 1, stdout);
	}

	pm_close(ifp);

	exit(0);
}