You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.6 KiB
144 lines
3.6 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
'''
|
|
Compile thusly:
|
|
cc -o yuv2ppm yuv2ppm.c
|
|
'''
|
|
''' example.ppm
|
|
P3
|
|
# feep.ppm
|
|
4 4
|
|
15
|
|
0 0 0 0 0 0 0 0 0 15 0 15
|
|
0 0 0 0 15 7 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 15 7 0 0 0
|
|
15 0 15 0 0 0 0 0 0 0 0 0
|
|
'''
|
|
'''
|
|
Use "P6" for binary data, or "P3" for ascii data.
|
|
'''
|
|
def make_outfile(self, *outfile, *infile): int i
|
|
for(i=0; infile[i]; i++)
|
|
outfile[i] = infile[i]
|
|
outfile[i++] = '.'
|
|
outfile[i++] = 'p'
|
|
outfile[i++] = 'p'
|
|
outfile[i++] = 'm'
|
|
outfile[i++] = 0
|
|
return 0
|
|
|
|
|
|
def yuv2rgb(self, y, u, v): unsigned int pixel32
|
|
unsigned char *pixel = (unsigned char *)&pixel32
|
|
int r, g, b
|
|
#if 0
|
|
'''
|
|
One formula I found: (not the right one)
|
|
R = 1.164(Y - 16) + 1.596(Cr - 128)
|
|
G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.391(Cb - 128)
|
|
B = 1.164(Y - 16) + 2.018(Cb - 128)
|
|
'''
|
|
r = (1.164 * (y - 16))
|
|
+ (2.018 * (v - 128))
|
|
g = (1.164 * (y - 16))
|
|
- (0.813 * (u - 128))
|
|
- (0.391 * (v - 128))
|
|
b = (1.164 * (y - 16))
|
|
+ (1.596 * (u - 128))
|
|
#else:
|
|
'''
|
|
Another formula I found: (seems to work)
|
|
R = Y + 1.370705 (V-128)
|
|
G = Y - 0.698001 (V-128) - 0.337633 (U-128)
|
|
B = Y + 1.732446 (U-128)
|
|
'''
|
|
r = y + (1.370705 * (v-128))
|
|
g = y - (0.698001 * (v-128)) - (0.337633 * (u-128))
|
|
b = y + (1.732446 * (u-128))
|
|
#endif
|
|
# Even with proper conversion, values still need clipping.
|
|
if (r > 255) r = 255
|
|
if (g > 255) g = 255
|
|
if (b > 255) b = 255
|
|
if (r < 0) r = 0
|
|
if (g < 0) g = 0
|
|
if (b < 0) b = 0
|
|
# Values only go from 0-220.. Why?
|
|
pixel[0] = r * 220 / 256
|
|
pixel[1] = g * 220 / 256
|
|
pixel[2] = b * 220 / 256
|
|
pixel[3] = 0
|
|
''' Debug
|
|
printf("yuv2rgb(%i, %i, %i) . %i, %i, %i (0x%x)\n",
|
|
y, u, v,
|
|
pixel[0], pixel[1], pixel[2],
|
|
pixel32)
|
|
'''
|
|
return pixel32
|
|
|
|
|
|
def yuv2ppm(self, *infile, *outfile): FILE *in, *out
|
|
int i
|
|
unsigned int pixel_16
|
|
unsigned char pixel_24[3]
|
|
unsigned int pixel32
|
|
int y, u, v, y2
|
|
char *ppmheader = "P6\n# Generated by yuv2ppm\n720 486\n255\n"
|
|
in = fopen(infile, "rb")
|
|
out = fopen(outfile, "wb")
|
|
if (not in or not out) return 0
|
|
fprintf(out, ppmheader)
|
|
for(i=0; i<720*486/2; i++)
|
|
fread(&pixel_16, 4, 1, in)
|
|
pixel_24[0] = pixel_24[1] = pixel_24[2] = 0
|
|
u = ((pixel_16 & 0x000000ff))
|
|
y = ((pixel_16 & 0x0000ff00)>>8)
|
|
v = ((pixel_16 & 0x00ff0000)>>16)
|
|
y2 = ((pixel_16 & 0xff000000)>>24)
|
|
pixel32 = yuv2rgb(y, u, v)
|
|
pixel_24[0] = (pixel32 & 0x000000ff)
|
|
pixel_24[1] = (pixel32 & 0x0000ff00) >> 8
|
|
pixel_24[2] = (pixel32 & 0x00ff0000) >> 16
|
|
# For binary PPM
|
|
fwrite(pixel_24, 3, 1, out)
|
|
# For ascii PPM
|
|
#fprintf(out, "%i %i %i\n",
|
|
# pixel_24[0],
|
|
# pixel_24[1],
|
|
# pixel_24[2])
|
|
pixel32 = yuv2rgb(y2, u, v)
|
|
pixel_24[0] = (pixel32 & 0x000000ff)
|
|
pixel_24[1] = (pixel32 & 0x0000ff00) >> 8
|
|
pixel_24[2] = (pixel32 & 0x00ff0000) >> 16
|
|
# For binary PPM
|
|
fwrite(pixel_24, 3, 1, out)
|
|
# For ascii PPM
|
|
#fprintf(out, "%i %i %i\n",
|
|
# pixel_24[0],
|
|
# pixel_24[1],
|
|
# pixel_24[2])
|
|
|
|
fclose(in)
|
|
fclose(out)
|
|
return 1
|
|
|
|
|
|
def main(self, argc, **argv): char *infile, outfile[256]
|
|
int i
|
|
int success
|
|
for(i=1; i<argc; i++)
|
|
success = 0
|
|
infile = argv[i]
|
|
make_outfile(outfile, infile)
|
|
printf("%s . %s... ", infile, outfile)
|
|
fflush(stdout)
|
|
success = yuv2ppm(infile, outfile)
|
|
if success:
|
|
printf("Done.\n")
|
|
|
|
else:
|
|
printf("Failed. Aborting.\n")
|
|
return 1
|
|
|
|
|
|
return 0
|
|
|