From 1fd361a1ea06e44286c213ca1f814f49306fdc43 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 19 Aug 2006 03:12:28 +0000 Subject: Create Subversion repository git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/ppm/yuvsplittoppm.c | 251 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 converter/ppm/yuvsplittoppm.c (limited to 'converter/ppm/yuvsplittoppm.c') diff --git a/converter/ppm/yuvsplittoppm.c b/converter/ppm/yuvsplittoppm.c new file mode 100644 index 00000000..0f5e19a3 --- /dev/null +++ b/converter/ppm/yuvsplittoppm.c @@ -0,0 +1,251 @@ +/* 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" +#include "nstring.h" +#include "shhopt.h" +#include "mallocvar.h" + +/* x must be signed for the following to work correctly */ +#define limit(x) (((x>0xffffff)?0xff0000:((x<=0xffff)?0:x&0xff0000))>>16) + +struct cmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + const char *filenameBase; + unsigned int width; + unsigned int height; + unsigned int ccir601; + /* Whether to create YUV in JFIF(JPEG) or CCIR.601(MPEG) scale */ +}; + + +static void +parseCommandLine(int argc, + char ** argv, + struct cmdlineInfo *cmdlineP ) { +/*---------------------------------------------------------------------------- + Parse program command line described in Unix standard form by argc + and argv. Return the information in the options as *cmdlineP. + + If command line is internally inconsistent (invalid options, etc.), + issue error message to stderr and abort program. + + Note that the strings we return are stored in the storage that + was passed to us as the argv array. We also trash *argv. +-----------------------------------------------------------------------------*/ + optEntry *option_def = malloc(100*sizeof(optEntry)); + /* Instructions to optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "ccir601", OPT_FLAG, NULL, + &cmdlineP->ccir601, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ + + optParseOptions3( &argc, argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + + if (argc-1 !=3) + pm_error("You must specify 3 arguments. " + "You specified %d", argc-1); + else { + int width, height; + cmdlineP->filenameBase = argv[1]; + width = atoi(argv[2]); + if (width < 1) + pm_error("Width must be at least 1. You specified %d", width); + height = atoi(argv[3]); + if (height < 1) + pm_error("Height must be at least 1. You specified %d", height); + cmdlineP->width = width; + cmdlineP->height = height; + } +} + + + +static void +computeTwoOutputRows(int const cols, + bool const ccir601, + unsigned char * const y1buf, + unsigned char * const y2buf, + unsigned char * const ubuf, + unsigned char * const vbuf, + pixel * const pixelrow1, + pixel * const pixelrow2) { + + int col; + + for (col = 0; col < cols; col += 2) { + long int r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3; + long int u,v,y0,y1,y2,y3,u0,u1,u2,u3,v0,v1,v2,v3; + + y0 = y1buf[col]; + y1 = y1buf[col+1]; + y2 = y2buf[col]; + y3 = y2buf[col+1]; + + u = ubuf[col/2] - 128; + v = vbuf[col/2] - 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); + + PPM_ASSIGN(pixelrow1[col], (pixval)r0, (pixval)g0, (pixval)b0); + PPM_ASSIGN(pixelrow1[col+1], (pixval)r1, (pixval)g1, (pixval)b1); + PPM_ASSIGN(pixelrow2[col], (pixval)r2, (pixval)g2, (pixval)b2); + PPM_ASSIGN(pixelrow2[col+1], (pixval)r3, (pixval)g3, (pixval)b3); + } +} + + + +int +main(int argc, char **argv) { + + struct cmdlineInfo cmdline; + FILE *vf,*uf,*yf; + int cols, rows; + pixel *pixelrow1,*pixelrow2; + int row; + unsigned char *y1buf,*y2buf,*ubuf,*vbuf; + const char * ufname; + const char * vfname; + const char * yfname; + + ppm_init(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + asprintfN(&ufname, "%s.U", cmdline.filenameBase); + asprintfN(&vfname, "%s.V", cmdline.filenameBase); + asprintfN(&yfname, "%s.Y", cmdline.filenameBase); + + uf = pm_openr(ufname); + vf = pm_openr(vfname); + yf = pm_openr(yfname); + + ppm_writeppminit(stdout, cmdline.width, cmdline.height, 255, 0); + + if (cmdline.width % 2 != 0) { + pm_message("Warning: odd width; last column ignored"); + cols = cmdline.width - 1; + } else + cols = cmdline.width; + + if (cmdline.height % 2 != 0) { + pm_message("Warning: odd height; last row ignored"); + rows = cmdline.height - 1; + } else + rows = cmdline.height; + + pixelrow1 = ppm_allocrow(cols); + pixelrow2 = ppm_allocrow(cols); + + MALLOCARRAY_NOFAIL(y1buf, cmdline.width); + MALLOCARRAY_NOFAIL(y2buf, cmdline.width); + MALLOCARRAY_NOFAIL(ubuf, cmdline.width/2); + MALLOCARRAY_NOFAIL(vbuf, cmdline.width/2); + + for (row = 0; row < rows; row += 2) { + fread(y1buf, cmdline.width, 1, yf); + fread(y2buf, cmdline.width, 1, yf); + fread(ubuf, cmdline.width/2, 1, uf); + fread(vbuf, cmdline.width/2, 1, vf); + + computeTwoOutputRows(cols, cmdline.ccir601, + y1buf, y2buf, ubuf, vbuf, + pixelrow1, pixelrow2); + + ppm_writeppmrow(stdout, pixelrow1, cols, (pixval) 255, 0); + ppm_writeppmrow(stdout, pixelrow2, cols, (pixval) 255, 0); + } + pm_close(stdout); + + strfree(yfname); + strfree(vfname); + strfree(ufname); + + pm_close(yf); + pm_close(uf); + pm_close(vf); + + exit(0); +} -- cgit 1.4.1