/* yuvsplittoppm.c - construct a portable pixmap from 3 raw files: ** - basename.Y : The Luminance chunk at the size of the Image ** - basename.U : The Chrominance chunk U at 1/4 ** - basename.V : The Chrominance chunk V at 1/4 ** The subsampled U and V values are made by arithmetic mean. ** ** If ccir601 is defined, the produced YUV triples have been scaled again ** to fit into the smaller range of values for this standard. ** ** by Marcel Wijkstra ** ** Based on ppmtoyuvsplit.c ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include #include "ppm.h" /* x must be signed for the following to work correctly */ #define limit(x) (((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16) int main(argc, argv) char **argv; { FILE *vf,*uf,*yf; pixel *pixelrow1,*pixelrow2; register pixel *pP1,*pP2; int rows, cols, row; register int col; const char * const usage=" [-ccir601]"; long int u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3; unsigned char *y1buf,*y2buf,*ubuf,*vbuf; char ufname[256],vfname[256],yfname[256]; int ccir601=0; /* Whether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */ ppm_init(&argc, argv); if ((argc>5) || (argc<4)) pm_usage(usage); if (argc==5) { if (strncmp(argv[4],"-c",2) == 0) ccir601 = 1; else pm_usage(usage); } strcpy(ufname,argv[1]); strcpy(vfname,argv[1]); strcpy(yfname,argv[1]); strcat(ufname,".U"); strcat(vfname,".V"); strcat(yfname,".Y"); uf = fopen(ufname,"rb"); vf = fopen(vfname,"rb"); yf = fopen(yfname,"rb"); if(!(uf && vf && yf)) { perror("error opening input files"); exit(0); } cols = atoi(argv[2]); rows = atoi(argv[3]); if (cols <= 0 || rows <= 0) pm_usage(usage); ppm_writeppminit(stdout, cols, rows, (pixval) 255, 0); if(cols & 1) fprintf(stderr, "%s: Warning: odd columns count, exceed ignored\n", argv[0]); if(rows & 1) fprintf(stderr, "%s: Warning: odd rows count, exceed ignored\n", argv[0]); pixelrow1 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); pixelrow2 = ((pixel*) pm_allocrow( cols, sizeof(pixel) )); y1buf = (unsigned char *) pm_allocrow( cols, 1 ); y2buf = (unsigned char *) pm_allocrow( cols, 1 ); ubuf = (unsigned char *) pm_allocrow( cols, 1 ); vbuf = (unsigned char *) pm_allocrow( cols, 1 ); for (row = 0; row < (rows & ~1); row += 2) { unsigned char *y1ptr,*y2ptr,*uptr,*vptr; fread(y1buf, (cols & ~1), 1, yf); fread(y2buf, (cols & ~1), 1, yf); fread(ubuf, cols/2, 1, uf); fread(vbuf, cols/2, 1, vf); y1ptr = y1buf; y2ptr = y2buf; vptr = vbuf; uptr = ubuf; pP1 = pixelrow1; pP2 = pixelrow2; for (col = 0 ; col < (cols & ~1); col += 2) { long int r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; y0 = (long int) *y1ptr++; y1 = (long int) *y1ptr++; y2 = (long int) *y2ptr++; y3 = (long int) *y2ptr++; u = (long int) ((*uptr++) - 128); v = (long int) ((*vptr++) - 128); if (ccir601) { y0 = ((y0-16)*255)/219; y1 = ((y1-16)*255)/219; y2 = ((y2-16)*255)/219; y3 = ((y3-16)*255)/219; u = (u*255)/224 ; v = (v*255)/224 ; } /* mean the chroma for subsampling */ u0=u1=u2=u3=u; v0=v1=v2=v3=v; /* The inverse of the JFIF RGB to YUV Matrix for $00010000 = 1.0 [Y] [65496 0 91880][R] [U] = [65533 -22580 -46799[G] [V] [65537 116128 -8][B] */ r0 = 65536 * y0 + 91880 * v0; g0 = 65536 * y0 - 22580 * u0 - 46799 * v0; b0 = 65536 * y0 + 116128 * u0 ; r1 = 65536 * y1 + 91880 * v1; g1 = 65536 * y1 - 22580 * u1 - 46799 * v1; b1 = 65536 * y1 + 116128 * u1 ; r2 = 65536 * y2 + 91880 * v2; g2 = 65536 * y2 - 22580 * u2 - 46799 * v2; b2 = 65536 * y2 + 116128 * u2 ; r3 = 65536 * y3 + 91880 * v3; g3 = 65536 * y3 - 22580 * u3 - 46799 * v3; b3 = 65536 * y3 + 116128 * u3 ; r0 = limit(r0); r1 = limit(r1); r2 = limit(r2); r3 = limit(r3); g0 = limit(g0); g1 = limit(g1); g2 = limit(g2); g3 = limit(g3); b0 = limit(b0); b1 = limit(b1); b2 = limit(b2); b3 = limit(b3); /* first pixel */ PPM_ASSIGN(*pP1, (pixval)r0, (pixval)g0, (pixval)b0); pP1++; /* 2nd pixval */ PPM_ASSIGN(*pP1, (pixval)r1, (pixval)g1, (pixval)b1); pP1++; /* 3rd pixval */ PPM_ASSIGN(*pP2, (pixval)r2, (pixval)g2, (pixval)b2); pP2++; /* 4th pixval */ PPM_ASSIGN(*pP2, (pixval)r3, (pixval)g3, (pixval)b3); pP2++; } ppm_writeppmrow(stdout, pixelrow1, cols, (pixval) 255, 0); ppm_writeppmrow(stdout, pixelrow2, cols, (pixval) 255, 0); } pm_close(stdout); fclose(yf); fclose(uf); fclose(vf); exit(0); }