Blame exrenvmap/main.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2004, 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
//      exrenvmap -- makes OpenEXR environment maps
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <makeCubeMap.h>
Packit 0d464f
#include <makeLatLongMap.h>
Packit 0d464f
#include <blurImage.h>
Packit 0d464f
#include <EnvmapImage.h>
Packit 0d464f
#include <ImfEnvmap.h>
Packit 0d464f
#include <ImfHeader.h>
Packit 0d464f
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <exception>
Packit 0d464f
#include <string>
Packit 0d464f
#include <string.h>
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
Packit 0d464f
#include "namespaceAlias.h"
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace std;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
usageMessage (const char argv0[], bool verbose = false)
Packit 0d464f
{
Packit 0d464f
    cerr << "usage: " << argv0 << " [options] infile outfile" << endl;
Packit 0d464f
Packit 0d464f
    if (verbose)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n"
Packit 0d464f
                "Converts OpenEXR latitude-longitude environment maps\n"
Packit 0d464f
                "into cube-face environment maps or vice versa.\n"
Packit 0d464f
                "Reads an environment map image from infile, converts\n"
Packit 0d464f
                "it, and stores the result in outfile.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "If the input file name contains a '%' character, then an\n"
Packit 0d464f
                "input cube-face environment map is assembled from six\n"
Packit 0d464f
                "square sub-images that represent the six faces of the cube.\n"
Packit 0d464f
                "The names of the six image files are generated by replacing\n"
Packit 0d464f
                "the % with +X, -X, +Y, -Y, +Z and -Z respectively.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "If the output file name contains a '%' character and\n"
Packit 0d464f
                "the program has been instructed to produce a cube-face\n"
Packit 0d464f
                "environment map, then the output image is split into six\n"
Packit 0d464f
                "square sub-images that are saved in six separate output\n"
Packit 0d464f
                "files.  The names of the files are generated by replacing\n"
Packit 0d464f
                "the % with +X, -X, +Y, -Y, +Z and -Z respectively.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "Options:\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-o         produces a ONE_LEVEL output file (default)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-m         produces a MIPMAP_LEVELS output file (-m has\n"
Packit 0d464f
                "           no effect if the output image is split into\n"
Packit 0d464f
                "           multiple files)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-c         the output file will be a cube-face environment\n"
Packit 0d464f
                "           map (default)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-l         the output file will be a latitude-longitude\n"
Packit 0d464f
                "           environment map\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-ci        the input file is interpreted as a cube-face\n"
Packit 0d464f
                "           environment map, regardless of its envmap\n"
Packit 0d464f
                "           attribute\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-li        the input file is interpreted as a latitude-\n"
Packit 0d464f
                "           longitude environment map, regardless of its\n"
Packit 0d464f
                "           envmap attribute (-li has no effect if the\n"
Packit 0d464f
                "           input image is assembled from multiple files)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-w x       sets the width of the output image to x pixels\n"
Packit 0d464f
                "           (default is 256).  The height of the output image\n"
Packit 0d464f
                "           will be x*6 pixels for a cube-face map, or x/2\n"
Packit 0d464f
                "           pixels for a latitude-longitude map.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-f r n     sets the antialiasing filter radius to r\n"
Packit 0d464f
                "           (default is 1.0) and the sampling rate to\n"
Packit 0d464f
                "           n by n (default is 5 by 5).  Increasing r\n"
Packit 0d464f
                "           makes the output image blurrier; decreasing r\n"
Packit 0d464f
                "           makes the image sharper but may cause aliasing.\n"
Packit 0d464f
                "           Increasing n improves antialiasing, but\n"
Packit 0d464f
                "           generating the output image takes longer.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-b         blurs the environment map image by applying a\n"
Packit 0d464f
                "           180-degree-wide filter kernel such that point-\n"
Packit 0d464f
                "           sampling the blurred image at a location that\n"
Packit 0d464f
                "           corresponds to 3D direction N returns the color\n"
Packit 0d464f
                "           that a white diffuse reflector with surface\n"
Packit 0d464f
                "           normal N would have if it was illuminated using\n"
Packit 0d464f
                "           the original non-blurred image.\n"
Packit 0d464f
                "           Generating the blurred image can be fairly slow.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-t x y     sets the output file's tile size to x by y pixels\n"
Packit 0d464f
                "           (default is 64 by 64)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-p t b     if the input image is a latitude-longitude map,\n"
Packit 0d464f
                "           pad the image at the top and bottom with t*h\n"
Packit 0d464f
                "           and b*h extra scan lines, where h is the height\n"
Packit 0d464f
                "           of the input image.  This is useful for images\n"
Packit 0d464f
                "           from 360-degree panoramic scans that cover\n"
Packit 0d464f
                "           less than 180 degrees vertically.\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-d         sets level size rounding to ROUND_DOWN (default)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-u         sets level size rounding to ROUND_UP\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-z x       sets the data compression method to x\n"
Packit 0d464f
                "           (none/rle/zip/piz/pxr24/b44/b44a/dwaa/dwab,\n"
Packit 0d464f
                "           default is zip)\n"
Packit 0d464f
                "\n"
Packit 0d464f
                "-v         verbose mode\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
Compression
Packit 0d464f
getCompression (const string &str)
Packit 0d464f
{
Packit 0d464f
    Compression c;
Packit 0d464f
Packit 0d464f
    if (str == "no" || str == "none" || str == "NO" || str == "NONE")
Packit 0d464f
    {
Packit 0d464f
        c = NO_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "rle" || str == "RLE")
Packit 0d464f
    {
Packit 0d464f
        c = RLE_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "zip" || str == "ZIP")
Packit 0d464f
    {
Packit 0d464f
        c = ZIP_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "piz" || str == "PIZ")
Packit 0d464f
    {
Packit 0d464f
        c = PIZ_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "pxr24" || str == "PXR24")
Packit 0d464f
    {
Packit 0d464f
        c = PXR24_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "b44" || str == "B44")
Packit 0d464f
    {
Packit 0d464f
        c = B44_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "b44a" || str == "B44A")
Packit 0d464f
    {
Packit 0d464f
        c = B44A_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "dwaa" || str == "DWAA")
Packit 0d464f
    {
Packit 0d464f
        c = DWAA_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else if (str == "dwab" || str == "DWAB")
Packit 0d464f
    {
Packit 0d464f
        c = DWAB_COMPRESSION;
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        cerr << "Unknown compression method \"" << str << "\"." << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return c;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
main(int argc, char **argv)
Packit 0d464f
{
Packit 0d464f
    const char *inFile = 0;
Packit 0d464f
    const char *outFile = 0;
Packit 0d464f
    Envmap type = ENVMAP_CUBE;
Packit 0d464f
    Envmap overrideInputType = NUM_ENVMAPTYPES;
Packit 0d464f
    LevelMode levelMode = ONE_LEVEL;
Packit 0d464f
    LevelRoundingMode roundingMode = ROUND_DOWN;
Packit 0d464f
    Compression compression = ZIP_COMPRESSION;
Packit 0d464f
    int mapWidth = 256;
Packit 0d464f
    int tileWidth = 64;
Packit 0d464f
    int tileHeight = 64;
Packit 0d464f
    float padTop = 0;
Packit 0d464f
    float padBottom = 0;
Packit 0d464f
    float filterRadius = 1;
Packit 0d464f
    int numSamples = 5;
Packit 0d464f
    bool diffuseBlur = false;
Packit 0d464f
    bool verbose = false;
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 i = 1;
Packit 0d464f
Packit 0d464f
    while (i < argc)
Packit 0d464f
    {
Packit 0d464f
        if (!strcmp (argv[i], "-o"))    
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // generate a ONE_LEVEL image
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            levelMode = ONE_LEVEL;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-m"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Generate a MIPMAP_LEVELS image
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            levelMode = MIPMAP_LEVELS;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-c"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Generate a cube-face map
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            type = ENVMAP_CUBE;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-l"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Generate a latitude-longitude map
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            type = ENVMAP_LATLONG;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-ci"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Assume input is a cube-face map
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            overrideInputType = ENVMAP_CUBE;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-li"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Assume input is a latitude-longitude map
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            overrideInputType = ENVMAP_LATLONG;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-w"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Set output image width
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (i > argc - 2)
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
            mapWidth = strtol (argv[i + 1], 0, 0);
Packit 0d464f
Packit 0d464f
            if (mapWidth <= 0)
Packit 0d464f
            {
Packit 0d464f
                cerr << "Output image width must be greater than zero." << endl;
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            i += 2;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-f"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Set filter radius and supersampling rate
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (i > argc - 3)
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
            filterRadius = strtod (argv[i + 1], 0);
Packit 0d464f
            numSamples   = strtol (argv[i + 2], 0, 0);
Packit 0d464f
Packit 0d464f
            if (filterRadius < 0)
Packit 0d464f
            {
Packit 0d464f
                cerr << "Filter radius must not be less than zero." << endl;
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            if (numSamples <= 0)
Packit 0d464f
            {
Packit 0d464f
                cerr << "Sampling rate must be greater than zero." << endl;
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            i += 3;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-b"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Diffuse blur
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            diffuseBlur = true;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-t"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Set tile size
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (i > argc - 3)
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
            tileWidth  = strtol (argv[i + 1], 0, 0);
Packit 0d464f
            tileHeight = strtol (argv[i + 2], 0, 0);
Packit 0d464f
Packit 0d464f
            if (tileWidth <= 0 || tileHeight <= 0)
Packit 0d464f
            {
Packit 0d464f
                cerr << "Tile size must be greater than zero." << endl;
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            i += 3;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-p"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Set top and bottom padding
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (i > argc - 3)
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
            padTop    = strtod (argv[i + 1], 0);
Packit 0d464f
            padBottom = strtod (argv[i + 2], 0);
Packit 0d464f
Packit 0d464f
            if (padTop < 0 || padBottom < 0)
Packit 0d464f
            {
Packit 0d464f
                cerr << "Padding must not be less than zero." << endl;
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            i += 3;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-d"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Round down
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            roundingMode = ROUND_DOWN;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-u"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Round down
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            roundingMode = ROUND_UP;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-z"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Set compression method
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (i > argc - 2)
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
            compression = getCompression (argv[i + 1]);
Packit 0d464f
            i += 2;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-v"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Verbose mode
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            verbose = true;
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-h"))
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Print help message
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            usageMessage (argv[0], true);
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            //
Packit 0d464f
            // Image file name
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            if (inFile == 0)
Packit 0d464f
                inFile = argv[i];
Packit 0d464f
            else
Packit 0d464f
                outFile = argv[i];
Packit 0d464f
Packit 0d464f
            i += 1;
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (inFile == 0 || outFile == 0)
Packit 0d464f
        usageMessage (argv[0]);
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Load inFile, convert it, and save the result in outFile.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int exitStatus = 0;
Packit 0d464f
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        EnvmapImage image;
Packit 0d464f
        Header header;
Packit 0d464f
        RgbaChannels channels;
Packit 0d464f
Packit 0d464f
        readInputImage (inFile, padTop, padBottom,
Packit 0d464f
                        overrideInputType, verbose,
Packit 0d464f
                        image, header, channels);
Packit 0d464f
Packit 0d464f
        if (diffuseBlur)
Packit 0d464f
            blurImage (image, verbose);
Packit 0d464f
Packit 0d464f
        if (type == ENVMAP_CUBE)
Packit 0d464f
        {
Packit 0d464f
            makeCubeMap (image, header, channels,
Packit 0d464f
                         outFile,
Packit 0d464f
                         tileWidth, tileHeight,
Packit 0d464f
                         levelMode, roundingMode,
Packit 0d464f
                         compression, mapWidth,
Packit 0d464f
                         filterRadius, numSamples,
Packit 0d464f
                         verbose);
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            makeLatLongMap (image, header, channels,
Packit 0d464f
                            outFile,
Packit 0d464f
                            tileWidth, tileHeight,
Packit 0d464f
                            levelMode, roundingMode,
Packit 0d464f
                            compression, mapWidth,
Packit 0d464f
                            filterRadius, numSamples,
Packit 0d464f
                            verbose);
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
}