Blame exrstdattr/main.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2004-2014, Industrial Light & Magic, a division of Lucas
Packit 0d464f
// Digital Ltd. LLC
Packit 0d464f
// 
Packit 0d464f
// All rights reserved.
Packit 0d464f
// 
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission. 
Packit 0d464f
// 
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
//
Packit 0d464f
//	exrstdattr -- a program that can set the values of most
Packit 0d464f
//	standard attributes in an OpenEXR image file's header.
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <ImfStandardAttributes.h>
Packit 0d464f
#include <ImfVecAttribute.h>
Packit 0d464f
#include <ImfIntAttribute.h>
Packit 0d464f
#include <ImfInputFile.h>
Packit 0d464f
#include <ImfOutputFile.h>
Packit 0d464f
#include <ImfMultiPartInputFile.h>
Packit 0d464f
#include <ImfMultiPartOutputFile.h>
Packit 0d464f
#include <ImfTiledOutputFile.h>
Packit 0d464f
#include <ImfNamespace.h>
Packit 0d464f
#include <ImfPartType.h>
Packit 0d464f
#include <ImfInputPart.h>
Packit 0d464f
#include <ImfOutputPart.h>
Packit 0d464f
#include <ImfTiledInputPart.h>
Packit 0d464f
#include <ImfTiledOutputPart.h>
Packit 0d464f
#include <ImfDeepScanLineInputPart.h>
Packit 0d464f
#include <ImfDeepScanLineOutputPart.h>
Packit 0d464f
#include <ImfDeepTiledInputPart.h>
Packit 0d464f
#include <ImfDeepTiledOutputPart.h>
Packit 0d464f
#include <ImathNamespace.h>
Packit 0d464f
Packit 0d464f
#include <map>
Packit 0d464f
#include <string>
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <exception>
Packit 0d464f
#include <string.h>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace OPENEXR_IMF_NAMESPACE;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
usageMessage (const char argv0[], bool verbose = false)
Packit 0d464f
{
Packit 0d464f
    cerr << "usage: " << argv0 << " [commands] infile outfile" << endl;
Packit 0d464f
Packit 0d464f
    if (verbose)
Packit 0d464f
    {
Packit 0d464f
	cerr << "\n"
Packit 0d464f
		"Reads OpenEXR image file infile, sets the values of one\n"
Packit 0d464f
		"or more attributes in the headers of the file, and saves\n"
Packit 0d464f
		"the result in outfile.  Infile and outfile must not refer\n"
Packit 0d464f
		"to the same file (the program cannot edit an image file "
Packit 0d464f
                "\"in place\").\n"
Packit 0d464f
		"\n"
Packit 0d464f
                "Command for selecting headers:\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "  -part i\n"
Packit 0d464f
                "        If i is greater than or equal to zero, and less\n"
Packit 0d464f
                "        than the number of parts in the input file, then\n"
Packit 0d464f
                "        the header for part i becomes \"current.\" If i\n"
Packit 0d464f
                "        is \"any\" or -1, then all headers become current.\n"
Packit 0d464f
                "        Subsequent attribute setting commands affect only\n"
Packit 0d464f
                "        the current header or headers.  All headers are\n"
Packit 0d464f
                "        current before the first -part command.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "        For example, the command sequence\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "         -focus 3 -part 2 -aperture 8 -expTime 0.01 "
Packit 0d464f
                         "-part any -owner luke\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "        sets the focus and owner attributes in all\n"
Packit 0d464f
                "        headers, as well as the aperture and expTime\n"
Packit 0d464f
                "        attributes in the header of part 2.\n"
Packit 0d464f
                "\n"
Packit 0d464f
		"Commands for setting attribute values:\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -chromaticities f f f f f f f f\n"
Packit 0d464f
		"        CIE xy chromaticities for the red, green\n"
Packit 0d464f
		"	 and blue primaries, and for the white point\n"
Packit 0d464f
		"        (8 floats)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -whiteLuminance f\n"
Packit 0d464f
		"        white luminance, in candelas per square meter\n"
Packit 0d464f
		"        (float, >= 0.0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -adoptedNeutral f f\n"
Packit 0d464f
		"        CIE xy coordinates that should be considered\n"
Packit 0d464f
		"        \"neutral\" during color rendering.  Pixels in\n"
Packit 0d464f
		"        the image file whose xy coordinates match the\n"
Packit 0d464f
		"        adoptedNeutral value should be mapped to neutral\n"
Packit 0d464f
		"        values on the display. (2 floats)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -renderingTransform s\n"
Packit 0d464f
		"        name of the CTL rendering transform for this\n"
Packit 0d464f
		"        image (string)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -lookModTransform s\n"
Packit 0d464f
		"        name of the CTL look modification transform for\n"
Packit 0d464f
		"        this image (string)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -xDensity f\n"
Packit 0d464f
		"        horizontal output density, in pixels per inch\n"
Packit 0d464f
		"        (float, >= 0.0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -owner s\n"
Packit 0d464f
		"        name of the owner of the image (string)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -comments s\n"
Packit 0d464f
		"        additional information about the image (string)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -capDate s\n"
Packit 0d464f
		"        date when the image was created or\n"
Packit 0d464f
		"        captured, in local time (string,\n"
Packit 0d464f
		"        formatted as YYYY:MM:DD hh:mm:ss)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -utcOffset f\n"
Packit 0d464f
		"        offset of local time at capDate from UTC, in\n"
Packit 0d464f
		"        seconds (float, UTC == local time + x)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -longitude f\n"
Packit 0d464f
		"  -latitude f\n"
Packit 0d464f
		"  -altitude f\n"
Packit 0d464f
		"        location where the image was recorded, in\n"
Packit 0d464f
		"        degrees east of Greenwich and north of the\n"
Packit 0d464f
		"        equator, and in meters above sea level\n"
Packit 0d464f
		"        (float)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -focus f\n"
Packit 0d464f
		"        the camera's focus distance, in meters\n"
Packit 0d464f
		"        (float, > 0, or \"infinity\")\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -expTime f\n"
Packit 0d464f
		"        exposure time, in seconds (float, >= 0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -aperture f\n"
Packit 0d464f
		"        lens apterture, in f-stops (float, >= 0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -isoSpeed f\n"
Packit 0d464f
		"        effective speed of the film or image\n"
Packit 0d464f
		"        sensor that was used to record the image\n"
Packit 0d464f
		"        (float, >= 0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -envmap s\n"
Packit 0d464f
		"        indicates that the image is an environment map\n"
Packit 0d464f
		"        (string, LATLONG or CUBE)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -framesPerSecond i i\n"
Packit 0d464f
		"        playback frame rate expressed as a ratio of two\n"
Packit 0d464f
		"        integers, n and d (the frame rate is n/d frames\n"
Packit 0d464f
		"        per second)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -keyCode i i i i i i i\n"
Packit 0d464f
		"        key code that uniquely identifies a motion\n"
Packit 0d464f
		"        picture film frame using 7 integers:\n"
Packit 0d464f
	        "         * film manufacturer code (0 - 99)\n"
Packit 0d464f
	        "         * film type code (0 - 99)\n"
Packit 0d464f
	        "         * prefix to identify film roll (0 - 999999)\n"
Packit 0d464f
	        "         * count, increments once every perfsPerCount\n"
Packit 0d464f
		"           perforations (0 - 9999)\n"
Packit 0d464f
	        "         * offset of frame, in perforations from\n"
Packit 0d464f
		"           zero-frame reference mark (0 - 119)\n"
Packit 0d464f
	        "         * number of perforations per frame (1 - 15)\n"
Packit 0d464f
	        "         * number of perforations per count (20 - 120)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -timeCode i i\n"
Packit 0d464f
		"        SMPTE time and control code, specified as a pair\n"
Packit 0d464f
		"        of 8-digit base-16 integers.  The first number\n"
Packit 0d464f
		"        contains the time address and flags (drop frame,\n"
Packit 0d464f
		"        color frame, field/phase, bgf0, bgf1, bgf2).\n"
Packit 0d464f
		"        The second number contains the user data and\n"
Packit 0d464f
		"        control codes.\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -wrapmodes s\n"
Packit 0d464f
		"        if the image is used as a texture map, specifies\n"
Packit 0d464f
		"        how the image should be extrapolated outside the\n"
Packit 0d464f
		"        zero-to-one texture coordinate range\n"
Packit 0d464f
		"        (string, e.g. \"clamp\" or \"periodic,clamp\")\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -pixelAspectRatio f\n"
Packit 0d464f
		"        width divided by height of a pixel\n"
Packit 0d464f
		"        (float, >= 0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -screenWindowWidth f\n"
Packit 0d464f
		"        width of the screen window (float, >= 0)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -screenWindowCenter f f\n"
Packit 0d464f
		"        center of the screen window (2 floats)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -string s s\n"
Packit 0d464f
		"        custom string attribute\n"
Packit 0d464f
		"        (2 strings, attribute name and value)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -float s f\n"
Packit 0d464f
		"        custom float attribute (string + float,\n"
Packit 0d464f
		"        attribute name and value)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -int s i\n"
Packit 0d464f
		"        custom integer attribute (string + integer,\n"
Packit 0d464f
		"        attribute name and value)\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"Other Commands:\n"
Packit 0d464f
		"\n"
Packit 0d464f
		"  -h        prints this message\n";
Packit 0d464f
Packit 0d464f
	 cerr << endl;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    exit (1);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
struct SetAttr
Packit 0d464f
{
Packit 0d464f
    string      name;
Packit 0d464f
    int         part;
Packit 0d464f
    Attribute * attr;
Packit 0d464f
    
Packit 0d464f
    SetAttr (const string &name, int part, Attribute *attr):
Packit 0d464f
        name (name), part (part), attr (attr) {}
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
typedef vector <SetAttr> SetAttrVector;
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
isNonNegative (const char attrName[], float f)
Packit 0d464f
{
Packit 0d464f
    if (f < 0)
Packit 0d464f
    {
Packit 0d464f
	cerr << "The value for the " << attrName << " attribute "
Packit 0d464f
		"must not be less than zero." << endl;
Packit 0d464f
	exit (1);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
isPositive (const char attrName[], float f)
Packit 0d464f
{
Packit 0d464f
    if (f <= 0)
Packit 0d464f
    {
Packit 0d464f
	cerr << "The value for the " << attrName << " attribute "
Packit 0d464f
		"must be greater than zero." << endl;
Packit 0d464f
	exit (1);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
notValidDate (const char attrName[])
Packit 0d464f
{
Packit 0d464f
    cerr << "The value for the " << attrName << " attribute "
Packit 0d464f
	    "is not a valid date of the form \"YYYY:MM:DD yy:mm:ss\"." << endl;
Packit 0d464f
    exit (1);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
strToInt (const char str[], int length)
Packit 0d464f
{
Packit 0d464f
    int x = 0;
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < length; ++i)
Packit 0d464f
    {
Packit 0d464f
	if (str[i] < '0' || str[i] > '9')
Packit 0d464f
	    return -1;
Packit 0d464f
Packit 0d464f
	x = x * 10 + (str[i] - '0');
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return x;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
isDate (const char attrName[], const char str[])
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Check that str represents a valid
Packit 0d464f
    // date of the form YYYY:MM:DD hh:mm:ss.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    if (strlen (str) != 19 ||
Packit 0d464f
	str[4] != ':' || str[7] != ':' ||
Packit 0d464f
	str[10] != ' ' ||
Packit 0d464f
	str[13] != ':' || str[16] != ':')
Packit 0d464f
    {
Packit 0d464f
	notValidDate (attrName);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    int Y = strToInt (str + 0, 4);	// year
Packit 0d464f
    int M = strToInt (str + 5, 2);	// month
Packit 0d464f
    int D = strToInt (str + 8, 2);      // day
Packit 0d464f
    int h = strToInt (str + 11, 2);	// hour
Packit 0d464f
    int m = strToInt (str + 14, 2);	// minute
Packit 0d464f
    int s = strToInt (str + 17, 2);	// second
Packit 0d464f
Packit 0d464f
    if (Y < 0 ||
Packit 0d464f
	M < 1 || M > 12 ||
Packit 0d464f
	D < 1 ||
Packit 0d464f
	h < 0 || h > 23 ||
Packit 0d464f
	m < 0 || m > 59 ||
Packit 0d464f
	s < 0 || s > 59)
Packit 0d464f
    {
Packit 0d464f
	notValidDate (attrName);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (M == 2)
Packit 0d464f
    {
Packit 0d464f
	bool leapYear = (Y % 4 == 0) && (Y % 100 != 0 || Y % 400 == 0);
Packit 0d464f
Packit 0d464f
	if (D > (leapYear? 29: 28))
Packit 0d464f
	    notValidDate (attrName);
Packit 0d464f
    }
Packit 0d464f
    else if (M == 4 || M == 6 || M == 9 || M == 11)
Packit 0d464f
    {
Packit 0d464f
	if (D > 30)
Packit 0d464f
	    notValidDate (attrName);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	if (D > 31)
Packit 0d464f
	    notValidDate (attrName);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getFloat (const char attrName[],
Packit 0d464f
	  int argc,
Packit 0d464f
	  char **argv,
Packit 0d464f
	  int &i,
Packit 0d464f
          int part,
Packit 0d464f
	  SetAttrVector &attrs,
Packit 0d464f
	  void (*check) (const char attrName[], float f) = 0)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 2)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    float f = strtod (argv[i + 1], 0);
Packit 0d464f
Packit 0d464f
    if (check)
Packit 0d464f
	check (attrName, f);
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new FloatAttribute (f)));
Packit 0d464f
    i += 2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getPosFloatOrInf (const char attrName[],
Packit 0d464f
	          int argc,
Packit 0d464f
		  char **argv,
Packit 0d464f
		  int &i,
Packit 0d464f
                  int part,
Packit 0d464f
		  SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 2)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    float f;
Packit 0d464f
    
Packit 0d464f
    if (!strcmp (argv[i + 1], "inf") || !strcmp (argv[i + 1], "infinity"))
Packit 0d464f
    {
Packit 0d464f
	f = float (half::posInf());
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	f = strtod (argv[i + 1], 0);
Packit 0d464f
Packit 0d464f
	if (f <= 0)
Packit 0d464f
	{
Packit 0d464f
	    cerr << "The value for the " << attrName << " attribute "
Packit 0d464f
		    "must be greater than zero, or \"infinity\"." << endl;
Packit 0d464f
	    exit (1);
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new FloatAttribute (f)));
Packit 0d464f
    i += 2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getV2f (const char attrName[],
Packit 0d464f
	int argc,
Packit 0d464f
	char **argv,
Packit 0d464f
	int &i,
Packit 0d464f
        int part,
Packit 0d464f
	SetAttrVector &attrs,
Packit 0d464f
	void (*check) (const char attrName[], const V2f &v) = 0)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    V2f v (strtod (argv[i + 1], 0), strtod (argv[i + 2], 0));
Packit 0d464f
Packit 0d464f
    if (check)
Packit 0d464f
	check (attrName, v);
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new V2fAttribute (v)));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getRational (const char attrName[],
Packit 0d464f
	     int argc,
Packit 0d464f
	     char **argv,
Packit 0d464f
	     int &i,
Packit 0d464f
             int part,
Packit 0d464f
	     SetAttrVector &attrs,
Packit 0d464f
	     void (*check) (const char attrName[], const Rational &r) = 0)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    Rational r (strtol (argv[i + 1], 0, 0), strtol (argv[i + 2], 0, 0));
Packit 0d464f
Packit 0d464f
    if (check)
Packit 0d464f
	check (attrName, r);
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new RationalAttribute (r)));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getString (const char attrName[],
Packit 0d464f
	   int argc,
Packit 0d464f
	   char **argv,
Packit 0d464f
	   int &i,
Packit 0d464f
           int part,
Packit 0d464f
	   SetAttrVector &attrs,
Packit 0d464f
	   void (*check) (const char attrName[], const char str[]) = 0)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 2)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    const char *str = argv[i + 1];
Packit 0d464f
Packit 0d464f
    if (check)
Packit 0d464f
	check (attrName, str);
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new StringAttribute (str)));
Packit 0d464f
    i += 2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getNameAndString (int argc,
Packit 0d464f
		  char **argv,
Packit 0d464f
		  int &i,
Packit 0d464f
                  int part,
Packit 0d464f
		  SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    const char *attrName = argv[i + 1];
Packit 0d464f
    const char *str = argv[i + 2];
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new StringAttribute (str)));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getNameAndFloat (int argc,
Packit 0d464f
		 char **argv,
Packit 0d464f
		 int &i,
Packit 0d464f
                 int part,
Packit 0d464f
		 SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    const char *attrName = argv[i + 1];
Packit 0d464f
    float f = strtod (argv[i + 2], 0);
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new FloatAttribute (f)));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getNameAndInt (int argc,
Packit 0d464f
	       char **argv,
Packit 0d464f
	       int &i,
Packit 0d464f
               int part,
Packit 0d464f
	       SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    const char *attrName = argv[i + 1];
Packit 0d464f
    int j = strtol (argv[i + 2], 0, 0);
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new IntAttribute (j)));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getChromaticities (const char attrName[],
Packit 0d464f
		   int argc,
Packit 0d464f
	           char **argv,
Packit 0d464f
		   int &i,
Packit 0d464f
                   int part,
Packit 0d464f
		   SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 9)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    ChromaticitiesAttribute *a = new ChromaticitiesAttribute;
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, a));
Packit 0d464f
Packit 0d464f
    a->value().red.x   = strtod (argv[i + 1], 0);
Packit 0d464f
    a->value().red.y   = strtod (argv[i + 2], 0);
Packit 0d464f
    a->value().green.x = strtod (argv[i + 3], 0);
Packit 0d464f
    a->value().green.y = strtod (argv[i + 4], 0);
Packit 0d464f
    a->value().blue.x  = strtod (argv[i + 5], 0);
Packit 0d464f
    a->value().blue.y  = strtod (argv[i + 6], 0);
Packit 0d464f
    a->value().white.x = strtod (argv[i + 7], 0);
Packit 0d464f
    a->value().white.y = strtod (argv[i + 8], 0);
Packit 0d464f
    i += 9;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getEnvmap (const char attrName[],
Packit 0d464f
	   int argc,
Packit 0d464f
	   char **argv,
Packit 0d464f
	   int &i,
Packit 0d464f
           int part,
Packit 0d464f
	   SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 2)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    char *str = argv[i + 1];
Packit 0d464f
    Envmap type;
Packit 0d464f
Packit 0d464f
    if (!strcmp (str, "latlong") || !strcmp (str, "LATLONG"))
Packit 0d464f
    {
Packit 0d464f
	type = ENVMAP_LATLONG;
Packit 0d464f
    }
Packit 0d464f
    else if (!strcmp (str, "cube") || !strcmp (str, "CUBE"))
Packit 0d464f
    {
Packit 0d464f
	type = ENVMAP_CUBE;
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	cerr << "The value for the " << attrName << " attribute "
Packit 0d464f
	        "must be either LATLONG or CUBE." << endl;
Packit 0d464f
	exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, new EnvmapAttribute (type)));
Packit 0d464f
    i += 2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getKeyCode (const char attrName[],
Packit 0d464f
	    int argc,
Packit 0d464f
	    char **argv,
Packit 0d464f
	    int &i,
Packit 0d464f
            int part,
Packit 0d464f
	    SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 8)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    KeyCodeAttribute *a = new KeyCodeAttribute;
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, a));
Packit 0d464f
Packit 0d464f
    a->value().setFilmMfcCode   (strtol (argv[i + 1], 0, 0));
Packit 0d464f
    a->value().setFilmType      (strtol (argv[i + 2], 0, 0));
Packit 0d464f
    a->value().setPrefix        (strtol (argv[i + 3], 0, 0));
Packit 0d464f
    a->value().setCount         (strtol (argv[i + 4], 0, 0));
Packit 0d464f
    a->value().setPerfOffset    (strtol (argv[i + 5], 0, 0));
Packit 0d464f
    a->value().setPerfsPerFrame (strtol (argv[i + 6], 0, 0));
Packit 0d464f
    a->value().setPerfsPerCount (strtol (argv[i + 7], 0, 0));
Packit 0d464f
    i += 8;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getTimeCode (const char attrName[],
Packit 0d464f
	    int argc,
Packit 0d464f
	    char **argv,
Packit 0d464f
	    int &i,
Packit 0d464f
            int part,
Packit 0d464f
	    SetAttrVector &attrs)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 3)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    TimeCodeAttribute *a = new TimeCodeAttribute;
Packit 0d464f
    attrs.push_back (SetAttr (attrName, part, a));
Packit 0d464f
Packit 0d464f
    a->value().setTimeAndFlags (strtoul (argv[i + 1], 0, 16));
Packit 0d464f
    a->value().setUserData     (strtoul (argv[i + 2], 0, 16));
Packit 0d464f
    i += 3;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
getPart (const char attrName[],
Packit 0d464f
         int argc,
Packit 0d464f
         char **argv,
Packit 0d464f
         int &i,
Packit 0d464f
         int &part)
Packit 0d464f
{
Packit 0d464f
    if (i > argc - 2)
Packit 0d464f
	usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    if (!strcmp (argv[i + 1], "any"))
Packit 0d464f
        part = -1;
Packit 0d464f
    else
Packit 0d464f
        part = strtol (argv[i + 1], 0, 0);
Packit 0d464f
Packit 0d464f
    i += 2;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
main(int argc, char **argv)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Parse the command line.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    if (argc < 2)
Packit 0d464f
	usageMessage (argv[0], true);
Packit 0d464f
Packit 0d464f
    int exitStatus = 0;
Packit 0d464f
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
	const char *inFileName = 0;
Packit 0d464f
	const char *outFileName = 0;
Packit 0d464f
Packit 0d464f
	SetAttrVector attrs;
Packit 0d464f
	int part = -1;
Packit 0d464f
	int i = 1;
Packit 0d464f
Packit 0d464f
	while (i < argc)
Packit 0d464f
	{
Packit 0d464f
	    const char *attrName = argv[i] + 1;
Packit 0d464f
Packit 0d464f
	    if (!strcmp (argv[i], "-part"))
Packit 0d464f
	    {
Packit 0d464f
                getPart (attrName, argc, argv, i, part);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-chromaticities"))
Packit 0d464f
	    {
Packit 0d464f
		getChromaticities (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-whiteLuminance"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-adoptedNeutral"))
Packit 0d464f
	    {
Packit 0d464f
		getV2f (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-renderingTransform"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-lookModTransform"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-xDensity"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isPositive);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-owner"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-comments"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-capDate"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs, isDate);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-utcOffset"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-longitude"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-latitude"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-altitude"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-focus"))
Packit 0d464f
	    {
Packit 0d464f
		getPosFloatOrInf (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-expTime"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isPositive);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-aperture"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isPositive);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-isoSpeed"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isPositive);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-envmap"))
Packit 0d464f
	    {
Packit 0d464f
		getEnvmap (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-framesPerSecond"))
Packit 0d464f
	    {
Packit 0d464f
		getRational (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-keyCode"))
Packit 0d464f
	    {
Packit 0d464f
		getKeyCode (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-timeCode"))
Packit 0d464f
	    {
Packit 0d464f
		getTimeCode (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-wrapmodes"))
Packit 0d464f
	    {
Packit 0d464f
		getString (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-pixelAspectRatio"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isPositive);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-screenWindowWidth"))
Packit 0d464f
	    {
Packit 0d464f
		getFloat (attrName, argc, argv, i, part, attrs, isNonNegative);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-screenWindowCenter"))
Packit 0d464f
	    {
Packit 0d464f
		getV2f (attrName, argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-string"))
Packit 0d464f
	    {
Packit 0d464f
		getNameAndString (argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-float"))
Packit 0d464f
	    {
Packit 0d464f
		getNameAndFloat (argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-int"))
Packit 0d464f
	    {
Packit 0d464f
		getNameAndInt (argc, argv, i, part, attrs);
Packit 0d464f
	    }
Packit 0d464f
	    else if (!strcmp (argv[i], "-h"))
Packit 0d464f
	    {
Packit 0d464f
		usageMessage (argv[0], true);
Packit 0d464f
	    }
Packit 0d464f
	    else
Packit 0d464f
	    {
Packit 0d464f
		if (inFileName == 0)
Packit 0d464f
		    inFileName = argv[i];
Packit 0d464f
		else
Packit 0d464f
		    outFileName = argv[i];
Packit 0d464f
Packit 0d464f
		i += 1;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	if (inFileName == 0 || outFileName == 0)
Packit 0d464f
	    usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
	if (!strcmp (inFileName, outFileName))
Packit 0d464f
	{
Packit 0d464f
	    cerr << "Input and output cannot be the same file." << endl;
Packit 0d464f
	    return 1;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Load the headers from the input file
Packit 0d464f
        // and add attributes to the headers.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	MultiPartInputFile in (inFileName);
Packit 0d464f
	int numParts = in.parts();
Packit 0d464f
        vector <Header> headers;
Packit 0d464f
Packit 0d464f
        for (int part = 0; part < numParts; ++part)
Packit 0d464f
        {
Packit 0d464f
            Header h = in.header (part);
Packit 0d464f
Packit 0d464f
            for (int i = 0; i < attrs.size(); ++i)
Packit 0d464f
            {
Packit 0d464f
                const SetAttr &attr = attrs[i];
Packit 0d464f
Packit 0d464f
                if (attr.part == -1 || attr.part == part)
Packit 0d464f
                {
Packit 0d464f
                    h.insert (attr.name, *attr.attr);
Packit 0d464f
                }
Packit 0d464f
                else if (attr.part < 0 || attr.part >= numParts)
Packit 0d464f
                {
Packit 0d464f
                    cerr << "Invalid part number " << attr.part << ". "
Packit 0d464f
                            "Part numbers in file " << inFileName << " "
Packit 0d464f
                            "go from 0 to " << numParts - 1 << "." << endl;
Packit 0d464f
Packit 0d464f
                    return 1;
Packit 0d464f
                }
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            headers.push_back(h);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        //
Packit 0d464f
        // Crete an output file with the modified headers,
Packit 0d464f
        // and copy the pixels from the input file to the
Packit 0d464f
        // output file.
Packit 0d464f
        //
Packit 0d464f
Packit 0d464f
	MultiPartOutputFile out (outFileName, &headers[0], numParts);
Packit 0d464f
Packit 0d464f
	for (int p = 0; p < numParts; ++p)
Packit 0d464f
	{
Packit 0d464f
	    const Header &h = in.header (p);
Packit 0d464f
	    const string &type = h.type();
Packit 0d464f
Packit 0d464f
	    if (type == SCANLINEIMAGE)
Packit 0d464f
	    {
Packit 0d464f
	        InputPart  inPart  (in,  p);
Packit 0d464f
	        OutputPart outPart (out, p);
Packit 0d464f
	        outPart.copyPixels (inPart);
Packit 0d464f
	    }
Packit 0d464f
	    else if (type == TILEDIMAGE)
Packit 0d464f
	    {
Packit 0d464f
	        TiledInputPart  inPart  (in,  p);
Packit 0d464f
	        TiledOutputPart outPart (out, p);
Packit 0d464f
	        outPart.copyPixels (inPart);
Packit 0d464f
	    }
Packit 0d464f
	    else if (type == DEEPSCANLINE)
Packit 0d464f
	    {
Packit 0d464f
	        DeepScanLineInputPart  inPart  (in,  p);
Packit 0d464f
	        DeepScanLineOutputPart outPart (out, p);
Packit 0d464f
	        outPart.copyPixels (inPart);
Packit 0d464f
	    }
Packit 0d464f
	    else if (type == DEEPTILE)
Packit 0d464f
	    {
Packit 0d464f
	        DeepTiledInputPart  inPart  (in,  p);
Packit 0d464f
	        DeepTiledOutputPart outPart (out, p);
Packit 0d464f
	        outPart.copyPixels (inPart);
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
    catch (const exception &e)
Packit 0d464f
    {
Packit 0d464f
	cerr << e.what() << endl;
Packit 0d464f
	exitStatus = 1;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return exitStatus;
Packit 0d464f
}