Blame exrmultipart/exrmultipart.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2012, Industrial Light & Magic, a division of Lucas
Packit 0d464f
// Digital Ltd. LLC
Packit 0d464f
// Portions contributed and copyright held by others as indicated.
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
//	Utility program to combine or separate multipart image files
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
Packit 0d464f
#include <ImfMultiPartOutputFile.h>
Packit 0d464f
#include <ImfMultiPartInputFile.h>
Packit 0d464f
#include <ImfStringAttribute.h>
Packit 0d464f
#include <ImfChannelList.h>
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 <ImfPartHelper.h>
Packit 0d464f
#include <ImfPartType.h>
Packit 0d464f
Packit 0d464f
#include <OpenEXRConfig.h>
Packit 0d464f
#include <Iex.h>
Packit 0d464f
Packit 0d464f
#include <iostream>
Packit 0d464f
#include <vector>
Packit 0d464f
#include <utility> // pair
Packit 0d464f
#include <stdlib.h>
Packit 0d464f
#include <sstream>
Packit 0d464f
#include <assert.h>
Packit 0d464f
#include <cctype>
Packit 0d464f
#include <algorithm>
Packit 0d464f
Packit 0d464f
using std::cerr;
Packit 0d464f
using std::cout;
Packit 0d464f
using std::endl;
Packit 0d464f
using std::vector;
Packit 0d464f
using std::pair;
Packit 0d464f
using std::set;
Packit 0d464f
using std::ostringstream;
Packit 0d464f
using std::min;
Packit 0d464f
using std::max;
Packit 0d464f
using std::string;
Packit 0d464f
using std::make_pair;
Packit 0d464f
using IMATH_NAMESPACE::Box2i;
Packit 0d464f
Packit 0d464f
using namespace OPENEXR_IMF_NAMESPACE;
Packit 0d464f
Packit 0d464f
Packit 0d464f
#if defined(ANDROID) || defined(__ANDROID_API__)
Packit 0d464f
    #define IMF_PATH_SEPARATOR "/"
Packit 0d464f
#elif defined(_WIN32) || defined(_WIN64) || defined(__MWERKS__) || defined(PLATFORM_WINDOWS)
Packit 0d464f
    #define IMF_PATH_SEPARATOR "\\"
Packit 0d464f
#else
Packit 0d464f
    #define IMF_PATH_SEPARATOR "/"
Packit 0d464f
#endif
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
copy_tile (MultiPartInputFile & input,
Packit 0d464f
           MultiPartOutputFile & output,
Packit 0d464f
           int inPart, int outPart)
Packit 0d464f
{
Packit 0d464f
    TiledInputPart in (input, inPart);
Packit 0d464f
    TiledOutputPart out (output, outPart);
Packit 0d464f
Packit 0d464f
    out.copyPixels (in);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
copy_tiledeep (MultiPartInputFile & input,
Packit 0d464f
               MultiPartOutputFile & output,
Packit 0d464f
               int inPart, int outPart)
Packit 0d464f
{
Packit 0d464f
    DeepTiledInputPart in (input, inPart);
Packit 0d464f
    DeepTiledOutputPart out (output, outPart);
Packit 0d464f
Packit 0d464f
    out.copyPixels (in);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
copy_scanline (MultiPartInputFile & input,
Packit 0d464f
               MultiPartOutputFile & output,
Packit 0d464f
               int inPart, int outPart)
Packit 0d464f
{
Packit 0d464f
    InputPart in (input, inPart);
Packit 0d464f
    OutputPart out (output, outPart);
Packit 0d464f
Packit 0d464f
    out.copyPixels (in);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
copy_scanlinedeep (MultiPartInputFile & input,
Packit 0d464f
                   MultiPartOutputFile & output,
Packit 0d464f
                   int inPart, int outPart)
Packit 0d464f
{
Packit 0d464f
    DeepScanLineInputPart in (input, inPart);
Packit 0d464f
    DeepScanLineOutputPart out (output, outPart);
Packit 0d464f
Packit 0d464f
    out.copyPixels (in);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
bool
Packit 0d464f
is_number(const std::string& s)
Packit 0d464f
{
Packit 0d464f
    std::string::const_iterator it = s.begin();
Packit 0d464f
    while (it != s.end() && std::isdigit(*it)) ++it;
Packit 0d464f
    return !s.empty() && it == s.end();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
parse_partname (string & part_name)
Packit 0d464f
{
Packit 0d464f
    // strip off a path delimitation
Packit 0d464f
    size_t posSlash = part_name.rfind(IMF_PATH_SEPARATOR);
Packit 0d464f
    if (posSlash != string::npos)
Packit 0d464f
        part_name = part_name.substr(posSlash+1);
Packit 0d464f
Packit 0d464f
Packit 0d464f
    // strip the exr ext
Packit 0d464f
    size_t pos = part_name.rfind(".exr");
Packit 0d464f
    if (pos != string::npos)
Packit 0d464f
    {
Packit 0d464f
        part_name = part_name.substr(0, pos);
Packit 0d464f
Packit 0d464f
        // strip off the frame number
Packit 0d464f
        size_t pos2 = part_name.rfind(".");
Packit 0d464f
        if (pos2 != string::npos)
Packit 0d464f
        {
Packit 0d464f
            string frame = part_name.substr(pos2+1, pos);
Packit 0d464f
            if (is_number(frame))
Packit 0d464f
                part_name = part_name.substr(0, pos2);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
///
Packit 0d464f
/// If input is <...>::
Packit 0d464f
/// Else, use the stripped version of the filename for partname
Packit 0d464f
/// If input is <file>:<partnum> then extract part number,
Packit 0d464f
/// Else, use all parts
Packit 0d464f
///
Packit 0d464f
void
Packit 0d464f
parse_filename (string & file_name,
Packit 0d464f
                string & part_name,
Packit 0d464f
                bool   & force_part_name,
Packit 0d464f
                int    & part_num)
Packit 0d464f
{
Packit 0d464f
    force_part_name = false;
Packit 0d464f
    part_name = file_name; // default is the file_name
Packit 0d464f
    size_t doublecolon = file_name.rfind ("::");
Packit 0d464f
    if (doublecolon != string::npos)
Packit 0d464f
    {
Packit 0d464f
        part_name = file_name.substr (doublecolon+2);
Packit 0d464f
        file_name = file_name.substr (0, doublecolon);
Packit 0d464f
        force_part_name = true;
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        parse_partname(part_name);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    size_t colon = file_name.rfind (':');
Packit 0d464f
    if (colon == string::npos)
Packit 0d464f
    {
Packit 0d464f
        part_num = -1; // use all parts
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        string num = file_name.substr (colon + 1);
Packit 0d464f
        if (is_number(num))
Packit 0d464f
        {
Packit 0d464f
            part_num  = atoi (num.c_str());
Packit 0d464f
            file_name = file_name.substr (0, colon);
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            cerr <<"\n" << "ERROR: part number must be a number" << endl;
Packit 0d464f
            exit(1);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
make_unique_names (vector<Header> & headers)
Packit 0d464f
{
Packit 0d464f
    set<string> names;
Packit 0d464f
    for ( size_t i = 0 ; i < headers.size() ; i++ )
Packit 0d464f
    {
Packit 0d464f
        Header & h = headers[i];
Packit 0d464f
        std::string base_name;
Packit 0d464f
Packit 0d464f
        // if no name at all, set it to <type><partnum> (first part is part 1)
Packit 0d464f
        if (!h.hasName())
Packit 0d464f
        {
Packit 0d464f
            // We should not be here, we have populated all headers with names.
Packit 0d464f
            cerr << "\n" << "Software Error: header does not have a valid name"
Packit 0d464f
                 << ":" << __LINE__ << endl;
Packit 0d464f
            exit (1);
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            base_name = h.name();
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
Packit 0d464f
        // check name has already been used, if so add a _<number> to it
Packit 0d464f
        if (names.find (base_name) != names.end())
Packit 0d464f
        {
Packit 0d464f
            ostringstream s;
Packit 0d464f
            size_t backup=1;
Packit 0d464f
            do
Packit 0d464f
            {
Packit 0d464f
                s.clear();
Packit 0d464f
                s << h.name() << "_" << i << "_" << backup;
Packit 0d464f
                backup++;
Packit 0d464f
            }
Packit 0d464f
            while (names.find(s.str()) != names.end());
Packit 0d464f
            h.setName (s.str());
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        names.insert (h.name());
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
filename_check (vector <string> names, const char* aname)
Packit 0d464f
{
Packit 0d464f
    string bname(aname);
Packit 0d464f
    for (size_t i = 0; i < names.size(); i++)
Packit 0d464f
    {
Packit 0d464f
        if (bname.compare (names[i]) == 0)
Packit 0d464f
        {
Packit 0d464f
            cerr << "\n" << "ERROR: "
Packit 0d464f
            "input and output file names cannot be the same." << endl;
Packit 0d464f
            exit (1);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
convert(vector <const char*> in,
Packit 0d464f
        vector<const char *> views,
Packit 0d464f
        const char* outname,
Packit 0d464f
        bool override)
Packit 0d464f
{
Packit 0d464f
    if(in.size()!=1)
Packit 0d464f
    {
Packit 0d464f
        cerr <<"\n" << "ERROR: " 
Packit 0d464f
        "can only convert one file at once - use 'combine' mode for multiple files" << endl;
Packit 0d464f
        exit(1);
Packit 0d464f
    }
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        MultiPartInputFile infile(in[0]);
Packit 0d464f
        
Packit 0d464f
        if(infile.parts() != 1)
Packit 0d464f
        {
Packit 0d464f
            cerr <<"\n" << "ERROR: " 
Packit 0d464f
            "can only convert single part EXRs to multipart EXR-2.0 files: use 'split' mode instead" << endl;
Packit 0d464f
            exit(1);
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        vector<MultiViewChannelName> input_channels;
Packit 0d464f
        
Packit 0d464f
        string hero;
Packit 0d464f
        if(hasMultiView(infile.header(0)))
Packit 0d464f
        {
Packit 0d464f
            StringVector h = multiView (infile.header(0));
Packit 0d464f
            if(h.size()>0)
Packit 0d464f
            {
Packit 0d464f
                hero=h[0];
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        // retrieve channel names from input file in view-friendly format
Packit 0d464f
        GetChannelsInMultiPartFile(infile,input_channels);
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        vector< MultiViewChannelName > output_channels = input_channels;
Packit 0d464f
        // remap channels to multiple output parts
Packit 0d464f
        int parts = SplitChannels(output_channels.begin(),output_channels.end(),true,hero);
Packit 0d464f
        
Packit 0d464f
        vector<Header> output_headers(parts);
Packit 0d464f
        vector<FrameBuffer> output_framebuffers(parts);
Packit 0d464f
        FrameBuffer input_framebuffer;
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // make all output headers the same as the input header but 
Packit 0d464f
        // with no channels
Packit 0d464f
        //
Packit 0d464f
        for(int i=0;i
Packit 0d464f
        {
Packit 0d464f
            Header & h = output_headers[i];
Packit 0d464f
            h = infile.header(0);
Packit 0d464f
            if (hasMultiView(h))
Packit 0d464f
                h.erase("multiView");
Packit 0d464f
Packit 0d464f
            string fn, pname;
Packit 0d464f
            int  pnum;
Packit 0d464f
            bool pforce;
Packit 0d464f
            parse_filename(fn, pname, pforce, pnum);
Packit 0d464f
            if (!h.hasName() || pforce)
Packit 0d464f
                h.setName (pname);
Packit 0d464f
Packit 0d464f
            h.channels()=ChannelList();
Packit 0d464f
        }   
Packit 0d464f
Packit 0d464f
        make_unique_names(output_headers);
Packit 0d464f
Packit 0d464f
        const ChannelList & in_chanlist = infile.header(0).channels();
Packit 0d464f
Packit 0d464f
        int channel_count = 0;
Packit 0d464f
        for(ChannelList::ConstIterator i=in_chanlist.begin();i!=in_chanlist.end();++i)
Packit 0d464f
        {
Packit 0d464f
            ++channel_count;
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        Box2i dataWindow = infile.header(0).dataWindow();
Packit 0d464f
        int pixel_count = (dataWindow.size().y+1)*(dataWindow.size().x+1);
Packit 0d464f
        int pixel_width = dataWindow.size().x+1;
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        // offset in pixels between base of array and 0,0
Packit 0d464f
        int pixel_base = dataWindow.min.y*pixel_width+dataWindow.min.x;
Packit 0d464f
Packit 0d464f
        vector< vector<char> > channelstore(channel_count);
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // insert channels into correct header and framebuffers
Packit 0d464f
        //
Packit 0d464f
        for( size_t i=0 ; i
Packit 0d464f
        {
Packit 0d464f
            // read the part we should be writing channel into, insert into header
Packit 0d464f
            int part = output_channels[i].part_number;
Packit 0d464f
            ChannelList::ConstIterator chan = in_chanlist.find(input_channels[i].internal_name);
Packit 0d464f
            Header & h = output_headers[part];
Packit 0d464f
            h.channels().insert(output_channels[i].name,chan.channel());
Packit 0d464f
            
Packit 0d464f
            if( output_channels[i].view!="" )
Packit 0d464f
            {
Packit 0d464f
                h.setView( output_channels[i].view );
Packit 0d464f
            }
Packit 0d464f
            
Packit 0d464f
            // compute size of channel
Packit 0d464f
            size_t samplesize=sizeof(float);
Packit 0d464f
            if(chan.channel().type==HALF)
Packit 0d464f
            {
Packit 0d464f
                samplesize=sizeof(half);
Packit 0d464f
            }
Packit 0d464f
            channelstore[i].resize(samplesize*pixel_count);
Packit 0d464f
            
Packit 0d464f
            output_framebuffers[part].insert(output_channels[i].name,
Packit 0d464f
                                             Slice(chan.channel().type,
Packit 0d464f
                                                   &channelstore[i][0]-pixel_base*samplesize,
Packit 0d464f
                                                   samplesize,
Packit 0d464f
                                                   pixel_width*samplesize));
Packit 0d464f
Packit 0d464f
            input_framebuffer.insert(input_channels[i].internal_name,
Packit 0d464f
                                     Slice(chan.channel().type,
Packit 0d464f
                                           &channelstore[i][0] - pixel_base*samplesize,
Packit 0d464f
                                           samplesize,
Packit 0d464f
                                           pixel_width*samplesize));
Packit 0d464f
                                                    
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // create output file
Packit 0d464f
        //
Packit 0d464f
        MultiPartOutputFile outfile(outname,&output_headers[0],
Packit 0d464f
                                    output_headers.size());
Packit 0d464f
        InputPart inpart(infile,0);
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // read file
Packit 0d464f
        //
Packit 0d464f
        inpart.setFrameBuffer(input_framebuffer);
Packit 0d464f
        inpart.readPixels(dataWindow.min.y,dataWindow.max.y);
Packit 0d464f
        
Packit 0d464f
        //
Packit 0d464f
        // write each part
Packit 0d464f
        //
Packit 0d464f
        
Packit 0d464f
        for(size_t i=0;i
Packit 0d464f
        {
Packit 0d464f
            OutputPart outpart(outfile,i);
Packit 0d464f
            outpart.setFrameBuffer(output_framebuffers[i]);
Packit 0d464f
            outpart.writePixels(dataWindow.max.y+1-dataWindow.min.y);
Packit 0d464f
        }
Packit 0d464f
        
Packit 0d464f
        
Packit 0d464f
    }
Packit 0d464f
    catch (IEX_NAMESPACE::BaseExc &e)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n" << "ERROR:" << endl;
Packit 0d464f
        cerr << e.what() << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
    
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
combine (vector <const char*> in,
Packit 0d464f
         vector<const char *> views,
Packit 0d464f
         const char* outname,
Packit 0d464f
         bool override)
Packit 0d464f
{
Packit 0d464f
    size_t numInputs = in.size();
Packit 0d464f
    int numparts;
Packit 0d464f
    vector<int> partnums;
Packit 0d464f
    vector<MultiPartInputFile *> inputs;
Packit 0d464f
    vector<MultiPartInputFile *> fordelete;
Packit 0d464f
    MultiPartInputFile *infile;
Packit 0d464f
    vector<Header> headers;
Packit 0d464f
    vector<string> fornamecheck;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // parse all inputs
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    // Input format :
Packit 0d464f
    // We support the following syntax for each input
Packit 0d464f
    // <file>[:<partnum>][::<newpartname>]
Packit 0d464f
Packit 0d464f
    for (size_t i = 0 ; i < numInputs; i++)
Packit 0d464f
    {
Packit 0d464f
        string filename (in[i]);
Packit 0d464f
        string partname;
Packit 0d464f
        bool   forcepartname;
Packit 0d464f
        int    partnum;
Packit 0d464f
        parse_filename (filename, partname, forcepartname, partnum);
Packit 0d464f
Packit 0d464f
        if (partnum == -1)
Packit 0d464f
        {
Packit 0d464f
            fornamecheck.push_back (filename);
Packit 0d464f
Packit 0d464f
            try
Packit 0d464f
            {
Packit 0d464f
                infile = new MultiPartInputFile (filename.c_str());
Packit 0d464f
                fordelete.push_back (infile);
Packit 0d464f
                numparts = infile->parts();
Packit 0d464f
Packit 0d464f
                //copy header from all parts of input to our header array
Packit 0d464f
                for (int j = 0; j < numparts; j++)
Packit 0d464f
                {
Packit 0d464f
                    inputs.push_back (infile);
Packit 0d464f
Packit 0d464f
                    Header h = infile->header(j);
Packit 0d464f
                    if (!h.hasName() || forcepartname)
Packit 0d464f
                        h.setName (partname);
Packit 0d464f
Packit 0d464f
                    headers.push_back (h);
Packit 0d464f
Packit 0d464f
                    if( views[i] != NULL )
Packit 0d464f
                        headers[headers.size()-1].setView( views[i] );
Packit 0d464f
Packit 0d464f
                    partnums.push_back (j);
Packit 0d464f
                }
Packit 0d464f
            }
Packit 0d464f
            catch (IEX_NAMESPACE::BaseExc &e)
Packit 0d464f
            {
Packit 0d464f
                cerr << "\n" << "ERROR:" << endl;
Packit 0d464f
                cerr << e.what() << endl;
Packit 0d464f
                exit (1);
Packit 0d464f
            }
Packit 0d464f
        } // no user parts specified
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            fornamecheck.push_back (filename);
Packit 0d464f
Packit 0d464f
            try
Packit 0d464f
            {
Packit 0d464f
                infile = new MultiPartInputFile (filename.c_str());
Packit 0d464f
                fordelete.push_back (infile);
Packit 0d464f
Packit 0d464f
                if (partnum >= infile->parts())
Packit 0d464f
                {
Packit 0d464f
                    cerr << "ERROR: you asked for part " << partnum << " in " << in[i];
Packit 0d464f
                    cerr << ", which only has " << infile->parts() << " parts\n";
Packit 0d464f
                    exit (1);
Packit 0d464f
                }
Packit 0d464f
                //copy header from required part of input to our header array
Packit 0d464f
                inputs.push_back (infile);
Packit 0d464f
Packit 0d464f
                Header h = infile->header(partnum);
Packit 0d464f
                if (!h.hasName() || forcepartname)
Packit 0d464f
                    h.setName (partname);
Packit 0d464f
Packit 0d464f
                headers.push_back (h);
Packit 0d464f
Packit 0d464f
Packit 0d464f
                if( views[i] != NULL )
Packit 0d464f
                     headers[headers.size()-1].setView( views[i] );
Packit 0d464f
Packit 0d464f
                partnums.push_back (partnum);
Packit 0d464f
            }
Packit 0d464f
            catch (IEX_NAMESPACE::BaseExc &e)
Packit 0d464f
            {
Packit 0d464f
                cerr << "\n" << "ERROR:" << endl;
Packit 0d464f
                cerr << e.what()<< endl;
Packit 0d464f
                exit (1);
Packit 0d464f
            }
Packit 0d464f
        } // user parts specified
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    filename_check (fornamecheck, outname);
Packit 0d464f
    //
Packit 0d464f
    // sort out names - make unique
Packit 0d464f
    //
Packit 0d464f
    if (numInputs>1)
Packit 0d464f
    {
Packit 0d464f
        make_unique_names (headers);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // do combine
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    // early bail if need be
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        MultiPartOutputFile temp (outname, &headers[0], headers.size(), override);
Packit 0d464f
    }
Packit 0d464f
    catch (IEX_NAMESPACE::BaseExc &e)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n" << "ERROR: " << e.what() << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
    MultiPartOutputFile out (outname, &headers[0], headers.size(), override);
Packit 0d464f
Packit 0d464f
    for (size_t p = 0 ; p < partnums.size();p++)
Packit 0d464f
    {
Packit 0d464f
        std::string type = headers[p].type();
Packit 0d464f
        if (type == SCANLINEIMAGE)
Packit 0d464f
        {
Packit 0d464f
            cout << "part " << p << ": "<< "scanlineimage" << endl;
Packit 0d464f
            copy_scanline (*inputs[p], out, partnums[p], p);
Packit 0d464f
        }
Packit 0d464f
        else if (type == TILEDIMAGE)
Packit 0d464f
        {
Packit 0d464f
            cout << "part " << p << ": "<< "tiledimage" << endl;
Packit 0d464f
            copy_tile (*inputs[p], out, partnums[p], p);
Packit 0d464f
        }
Packit 0d464f
        else if (type == DEEPSCANLINE)
Packit 0d464f
        {
Packit 0d464f
            cout << "part " << p << ": "<< "deepscanlineimage" << endl;
Packit 0d464f
            copy_scanlinedeep (*inputs[p], out, partnums[p], p);
Packit 0d464f
        }
Packit 0d464f
        else if (type == DEEPTILE)
Packit 0d464f
        {
Packit 0d464f
            cout << "part " << p << ": "<< "deeptile" << endl;
Packit 0d464f
            copy_tiledeep (*inputs[p], out, partnums[p], p);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
Packit 0d464f
    for (size_t k = 0; k < fordelete.size(); k++)
Packit 0d464f
    {
Packit 0d464f
        delete fordelete[k];
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    inputs.clear();
Packit 0d464f
    fordelete.size();
Packit 0d464f
Packit 0d464f
    cout << "\n" << "Combine Success" << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
separate (vector <const char*> in, const char* out, bool override)
Packit 0d464f
{
Packit 0d464f
    if (in.size() > 1)
Packit 0d464f
    {
Packit 0d464f
        cerr << "ERROR: -separate only take one input file\n"
Packit 0d464f
        "syntax: exrmultipart -separate -i infile.exr -o outfileBaseName\n";
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // parse the multipart input
Packit 0d464f
    //
Packit 0d464f
    string filename (in[0]);
Packit 0d464f
    MultiPartInputFile *inputimage;
Packit 0d464f
    int numOutputs;
Packit 0d464f
    vector<string> fornamecheck;
Packit 0d464f
Packit 0d464f
    // add check for existance of the file
Packit 0d464f
    try
Packit 0d464f
    {
Packit 0d464f
        MultiPartInputFile temp (filename.c_str());
Packit 0d464f
    }
Packit 0d464f
    catch (IEX_NAMESPACE::BaseExc &e)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n" << "ERROR: " << e.what() << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    inputimage = new MultiPartInputFile (filename.c_str());
Packit 0d464f
    numOutputs = inputimage->parts();
Packit 0d464f
    cout << "numOutputs: " << numOutputs << endl;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // set outputs names
Packit 0d464f
    //
Packit 0d464f
    for (int p = 0 ; p 
Packit 0d464f
    {
Packit 0d464f
        string outfilename (out);
Packit 0d464f
Packit 0d464f
        //add number to outfilename
Packit 0d464f
        std::ostringstream oss;
Packit 0d464f
        oss << '.' << p + 1;
Packit 0d464f
        outfilename += oss.str();
Packit 0d464f
        outfilename += ".exr";
Packit 0d464f
        cout << "outputfilename: " << outfilename << endl;
Packit 0d464f
        fornamecheck.push_back (outfilename);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    filename_check (fornamecheck, in[0]);
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // separate outputs
Packit 0d464f
    //
Packit 0d464f
    for (int p = 0 ; p < numOutputs; p++)
Packit 0d464f
    {
Packit 0d464f
        Header header = inputimage->header (p);
Packit 0d464f
Packit 0d464f
        MultiPartOutputFile out (fornamecheck[p].c_str(), &header, 1, override);
Packit 0d464f
Packit 0d464f
        std::string type = header.type();
Packit 0d464f
        if (type == "scanlineimage")
Packit 0d464f
        {
Packit 0d464f
            cout << "scanlineimage" << endl;
Packit 0d464f
            copy_scanline (*inputimage, out, p, 0);
Packit 0d464f
        }
Packit 0d464f
        else if (type == "tiledimage")
Packit 0d464f
        {
Packit 0d464f
            cout << "tiledimage" << endl;
Packit 0d464f
            copy_tile (*inputimage, out, p, 0);
Packit 0d464f
        }
Packit 0d464f
        else if (type == "deepscanline")
Packit 0d464f
        {
Packit 0d464f
            cout << "deepscanline" << endl;
Packit 0d464f
            copy_scanlinedeep (*inputimage, out, p, 0);
Packit 0d464f
        }
Packit 0d464f
        else if (type == "deeptile")
Packit 0d464f
        {
Packit 0d464f
            cout << "deeptile" << endl;
Packit 0d464f
            copy_tiledeep (*inputimage, out, p, 0);
Packit 0d464f
        }
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    delete inputimage;
Packit 0d464f
    cout << "\n" << "Seperate Success" << endl;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
usageMessage (const char argv[])
Packit 0d464f
{
Packit 0d464f
    cout << argv << " handles the combining and splitting of multipart data\n";
Packit 0d464f
    cout << "\n" << "Usage: "
Packit 0d464f
            "exrmultipart -combine -i input.exr[:partnum][::partname] "
Packit 0d464f
            "[input2.exr[:partnum]][::partname] [...] -o outfile.exr [options]\n";
Packit 0d464f
    cout << "   or: exrmultipart -separate -i infile.exr -o outfileBaseName "
Packit 0d464f
            "[options]\n";
Packit 0d464f
    cout << "   or: exrmultipart -convert -i infile.exr -o outfile.exr "
Packit 0d464f
            "[options]\n";
Packit 0d464f
            cout << "\n" << "Options:\n";
Packit 0d464f
    cout << "-override [0/1]      0-do not override conflicting shared "
Packit 0d464f
            "attributes [default]\n"
Packit 0d464f
            "                     1-override conflicting shared attributes\n";
Packit 0d464f
Packit 0d464f
    cout << "-view name           (after specifying -i) "
Packit 0d464f
            "assign following inputs to view 'name'\n";
Packit 0d464f
    exit (1);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
main (int argc, char * argv[])
Packit 0d464f
{
Packit 0d464f
    if (argc < 6)
Packit 0d464f
    {
Packit 0d464f
        usageMessage (argv[0]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    vector <const char*> inFiles;
Packit 0d464f
    vector <const char*> views;
Packit 0d464f
    const char* view = 0;
Packit 0d464f
    const char *outFile = 0;
Packit 0d464f
    bool override = false;
Packit 0d464f
Packit 0d464f
    int i = 1;
Packit 0d464f
    int mode = 0; // 0-do not read input, 1-infiles, 2-outfile, 3-override, 4-view
Packit 0d464f
Packit 0d464f
    while (i < argc)
Packit 0d464f
    {
Packit 0d464f
        if (!strcmp (argv[i], "-h"))
Packit 0d464f
        {
Packit 0d464f
            usageMessage (argv[0]);
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        if (!strcmp (argv[i], "-i"))
Packit 0d464f
        {
Packit 0d464f
            mode = 1;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-o"))
Packit 0d464f
        {
Packit 0d464f
            mode = 2;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-override"))
Packit 0d464f
        {
Packit 0d464f
            mode = 3;
Packit 0d464f
        }
Packit 0d464f
        else if (!strcmp (argv[i], "-view"))
Packit 0d464f
        {
Packit 0d464f
            if(mode !=1 )
Packit 0d464f
            {
Packit 0d464f
                usageMessage (argv[0]);
Packit 0d464f
                return 1;
Packit 0d464f
            }
Packit 0d464f
            mode = 4;
Packit 0d464f
        }
Packit 0d464f
        else
Packit 0d464f
        {
Packit 0d464f
            switch (mode)
Packit 0d464f
            {
Packit 0d464f
                case 1:
Packit 0d464f
                    inFiles.push_back (argv[i]);
Packit 0d464f
                    views.push_back (view);
Packit 0d464f
                    break;
Packit 0d464f
                case 2: outFile = argv[i];
Packit 0d464f
                    break;
Packit 0d464f
                case 3: override = atoi (argv[i]);
Packit 0d464f
                    break;
Packit 0d464f
                case 4: view = argv[i];
Packit 0d464f
                    mode=1;
Packit 0d464f
                    break;
Packit 0d464f
            }
Packit 0d464f
        }
Packit 0d464f
        i++;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    // check input and output files found or not
Packit 0d464f
    if (inFiles.size() == 0)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n" << "ERROR: found no input files" << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << "input:" << endl;
Packit 0d464f
    for (size_t i = 0; i < inFiles.size(); i++)
Packit 0d464f
    {
Packit 0d464f
        cout << "      " << inFiles[i];
Packit 0d464f
        if(views[i]) cout << " in view " << views[i];
Packit 0d464f
        cout << endl;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (!outFile)
Packit 0d464f
    {
Packit 0d464f
        cerr << "\n"<<"ERROR: found no output file" << endl;
Packit 0d464f
        exit (1);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    cout << "output:\n      " << outFile << endl;
Packit 0d464f
    cout << "override:" << override << "\n" << endl;
Packit 0d464f
Packit 0d464f
Packit 0d464f
    if (!strcmp (argv[1], "-combine"))
Packit 0d464f
    {
Packit 0d464f
        cout << "-combine multipart input " << endl;
Packit 0d464f
        combine (inFiles, views, outFile, override);
Packit 0d464f
    }
Packit 0d464f
    else if (!strcmp(argv[1], "-separate"))
Packit 0d464f
    {
Packit 0d464f
        cout << "-separate multipart input " << endl;
Packit 0d464f
        separate (inFiles, outFile, override);
Packit 0d464f
    }
Packit 0d464f
    else if(!strcmp(argv[1],"-convert"))
Packit 0d464f
    {
Packit 0d464f
        cout << "-convert input to EXR2 multipart" << endl;
Packit 0d464f
        convert (inFiles, views, outFile, override);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        usageMessage (argv[0]);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    return 0;
Packit 0d464f
}
Packit 0d464f