1
/* yuvsplittoppm.c - construct a portable pixmap from 3 raw files:
2
** - basename.Y : The Luminance chunk at the size of the Image
3
** - basename.U : The Chrominance chunk U at 1/4
4
** - basename.V : The Chrominance chunk V at 1/4
5
** The subsampled U and V values are made by arithmetic mean.
7
** If ccir601 is defined, the produced YUV triples have been scaled again
8
** to fit into the smaller range of values for this standard.
10
** by Marcel Wijkstra <wijkstra@fwi.uva.nl>
12
** Based on ppmtoyuvsplit.c
14
** Permission to use, copy, modify, and distribute this software and its
15
** documentation for any purpose and without fee is hereby granted, provided
16
** that the above copyright notice appear in all copies and that both that
17
** copyright notice and this permission notice appear in supporting
18
** documentation. This software is provided "as is" without express or
25
/* x must be signed for the following to work correctly */
26
#define limit(x) (((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16)
33
pixel *pixelrow1,*pixelrow2;
34
register pixel *pP1,*pP2;
37
char *usage="<basename> <width> <height> [-ccir601]";
38
long int u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3;
39
unsigned char *y1buf,*y2buf,*ubuf,*vbuf;
40
char ufname[256],vfname[256],yfname[256];
42
/* Whether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */
46
ppm_init(&argc, argv);
48
if ((argc>5) || (argc<4)) pm_usage(usage);
51
if (strncmp(argv[4],"-c",2) != 0) ccir601 = 1;
52
} else pm_usage(usage);
54
strcpy(ufname,argv[1]);
55
strcpy(vfname,argv[1]);
56
strcpy(yfname,argv[1]);
62
uf = fopen(ufname,"rb");
63
vf = fopen(vfname,"rb");
64
yf = fopen(yfname,"rb");
66
if(!(uf && vf && yf)) {
67
perror("error opening input files");
73
if (cols <= 0 || rows <= 0)
76
ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0);
78
if(cols & 1) fprintf(stderr,
79
"%s: Warning: odd columns count, exceed ignored\n",
81
if(rows & 1) fprintf(stderr,
82
"%s: Warning: odd rows count, exceed ignored\n",
85
pixelrow1 = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
86
pixelrow2 = ((pixel*) pm_allocrow( cols, sizeof(pixel) ));
88
y1buf = (unsigned char *) pm_allocrow( cols, 1 );
89
y2buf = (unsigned char *) pm_allocrow( cols, 1 );
90
ubuf = (unsigned char *) pm_allocrow( cols, 1 );
91
vbuf = (unsigned char *) pm_allocrow( cols, 1 );
93
for (row = 0; row < (rows & ~1); row += 2) {
94
unsigned char *y1ptr,*y2ptr,*uptr,*vptr;
96
fread(y1buf, (cols & ~1), 1, yf);
97
fread(y2buf, (cols & ~1), 1, yf);
98
fread(ubuf, cols/2, 1, uf);
99
fread(vbuf, cols/2, 1, vf);
101
y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf;
103
pP1 = pixelrow1; pP2 = pixelrow2;
105
for (col = 0 ; col < (cols & ~1); col += 2) {
106
long int r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3;
108
y0 = (long int) *y1ptr++;
109
y1 = (long int) *y1ptr++;
110
y2 = (long int) *y2ptr++;
111
y3 = (long int) *y2ptr++;
113
u = (long int) ((*uptr++) - 128);
114
v = (long int) ((*vptr++) - 128);
117
y0 = ((y0-16)*255)/219;
118
y1 = ((y1-16)*255)/219;
119
y2 = ((y2-16)*255)/219;
120
y3 = ((y3-16)*255)/219;
125
/* mean the chroma for subsampling */
131
/* The inverse of the JFIF RGB to YUV Matrix for $00010000 = 1.0
133
[Y] [65496 0 91880][R]
134
[U] = [65533 -22580 -46799[G]
135
[V] [65537 116128 -8][B]
139
r0 = 65536 * y0 + 91880 * v0;
140
g0 = 65536 * y0 - 22580 * u0 - 46799 * v0;
141
b0 = 65536 * y0 + 116128 * u0 ;
143
r1 = 65536 * y1 + 91880 * v1;
144
g1 = 65536 * y1 - 22580 * u1 - 46799 * v1;
145
b1 = 65536 * y1 + 116128 * u1 ;
147
r2 = 65536 * y2 + 91880 * v2;
148
g2 = 65536 * y2 - 22580 * u2 - 46799 * v2;
149
b2 = 65536 * y2 + 116128 * u2 ;
151
r3 = 65536 * y3 + 91880 * v3;
152
g3 = 65536 * y3 - 22580 * u3 - 46799 * v3;
153
b3 = 65536 * y3 + 116128 * u3 ;
169
PPM_ASSIGN(*pP1, (pixval)r0, (pixval)g0, (pixval)b0);
172
PPM_ASSIGN(*pP1, (pixval)r1, (pixval)g1, (pixval)b1);
175
PPM_ASSIGN(*pP2, (pixval)r2, (pixval)g2, (pixval)b2);
178
PPM_ASSIGN(*pP2, (pixval)r3, (pixval)g3, (pixval)b3);
181
ppm_writeppmrow(stdout, pixelrow1, cols, (pixval) 255, 0);
182
ppm_writeppmrow(stdout, pixelrow2, cols, (pixval) 255, 0);