Blame IlmImf/ImfMultiPartOutputFile.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2011, Industrial Light & Magic, a division of Lucas
Packit Service 6754ca
// Digital Ltd. LLC
Packit Service 6754ca
//
Packit Service 6754ca
// All rights reserved.
Packit Service 6754ca
//
Packit Service 6754ca
// Redistribution and use in source and binary forms, with or without
Packit Service 6754ca
// modification, are permitted provided that the following conditions are
Packit Service 6754ca
// met:
Packit Service 6754ca
// *       Redistributions of source code must retain the above copyright
Packit Service 6754ca
// notice, this list of conditions and the following disclaimer.
Packit Service 6754ca
// *       Redistributions in binary form must reproduce the above
Packit Service 6754ca
// copyright notice, this list of conditions and the following disclaimer
Packit Service 6754ca
// in the documentation and/or other materials provided with the
Packit Service 6754ca
// distribution.
Packit Service 6754ca
// *       Neither the name of Industrial Light & Magic nor the names of
Packit Service 6754ca
// its contributors may be used to endorse or promote products derived
Packit Service 6754ca
// from this software without specific prior written permission.
Packit Service 6754ca
//
Packit Service 6754ca
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6754ca
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 6754ca
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 6754ca
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 6754ca
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 6754ca
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 6754ca
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 6754ca
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 6754ca
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 6754ca
//
Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
Packit Service 6754ca
#include "ImfMultiPartOutputFile.h"
Packit Service 6754ca
#include "ImfBoxAttribute.h"
Packit Service 6754ca
#include "ImfFloatAttribute.h"
Packit Service 6754ca
#include "ImfTimeCodeAttribute.h"
Packit Service 6754ca
#include "ImfChromaticitiesAttribute.h"
Packit Service 6754ca
#include "ImfOutputPartData.h"
Packit Service 6754ca
#include "ImfPartType.h"
Packit Service 6754ca
#include "ImfOutputFile.h"
Packit Service 6754ca
#include "ImfTiledOutputFile.h"
Packit Service 6754ca
#include "ImfThreading.h"
Packit Service 6754ca
#include "IlmThreadMutex.h"
Packit Service 6754ca
#include "ImfMisc.h"
Packit Service 6754ca
#include "ImfStdIO.h"
Packit Service 6754ca
#include "ImfDeepScanLineOutputFile.h"
Packit Service 6754ca
#include "ImfDeepTiledOutputFile.h"
Packit Service 6754ca
#include "ImfOutputStreamMutex.h"
Packit Service 6754ca
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
#include <Iex.h>
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
#include <set>
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
Packit Service 6754ca
using IMATH_NAMESPACE::Box2i;
Packit Service 6754ca
using ILMTHREAD_NAMESPACE::Lock;
Packit Service 6754ca
    
Packit Service 6754ca
Packit Service 6754ca
using std::vector;
Packit Service 6754ca
using std::map;
Packit Service 6754ca
using std::set;
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
struct MultiPartOutputFile::Data: public OutputStreamMutex
Packit Service 6754ca
{
Packit Service 6754ca
        vector<OutputPartData*>         parts;        // Contains data to initialize Output files.
Packit Service 6754ca
        bool                            deleteStream; // If we should delete the stream when destruction.
Packit Service 6754ca
        int                             numThreads;   // The number of threads.
Packit Service 6754ca
        std::map<int, GenericOutputFile*>    _outputFiles;
Packit Service 6754ca
        std::vector<Header>                  _headers;
Packit Service 6754ca
        
Packit Service 6754ca
        
Packit Service 6754ca
        void                    headerNameUniquenessCheck (const std::vector<Header> &headers);
Packit Service 6754ca
        
Packit Service 6754ca
        void                    writeHeadersToFile (const std::vector<Header> &headers); 
Packit Service 6754ca
        
Packit Service 6754ca
        void                    writeChunkTableOffsets (std::vector<OutputPartData*> &parts;;
Packit Service 6754ca
        
Packit Service 6754ca
        
Packit Service 6754ca
        //-------------------------------------
Packit Service 6754ca
        // ensure that _headers is valid: called by constructors
Packit Service 6754ca
        //-------------------------------------
Packit Service 6754ca
        void                    do_header_sanity_checks(bool overrideSharedAttributes);
Packit Service 6754ca
        
Packit Service 6754ca
        // ------------------------------------------------
Packit Service 6754ca
        // Given a source header, we copy over all the 'shared attributes' to
Packit Service 6754ca
        // the destination header and remove any conflicting ones.
Packit Service 6754ca
        // ------------------------------------------------
Packit Service 6754ca
        void                    overrideSharedAttributesValues (const Header & src,
Packit Service 6754ca
                                                                Header & dst);
Packit Service 6754ca
                                                                
Packit Service 6754ca
        // ------------------------------------------------
Packit Service 6754ca
        // Given a source header, we check the destination header for any
Packit Service 6754ca
        // attributes that are part of the shared attribute set. For attributes
Packit Service 6754ca
        // present in both we check the values. For attribute present in 
Packit Service 6754ca
        // destination but absent in source we return false.
Packit Service 6754ca
        // For attributes present in src but missing from dst we return false
Packit Service 6754ca
        // and add the attribute to dst.
Packit Service 6754ca
        // We return false for all other cases.
Packit Service 6754ca
        // If we return true then we also populate the conflictingAttributes
Packit Service 6754ca
        // vector with the names of the attributes that failed the above.
Packit Service 6754ca
        // ------------------------------------------------
Packit Service 6754ca
        bool                    checkSharedAttributesValues (const Header & src,
Packit Service 6754ca
                                                             const Header & dst, 
Packit Service 6754ca
                                                             std::vector<std::string> & conflictingAttributes) const;
Packit Service 6754ca
        Data (bool deleteStream, int numThreads):
Packit Service 6754ca
            OutputStreamMutex(),
Packit Service 6754ca
            deleteStream (deleteStream),
Packit Service 6754ca
            numThreads (numThreads)
Packit Service 6754ca
        {
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
Packit Service 6754ca
        ~Data()
Packit Service 6754ca
        {
Packit Service 6754ca
            if (deleteStream) delete os;
Packit Service 6754ca
Packit Service 6754ca
            for (size_t i = 0; i < parts.size(); i++)
Packit Service 6754ca
                delete parts[i];
Packit Service 6754ca
        }
Packit Service 6754ca
};
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
MultiPartOutputFile::Data::do_header_sanity_checks(bool overrideSharedAttributes)
Packit Service 6754ca
{
Packit Service 6754ca
    size_t parts = _headers.size();
Packit Service 6754ca
    if (parts == 0) 
Packit Service 6754ca
        throw IEX_NAMESPACE::ArgExc ("Empty header list.");
Packit Service 6754ca
    
Packit Service 6754ca
    bool isMultiPart = (parts > 1); 
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Do part 0 checks first.
Packit Service 6754ca
    //
Packit Service 6754ca
    
Packit Service 6754ca
    _headers[0].sanityCheck (_headers[0].hasTileDescription(), isMultiPart);
Packit Service 6754ca
        
Packit Service 6754ca
    
Packit Service 6754ca
    if (isMultiPart)
Packit Service 6754ca
    {
Packit Service 6754ca
        // multipart files must contain a chunkCount attribute
Packit Service 6754ca
        _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0],true));
Packit Service 6754ca
        
Packit Service 6754ca
        for (size_t i = 1; i < parts; i++)
Packit Service 6754ca
        {
Packit Service 6754ca
            if (_headers[i].hasType() == false)
Packit Service 6754ca
                throw IEX_NAMESPACE::ArgExc ("Every header in a multipart file should have a type");
Packit Service 6754ca
            
Packit Service 6754ca
            
Packit Service 6754ca
            _headers[i].setChunkCount(getChunkOffsetTableSize(_headers[i],true));
Packit Service 6754ca
            _headers[i].sanityCheck (_headers[i].hasTileDescription(), isMultiPart);
Packit Service 6754ca
            
Packit Service 6754ca
            
Packit Service 6754ca
            if (overrideSharedAttributes)
Packit Service 6754ca
                overrideSharedAttributesValues(_headers[0],_headers[i]);
Packit Service 6754ca
            else
Packit Service 6754ca
            {
Packit Service 6754ca
                std::vector<std::string> conflictingAttributes;
Packit Service 6754ca
                bool valid =checkSharedAttributesValues (_headers[0],
Packit Service 6754ca
                                                         _headers[i], 
Packit Service 6754ca
                                                         conflictingAttributes);
Packit Service 6754ca
                if (valid)
Packit Service 6754ca
                {
Packit Service 6754ca
                    string excMsg("Conflicting attributes found for header :: ");
Packit Service 6754ca
                    excMsg += _headers[i].name();
Packit Service 6754ca
                    for (size_t i=0; i
Packit Service 6754ca
                        excMsg += " '" + conflictingAttributes[i] + "' ";
Packit Service 6754ca
                                                             
Packit Service 6754ca
                    THROW (IEX_NAMESPACE::ArgExc, excMsg);
Packit Service 6754ca
                }
Packit Service 6754ca
            }
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
        headerNameUniquenessCheck(_headers);
Packit Service 6754ca
        
Packit Service 6754ca
    }else{
Packit Service 6754ca
        
Packit Service 6754ca
        // add chunk count offset to single part data (if not an image)
Packit Service 6754ca
        
Packit Service 6754ca
        if (_headers[0].hasType() && isImage(_headers[0].type()) == false)
Packit Service 6754ca
        {
Packit Service 6754ca
            _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0],true));
Packit Service 6754ca
        }
Packit Service 6754ca
        
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
    
Packit Service 6754ca
MultiPartOutputFile::MultiPartOutputFile (const char fileName[],
Packit Service 6754ca
                                          const Header * headers,
Packit Service 6754ca
                                          int parts,
Packit Service 6754ca
                                          bool overrideSharedAttributes,
Packit Service 6754ca
                                          int numThreads)
Packit Service 6754ca
:
Packit Service 6754ca
    _data (new Data (true, numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    // grab headers
Packit Service 6754ca
    _data->_headers.resize(parts);
Packit Service 6754ca
    
Packit Service 6754ca
    for(int i=0;i
Packit Service 6754ca
    {
Packit Service 6754ca
       _data->_headers[i]=headers[i];
Packit Service 6754ca
    }
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
  
Packit Service 6754ca
         _data->do_header_sanity_checks(overrideSharedAttributes);
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Build parts and write headers and offset tables to file.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        _data->os = new StdOFStream (fileName);
Packit Service 6754ca
        for (size_t i = 0; i < _data->_headers.size(); i++)
Packit Service 6754ca
            _data->parts.push_back( new OutputPartData(_data, _data->_headers[i], i, numThreads, parts>1 ) );
Packit Service 6754ca
Packit Service 6754ca
        writeMagicNumberAndVersionField(*_data->os, &_data->_headers[0],_data->_headers.size());
Packit Service 6754ca
        _data->writeHeadersToFile(_data->_headers);
Packit Service 6754ca
        _data->writeChunkTableOffsets(_data->parts);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot open image file "
Packit Service 6754ca
                        "\"" << fileName << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
MultiPartOutputFile::MultiPartOutputFile(OStream& os, 
Packit Service 6754ca
                                         const Header* headers, 
Packit Service 6754ca
                                         int parts, 
Packit Service 6754ca
                                         bool overrideSharedAttributes, 
Packit Service 6754ca
                                         int numThreads): 
Packit Service 6754ca
                                         _data(new Data(false,numThreads))
Packit Service 6754ca
{
Packit Service 6754ca
    // grab headers
Packit Service 6754ca
    _data->_headers.resize(parts);
Packit Service 6754ca
    _data->os=&os;
Packit Service 6754ca
    
Packit Service 6754ca
    for(int i=0;i
Packit Service 6754ca
    {
Packit Service 6754ca
        _data->_headers[i]=headers[i];
Packit Service 6754ca
    }
Packit Service 6754ca
    try
Packit Service 6754ca
    {
Packit Service 6754ca
        
Packit Service 6754ca
        _data->do_header_sanity_checks(overrideSharedAttributes);
Packit Service 6754ca
        
Packit Service 6754ca
        //
Packit Service 6754ca
        // Build parts and write headers and offset tables to file.
Packit Service 6754ca
        //
Packit Service 6754ca
        
Packit Service 6754ca
        for (size_t i = 0; i < _data->_headers.size(); i++)
Packit Service 6754ca
            _data->parts.push_back( new OutputPartData(_data, _data->_headers[i], i, numThreads, parts>1 ) );
Packit Service 6754ca
        
Packit Service 6754ca
        writeMagicNumberAndVersionField(*_data->os, &_data->_headers[0],_data->_headers.size());
Packit Service 6754ca
        _data->writeHeadersToFile(_data->_headers);
Packit Service 6754ca
        _data->writeChunkTableOffsets(_data->parts);
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (IEX_NAMESPACE::BaseExc &e)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        
Packit Service 6754ca
        REPLACE_EXC (e, "Cannot open image stream "
Packit Service 6754ca
        "\"" << os.fileName() << "\". " << e);
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
    catch (...)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete _data;
Packit Service 6754ca
        throw;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
const Header &
Packit Service 6754ca
MultiPartOutputFile::header(int n) const
Packit Service 6754ca
{
Packit Service 6754ca
    if(n<0 || n>int(_data->_headers.size()))
Packit Service 6754ca
    {
Packit Service 6754ca
        throw IEX_NAMESPACE::ArgExc("MultiPartOutputFile::header called with invalid part number");
Packit Service 6754ca
    }
Packit Service 6754ca
    return _data->_headers[n];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
MultiPartOutputFile::parts() const
Packit Service 6754ca
{
Packit Service 6754ca
   return _data->_headers.size();
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
MultiPartOutputFile::~MultiPartOutputFile ()
Packit Service 6754ca
{
Packit Service 6754ca
    for (map<int, GenericOutputFile*>::iterator it = _data->_outputFiles.begin();
Packit Service 6754ca
         it != _data->_outputFiles.end(); it++)
Packit Service 6754ca
    {
Packit Service 6754ca
        delete it->second;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    delete _data;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
template <class T>
Packit Service 6754ca
T*
Packit Service 6754ca
MultiPartOutputFile::getOutputPart(int partNumber)
Packit Service 6754ca
{
Packit Service 6754ca
    Lock lock(*_data);
Packit Service 6754ca
    if (_data->_outputFiles.find(partNumber) == _data->_outputFiles.end())
Packit Service 6754ca
    {
Packit Service 6754ca
        T* file = new T(_data->parts[partNumber]);
Packit Service 6754ca
        _data->_outputFiles.insert(std::make_pair(partNumber, (GenericOutputFile*) file));
Packit Service 6754ca
        return file;
Packit Service 6754ca
    }
Packit Service 6754ca
    else return (T*) _data->_outputFiles[partNumber];
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
// instance above function for all four types
Packit Service 6754ca
template OutputFile* MultiPartOutputFile::getOutputPart<OutputFile>(int);
Packit Service 6754ca
template TiledOutputFile * MultiPartOutputFile::getOutputPart<TiledOutputFile>(int);
Packit Service 6754ca
template DeepScanLineOutputFile * MultiPartOutputFile::getOutputPart<DeepScanLineOutputFile> (int);
Packit Service 6754ca
template DeepTiledOutputFile * MultiPartOutputFile::getOutputPart<DeepTiledOutputFile> (int);
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void 
Packit Service 6754ca
MultiPartOutputFile::Data::overrideSharedAttributesValues(const Header & src, Header & dst)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Display Window
Packit Service 6754ca
    //
Packit Service 6754ca
    const Box2iAttribute * displayWindow = 
Packit Service 6754ca
    src.findTypedAttribute<Box2iAttribute> ("displayWindow");
Packit Service 6754ca
    
Packit Service 6754ca
    if (displayWindow)
Packit Service 6754ca
        dst.insert ("displayWindow", *displayWindow);
Packit Service 6754ca
    else 
Packit Service 6754ca
        dst.erase ("displayWindow");
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Pixel Aspect Ratio
Packit Service 6754ca
    //
Packit Service 6754ca
    const FloatAttribute * pixelAspectRatio = 
Packit Service 6754ca
    src.findTypedAttribute<FloatAttribute> ("pixelAspectRatio");
Packit Service 6754ca
    
Packit Service 6754ca
    if (pixelAspectRatio)
Packit Service 6754ca
        dst.insert ("pixelAspectRatio", *pixelAspectRatio);
Packit Service 6754ca
    else 
Packit Service 6754ca
        dst.erase ("pixelAspectRatio");
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Timecode
Packit Service 6754ca
    //
Packit Service 6754ca
    const TimeCodeAttribute * timeCode = 
Packit Service 6754ca
    src.findTypedAttribute<TimeCodeAttribute> ("timecode");
Packit Service 6754ca
    
Packit Service 6754ca
    if (timeCode)
Packit Service 6754ca
        dst.insert ("timecode", *timeCode);
Packit Service 6754ca
    else 
Packit Service 6754ca
        dst.erase ("timecode");
Packit Service 6754ca
    
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Chromaticities
Packit Service 6754ca
    //
Packit Service 6754ca
    const ChromaticitiesAttribute * chromaticities = 
Packit Service 6754ca
    src.findTypedAttribute<ChromaticitiesAttribute> ("chromaticities");
Packit Service 6754ca
    
Packit Service 6754ca
    if (chromaticities)
Packit Service 6754ca
        dst.insert ("chromaticities", *chromaticities);
Packit Service 6754ca
    else 
Packit Service 6754ca
        dst.erase ("chromaticities");
Packit Service 6754ca
    
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
bool 
Packit Service 6754ca
MultiPartOutputFile::Data::checkSharedAttributesValues(const Header & src,
Packit Service 6754ca
        const Header & dst,
Packit Service 6754ca
        vector<string> & conflictingAttributes) const
Packit Service 6754ca
{
Packit Service 6754ca
    bool conflict = false;
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Display Window
Packit Service 6754ca
    //
Packit Service 6754ca
    if (src.displayWindow() != dst.displayWindow())
Packit Service 6754ca
    {
Packit Service 6754ca
        conflict = true;
Packit Service 6754ca
        conflictingAttributes.push_back ("displayWindow");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Pixel Aspect Ratio
Packit Service 6754ca
    //
Packit Service 6754ca
    if (src.pixelAspectRatio() != dst.pixelAspectRatio())
Packit Service 6754ca
    {
Packit Service 6754ca
        conflict = true;
Packit Service 6754ca
        conflictingAttributes.push_back ("pixelAspectRatio");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Timecode
Packit Service 6754ca
    //
Packit Service 6754ca
    const TimeCodeAttribute * srcTimeCode = src.findTypedAttribute<
Packit Service 6754ca
                                            TimeCodeAttribute> (TimeCodeAttribute::staticTypeName());
Packit Service 6754ca
    const TimeCodeAttribute * dstTimeCode = dst.findTypedAttribute<
Packit Service 6754ca
                                            TimeCodeAttribute> (TimeCodeAttribute::staticTypeName());
Packit Service 6754ca
Packit Service 6754ca
    if (dstTimeCode)
Packit Service 6754ca
    {
Packit Service 6754ca
        if ((srcTimeCode && (srcTimeCode->value() != dstTimeCode->value())) ||
Packit Service 6754ca
                (!srcTimeCode))
Packit Service 6754ca
        {
Packit Service 6754ca
            conflict = true;
Packit Service 6754ca
            conflictingAttributes.push_back (TimeCodeAttribute::staticTypeName());
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Chromaticities
Packit Service 6754ca
    //
Packit Service 6754ca
    const ChromaticitiesAttribute * srcChrom =  src.findTypedAttribute<
Packit Service 6754ca
            ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName());
Packit Service 6754ca
    const ChromaticitiesAttribute * dstChrom =  dst.findTypedAttribute<
Packit Service 6754ca
            ChromaticitiesAttribute> (ChromaticitiesAttribute::staticTypeName());
Packit Service 6754ca
Packit Service 6754ca
    if (dstChrom)
Packit Service 6754ca
    {
Packit Service 6754ca
        if ( (srcChrom && (srcChrom->value() != dstChrom->value())) ||
Packit Service 6754ca
                (!srcChrom))
Packit Service 6754ca
        {
Packit Service 6754ca
            conflict = true;
Packit Service 6754ca
            conflictingAttributes.push_back (ChromaticitiesAttribute::staticTypeName());
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return conflict;
Packit Service 6754ca
}
Packit Service 6754ca
                                                      
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
MultiPartOutputFile::Data::headerNameUniquenessCheck (const vector<Header> &headers)
Packit Service 6754ca
{
Packit Service 6754ca
    set<string> names;
Packit Service 6754ca
    for (size_t i = 0; i < headers.size(); i++)
Packit Service 6754ca
    {
Packit Service 6754ca
        if (names.find(headers[i].name()) != names.end())
Packit Service 6754ca
            throw IEX_NAMESPACE::ArgExc ("Each part should have a unique name.");
Packit Service 6754ca
        names.insert(headers[i].name());
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
MultiPartOutputFile::Data::writeHeadersToFile (const vector<Header> &headers)
Packit Service 6754ca
{
Packit Service 6754ca
    for (size_t i = 0; i < headers.size(); i++)
Packit Service 6754ca
    {
Packit Service 6754ca
Packit Service 6754ca
        // (TODO) consider deep files' preview images here.
Packit Service 6754ca
        if (headers[i].type() == TILEDIMAGE)
Packit Service 6754ca
            parts[i]->previewPosition = headers[i].writeTo(*os, true);
Packit Service 6754ca
        else
Packit Service 6754ca
            parts[i]->previewPosition = headers[i].writeTo(*os, false);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // If a multipart file, write zero-length attribute name to mark the end of all headers.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    if (headers.size() !=1)
Packit Service 6754ca
         OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*os, "");
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
MultiPartOutputFile::Data::writeChunkTableOffsets (vector<OutputPartData*> &parts)
Packit Service 6754ca
{
Packit Service 6754ca
    for (size_t i = 0; i < parts.size(); i++)
Packit Service 6754ca
    {
Packit Service 6754ca
        int chunkTableSize = getChunkOffsetTableSize(parts[i]->header,false);
Packit Service 6754ca
Packit Service 6754ca
        Int64 pos = os->tellp();
Packit Service 6754ca
Packit Service 6754ca
        if (pos == -1)
Packit Service 6754ca
            IEX_NAMESPACE::throwErrnoExc ("Cannot determine current file position (%T).");
Packit Service 6754ca
Packit Service 6754ca
        parts[i]->chunkOffsetTablePosition = os->tellp();
Packit Service 6754ca
Packit Service 6754ca
        //
Packit Service 6754ca
        // Fill in empty data for now. We'll write actual offsets during destruction.
Packit Service 6754ca
        //
Packit Service 6754ca
Packit Service 6754ca
        for (int j = 0; j < chunkTableSize; j++)
Packit Service 6754ca
        {
Packit Service 6754ca
            Int64 empty = 0;
Packit Service 6754ca
            OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::write <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (*os, empty);
Packit Service 6754ca
        }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT