Blame exrenvmap/makeCubeMap.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
//      function makeCubeMap() -- makes cube-face environment maps
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <makeCubeMap.h>
Packit 0d464f
Packit 0d464f
#include <resizeImage.h>
Packit 0d464f
#include <ImfRgbaFile.h>
Packit 0d464f
#include <ImfTiledRgbaFile.h>
Packit 0d464f
#include <ImfStandardAttributes.h>
Packit 0d464f
#include "Iex.h"
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <algorithm>
Packit 0d464f
#include <string>
Packit 0d464f
#include <string.h>
Packit 0d464f
Packit 0d464f
Packit 0d464f
#include "namespaceAlias.h"
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace IMATH;
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
makeCubeMapSingleFile (EnvmapImage &image1,
Packit 0d464f
                       Header &header,
Packit 0d464f
                       RgbaChannels channels,
Packit 0d464f
                       const char outFileName[],
Packit 0d464f
                       int tileWidth,
Packit 0d464f
                       int tileHeight,
Packit 0d464f
                       LevelMode levelMode,
Packit 0d464f
                       LevelRoundingMode roundingMode,
Packit 0d464f
                       Compression compression,
Packit 0d464f
                       int mapWidth,
Packit 0d464f
                       float filterRadius,
Packit 0d464f
                       int numSamples,
Packit 0d464f
                       bool verbose)
Packit 0d464f
{
Packit 0d464f
    if (levelMode == RIPMAP_LEVELS)
Packit 0d464f
        throw IEX::NoImplExc ("Cannot generate ripmap cube-face environments.");
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Open the file that will contain the cube-face map,
Packit 0d464f
    // and write the header.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int mapHeight = mapWidth * 6;
Packit 0d464f
Packit 0d464f
    header.dataWindow() = Box2i (V2i (0, 0), V2i (mapWidth - 1, mapHeight - 1));
Packit 0d464f
    header.displayWindow() = header.dataWindow();
Packit 0d464f
    header.compression() = compression;
Packit 0d464f
Packit 0d464f
    addEnvmap (header, ENVMAP_CUBE);
Packit 0d464f
Packit 0d464f
    TiledRgbaOutputFile out (outFileName,
Packit 0d464f
                             header,
Packit 0d464f
                             channels,
Packit 0d464f
                             tileWidth, tileHeight,
Packit 0d464f
                             levelMode,
Packit 0d464f
                             roundingMode);
Packit 0d464f
    if (verbose)
Packit 0d464f
        cout << "writing file " << outFileName << endl;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Generate the pixels for the various levels of the cube-face map,
Packit 0d464f
    // and store them in the file.  The pixels for the highest-resolution
Packit 0d464f
    // level are generated by resampling the original input image; for
Packit 0d464f
    // each of the other levels, the pixels are generated by resampling
Packit 0d464f
    // the previous level.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    EnvmapImage image2;
Packit 0d464f
    EnvmapImage *iptr1 = &image1;
Packit 0d464f
    EnvmapImage *iptr2 = &image2;
Packit 0d464f
    
Packit 0d464f
    for (int level = 0; level < out.numLevels(); ++level)
Packit 0d464f
    {
Packit 0d464f
        if (verbose)
Packit 0d464f
            cout << "level " << level << endl;
Packit 0d464f
Packit 0d464f
        Box2i dw = out.dataWindowForLevel (level);
Packit 0d464f
        resizeCube (*iptr1, *iptr2, dw, filterRadius, numSamples);
Packit 0d464f
Packit 0d464f
        out.setFrameBuffer (&iptr2->pixels()[0][0], 1, dw.max.x + 1);
Packit 0d464f
Packit 0d464f
        for (int tileY = 0; tileY < out.numYTiles (level); ++tileY)
Packit 0d464f
            for (int tileX = 0; tileX < out.numXTiles (level); ++tileX)
Packit 0d464f
                out.writeTile (tileX, tileY, level);
Packit 0d464f
Packit 0d464f
        swap (iptr1, iptr2);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (verbose)
Packit 0d464f
        cout << "done." << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
makeCubeMapSixFiles (EnvmapImage &image1,
Packit 0d464f
                     Header &header,
Packit 0d464f
                     RgbaChannels channels,
Packit 0d464f
                     const char outFileName[],
Packit 0d464f
                     int tileWidth,
Packit 0d464f
                     int tileHeight,
Packit 0d464f
                     Compression compression,
Packit 0d464f
                     int mapWidth,
Packit 0d464f
                     float filterRadius,
Packit 0d464f
                     int numSamples,
Packit 0d464f
                     bool verbose)
Packit 0d464f
{
Packit 0d464f
    static const char *faceNames[] =
Packit 0d464f
        {"+X", "-X", "+Y", "-Y", "+Z", "-Z"};
Packit 0d464f
Packit 0d464f
    size_t pos = strchr (outFileName, '%') - outFileName;
Packit 0d464f
Packit 0d464f
    int mapHeight = mapWidth * 6;
Packit 0d464f
    const Box2i dw (V2i (0, 0), V2i (mapWidth - 1, mapHeight - 1));
Packit 0d464f
    const Box2i faceDw (V2i (0, 0), V2i (mapWidth - 1, mapWidth - 1));
Packit 0d464f
Packit 0d464f
    EnvmapImage image2;
Packit 0d464f
    resizeCube (image1, image2, dw, filterRadius, numSamples);
Packit 0d464f
    const Rgba *pixels = &(image2.pixels())[0][0];
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < 6; ++i)
Packit 0d464f
    {
Packit 0d464f
        string name = string (outFileName).replace (pos, 1, faceNames[i]);
Packit 0d464f
Packit 0d464f
        if (verbose)
Packit 0d464f
            cout << "writing file " << name << endl;
Packit 0d464f
Packit 0d464f
        TiledRgbaOutputFile out (name.c_str(),
Packit 0d464f
                                 tileWidth, tileHeight,
Packit 0d464f
                                 ONE_LEVEL, ROUND_DOWN,
Packit 0d464f
                                 faceDw,        // displayWindow
Packit 0d464f
                                 faceDw,        // dataWindow
Packit 0d464f
                                 channels,
Packit 0d464f
                                 1,             // pixelAspectRatio
Packit 0d464f
                                 V2f (0, 0),    // screenWindowCenter
Packit 0d464f
                                 1,             // screenWindowWidth
Packit 0d464f
                                 INCREASING_Y,  // lineOrder
Packit 0d464f
                                 compression);
Packit 0d464f
Packit 0d464f
        out.setFrameBuffer (pixels, 1, dw.max.x + 1);
Packit 0d464f
Packit 0d464f
        for (int tileY = 0; tileY < out.numYTiles(); ++tileY)
Packit 0d464f
            for (int tileX = 0; tileX < out.numXTiles(); ++tileX)
Packit 0d464f
                    out.writeTile (tileX, tileY);
Packit 0d464f
Packit 0d464f
        pixels += mapWidth * mapWidth;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (verbose)
Packit 0d464f
        cout << "done." << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} //namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
makeCubeMap (EnvmapImage &image1,
Packit 0d464f
             Header &header,
Packit 0d464f
             RgbaChannels channels,
Packit 0d464f
             const char outFileName[],
Packit 0d464f
             int tileWidth,
Packit 0d464f
             int tileHeight,
Packit 0d464f
             LevelMode levelMode,
Packit 0d464f
             LevelRoundingMode roundingMode,
Packit 0d464f
             Compression compression,
Packit 0d464f
             int mapWidth,
Packit 0d464f
             float filterRadius,
Packit 0d464f
             int numSamples,
Packit 0d464f
             bool verbose)
Packit 0d464f
{
Packit 0d464f
    if (strchr (outFileName, '%'))
Packit 0d464f
    {
Packit 0d464f
        makeCubeMapSixFiles (image1,
Packit 0d464f
                             header,
Packit 0d464f
                             channels,
Packit 0d464f
                             outFileName,
Packit 0d464f
                             tileWidth,
Packit 0d464f
                             tileHeight,
Packit 0d464f
                             compression,
Packit 0d464f
                             mapWidth,
Packit 0d464f
                             filterRadius,
Packit 0d464f
                             numSamples,
Packit 0d464f
                             verbose);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        makeCubeMapSingleFile (image1,
Packit 0d464f
                               header,
Packit 0d464f
                               channels,
Packit 0d464f
                               outFileName,
Packit 0d464f
                               tileWidth,
Packit 0d464f
                               tileHeight,
Packit 0d464f
                               levelMode,
Packit 0d464f
                               roundingMode,
Packit 0d464f
                               compression,
Packit 0d464f
                               mapWidth,
Packit 0d464f
                               filterRadius,
Packit 0d464f
                               numSamples,
Packit 0d464f
                               verbose);
Packit 0d464f
    }
Packit 0d464f
}