#include #include ''' 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