|
Packit |
78deda |
/* Bryan got this from mm.ftp-cs.berkeley.edu from the package
|
|
Packit |
78deda |
mpeg-encode-1.5b-src under the name eyuvtoppm.c on March 30, 2000.
|
|
Packit |
78deda |
The file was dated April 14, 1995.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Bryan rewrote the program entirely to match Netpbm coding style,
|
|
Packit |
78deda |
use the Netpbm libraries and also to output to stdout and ignore
|
|
Packit |
78deda |
any specification of an output file on the command line and not
|
|
Packit |
78deda |
segfault when called with no arguments.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
There was no attached documentation except for this: Encoder/Berkeley
|
|
Packit |
78deda |
YUV format is merely the concatenation of Y, U, and V data in order.
|
|
Packit |
78deda |
Compare with Abekda YUV, which interlaces Y, U, and V data. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Copyright (c) 1995 The Regents of the University of California.
|
|
Packit |
78deda |
* All rights reserved.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
78deda |
* documentation for any purpose, without fee, and without written agreement is
|
|
Packit |
78deda |
* hereby granted, provided that the above copyright notice and the following
|
|
Packit |
78deda |
* two paragraphs appear in all copies of this software.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
|
|
Packit |
78deda |
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
|
|
Packit |
78deda |
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
|
|
Packit |
78deda |
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
|
Packit |
78deda |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
Packit |
78deda |
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
|
Packit |
78deda |
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
|
|
Packit |
78deda |
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <stdio.h>
|
|
Packit |
78deda |
#include <stdlib.h>
|
|
Packit |
78deda |
#include <unistd.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "shhopt.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
#include "ppm.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
typedef unsigned char uint8;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define CHOP(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x))
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct CmdlineInfo {
|
|
Packit |
78deda |
/* All the information the user supplied in the command line,
|
|
Packit |
78deda |
in a form easy for the program to use.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
const char * inputFileName; /* Name of input file */
|
|
Packit |
78deda |
unsigned int width;
|
|
Packit |
78deda |
unsigned int height;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int argc, char ** argv,
|
|
Packit |
78deda |
struct CmdlineInfo * const cmdlineP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
optStruct3 opt; /* Set by OPTENT3 */
|
|
Packit |
78deda |
unsigned int option_def_index;
|
|
Packit |
78deda |
optEntry * option_def;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(option_def, 100);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
option_def_index = 0; /* incremented by OPTENT3 */
|
|
Packit |
78deda |
OPTENT3('w', "width", OPT_UINT, &cmdlineP->width, NULL, 0);
|
|
Packit |
78deda |
OPTENT3('h', "height", OPT_UINT, &cmdlineP->height, NULL, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* DEFAULTS */
|
|
Packit |
78deda |
cmdlineP->width = 352;
|
|
Packit |
78deda |
cmdlineP->height = 240;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
opt.opt_table = option_def;
|
|
Packit |
78deda |
opt.short_allowed = TRUE;
|
|
Packit |
78deda |
opt.allowNegNum = FALSE;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (cmdlineP->width == 0)
|
|
Packit |
78deda |
pm_error("The width cannot be zero.");
|
|
Packit |
78deda |
if (cmdlineP->width % 2 != 0)
|
|
Packit |
78deda |
pm_error("The width of an eyuv image must be an even number. "
|
|
Packit |
78deda |
"You specified %u.", cmdlineP->width);
|
|
Packit |
78deda |
if (cmdlineP->height == 0)
|
|
Packit |
78deda |
pm_error("The height cannot be zero.");
|
|
Packit |
78deda |
if (cmdlineP->height % 2 != 0)
|
|
Packit |
78deda |
pm_error("The height of an eyuv image must be an even number. "
|
|
Packit |
78deda |
"You specified %u.", cmdlineP->height);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 == 0)
|
|
Packit |
78deda |
cmdlineP->inputFileName = "-";
|
|
Packit |
78deda |
else if (argc-1 != 1)
|
|
Packit |
78deda |
pm_error("Program takes zero or one argument (filename). You "
|
|
Packit |
78deda |
"specified %u", argc-1);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
cmdlineP->inputFileName = argv[1];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(option_def);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static uint8 **
|
|
Packit |
78deda |
allocUint8Array(unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const rows) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
uint8 ** retval;
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY(retval, rows);
|
|
Packit |
78deda |
if (retval == NULL)
|
|
Packit |
78deda |
pm_error("Unable to allocate storage for %u x %u byte array.",
|
|
Packit |
78deda |
cols, rows);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
MALLOCARRAY(retval[row], cols);
|
|
Packit |
78deda |
if (retval[row] == NULL)
|
|
Packit |
78deda |
pm_error("Unable to allocate storage for %u x %u byte array.",
|
|
Packit |
78deda |
cols, rows);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
return retval;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
freeUint8Array(uint8 ** const array,
|
|
Packit |
78deda |
unsigned int const rows) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row)
|
|
Packit |
78deda |
free(array[row]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(array);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
allocateStorage(unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const rows,
|
|
Packit |
78deda |
uint8 *** const orig_yP,
|
|
Packit |
78deda |
uint8 *** const orig_cbP,
|
|
Packit |
78deda |
uint8 *** const orig_crP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*orig_yP = allocUint8Array(cols, rows);
|
|
Packit |
78deda |
*orig_cbP = allocUint8Array(cols, rows);
|
|
Packit |
78deda |
*orig_crP = allocUint8Array(cols, rows);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
freeStorage(unsigned int const rows,
|
|
Packit |
78deda |
uint8 ** const orig_y,
|
|
Packit |
78deda |
uint8 ** const orig_cb,
|
|
Packit |
78deda |
uint8 ** const orig_cr) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
freeUint8Array(orig_y, rows);
|
|
Packit |
78deda |
freeUint8Array(orig_cb, rows);
|
|
Packit |
78deda |
freeUint8Array(orig_cr, rows);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
YUVtoPPM(FILE * const ofP,
|
|
Packit |
78deda |
unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const rows,
|
|
Packit |
78deda |
uint8 ** const orig_y,
|
|
Packit |
78deda |
uint8 ** const orig_cb,
|
|
Packit |
78deda |
uint8 ** const orig_cr) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Convert the YUV image in arrays orig_y[][], orig_cb[][], and orig_cr[][]
|
|
Packit |
78deda |
to a PPM image and write it to file *ofP.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
pixel * const pixrow = ppm_allocrow(cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ppm_writeppminit(ofP, cols, rows, 255, FALSE);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows; ++row) {
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col) {
|
|
Packit |
78deda |
int const y = orig_y[row][col] - 16;
|
|
Packit |
78deda |
int const u = orig_cb[row/2][col/2] - 128;
|
|
Packit |
78deda |
int const v = orig_cr[row/2][col/2] - 128;
|
|
Packit |
78deda |
long tempR, tempG, tempB;
|
|
Packit |
78deda |
int r, g, b;
|
|
Packit |
78deda |
/* look at yuvtoppm source for explanation */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
tempR = 104635*v + 76310*y;
|
|
Packit |
78deda |
tempG = -25690*u + -53294*v + 76310*y;
|
|
Packit |
78deda |
tempB = 132278*u + 76310*y;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
r = CHOP((int)(tempR >> 16));
|
|
Packit |
78deda |
g = CHOP((int)(tempG >> 16));
|
|
Packit |
78deda |
b = CHOP((int)(tempB >> 16));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
PPM_ASSIGN(pixrow[col], r, g, b);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_writeppmrow(stdout, pixrow, cols, 255, FALSE);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
ppm_freerow(pixrow);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
ReadYUV(FILE * const ifP,
|
|
Packit |
78deda |
unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const rows,
|
|
Packit |
78deda |
uint8 ** const orig_y,
|
|
Packit |
78deda |
uint8 ** const orig_cb,
|
|
Packit |
78deda |
uint8 ** const orig_cr,
|
|
Packit |
78deda |
bool * const eofP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
unsigned int totalRead;
|
|
Packit |
78deda |
bool eof;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
eof = false; /* initial value */
|
|
Packit |
78deda |
totalRead = 0; /* initial value */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows && !eof; ++row) { /* Y */
|
|
Packit |
78deda |
size_t bytesRead;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesRead = fread(orig_y[row], 1, cols, ifP);
|
|
Packit |
78deda |
totalRead += bytesRead;
|
|
Packit |
78deda |
if (bytesRead != cols)
|
|
Packit |
78deda |
eof = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows / 2 && !eof; ++row) { /* U */
|
|
Packit |
78deda |
size_t bytesRead;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesRead = fread(orig_cb[row], 1, cols / 2, ifP);
|
|
Packit |
78deda |
totalRead += bytesRead;
|
|
Packit |
78deda |
if (bytesRead != cols / 2)
|
|
Packit |
78deda |
eof = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < rows / 2 && !eof; ++row) { /* V */
|
|
Packit |
78deda |
size_t bytesRead;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
bytesRead = fread(orig_cr[row], 1, cols / 2, ifP);
|
|
Packit |
78deda |
totalRead += bytesRead;
|
|
Packit |
78deda |
if (bytesRead != cols / 2)
|
|
Packit |
78deda |
eof = true;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (eof) {
|
|
Packit |
78deda |
if (totalRead == 0)
|
|
Packit |
78deda |
*eofP = TRUE;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
pm_error("Premature end of file reading EYUV input file");
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
*eofP = FALSE;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, const char **argv) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
FILE * ifP;
|
|
Packit |
78deda |
struct CmdlineInfo cmdline;
|
|
Packit |
78deda |
unsigned int frameSeq;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* The following are addresses of malloc'ed storage areas for use by
|
|
Packit |
78deda |
subroutines.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
uint8 ** orig_y;
|
|
Packit |
78deda |
uint8 ** orig_cb;
|
|
Packit |
78deda |
uint8 ** orig_cr;
|
|
Packit |
78deda |
bool eof;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_proginit(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, (char **)argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/* Allocate all the storage at once, to save time. */
|
|
Packit |
78deda |
allocateStorage(cmdline.width, cmdline.height,
|
|
Packit |
78deda |
&orig_y, &orig_cb, &orig_cr);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ifP = pm_openr(cmdline.inputFileName);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (frameSeq = 0, eof = false; !eof; ++frameSeq) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ReadYUV(ifP, cmdline.width, cmdline.height,
|
|
Packit |
78deda |
orig_y, orig_cb, orig_cr, &eof;;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!eof) {
|
|
Packit |
78deda |
pm_message("Converting Frame %u", frameSeq);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
YUVtoPPM(stdout, cmdline.width, cmdline.height,
|
|
Packit |
78deda |
orig_y, orig_cb, orig_cr);
|
|
Packit |
78deda |
} else if (frameSeq == 0)
|
|
Packit |
78deda |
pm_error("Empty EYUV input file");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
freeStorage(cmdline.height, orig_y, orig_cb, orig_cr);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_close(ifP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|