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