Blame exrmaketiled/makeTiled.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2012, 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
//	Produce a tiled version of an OpenEXR image.
Packit 0d464f
//
Packit 0d464f
//----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include "makeTiled.h"
Packit 0d464f
#include "Image.h"
Packit 0d464f
Packit 0d464f
#include "ImfTiledInputPart.h"
Packit 0d464f
#include "ImfTiledOutputPart.h"
Packit 0d464f
#include "ImfInputPart.h"
Packit 0d464f
#include "ImfOutputPart.h"
Packit 0d464f
#include "ImfDeepScanLineInputPart.h"
Packit 0d464f
#include "ImfDeepScanLineOutputPart.h"
Packit 0d464f
#include "ImfDeepTiledInputPart.h"
Packit 0d464f
#include "ImfDeepTiledOutputPart.h"
Packit 0d464f
#include "ImfChannelList.h"
Packit 0d464f
#include "ImfChannelList.h"
Packit 0d464f
#include "ImfFrameBuffer.h"
Packit 0d464f
#include "ImfStandardAttributes.h"
Packit 0d464f
#include "ImathFun.h"
Packit 0d464f
#include "Iex.h"
Packit 0d464f
#include "ImfMisc.h"
Packit 0d464f
Packit 0d464f
#include <map>
Packit 0d464f
#include <algorithm>
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <vector>
Packit 0d464f
Packit 0d464f
#include "namespaceAlias.h"
Packit 0d464f
using namespace IMF;
Packit 0d464f
using namespace IMATH_NAMESPACE;
Packit 0d464f
using namespace std;
Packit 0d464f
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
string
Packit 0d464f
extToString (Extrapolation ext)
Packit 0d464f
{
Packit 0d464f
    string str;
Packit 0d464f
Packit 0d464f
    switch (ext)
Packit 0d464f
    {
Packit 0d464f
        case BLACK:
Packit 0d464f
            str = "black";
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case CLAMP:
Packit 0d464f
            str = "clamp";
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case PERIODIC:
Packit 0d464f
            str = "periodic";
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case MIRROR:
Packit 0d464f
            str = "mirror";
Packit 0d464f
            break;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return str;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
mirror (int x, int w)
Packit 0d464f
{
Packit 0d464f
    int d = divp (x, w);
Packit 0d464f
    int m = modp (x, w);
Packit 0d464f
    return (d & 1)? w - 1 - m: m;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
double
Packit 0d464f
sampleX (const TypedImageChannel<T> &channel,
Packit 0d464f
         int w,
Packit 0d464f
         double x,
Packit 0d464f
         int y,
Packit 0d464f
         Extrapolation ext)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Sample an image channel at location (x, y), where
Packit 0d464f
    // x is a floating point number, and y is an integer.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int xs = IMATH_NAMESPACE::floor (x);
Packit 0d464f
    int xt = xs + 1;
Packit 0d464f
    double s = xt - x;
Packit 0d464f
    double t = 1 - s;
Packit 0d464f
    double vs=0.0;
Packit 0d464f
    double vt=0.0;
Packit 0d464f
Packit 0d464f
    switch (ext)
Packit 0d464f
    {
Packit 0d464f
        case BLACK:
Packit 0d464f
Packit 0d464f
            vs = (xs >= 0 && xs < w)? double (channel (xs, y)): 0.0;
Packit 0d464f
            vt = (xt >= 0 && xt < w)? double (channel (xt, y)): 0.0;
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case CLAMP:
Packit 0d464f
Packit 0d464f
            xs = clamp (xs, 0, w - 1);
Packit 0d464f
            xt = clamp (xt, 0, w - 1);
Packit 0d464f
            vs = channel (xs, y);
Packit 0d464f
            vt = channel (xt, y);
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case PERIODIC:
Packit 0d464f
Packit 0d464f
            xs = modp (xs, w);
Packit 0d464f
            xt = modp (xt, w);
Packit 0d464f
            vs = channel (xs, y);
Packit 0d464f
            vt = channel (xt, y);
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case MIRROR:
Packit 0d464f
Packit 0d464f
            xs = mirror (xs, w);
Packit 0d464f
            xt = mirror (xt, w);
Packit 0d464f
            vs = channel (xs, y);
Packit 0d464f
            vt = channel (xt, y);
Packit 0d464f
            break;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return s * vs + t * vt;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
double
Packit 0d464f
sampleY (const TypedImageChannel<T> &channel,
Packit 0d464f
         int h,
Packit 0d464f
         int x,
Packit 0d464f
         double y,
Packit 0d464f
         Extrapolation ext)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Sample an image channel at location (x, y), where
Packit 0d464f
    // x is an integer, and y is a floating point number.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int ys = IMATH_NAMESPACE::floor (y);
Packit 0d464f
    int yt = ys + 1;
Packit 0d464f
    double s = yt - y;
Packit 0d464f
    double t = 1 - s;
Packit 0d464f
    double vs=0.0;
Packit 0d464f
    double vt=0.0;
Packit 0d464f
Packit 0d464f
    switch (ext)
Packit 0d464f
    {
Packit 0d464f
        case BLACK:
Packit 0d464f
Packit 0d464f
            vs = (ys >= 0 && ys < h)? double (channel (x, ys)): 0.0;
Packit 0d464f
            vt = (yt >= 0 && yt < h)? double (channel (x, yt)): 0.0;
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case CLAMP:
Packit 0d464f
Packit 0d464f
            ys = clamp (ys, 0, h - 1);
Packit 0d464f
            yt = clamp (yt, 0, h - 1);
Packit 0d464f
            vs = channel (x, ys);
Packit 0d464f
            vt = channel (x, yt);
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case PERIODIC:
Packit 0d464f
Packit 0d464f
            ys = modp (ys, h);
Packit 0d464f
            yt = modp (yt, h);
Packit 0d464f
            vs = channel (x, ys);
Packit 0d464f
            vt = channel (x, yt);
Packit 0d464f
            break;
Packit 0d464f
Packit 0d464f
        case MIRROR:
Packit 0d464f
Packit 0d464f
            ys = mirror (ys, h);
Packit 0d464f
            yt = mirror (yt, h);
Packit 0d464f
            vs = channel (x, ys);
Packit 0d464f
            vt = channel (x, yt);
Packit 0d464f
            break;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return s * vs + t * vt;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
T
Packit 0d464f
filterX (const TypedImageChannel<T> &channel,
Packit 0d464f
         int w,
Packit 0d464f
         double x,
Packit 0d464f
         int y,
Packit 0d464f
         Extrapolation ext)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Horizontal four-tap filter, centered on pixel (x + 0.5, y)
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    return T (0.125 * sampleX (channel, w, x - 1, y, ext) +
Packit 0d464f
              0.375 * sampleX (channel, w, x,     y, ext) +
Packit 0d464f
              0.375 * sampleX (channel, w, x + 1, y, ext) +
Packit 0d464f
              0.125 * sampleX (channel, w, x + 2, y, ext));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
T
Packit 0d464f
filterY (const TypedImageChannel<T> &channel,
Packit 0d464f
         int h,
Packit 0d464f
         int x,
Packit 0d464f
         double y,
Packit 0d464f
         Extrapolation ext)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Vertical four-tap filter, centered on pixel (x, y + 0.5)
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    return T (0.125 * sampleY (channel, h, x, y - 1, ext) +
Packit 0d464f
              0.375 * sampleY (channel, h, x, y,     ext) +
Packit 0d464f
              0.375 * sampleY (channel, h, x, y + 1, ext) +
Packit 0d464f
              0.125 * sampleY (channel, h, x, y + 2, ext));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
void
Packit 0d464f
reduceX (const TypedImageChannel<T> &channel0,
Packit 0d464f
         TypedImageChannel<T> &channel1,
Packit 0d464f
         bool filter,
Packit 0d464f
         Extrapolation &ext,
Packit 0d464f
         bool odd)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Shrink an image channel, channel0, horizontally
Packit 0d464f
    // by a factor of 2, and store the result in channel1.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int w0 = channel0.image().width();
Packit 0d464f
    int w1 = channel1.image().width();
Packit 0d464f
    int h1 = channel1.image().height();
Packit 0d464f
Packit 0d464f
    if (filter)
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // Low-pass filter and resample.
Packit 0d464f
        // For pixels (0, y) and (w1 - 1, y) in channel 1,
Packit 0d464f
        // the low-pass filter in channel0 is centered on
Packit 0d464f
        // pixels (0.5, y) and (w0 - 1.5, y) respectively.
Packit 0d464f
        //
Packit 0d464f
Packit 0d464f
        double f = (w1 > 1)? double (w0 - 2) / (w1 - 1): 1;
Packit 0d464f
Packit 0d464f
        for (int y = 0; y < h1; ++y)
Packit 0d464f
            for (int x = 0; x < w1; ++x)
Packit 0d464f
                channel1 (x, y) = filterX (channel0, w0, x * f, y, ext);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // Resample, skipping every other pixel, without
Packit 0d464f
        // low-pass filtering.  In order to keep the image
Packit 0d464f
        // from sliding to the right if the channel is
Packit 0d464f
        // resampled repeatedly, we skip the rightmost
Packit 0d464f
        // pixel of every row on even passes, and the
Packit 0d464f
        // leftmost pixel on odd passes.
Packit 0d464f
        //
Packit 0d464f
Packit 0d464f
        int offset = odd? ((w0 - 1) - 2 * (w1 - 1)): 0;
Packit 0d464f
Packit 0d464f
        for (int y = 0; y < h1; ++y)
Packit 0d464f
            for (int x = 0; x < w1; ++x)
Packit 0d464f
                channel1 (x, y) = channel0 (2 * x + offset, y);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
template <class T>
Packit 0d464f
void
Packit 0d464f
reduceY (const TypedImageChannel<T> &channel0,
Packit 0d464f
         TypedImageChannel<T> &channel1,
Packit 0d464f
         bool filter,
Packit 0d464f
         Extrapolation ext,
Packit 0d464f
         bool odd)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Shrink an image channel, channel0, vertically
Packit 0d464f
    // by a factor of 2, and store the result in channel1.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int w1 = channel1.image().width();
Packit 0d464f
    int h0 = channel0.image().height();
Packit 0d464f
    int h1 = channel1.image().height();
Packit 0d464f
Packit 0d464f
    if (filter)
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // Low-pass filter and resample.
Packit 0d464f
        // For pixels (x, 0) and (x, h1 - 1) in channel 1,
Packit 0d464f
        // the low-pass filter in channel0 is centered on
Packit 0d464f
        // pixels (x, 0.5) and (x, h0 - 1.5) respectively.
Packit 0d464f
        //
Packit 0d464f
Packit 0d464f
        double f = (h1 > 1)? double (h0 - 2) / (h1 - 1): 1;
Packit 0d464f
Packit 0d464f
        for (int y = 0; y < h1; ++y)
Packit 0d464f
            for (int x = 0; x < w1; ++x)
Packit 0d464f
                channel1 (x, y) = filterY (channel0, h0, x, y * f, ext);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        //
Packit 0d464f
        // Resample, skipping every other pixel, without
Packit 0d464f
        // low-pass filtering.  In order to keep the image
Packit 0d464f
        // from sliding towards the top if the channel is
Packit 0d464f
        // resampled repeatedly, we skip the top pixel of
Packit 0d464f
        // every column on even passes, and the bottom pixel
Packit 0d464f
        // on odd passes.
Packit 0d464f
        //
Packit 0d464f
Packit 0d464f
        int offset = odd? ((h0 - 1) - 2 * (h1 - 1)): 0;
Packit 0d464f
Packit 0d464f
        for (int y = 0; y < h1; ++y)
Packit 0d464f
            for (int x = 0; x < w1; ++x)
Packit 0d464f
                channel1 (x, y) = channel0 (x, 2 * y + offset);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
reduceX (const ChannelList &channels,
Packit 0d464f
         const set<string> &doNotFilter,
Packit 0d464f
         Extrapolation ext,
Packit 0d464f
         bool odd,
Packit 0d464f
         const Image &image0,
Packit 0d464f
         Image &image1)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Shrink image image0 horizontally by a factor of 2,
Packit 0d464f
    // and store the result in image image1.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (ChannelList::ConstIterator i = channels.begin();
Packit 0d464f
         i != channels.end();
Packit 0d464f
         ++i)
Packit 0d464f
    {
Packit 0d464f
        const char *name = i.name();
Packit 0d464f
        const Channel &channel = i.channel();
Packit 0d464f
        bool filter = (doNotFilter.find (name) == doNotFilter.end());
Packit 0d464f
Packit 0d464f
        switch (channel.type)
Packit 0d464f
        {
Packit 0d464f
            case IMF::HALF:
Packit 0d464f
Packit 0d464f
                reduceX (image0.typedChannel<half> (name),
Packit 0d464f
                         image1.typedChannel<half> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
Packit 0d464f
            case IMF::FLOAT:
Packit 0d464f
Packit 0d464f
                reduceX (image0.typedChannel<float> (name),
Packit 0d464f
                         image1.typedChannel<float> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
Packit 0d464f
            case IMF::UINT:
Packit 0d464f
Packit 0d464f
                reduceX (image0.typedChannel<unsigned int> (name),
Packit 0d464f
                         image1.typedChannel<unsigned int> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
            default : 
Packit 0d464f
                break;
Packit 0d464f
           
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
reduceY (const ChannelList &channels,
Packit 0d464f
         const set<string> &doNotFilter,
Packit 0d464f
         Extrapolation ext,
Packit 0d464f
         bool odd,
Packit 0d464f
         const Image &image0,
Packit 0d464f
         Image &image1)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Shrink image image0 vertically by a factor of 2,
Packit 0d464f
    // and store the result in image image1.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (ChannelList::ConstIterator i = channels.begin();
Packit 0d464f
         i != channels.end();
Packit 0d464f
         ++i)
Packit 0d464f
    {
Packit 0d464f
        const char *name = i.name();
Packit 0d464f
        const Channel &channel = i.channel();
Packit 0d464f
        bool filter = (doNotFilter.find (name) == doNotFilter.end());
Packit 0d464f
Packit 0d464f
        switch (channel.type)
Packit 0d464f
        {
Packit 0d464f
            case IMF::HALF:
Packit 0d464f
Packit 0d464f
                reduceY (image0.typedChannel<half> (name),
Packit 0d464f
                         image1.typedChannel<half> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
Packit 0d464f
            case IMF::FLOAT:
Packit 0d464f
Packit 0d464f
                reduceY (image0.typedChannel<float> (name),
Packit 0d464f
                         image1.typedChannel<float> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
Packit 0d464f
            case IMF::UINT:
Packit 0d464f
Packit 0d464f
                reduceY (image0.typedChannel<unsigned int> (name),
Packit 0d464f
                         image1.typedChannel<unsigned int> (name),
Packit 0d464f
                         filter, ext, odd);
Packit 0d464f
                break;
Packit 0d464f
            default : 
Packit 0d464f
                break;
Packit 0d464f
                
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
storeLevel (TiledOutputPart &out,
Packit 0d464f
            const ChannelList &channels,
Packit 0d464f
            int lx,
Packit 0d464f
            int ly,
Packit 0d464f
            const Image &image)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Store the pixels for level (lx, ly) in output file out.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    FrameBuffer fb;
Packit 0d464f
Packit 0d464f
    for (ChannelList::ConstIterator i = channels.begin();
Packit 0d464f
         i != channels.end();
Packit 0d464f
         ++i)
Packit 0d464f
    {
Packit 0d464f
        const char *name = i.name();
Packit 0d464f
        fb.insert (name, image.channel(name).slice());
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    out.setFrameBuffer (fb);
Packit 0d464f
Packit 0d464f
    for (int y = 0; y < out.numYTiles (ly); ++y)
Packit 0d464f
        for (int x = 0; x < out.numXTiles (lx); ++x)
Packit 0d464f
            out.writeTile (x, y, lx, ly);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
makeTiled (const char inFileName[],
Packit 0d464f
           const char outFileName[],
Packit 0d464f
           int partnum,
Packit 0d464f
           LevelMode mode,
Packit 0d464f
           LevelRoundingMode roundingMode,
Packit 0d464f
           Compression compression,
Packit 0d464f
           int tileSizeX,
Packit 0d464f
           int tileSizeY,
Packit 0d464f
           const set<string> &doNotFilter,
Packit 0d464f
           Extrapolation extX,
Packit 0d464f
           Extrapolation extY,
Packit 0d464f
           bool verbose)
Packit 0d464f
{
Packit 0d464f
    Image image0;
Packit 0d464f
    Image image1;
Packit 0d464f
    Image image2;
Packit 0d464f
    Header header;
Packit 0d464f
    FrameBuffer fb;
Packit 0d464f
    vector<Header> headers;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Load the input image
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    MultiPartInputFile input (inFileName);
Packit 0d464f
    int parts = input.parts();
Packit 0d464f
Packit 0d464f
    for (int p = 0 ; p < parts; p++)
Packit 0d464f
    {
Packit 0d464f
        if (verbose)
Packit 0d464f
            cout << "reading file " << inFileName << endl;
Packit 0d464f
Packit 0d464f
        if(p == partnum)
Packit 0d464f
        {
Packit 0d464f
            InputPart in (input, p);
Packit 0d464f
            header = in.header();
Packit 0d464f
            if (hasEnvmap (header) && mode != ONE_LEVEL)
Packit 0d464f
            {
Packit 0d464f
                //
Packit 0d464f
                // Proper low-pass filtering and subsampling
Packit 0d464f
                // of environment maps is not implemented in
Packit 0d464f
                // this program.
Packit 0d464f
                //
Packit 0d464f
Packit 0d464f
                throw IEX_NAMESPACE::NoImplExc ("This program cannot generate "
Packit 0d464f
                                      "multiresolution environment maps.  "
Packit 0d464f
                                      "Use exrenvmap instead.");
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            image0.resize (header.dataWindow());
Packit 0d464f
Packit 0d464f
            for (ChannelList::ConstIterator i = header.channels().begin();
Packit 0d464f
                            i != header.channels().end();
Packit 0d464f
                            ++i)
Packit 0d464f
            {
Packit 0d464f
                const char *name = i.name();
Packit 0d464f
                const Channel &channel = i.channel();
Packit 0d464f
Packit 0d464f
                if (channel.xSampling != 1 || channel.ySampling != 1)
Packit 0d464f
                {
Packit 0d464f
                    throw IEX_NAMESPACE::InputExc ("Sub-sampled image channels are "
Packit 0d464f
                                         "not supported in tiled files.");
Packit 0d464f
                }
Packit 0d464f
Packit 0d464f
                image0.addChannel (name, channel.type);
Packit 0d464f
                image1.addChannel (name, channel.type);
Packit 0d464f
                image2.addChannel (name, channel.type);
Packit 0d464f
                fb.insert (name, image0.channel(name).slice());
Packit 0d464f
            }
Packit 0d464f
Packit 0d464f
            in.setFrameBuffer (fb);
Packit 0d464f
            in.readPixels (header.dataWindow().min.y, header.dataWindow().max.y);
Packit 0d464f
Packit 0d464f
Packit 0d464f
            //
Packit 0d464f
            // Generate the header for the output file by modifying
Packit 0d464f
            // the input file's header
Packit 0d464f
            //
Packit 0d464f
Packit 0d464f
            header.setTileDescription (TileDescription (tileSizeX, tileSizeY,
Packit 0d464f
                                                        mode, roundingMode));
Packit 0d464f
Packit 0d464f
            header.compression() = compression;
Packit 0d464f
            header.lineOrder() = INCREASING_Y;
Packit 0d464f
Packit 0d464f
            if (mode != ONE_LEVEL)
Packit 0d464f
                addWrapmodes (header, extToString (extX) + "," + extToString (extY));
Packit 0d464f
Packit 0d464f
            //
Packit 0d464f
            // set tileDescription, type, and chunckcount for multipart
Packit 0d464f
            //
Packit 0d464f
            header.setType(TILEDIMAGE);
Packit 0d464f
            int chunkcount = getChunkOffsetTableSize(header, true);
Packit 0d464f
            header.setChunkCount(chunkcount);
Packit 0d464f
Packit 0d464f
            headers.push_back(header);
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            Header h = input.header(p);
Packit 0d464f
            headers.push_back(h);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Store the highest-resolution level of the image in the output file
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    MultiPartOutputFile output (outFileName, &headers[0], headers.size());
Packit 0d464f
Packit 0d464f
    for(int p = 0 ; p < parts; p++)
Packit 0d464f
    {
Packit 0d464f
        if (p == partnum)
Packit 0d464f
        {
Packit 0d464f
            try
Packit 0d464f
            {
Packit 0d464f
                TiledOutputPart out (output, partnum);
Packit 0d464f
            //    TiledOutputFile out (outFileName, header);
Packit 0d464f
Packit 0d464f
Packit 0d464f
                out.setFrameBuffer (fb);
Packit 0d464f
Packit 0d464f
                if (verbose)
Packit 0d464f
                    cout << "writing file " << outFileName << "\n"
Packit 0d464f
                            "level (0, 0)" << endl;
Packit 0d464f
Packit 0d464f
                for (int y = 0; y < out.numYTiles (0); ++y)
Packit 0d464f
                    for (int x = 0; x < out.numXTiles (0); ++x)
Packit 0d464f
                        out.writeTile (x, y, 0);
Packit 0d464f
Packit 0d464f
                //
Packit 0d464f
                // If necessary, generate the lower-resolution mipmap
Packit 0d464f
                // or ripmap levels, and store them in the output file.
Packit 0d464f
                //
Packit 0d464f
Packit 0d464f
                if (mode == MIPMAP_LEVELS)
Packit 0d464f
                {
Packit 0d464f
                    for (int l = 1; l < out.numLevels(); ++l)
Packit 0d464f
                    {
Packit 0d464f
                        image1.resize (out.dataWindowForLevel (l, l - 1));
Packit 0d464f
Packit 0d464f
                        reduceX (header.channels(),
Packit 0d464f
                                 doNotFilter,
Packit 0d464f
                                 extX,
Packit 0d464f
                                 l & 1,
Packit 0d464f
                                 image0,
Packit 0d464f
                                 image1);
Packit 0d464f
Packit 0d464f
                        image0.resize (out.dataWindowForLevel (l, l));
Packit 0d464f
Packit 0d464f
                        reduceY (header.channels(),
Packit 0d464f
                                 doNotFilter,
Packit 0d464f
                                 extY,
Packit 0d464f
                                 l & 1,
Packit 0d464f
                                 image1,
Packit 0d464f
                                 image0);
Packit 0d464f
Packit 0d464f
                        if (verbose)
Packit 0d464f
                            cout << "level (" << l << ", " << l << ")" << endl;
Packit 0d464f
Packit 0d464f
                        storeLevel (out, header.channels(), l, l, image0);
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
Packit 0d464f
                if (mode == RIPMAP_LEVELS)
Packit 0d464f
                {
Packit 0d464f
                    Image *iptr0 = &image0;
Packit 0d464f
                    Image *iptr1 = &image1;
Packit 0d464f
                    Image *iptr2 = &image2;
Packit 0d464f
Packit 0d464f
                    for (int ly = 0; ly < out.numYLevels(); ++ly)
Packit 0d464f
                    {
Packit 0d464f
                        if (ly < out.numYLevels() - 1)
Packit 0d464f
                        {
Packit 0d464f
                            iptr2->resize (out.dataWindowForLevel (0, ly + 1));
Packit 0d464f
Packit 0d464f
                            reduceY (header.channels(),
Packit 0d464f
                                     doNotFilter,
Packit 0d464f
                                     extY,
Packit 0d464f
                                     ly & 1,
Packit 0d464f
                                     *iptr0,
Packit 0d464f
                                     *iptr2);
Packit 0d464f
                        }
Packit 0d464f
Packit 0d464f
                        for (int lx = 0; lx < out.numXLevels(); ++lx)
Packit 0d464f
                        {
Packit 0d464f
                            if (lx != 0 || ly != 0)
Packit 0d464f
                            {
Packit 0d464f
                                if (verbose)
Packit 0d464f
                                    cout << "level (" << lx << ", " << ly << ")" << endl;
Packit 0d464f
Packit 0d464f
                                storeLevel (out, header.channels(), lx, ly, *iptr0);
Packit 0d464f
                            }
Packit 0d464f
Packit 0d464f
                            if (lx < out.numXLevels() - 1)
Packit 0d464f
                            {
Packit 0d464f
                                iptr1->resize (out.dataWindowForLevel (lx + 1, ly));
Packit 0d464f
Packit 0d464f
                                reduceX (header.channels(),
Packit 0d464f
                                         doNotFilter,
Packit 0d464f
                                         extX,
Packit 0d464f
                                         lx & 1,
Packit 0d464f
                                         *iptr0,
Packit 0d464f
                                         *iptr1);
Packit 0d464f
Packit 0d464f
                                swap (iptr0, iptr1);
Packit 0d464f
                            }
Packit 0d464f
                        }
Packit 0d464f
Packit 0d464f
                        swap (iptr2, iptr0);
Packit 0d464f
                    }
Packit 0d464f
                }
Packit 0d464f
            }
Packit 0d464f
            catch (const exception &e)
Packit 0d464f
            {
Packit 0d464f
                cerr << e.what() << endl;
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            Header header = headers[p];
Packit 0d464f
            std::string type = header.type();
Packit 0d464f
            if (type == TILEDIMAGE)
Packit 0d464f
            {
Packit 0d464f
                TiledInputPart in (input, p);
Packit 0d464f
                TiledOutputPart out (output, p);
Packit 0d464f
                out.copyPixels (in);
Packit 0d464f
            }
Packit 0d464f
            else if (type == SCANLINEIMAGE)
Packit 0d464f
            {
Packit 0d464f
                using std::max;  InputPart in (input, p);
Packit 0d464f
                OutputPart out (output, p);
Packit 0d464f
                out.copyPixels (in);
Packit 0d464f
            }
Packit 0d464f
            else if (type == DEEPSCANLINE)
Packit 0d464f
            {
Packit 0d464f
                DeepScanLineInputPart in (input,p);
Packit 0d464f
                DeepScanLineOutputPart out (output,p);
Packit 0d464f
                out.copyPixels (in);
Packit 0d464f
            }
Packit 0d464f
            else if (type == DEEPTILE)
Packit 0d464f
            {
Packit 0d464f
                DeepTiledInputPart in (input,p);
Packit 0d464f
                DeepTiledOutputPart out (output,p);
Packit 0d464f
                out.copyPixels (in);
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (verbose)
Packit 0d464f
	cout << "done." << endl;
Packit 0d464f
}
Packit 0d464f