1 /*
2  * Copyright (c) 1995 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation for any purpose, without fee, and without written agreement is
7  * hereby granted, provided that the above copyright notice and the following
8  * two paragraphs appear in all copies of this software.
9  *
10  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
11  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
12  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
13  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  *
15  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
18  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
19  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
20  */
21 
22 /*==============*
23  * HEADER FILES *
24  *==============*/
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdlib.h>
28 
29 typedef unsigned char uint8;
30 
31 #define CHOP(x)	    ((x < 0) ? 0 : ((x > 255) ? 255 : x))
32 
33 
34 uint8 **orig_y, **orig_cb, **orig_cr;
35 uint8 **red, **green, **blue;
36 int	width = 352;
37 int	height = 240;
38 
39 void YUVtoPPM(void);
40 void WritePPM(FILE *fpointer);
41 void Usage(void);
42 void ReadYUV(FILE *fp);
43 void AllocYCC(void);
44 
45 
main(int argc,char ** argv)46 void	main(int argc, char **argv)
47 {
48     FILE *fpointer;
49     char src[256], dest[256];
50 
51     if ((strcmp(argv[1],"-?") == 0) ||
52 	(strcmp(argv[1],"-h") == 0) ||
53 	(strcmp(argv[1],"-help") == 0)) {
54       Usage();
55     }
56 
57     switch (argc) {
58     case 1:
59       Usage();
60       break;
61     case 2:
62       strcpy(src, argv[1]);
63       sprintf(dest, "%s.ppm", argv[1]);
64       break;
65     case 3:
66       strcpy(src, argv[1]);
67       strcpy(dest, argv[2]);
68       break;
69     case 4:
70       width = atoi(argv[1]);
71       height = atoi(argv[2]);
72       if (width==0 || height==0) Usage();
73       strcpy(src, argv[3]);
74       sprintf(dest, "%s.ppm", argv[3]);
75       break;
76     case 5:
77       width = atoi(argv[1]);
78       height = atoi(argv[2]);
79       if (width==0 || height==0) Usage();
80       strcpy(src, argv[3]);
81       strcpy(dest, argv[4]);
82       break;
83     default:
84       Usage();
85     }
86 
87     AllocYCC();
88 
89     fprintf(stdout, "Reading (%dx%d):  %s\n", width, height, src);
90     fpointer = fopen(src, "r");
91     ReadYUV(fpointer);
92     fclose(fpointer);
93 
94     fprintf(stdout, "Converting to PPM\n");
95     YUVtoPPM();
96 
97     fprintf(stdout, "Writing PPM (%s)\n", dest);
98 
99     fpointer = fopen(dest, "w");
100     if (fpointer == NULL) {
101       fprintf(stderr, "Problems opening %s!\n", dest);
102       fprintf(stderr, "Trying /tmp/foobar instead\n");
103       strcpy(dest, "/tmp/foobar");
104       fpointer = fopen(dest, "w");
105       if (fpointer == NULL) {
106 	fprintf(stderr, "Nope, exiting.\n");
107 	exit(1);
108       }}
109 
110     WritePPM(fpointer);
111     fclose(fpointer);
112 
113 }
114 
Usage(void)115 void Usage(void)
116 {
117   printf("USAGE:  eyuvtoppm yuv [ppm]  (assumes %d by %d)\n", width, height);
118   printf("\teyuvtoppm width height yuv [ppm]\n");
119   exit(0);
120 }
121 
WritePPM(FILE * fpointer)122 void	WritePPM(FILE *fpointer)
123 {
124     register int y, x;
125 
126     /* magic number */
127     fprintf(fpointer, "P6\n");
128 
129     /* width, height */
130     fprintf(fpointer, "%d %d\n", width, height);
131 
132     /* max value */
133     fprintf(fpointer, "255\n");
134 
135     for ( y = 0; y < height; y++ )
136 	for ( x = 0; x < width; x++ )
137 	{
138 	    fwrite(&red[y][x], 1, 1, fpointer);
139 	    fwrite(&green[y][x], 1, 1, fpointer);
140 	    fwrite(&blue[y][x], 1, 1, fpointer);
141 	}
142 }
143 
144 
YUVtoPPM(void)145 void YUVtoPPM(void)
146 {
147     long   tempR, tempG, tempB;
148     int	    r, g, b;
149     int	    **Y, **U, **V;
150     int	    x, y;
151 
152     /* * first, allocate tons of memory */
153 
154     Y = (int **) malloc(sizeof(int *) * height);
155     for (y = 0; y < height; y++) {
156       Y[y] = (int *) malloc(sizeof(int) * width);
157     }
158 
159     U = (int **) malloc(sizeof(int *) * height / 2);
160     for (y = 0; y < height / 2; y++) {
161 	U[y] = (int *) malloc(sizeof(int) * width / 2);
162     }
163 
164     V = (int **) malloc(sizeof(int *) * height / 2);
165     for (y = 0; y < height / 2; y++) {
166 	V[y] = (int *) malloc(sizeof(int) * width / 2);
167     }
168 
169 	for ( y = 0; y < height/2; y ++ )
170 	    for ( x = 0; x < width/2; x ++ )
171 	    {
172 		U[y][x] = orig_cb[y][x] - 128;
173 		V[y][x] = orig_cr[y][x] - 128;
174 	    }
175 
176 	for ( y = 0; y < height; y ++ )
177 	    for ( x = 0; x < width; x ++ )
178 	    {
179 		Y[y][x] = orig_y[y][x] - 16;
180 	    }
181 
182     for ( y = 0; y < height; y++ )
183 	for ( x = 0; x < width; x++ )
184 	{
185 	    /* look at yuvtoppm source for explanation */
186 
187 	    tempR = 104635*V[y/2][x/2];
188 	    tempG = -25690*U[y/2][x/2] + -53294 * V[y/2][x/2];
189             tempB = 132278*U[y/2][x/2];
190 
191 	    tempR += (Y[y][x]*76310);
192 	    tempG += (Y[y][x]*76310);
193 	    tempB += (Y[y][x]*76310);
194 
195 	    r = CHOP((int)(tempR >> 16));
196 	    g = CHOP((int)(tempG >> 16));
197 	    b = CHOP((int)(tempB >> 16));
198 
199 	    red[y][x] = r;  green[y][x] = g;	blue[y][x] = b;
200 	}
201 }
202 
203 
204 /*=====================*
205  * EXPORTED PROCEDURES *
206  *=====================*/
207 
ReadYUV(fpointer)208 void ReadYUV(fpointer)
209      FILE *fpointer;
210 {
211     register int y;
212 
213     for (y = 0; y < height; y++)			/* Y */
214 	fread(orig_y[y], 1, width, fpointer);
215 
216     for (y = 0; y < height / 2; y++)			/* U */
217 	fread(orig_cb[y], 1, width / 2, fpointer);
218 
219     for (y = 0; y < height / 2; y++)			/* V */
220 	fread(orig_cr[y], 1, width / 2, fpointer);
221 }
222 
223 
AllocYCC()224 void AllocYCC()
225 {
226     register int y;
227 
228     /*
229      * first, allocate tons of memory
230      */
231     orig_y = (uint8 **) malloc(sizeof(uint8 *) * height);
232     for (y = 0; y < height; y++) {
233 	orig_y[y] = (uint8 *) malloc(sizeof(uint8) * width);
234     }
235 
236     orig_cr = (uint8 **) malloc(sizeof(uint8 *) * height / 2);
237     for (y = 0; y < height / 2; y++) {
238 	orig_cr[y] = (uint8 *) malloc(sizeof(uint8) * width / 2);
239     }
240 
241     orig_cb = (uint8 **) malloc(sizeof(uint8 *) * height / 2);
242     for (y = 0; y < height / 2; y++) {
243 	orig_cb[y] = (uint8 *) malloc(sizeof(uint8) * width / 2);
244     }
245 
246     /* * first, allocate tons of memory */
247 
248     red = (uint8 **) malloc(sizeof(uint8 *) * height);
249     for (y = 0; y < height; y++) {
250       red[y] = (uint8 *) malloc(sizeof(uint8) * width);
251     }
252 
253     green = (uint8 **) malloc(sizeof(uint8 *) * height);
254     for (y = 0; y < height; y++) {
255 	green[y] = (uint8 *) malloc(sizeof(uint8) * width);
256     }
257 
258     blue = (uint8 **) malloc(sizeof(uint8 *) * height);
259     for (y = 0; y < height; y++) {
260 	blue[y] = (uint8 *) malloc(sizeof(uint8) * width);
261     }
262 }
263 
264 
265