Пример #1
0
bool ImageIO::writeImage(QVector<float> &pixels, const QString &filePath, const LayerDesc &desc, int width, int height)
{
    try
    {
        Imf::Header header (width, height);
        Imf::FrameBuffer frameBuffer;

        for (int chan = 0; chan < desc.numChannels(); chan++) {
            QString chan_name = QString("%1.%2").arg(desc._layer_name).arg(desc._channels[chan]);
            header.channels().insert(qPrintable(chan_name), Imf::Channel(Imf::FLOAT));
            frameBuffer.insert(qPrintable(chan_name), Imf::Slice(Imf::FLOAT, (char *) pixels.data() + chan*sizeof(float), sizeof(float)*desc.numChannels(), sizeof(float)*width*desc.numChannels()));
        }

        Imf::OutputFile file(qPrintable(remapFilePath(filePath)), header);
        file.setFrameBuffer(frameBuffer);

        file.writePixels(height);
    }
    catch (const std::exception &e)
    {
        qWarning() << e.what();
        return false;
    }
    return true;
}
Пример #2
0
void write_half_exr( const boost::filesystem::path& p, Imf::Header& header,
			    const image::const_image_view_t& view, bool write_alpha)
{
    boost::gil::rgba16f_image_t img( view.width(), view.height());
    boost::gil::copy_and_convert_pixels( view, boost::gil::view( img));

    header.channels().insert( "R", Imf::HALF);
    header.channels().insert( "G", Imf::HALF);
    header.channels().insert( "B", Imf::HALF);

    if( write_alpha)
        header.channels().insert( "A", Imf::HALF);

    Imf::FrameBuffer frameBuffer;

    char *ptr = (char *) boost::gil::interleaved_view_get_raw_data( boost::gil::view( img));
    std::size_t xstride = 4 * sizeof(half);
    std::size_t ystride = xstride * img.width();

    frameBuffer.insert( "R", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);
    frameBuffer.insert( "G", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);
    frameBuffer.insert( "B", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);

    if( write_alpha)
        frameBuffer.insert( "A", Imf::Slice( Imf::HALF, ptr, xstride, ystride));

    Imf::OutputFile out_file( p.external_file_string().c_str(), header);
    out_file.setFrameBuffer( frameBuffer);
    out_file.writePixels( img.height());
}
Пример #3
0
 fcExrTaskData(const char *p, int w, int h, fcExrCompression compression)
     : path(p), width(w), height(h), header(w, h)
 {
     switch (compression) {
     case fcExrCompression::None:    header.compression() = Imf::NO_COMPRESSION; break;
     case fcExrCompression::RLE:     header.compression() = Imf::RLE_COMPRESSION; break;
     case fcExrCompression::ZipS:    header.compression() = Imf::ZIPS_COMPRESSION; break;
     case fcExrCompression::Zip:     header.compression() = Imf::ZIP_COMPRESSION; break;
     case fcExrCompression::PIZ:     header.compression() = Imf::PIZ_COMPRESSION; break;
     }
 }
Пример #4
0
static void headerToCompoundData( const Imf::Header &header, CompoundData *blindData )
{
	for ( Imf::Header::ConstIterator attrIt = header.begin(); attrIt != header.end(); attrIt++ )
	{
		std::string name = attrIt.name();
		DataPtr data = attributeToData( attrIt.attribute() );
		if ( data )
		{
			addHeaderAttribute( name, data, blindData );
		}
	}
}
Пример #5
0
void SaveExr(const Image<unsigned char>& image_in, const pangolin::PixelFormat& fmt, const std::string& filename, bool top_line_first)
{
    PANGOLIN_UNUSED(image_in);
    PANGOLIN_UNUSED(fmt);
    PANGOLIN_UNUSED(filename);
    PANGOLIN_UNUSED(top_line_first);

#ifdef HAVE_OPENEXR
    ManagedImage<unsigned char> flip_image;
    Image<unsigned char> image;

    if(top_line_first) {
        image = image_in;
    }else{
        flip_image.Reinitialise(image_in.pitch,image_in.h);
        for(size_t y=0; y<image_in.h; ++y) {
            std::memcpy(flip_image.RowPtr(y), image_in.RowPtr(y), image_in.pitch);
        }
        image = flip_image;
    }


    Imf::Header header (image.w, image.h);
    SetOpenEXRChannels(header.channels(), fmt);

    Imf::OutputFile file (filename.c_str(), header);
    Imf::FrameBuffer frameBuffer;

    int ch=0;
    size_t ch_bits = 0;
    for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
    {
        frameBuffer.insert(
            it.name(),
            Imf::Slice(
                it.channel().type,
                (char*)image.ptr + ch_bits/8,
                fmt.channel_bits[ch]/8,
                image.pitch
            )
        );

        ch_bits += fmt.channel_bits[ch++];
    }

    file.setFrameBuffer(frameBuffer);
    file.writePixels(image.h);

#else
    throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
#endif // HAVE_OPENEXR
}
Пример #6
0
void SaveExr(const Image<unsigned char>& image_in, const pangolin::VideoPixelFormat& fmt, const std::string& filename, bool top_line_first)
{
#ifdef HAVE_OPENEXR
    Image<unsigned char> image;

    if(top_line_first) {
        image = image_in;
    }else{
        image.Alloc(image_in.w,image_in.h,image_in.pitch);
        for(size_t y=0; y<image_in.h; ++y) {
            std::memcpy(image.ptr + y*image.pitch, image_in.ptr + (image_in.h-y-1)*image_in.pitch, image.pitch);
        }
    }


    Imf::Header header (image.w, image.h);
    SetOpenEXRChannels(header.channels(), fmt);

    Imf::OutputFile file (filename.c_str(), header);
    Imf::FrameBuffer frameBuffer;

    int ch=0;
    size_t ch_bits = 0;
    for(Imf::ChannelList::Iterator it = header.channels().begin(); it != header.channels().end(); ++it)
    {
        frameBuffer.insert(
            it.name(),
            Imf::Slice(
                it.channel().type,
                (char*)image.ptr + ch_bits/8,
                fmt.channel_bits[ch]/8,
                image.pitch
            )
        );

        ch_bits += fmt.channel_bits[ch++];
    }

    file.setFrameBuffer(frameBuffer);
    file.writePixels(image.h);

    if(!top_line_first) {
        image.Dealloc();
    }

#else
    throw std::runtime_error("EXR Support not enabled. Please rebuild Pangolin.");
#endif // HAVE_OPENEXR
}
Пример #7
0
/** \brief Convert an OpenEXR header to our own header representation.
 *
 * \param exrHeader - input header
 * \param header - output header
 */
void convertHeader(const Imf::Header& exrHeader, CqTexFileHeader& header)
{
	// Set width, height
	const Imath::Box2i& dataBox = exrHeader.dataWindow();
	header.setWidth(dataBox.max.x - dataBox.min.x+1);
	header.setHeight(dataBox.max.y - dataBox.min.y+1);
	// display window
	const Imath::Box2i& displayBox = exrHeader.displayWindow();
	header.set<Attr::DisplayWindow>( SqImageRegion(
				displayBox.max.x - displayBox.min.x,
				displayBox.max.y - displayBox.min.y,
				displayBox.min.x - dataBox.min.x,
				displayBox.min.y - dataBox.min.y) );

	// Set tiling information ?

	// Aspect ratio
	header.set<Attr::PixelAspectRatio>(exrHeader.pixelAspectRatio());

	TqChannelNameMap channelNameMap;
	// Convert channel representation
	const Imf::ChannelList& exrChannels = exrHeader.channels();
	CqChannelList& channels = header.channelList();
	for(Imf::ChannelList::ConstIterator i = exrChannels.begin();
			i != exrChannels.end(); ++i)
	{
		// use lower case names for channels; OpenEXR uses upper case.
		std::string chanName = i.name();
		std::transform(chanName.begin(), chanName.end(), chanName.begin(),
				::tolower);
		channelNameMap[chanName] = i.name();
		channels.addChannel( SqChannelInfo(chanName,
				channelTypeFromExr(i.channel().type)) );
	}
	header.set<Attr::ExrChannelNameMap>(channelNameMap);
	channels.reorderChannels();

	// Set compresssion type
	header.set<Attr::Compression>(exrCompressionToString(exrHeader.compression()));
}
Пример #8
0
void write_half_rgb_exr( Imf::OStream& os, Imf::Header& header, const image::const_image_view_t& view)
{
    boost::gil::rgba16f_image_t img( view.width(), view.height());
    boost::gil::copy_and_convert_pixels( view, boost::gil::view( img));

    header.channels().insert( "R", Imf::HALF);
    header.channels().insert( "G", Imf::HALF);
    header.channels().insert( "B", Imf::HALF);

    Imf::FrameBuffer frameBuffer;

    char *ptr = (char *) boost::gil::interleaved_view_get_raw_data( boost::gil::view( img));
    std::size_t xstride = 4 * sizeof(half);
    std::size_t ystride = xstride * img.width();

    frameBuffer.insert( "R", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);
    frameBuffer.insert( "G", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);
    frameBuffer.insert( "B", Imf::Slice( Imf::HALF, ptr, xstride, ystride)); ptr += sizeof(half);

    Imf::OutputFile out_file( os, header);
    out_file.setFrameBuffer( frameBuffer);
    out_file.writePixels( img.height());
}
Пример #9
0
/**
Set the preview image using the dib embedded thumbnail
*/
static BOOL
SetPreviewImage(FIBITMAP *dib, Imf::Header& header) {
    if(!FreeImage_GetThumbnail(dib)) {
        return FALSE;
    }
    FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib);

    if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 32)) {
        // invalid thumbnail - ignore it
        FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL);
    } else {
        const unsigned thWidth = FreeImage_GetWidth(thumbnail);
        const unsigned thHeight = FreeImage_GetHeight(thumbnail);

        Imf::PreviewImage preview(thWidth, thHeight);

        // copy thumbnail to 32-bit RGBA preview image

        const BYTE* src_line = FreeImage_GetScanLine(thumbnail, thHeight - 1);
        Imf::PreviewRgba* dst_line = preview.pixels();
        const unsigned srcPitch = FreeImage_GetPitch(thumbnail);

        for (unsigned y = 0; y < thHeight; y++) {
            const RGBQUAD* src_pixel = (RGBQUAD*)src_line;
            Imf::PreviewRgba* dst_pixel = dst_line;

            for(unsigned x = 0; x < thWidth; x++) {
                dst_pixel->r = src_pixel->rgbRed;
                dst_pixel->g = src_pixel->rgbGreen;
                dst_pixel->b = src_pixel->rgbBlue;
                dst_pixel->a = src_pixel->rgbReserved;

                src_pixel++;
                dst_pixel++;
            }

            src_line -= srcPitch;
            dst_line += thWidth;
        }

        header.setPreviewImage(preview);
    }

    return TRUE;
}
Пример #10
0
void
applyCtlExrToExr
    (Imf::Header inHeader,
     Imf::Header &outHeader,
     const Imf::Array2D<Imf::Rgba> &inPixels,
     Imf::Array2D<Imf::Rgba> &outPixels,
     int w,
     int h,
     const std::vector<std::string> &transformNames,
     const AttrMap &extraAttrs)
{
    //
    // Make sure that the input and output headers contain
    // chromaticities and adoptedNeutral attributes.
    //

    if (!hasChromaticities (inHeader))
	addChromaticities (inHeader, Chromaticities());

    if (!hasAdoptedNeutral (inHeader))
	addAdoptedNeutral (inHeader, chromaticities(inHeader).white);

    if (!hasChromaticities (outHeader))
	addChromaticities (outHeader, chromaticities (inHeader));

    if (!hasAdoptedNeutral (outHeader))
	addAdoptedNeutral (outHeader, adoptedNeutral (inHeader));

    //
    // Add extraAttrs to the input header, possibly overriding
    // the values of existing input header attributes.
    //

    for (AttrMap::const_iterator i = extraAttrs.begin();
	 i != extraAttrs.end();
	 ++i)
    {
	inHeader.insert (i->first.c_str(), *i->second);
    }

    //
    // Initialize an "environment" header with the same data that
    // would be available to rendering transforms in an image viewing
    // program.  This allows transforms to bake color rendering into
    // the output file's pixels.
    //

    Header envHeader;
    initializeEnvHeader (envHeader);

    //
    // Set up input and output FrameBuffer objects for the transforms.
    //

    FrameBuffer inFb;
    initializeFrameBuffer (w, h, inPixels, inFb);

    FrameBuffer outFb;
    initializeFrameBuffer (w, h, outPixels, outFb);

    //
    // Run the CTL transforms
    //

    Box2i transformWindow (V2i (0, 0), V2i (w - 1, h - 1));

    SimdInterpreter interpreter;

    #ifdef CTL_MODULE_BASE_PATH

	//
	// The configuration script has defined a default
	// location for CTL modules.  Include this location
	// in the CTL module search path.
	//

	vector<string> paths = interpreter.modulePaths();
	paths.push_back (CTL_MODULE_BASE_PATH);
	interpreter.setModulePaths (paths);

    #endif

    ImfCtl::applyTransforms (interpreter,
			     transformNames,
			     transformWindow,
			     envHeader,
			     inHeader,
			     inFb,
			     outHeader,
			     outFb);
}
Пример #11
0
bool
OpenEXRInput::seek_subimage (int subimage, int miplevel, ImageSpec &newspec)
{
    if (subimage < 0 || subimage >= m_nsubimages)   // out of range
        return false;

    if (miplevel < 0 || miplevel >= m_nmiplevels)   // out of range
        return false;

    m_subimage = subimage;
    m_miplevel = miplevel;

    if (miplevel == 0 && m_levelmode == Imf::ONE_LEVEL) {
        newspec = m_spec;
        return true;
    }

    // Compute the resolution of the requested mip level.
    int w = m_topwidth, h = m_topheight;
    if (m_levelmode == Imf::MIPMAP_LEVELS) {
        while (miplevel--) {
            if (m_roundingmode == Imf::ROUND_DOWN) {
                w = w / 2;
                h = h / 2;
            } else {
                w = (w + 1) / 2;
                h = (h + 1) / 2;
            }
            w = std::max (1, w);
            h = std::max (1, h);
        }
    } else if (m_levelmode == Imf::RIPMAP_LEVELS) {
        // FIXME
    } else {
        ASSERT(0);
    }

    m_spec.width = w;
    m_spec.height = h;
    // N.B. OpenEXR doesn't support data and display windows per MIPmap
    // level.  So always take from the top level.
    Imath::Box2i datawindow = m_header->dataWindow();
    Imath::Box2i displaywindow = m_header->displayWindow();
    m_spec.x = datawindow.min.x;
    m_spec.y = datawindow.min.y;
    if (miplevel == 0) {
        m_spec.full_x = displaywindow.min.x;
        m_spec.full_y = displaywindow.min.y;
        m_spec.full_width = displaywindow.max.x - displaywindow.min.x + 1;
        m_spec.full_height = displaywindow.max.y - displaywindow.min.y + 1;
    } else {
        m_spec.full_x = m_spec.x;
        m_spec.full_y = m_spec.y;
        m_spec.full_width = m_spec.width;
        m_spec.full_height = m_spec.height;
    }
    if (m_cubeface) {
        m_spec.full_width = w;
        m_spec.full_height = w;
    }
    newspec = m_spec;

    return true;
}
Пример #12
0
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
    const char *channel_name[4] = { "R", "G", "B", "A" };
    BOOL bIsFlipped = FALSE;
    half *halfData = NULL;

    if(!dib || !handle) return FALSE;

    try {
        // check for EXR_LC compression and verify that the format is RGB
        if((flags & EXR_LC) == EXR_LC) {
            FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
            if(((image_type != FIT_RGBF) && (image_type != FIT_RGBAF)) || ((flags & EXR_FLOAT) == EXR_FLOAT)) {
                THROW (Iex::IoExc, "EXR_LC compression is only available with RGB[A]F images");
            }
            if((FreeImage_GetWidth(dib) % 2) || (FreeImage_GetHeight(dib) % 2)) {
                THROW (Iex::IoExc, "EXR_LC compression only works when the width and height are a multiple of 2");
            }
        }

        // wrap the FreeImage IO stream
        C_OStream ostream(io, handle);

        // compression
        Imf::Compression compress;
        if((flags & EXR_NONE) == EXR_NONE) {
            // no compression
            compress = Imf::NO_COMPRESSION;
        } else if((flags & EXR_ZIP) == EXR_ZIP) {
            // zlib compression, in blocks of 16 scan lines
            compress = Imf::ZIP_COMPRESSION;
        } else if((flags & EXR_PIZ) == EXR_PIZ) {
            // piz-based wavelet compression
            compress = Imf::PIZ_COMPRESSION;
        } else if((flags & EXR_PXR24) == EXR_PXR24) {
            // lossy 24-bit float compression
            compress = Imf::PXR24_COMPRESSION;
        } else if((flags & EXR_B44) == EXR_B44) {
            // lossy 44% float compression
            compress = Imf::B44_COMPRESSION;
        } else {
            // default value
            compress = Imf::PIZ_COMPRESSION;
        }

        // create the header
        int width  = FreeImage_GetWidth(dib);
        int height = FreeImage_GetHeight(dib);
        int dx = 0, dy = 0;

        Imath::Box2i dataWindow (Imath::V2i (0, 0), Imath::V2i (width - 1, height - 1));
        Imath::Box2i displayWindow (Imath::V2i (-dx, -dy), Imath::V2i (width - dx - 1, height - dy - 1));

        Imf::Header header = Imf::Header(displayWindow, dataWindow, 1,
                                         Imath::V2f(0,0), 1,
                                         Imf::INCREASING_Y, compress);

        // handle thumbnail
        SetPreviewImage(dib, header);

        // check for EXR_LC compression
        if((flags & EXR_LC) == EXR_LC) {
            return SaveAsEXR_LC(ostream, dib, header, width, height);
        }

        // output pixel type
        Imf::PixelType pixelType;
        if((flags & EXR_FLOAT) == EXR_FLOAT) {
            pixelType = Imf::FLOAT;	// save as float data type
        } else {
            // default value
            pixelType = Imf::HALF;	// save as half data type
        }

        // check the data type and number of channels
        int components = 0;
        FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
        switch(image_type) {
        case FIT_FLOAT:
            components = 1;
            // insert luminance channel
            header.channels().insert ("Y", Imf::Channel(pixelType));
            break;
        case FIT_RGBF:
            components = 3;
            for(int c = 0; c < components; c++) {
                // insert R, G and B channels
                header.channels().insert (channel_name[c], Imf::Channel(pixelType));
            }
            break;
        case FIT_RGBAF:
            components = 4;
            for(int c = 0; c < components; c++) {
                // insert R, G, B and A channels
                header.channels().insert (channel_name[c], Imf::Channel(pixelType));
            }
            break;
        default:
            THROW (Iex::ArgExc, "Cannot save: invalid data type.\nConvert the image to float before saving as OpenEXR.");
        }

        // build a frame buffer (i.e. what we have on input)
        Imf::FrameBuffer frameBuffer;

        BYTE *bits = NULL;	// pointer to our pixel buffer
        size_t bytespp = 0;	// size of our pixel in bytes
        size_t bytespc = 0;	// size of our pixel component in bytes
        unsigned pitch = 0;	// size of our yStride in bytes


        if(pixelType == Imf::HALF) {
            // convert from float to half
            halfData = new(std::nothrow) half[width * height * components];
            if(!halfData) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);

            for(int y = 0; y < height; y++) {
                float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
                half *dst_bits = halfData + y * width * components;
                for(int x = 0; x < width; x++) {
                    for(int c = 0; c < components; c++) {
                        dst_bits[c] = src_bits[c];
                    }
                    src_bits += components;
                    dst_bits += components;
                }
            }
            bits = (BYTE*)halfData;
            bytespc = sizeof(half);
            bytespp = sizeof(half) * components;
            pitch = sizeof(half) * width * components;
        } else if(pixelType == Imf::FLOAT) {
            // invert dib scanlines
            bIsFlipped = FreeImage_FlipVertical(dib);

            bits = FreeImage_GetBits(dib);
            bytespc = sizeof(float);
            bytespp = sizeof(float) * components;
            pitch = FreeImage_GetPitch(dib);
        }

        if(image_type == FIT_FLOAT) {
            frameBuffer.insert ("Y",	// name
                                Imf::Slice (pixelType,	// type
                                            (char*)(bits),			// base
                                            bytespp,				// xStride
                                            pitch));				// yStride
        } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) {
            for(int c = 0; c < components; c++) {
                char *channel_base = (char*)(bits) + c*bytespc;
                frameBuffer.insert (channel_name[c],// name
                                    Imf::Slice (pixelType,			// type
                                                channel_base,					// base
                                                bytespp,	// xStride
                                                pitch));	// yStride
            }
        }

        // write the data
        Imf::OutputFile file (ostream, header);
        file.setFrameBuffer (frameBuffer);
        file.writePixels (height);

        if(halfData != NULL) delete[] halfData;
        if(bIsFlipped) {
            // invert dib scanlines
            FreeImage_FlipVertical(dib);
        }

        return TRUE;

    } catch(Iex::BaseExc & e) {
        if(halfData != NULL) delete[] halfData;
        if(bIsFlipped) {
            // invert dib scanlines
            FreeImage_FlipVertical(dib);
        }

        FreeImage_OutputMessageProc(s_format_id, e.what());

        return FALSE;
    }
}
Пример #13
0
// All the work is done here
int joinEXRs( int tilesX, int tilesY, const char* baseName, bool deleteTiles, bool Verbose )
{
   int exitCode = 0;

   // Expand names
   if( Verbose ) printf("Image file name = '%s', tilesX=%d, tilesY=%d\n", baseName, tilesX, tilesY);
   int numTiles = tilesX * tilesY;

   // Allocate memory:
   char ** tileNames = new char * [numTiles];
   Imf::InputFile ** iFiles = new Imf::InputFile * [numTiles];
   for( int i = 0; i < numTiles; i++)
   {
      tileNames[i] = new char[FILENAME_MAXLEN];
      iFiles[i] = 0;
   }

   // Insert tile info and check if files exist
   int nonEmptyTile = -1;
   struct stat stFileInfo;

   for( int i = 0; i < numTiles; i++)
   {
      sprintf( tileNames[i], "%s.tile_%d.exr", baseName, i);
      if( Verbose ) printf("Tile name  %d = '%s'\n", i, tileNames[i]);

      if( stat( tileNames[i], &stFileInfo ) == 0 )
      {
         // File exists - so open it and check for validness
         iFiles[i] = new Imf::InputFile( tileNames[i]);
         if( false == iFiles[i]->isComplete())
         {
            fprintf( stderr, "Error: File '%s' is incomplete or is not an OpenEXR file.\n", tileNames[i]); fflush( stderr);
            delete iFiles[i];
            iFiles[i] = 0;
            exitCode = 1;
         }
         else if( nonEmptyTile == -1 )
         {
            nonEmptyTile = i;
         }
      }
      else
      {
         fprintf( stderr, "Error: File '%s' not founded.\n", tileNames[i]); fflush( stderr);
         exitCode = 1;
      }
   }

   if( nonEmptyTile < 0) // All tiles were empty
   {
      fprintf( stderr, "Error: No tile files founded.\n"); fflush( stderr);
   }
   else
   {
   // Gather info from a non-empty tile file
   Imf::Header inHeader = iFiles[nonEmptyTile]->header();
   Imath::Box2i imageBox = inHeader.displayWindow(); // size of the resulting image
   int imageWidth = imageBox.max.x - imageBox.min.x + 1;
   int imageHeight = imageBox.max.y - imageBox.min.y + 1;

   // Iterate through all the channels and reserve mem for the whole display window
   // also add channels to the header of the output file
   Imf::Header outHeader( imageWidth, imageHeight);
   std::map< Imf::Name, ChannelInfo* > chInfos; // this will hold pixel data and stride for each channel in input files
   Imf::ChannelList channels = inHeader.channels();
   Imf::ChannelList::ConstIterator itCh;
   for( itCh = channels.begin(); itCh != channels.end(); itCh++ )
   {
      chInfos[itCh.name()] = new ChannelInfo( typeSize( itCh.channel().type), imageHeight, imageWidth );
      outHeader.channels().insert( itCh.name(), Imf::Channel( itCh.channel().type));
      if( Verbose) printf("Channel: '%s' | stride: %d\n", itCh.name(), typeSize( itCh.channel().type));
   }

   // Collect data from files
   Imath::Box2i tileBox;      // each tile's data window
   Imath::Box2i resultBox;    // resulting data window (should be sum of all tiles' data windows)
   Imf::FrameBuffer fb;
   for( int i = 0; i < numTiles; i++)
   {
      if( iFiles[i] == 0) // no file for this tile
         continue;

      tileBox = iFiles[i]->header().dataWindow();
      resultBox.extendBy( tileBox );

      if( Verbose) printf("Data win: xmin=%d xmax=%d ymin=%d ymax=%d\n", tileBox.min.x, tileBox.max.x, tileBox.min.y, tileBox.max.y);

      channels = iFiles[i]->header().channels();
      for( itCh = channels.begin(); itCh != channels.end(); itCh++ )
         fb.insert( itCh.name(),
                    Imf::Slice( itCh.channel().type,                // pixel type
                    (char*)&chInfos[itCh.name()]->array2d[0][0],    // base
                    chInfos[itCh.name()]->stride,                   // x stride
                    chInfos[itCh.name()]->stride * imageWidth,      // y stride
                    1, 1, 0.0 ) );                                  // x,y sampling, fill value

      iFiles[i]->setFrameBuffer(fb);
      iFiles[i]->readPixels( tileBox.min.y, tileBox.max.y);
   }

   // Write out everything:
   outHeader.dataWindow() = resultBox;
   Imf::OutputFile imageFile( baseName, outHeader );
   imageFile.setFrameBuffer(fb);
   imageFile.writePixels( resultBox.max.y-resultBox.min.y+1 );

   printf("Joined EXR image successfully written.\n");

   // Free files:
   for( int i = 0; i < numTiles; i++)
      if( iFiles[i] != 0 ) delete iFiles[i];
   delete [] iFiles;

   if( deleteTiles )
   {
      for( int i = 0; i < numTiles; i++)
         if( unlink( tileNames[i]) != 0)
         {
            perror("Remove");
            printf("Can't remove file '%s'\n", tileNames[i]);
         }
   }
   }

   // Free names:
   for( int i = 0; i < numTiles; i++)
      delete [] tileNames[i];
   delete [] tileNames;

   return exitCode;
}
Пример #14
0
 fcExrFrameData(const char *p, int w, int h)
     : path(p), width(w), height(h), header(w, h)
 {
     header.compression() = Imf::ZIPS_COMPRESSION;
 }
Пример #15
0
bool render_flipbook( flipbook::flipbook_t *flip, node_t *n, int start, int end, bool mblur, int subsample)
{
    render_cancelled = false;
    signal_connection_t connection = flip->closed.connect( &cancel_render);
    std::size_t mem_size = 0;

    render_context_t new_context = document_t::Instance().composition().current_context();
    new_context.mode = flipbook_render;
    new_context.result_node = n;
    new_context.subsample = subsample;
    new_context.motion_blur_extra_samples = 0;
    new_context.motion_blur_shutter_factor = mblur ? 1 : 0;

    // recalc the domain, in case this is our first render
    n->recursive_calc_domain( new_context);

    image::image_t img( n->domain().size().x + 1, n->domain().size().y + 1);

    for( int i = start; i <= end; ++i)
    {
	try
	{
	    new_context.time = i;

	    renderer_t renderer( new_context, true);
	    renderer.render();

            // find the amount of memory required to store a frame.
            // not the most efficient way of doing it, but it's done only once.
            if( mem_size == 0)
            {
                // copy the renderer result to our buffer
                boost::gil::fill_pixels( boost::gil::view( img), image::pixel_t( 0, 0, 0, 0));
                Imath::Box2i area( intersect( n->domain(), n->defined()));

                if( !area.isEmpty())
                {
                    boost::gil::copy_pixels( n->const_subimage_view( area),
                                            boost::gil::subimage_view( boost::gil::view( img),
                                                                     area.min.x - n->domain().min.x,
                                                                     area.min.y - n->domain().min.y,
                                                                     area.size().x + 1,
                                                                     area.size().y + 1));
                }

                Imf::Header header = Imf::Header( renderer.domain().size().x + 1, renderer.domain().size().y + 1);
                header.compression() = Imf::B44_COMPRESSION;

                imageio::imf_null_ostream os;
                imageio::write_half_rgb_exr( os, header, boost::gil::const_view( img));
                mem_size = os.size();
                std::cout << "Flipbook: frame size = " << mem_size / 1024 << " kb \n";
            }

	    std::auto_ptr<imageio::imf_memory_ostream> os( new imageio::imf_memory_ostream( mem_size));

	    if( !os.get())
	    {
		// out of memory
		connection.disconnect();
		return true;
	    }

	    // copy the renderer result to our buffer
	    boost::gil::fill_pixels( boost::gil::view( img), image::pixel_t( 0, 0, 0, 0));
	    Imath::Box2i area( intersect( n->domain(), n->defined()));

	    if( !area.isEmpty())
	    {
		boost::gil::copy_pixels( n->const_subimage_view( area),
					boost::gil::subimage_view( boost::gil::view( img),
								 area.min.x - n->domain().min.x,
								 area.min.y - n->domain().min.y,
								 area.size().x + 1,
								 area.size().y + 1));
	    }

	    Imf::Header header = Imf::Header( renderer.domain().size().x + 1, renderer.domain().size().y + 1);
	    header.compression() = Imf::B44_COMPRESSION;

	    imageio::write_half_rgb_exr( *os, header, boost::gil::const_view( img));

	    if( render_cancelled)
            {
		connection.disconnect();
                return false;
            }

	    flip->add_frame( os);
	}
	catch( ...)
	{
	    // TODO: report out of memory here
	    // if we have any frame, then play
            connection.disconnect();
	    return !flip->empty();
	}
    }

    connection.disconnect();
    return true;
}
Пример #16
0
void
OpenEXRInput::query_channels (void)
{
    m_spec.nchannels = 0;
    const Imf::ChannelList &channels (m_header->channels());
    Imf::ChannelList::ConstIterator ci;
    int c;
    int red = -1, green = -1, blue = -1, alpha = -1, zee = -1;
    for (c = 0, ci = channels.begin();  ci != channels.end();  ++c, ++ci) {
        // std::cerr << "Channel " << ci.name() << '\n';
        const char* name = ci.name();
        m_channelnames.push_back (name);
        if (red < 0 && (iequals(name, "R") || iequals(name, "Red") ||
                        iends_with(name,".R") || iends_with(name,".Red")))
            red = c;
        if (green < 0 && (iequals(name, "G") || iequals(name, "Green") ||
                          iends_with(name,".G") || iends_with(name,".Green")))
            green = c;
        if (blue < 0 && (iequals(name, "B") || iequals(name, "Blue") ||
                         iends_with(name,".B") || iends_with(name,".Blue")))
            blue = c;
        if (alpha < 0 && (iequals(name, "A") || iequals(name, "Alpha") ||
                          iends_with(name,".A") || iends_with(name,".Alpha")))
            alpha = c;
        if (zee < 0 && (iequals(name, "Z") || iequals(name, "Depth") ||
                        iends_with(name,".Z") || iends_with(name,".Depth")))
            zee = c;
        ++m_spec.nchannels;
    }
    m_userchannels.resize (m_spec.nchannels);
    int nc = 0;
    if (red >= 0) {
        m_spec.channelnames.push_back (m_channelnames[red]);
        m_userchannels[red] = nc++;
    }
    if (green >= 0) {
        m_spec.channelnames.push_back (m_channelnames[green]);
        m_userchannels[green] = nc++;
    }
    if (blue >= 0) {
        m_spec.channelnames.push_back (m_channelnames[blue]);
        m_userchannels[blue] = nc++;
    }
    if (alpha >= 0) {
        m_spec.channelnames.push_back (m_channelnames[alpha]);
        m_spec.alpha_channel = nc;
        m_userchannels[alpha] = nc++;
    }
    if (zee >= 0) {
        m_spec.channelnames.push_back (m_channelnames[zee]);
        m_spec.z_channel = nc;
        m_userchannels[zee] = nc++;
    }
    for (c = 0, ci = channels.begin();  ci != channels.end();  ++c, ++ci) {
        if (red == c || green == c || blue == c || alpha == c || zee == c)
            continue;   // Already accounted for this channel
        m_userchannels[c] = nc;
        m_spec.channelnames.push_back (ci.name());
        ++nc;
    }
    ASSERT ((int)m_spec.channelnames.size() == m_spec.nchannels);
    // FIXME: should we also figure out the layers?

    // Figure out data types -- choose the highest range
    m_spec.format = TypeDesc::UNKNOWN;
    std::vector<TypeDesc> chanformat;
    bool differing_chanformats = false;
    for (c = 0, ci = channels.begin();  ci != channels.end();  ++c, ++ci) {
        Imf::PixelType ptype = ci.channel().type;
        TypeDesc fmt = TypeDesc::HALF;
        switch (ptype) {
        case Imf::UINT :
            fmt = TypeDesc::UINT;
            if (m_spec.format == TypeDesc::UNKNOWN)
                m_spec.format = TypeDesc::UINT;
            break;
        case Imf::HALF :
            fmt = TypeDesc::HALF;
            if (m_spec.format != TypeDesc::FLOAT)
                m_spec.format = TypeDesc::HALF;
            break;
        case Imf::FLOAT :
            fmt = TypeDesc::FLOAT;
            m_spec.format = TypeDesc::FLOAT;
            break;
        default: ASSERT (0);
        }
        chanformat.push_back (fmt);
        m_pixeltype.push_back (ptype);
        if (fmt != chanformat[0])
            differing_chanformats = true;
    }
    ASSERT (m_spec.format != TypeDesc::UNKNOWN);
    if (differing_chanformats)
        m_spec.channelformats = chanformat;
}
Пример #17
0
bool
OpenEXRInput::open (const std::string &name, ImageSpec &newspec)
{
    // Quick check to reject non-exr files
    bool tiled;
    if (! Imf::isOpenExrFile (name.c_str(), tiled))
        return false;

    m_spec = ImageSpec(); // Clear everything with default constructor
    
    // Unless otherwise specified, exr files are assumed to be linear.
    m_spec.attribute ("oiio:ColorSpace", "Linear");
    
    try {
        if (tiled) {
            m_input_tiled = new Imf::TiledInputFile (name.c_str());
            m_header = &(m_input_tiled->header());
        } else {
            m_input_scanline = new Imf::InputFile (name.c_str());
            m_header = &(m_input_scanline->header());
        }
    }
    catch (const std::exception &e) {
        error ("OpenEXR exception: %s", e.what());
        return false;
    }
    if (! m_input_scanline && ! m_input_tiled) {
        error ("Unknown error opening EXR file");
        return false;
    }

    Imath::Box2i datawindow = m_header->dataWindow();
    m_spec.x = datawindow.min.x;
    m_spec.y = datawindow.min.y;
    m_spec.z = 0;
    m_spec.width = datawindow.max.x - datawindow.min.x + 1;
    m_spec.height = datawindow.max.y - datawindow.min.y + 1;
    m_spec.depth = 1;
    m_topwidth = m_spec.width;      // Save top-level mipmap dimensions
    m_topheight = m_spec.height;
    Imath::Box2i displaywindow = m_header->displayWindow();
    m_spec.full_x = displaywindow.min.x;
    m_spec.full_y = displaywindow.min.y;
    m_spec.full_z = 0;
    m_spec.full_width = displaywindow.max.x - displaywindow.min.x + 1;
    m_spec.full_height = displaywindow.max.y - displaywindow.min.y + 1;
    m_spec.full_depth = 1;
    if (tiled) {
        m_spec.tile_width = m_input_tiled->tileXSize();
        m_spec.tile_height = m_input_tiled->tileYSize();
    } else {
        m_spec.tile_width = 0;
        m_spec.tile_height = 0;
    }
    m_spec.tile_depth = 1;
    query_channels ();   // also sets format

    m_nsubimages = 1;
    if (tiled) {
        // FIXME: levelmode
        m_levelmode = m_input_tiled->levelMode();
        m_roundingmode = m_input_tiled->levelRoundingMode();
        if (m_levelmode == Imf::MIPMAP_LEVELS) {
            m_nmiplevels = m_input_tiled->numLevels();
            m_spec.attribute ("openexr:roundingmode", m_roundingmode);
        } else if (m_levelmode == Imf::RIPMAP_LEVELS) {
            m_nmiplevels = std::max (m_input_tiled->numXLevels(),
                                     m_input_tiled->numYLevels());
            m_spec.attribute ("openexr:roundingmode", m_roundingmode);
        } else {
            m_nmiplevels = 1;
        }
    } else {
        m_levelmode = Imf::ONE_LEVEL;
        m_nmiplevels = 1;
    }

    const Imf::EnvmapAttribute *envmap;
    envmap = m_header->findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    if (envmap) {
        m_cubeface = (envmap->value() == Imf::ENVMAP_CUBE);
        m_spec.attribute ("textureformat", m_cubeface ? "CubeFace Environment" : "LatLong Environment");
        // OpenEXR conventions for env maps
        if (! m_cubeface)
            m_spec.attribute ("oiio:updirection", "y");
        m_spec.attribute ("oiio:sampleborder", 1);
        // FIXME - detect CubeFace Shadow?
    } else {
        m_cubeface = false;
        if (tiled && m_levelmode == Imf::MIPMAP_LEVELS)
            m_spec.attribute ("textureformat", "Plain Texture");
        // FIXME - detect Shadow
    }

    const Imf::CompressionAttribute *compressattr;
    compressattr = m_header->findTypedAttribute<Imf::CompressionAttribute>("compression");
    if (compressattr) {
        const char *comp = NULL;
        switch (compressattr->value()) {
        case Imf::NO_COMPRESSION    : comp = "none"; break;
        case Imf::RLE_COMPRESSION   : comp = "rle"; break;
        case Imf::ZIPS_COMPRESSION  : comp = "zip"; break;
        case Imf::ZIP_COMPRESSION   : comp = "zip"; break;
        case Imf::PIZ_COMPRESSION   : comp = "piz"; break;
        case Imf::PXR24_COMPRESSION : comp = "pxr24"; break;
#ifdef IMF_B44_COMPRESSION
            // The enum Imf::B44_COMPRESSION is not defined in older versions
            // of OpenEXR, and there are no explicit version numbers in the
            // headers.  BUT this other related #define is present only in
            // the newer version.
        case Imf::B44_COMPRESSION   : comp = "b44"; break;
        case Imf::B44A_COMPRESSION  : comp = "b44a"; break;
#endif
        default:
            break;
        }
        if (comp)
            m_spec.attribute ("compression", comp);
    }

    for (Imf::Header::ConstIterator hit = m_header->begin();
             hit != m_header->end();  ++hit) {
        const Imf::IntAttribute *iattr;
        const Imf::FloatAttribute *fattr;
        const Imf::StringAttribute *sattr;
        const Imf::M44fAttribute *mattr;
        const Imf::V3fAttribute *vattr;        
        const char *name = hit.name();
        std::string oname = exr_tag_to_ooio_std[name];
        if (oname.empty())   // Empty string means skip this attrib
            continue;
//        if (oname == name)
//            oname = std::string(format_name()) + "_" + oname;
        const Imf::Attribute &attrib = hit.attribute();
        std::string type = attrib.typeName();
        if (type == "string" && 
            (sattr = m_header->findTypedAttribute<Imf::StringAttribute> (name)))
            m_spec.attribute (oname, sattr->value().c_str());
        else if (type == "int" && 
            (iattr = m_header->findTypedAttribute<Imf::IntAttribute> (name)))
            m_spec.attribute (oname, iattr->value());
        else if (type == "float" && 
            (fattr = m_header->findTypedAttribute<Imf::FloatAttribute> (name)))
            m_spec.attribute (oname, fattr->value());
        else if (type == "m44f" && 
            (mattr = m_header->findTypedAttribute<Imf::M44fAttribute> (name)))
            m_spec.attribute (oname, TypeDesc::TypeMatrix, &(mattr->value()));
        else if (type == "v3f" &&
                 (vattr = m_header->findTypedAttribute<Imf::V3fAttribute> (name)))
            m_spec.attribute (oname, TypeDesc::TypeVector, &(vattr->value()));
        else {
#if 0
            std::cerr << "  unknown attribute " << type << ' ' << name << "\n";
#endif
        }
    }

    m_subimage = 0;
    m_miplevel = 0;
    newspec = m_spec;
    return true;
}
Пример #18
0
bool
OpenEXROutput::open (const std::string &name, const ImageSpec &userspec,
                     OpenMode mode)
{
    if (mode == AppendSubimage) {
        error ("%s does not support subimages", format_name());
        return false;
    }

    if (mode == AppendMIPLevel && (m_output_scanline || m_output_tiled)) {
        // Special case for appending to an open file -- we don't need
        // to close and reopen
        if (m_spec.tile_width && m_levelmode != Imf::ONE_LEVEL) {
            // OpenEXR does not support differing tile sizes on different
            // MIP-map levels.  Reject the open() if not using the original
            // tile sizes.
            if (userspec.tile_width != m_spec.tile_width ||
                userspec.tile_height != m_spec.tile_height) {
                error ("OpenEXR tiles must have the same size on all MIPmap levels");
                return false;
            }
            // Copy the new mip level size.  Keep everything else from the
            // original level.
            m_spec.width = userspec.width;
            m_spec.height = userspec.height;
            // N.B. do we need to copy anything else from userspec?
            ++m_miplevel;
            return true;
        }
    }

    m_spec = userspec;  // Stash the spec

    if (m_spec.width < 1 || m_spec.height < 1) {
        error ("Image resolution must be at least 1x1, you asked for %d x %d",
               userspec.width, userspec.height);
        return false;
    }
    if (m_spec.depth < 1)
        m_spec.depth = 1;
    if (m_spec.depth > 1) {
        error ("%s does not support volume images (depth > 1)", format_name());
        return false;
    }

    if (m_spec.full_width <= 0)
        m_spec.full_width = m_spec.width;
    if (m_spec.full_height <= 0)
        m_spec.full_height = m_spec.height;

    // Force use of one of the three data types that OpenEXR supports
    switch (m_spec.format.basetype) {
    case TypeDesc::UINT:
        m_spec.format = TypeDesc::UINT;
        break;
    case TypeDesc::FLOAT:
    case TypeDesc::DOUBLE:
        m_spec.format = TypeDesc::FLOAT;
        break;
    default:
        // Everything else defaults to half
        m_spec.format = TypeDesc::HALF;
    }

    Imath::Box2i dataWindow (Imath::V2i (m_spec.x, m_spec.y),
                             Imath::V2i (m_spec.width + m_spec.x - 1,
                                         m_spec.height + m_spec.y - 1));
    Imath::Box2i displayWindow (Imath::V2i (m_spec.full_x, m_spec.full_y),
                                Imath::V2i (m_spec.full_width+m_spec.full_x-1,
                                            m_spec.full_height+m_spec.full_y-1));
    m_header = new Imf::Header (displayWindow, dataWindow);

    // Insert channels into the header.  Also give the channels names if
    // the user botched it.
    static const char *default_chan_names[] = { "R", "G", "B", "A" };
    m_spec.channelnames.resize (m_spec.nchannels);
    for (int c = 0;  c < m_spec.nchannels;  ++c) {
        if (m_spec.channelnames[c].empty())
            m_spec.channelnames[c] = (c<4) ? default_chan_names[c]
                                           : Strutil::format ("unknown %d", c);
        TypeDesc format = m_spec.channelformats.size() ?
                                  m_spec.channelformats[c] : m_spec.format;
        Imf::PixelType ptype;
        switch (format.basetype) {
        case TypeDesc::UINT:
            ptype = Imf::UINT;
            format = TypeDesc::UINT;
            break;
        case TypeDesc::FLOAT:
        case TypeDesc::DOUBLE:
            ptype = Imf::FLOAT;
            format = TypeDesc::FLOAT;
            break;
        default:
            // Everything else defaults to half
            ptype = Imf::HALF;
            format = TypeDesc::HALF;
        }
        
#ifdef OPENEXR_VERSION_IS_1_6_OR_LATER
        // Hint to lossy compression methods that indicates whether
        // human perception of the quantity represented by this channel
        // is closer to linear or closer to logarithmic.  Compression
        // methods may optimize image quality by adjusting pixel data
        // quantization acording to this hint.
        
        bool pLinear = iequals (m_spec.get_string_attribute ("oiio:ColorSpace", "Linear"), "Linear");
#endif
        m_pixeltype.push_back (ptype);
        if (m_spec.channelformats.size())
            m_spec.channelformats[c] = format;
        m_header->channels().insert (m_spec.channelnames[c].c_str(),
                                     Imf::Channel(ptype, 1, 1
#ifdef OPENEXR_VERSION_IS_1_6_OR_LATER
                                     , pLinear
#endif
                                     ));
    }
    ASSERT (m_pixeltype.size() == (size_t)m_spec.nchannels);

    // Default to ZIP compression if no request came with the user spec.
    if (! m_spec.find_attribute("compression"))
        m_spec.attribute ("compression", "zip");

    // Default to increasingY line order, same as EXR.
    if (! m_spec.find_attribute("openexr:lineOrder"))
        m_spec.attribute ("openexr:lineOrder", "increasingY");

    // Automatically set date field if the client didn't supply it.
    if (! m_spec.find_attribute("DateTime")) {
        time_t now;
        time (&now);
        struct tm mytm;
        Sysutil::get_local_time (&now, &mytm);
        std::string date = Strutil::format ("%4d:%02d:%02d %2d:%02d:%02d",
                               mytm.tm_year+1900, mytm.tm_mon+1, mytm.tm_mday,
                               mytm.tm_hour, mytm.tm_min, mytm.tm_sec);
        m_spec.attribute ("DateTime", date);
    }

    m_nsubimages = 1;
    m_subimage = 0;
    m_nmiplevels = 1;
    m_miplevel = 0;

    // Figure out if we are a mipmap or an environment map
    ImageIOParameter *param = m_spec.find_attribute ("textureformat");
    const char *textureformat = param ? *(char **)param->data() : NULL;
    m_levelmode = Imf::ONE_LEVEL;  // Default to no MIP-mapping
    m_roundingmode = m_spec.get_int_attribute ("openexr:roundingmode",
                                               Imf::ROUND_DOWN);

    if (textureformat) {
        if (iequals (textureformat, "Plain Texture")) {
            m_levelmode = m_spec.get_int_attribute ("openexr:levelmode",
                                                    Imf::MIPMAP_LEVELS);
        } else if (iequals (textureformat, "CubeFace Environment")) {
            m_levelmode = m_spec.get_int_attribute ("openexr:levelmode",
                                                    Imf::MIPMAP_LEVELS);
            m_header->insert ("envmap", Imf::EnvmapAttribute(Imf::ENVMAP_CUBE));
        } else if (iequals (textureformat, "LatLong Environment")) {
            m_levelmode = m_spec.get_int_attribute ("openexr:levelmode",
                                                    Imf::MIPMAP_LEVELS);
            m_header->insert ("envmap", Imf::EnvmapAttribute(Imf::ENVMAP_LATLONG));
        } else if (iequals (textureformat, "Shadow")) {
            m_levelmode = Imf::ONE_LEVEL;  // Force one level for shadow maps
        }

        if (m_levelmode == Imf::MIPMAP_LEVELS) {
            // Compute how many mip levels there will be
            int w = m_spec.width;
            int h = m_spec.height;
            while (w > 1 && h > 1) {
                if (m_roundingmode == Imf::ROUND_DOWN) {
                    w = w / 2;
                    h = h / 2;
                } else {
                    w = (w + 1) / 2;
                    h = (h + 1) / 2;
                }
                w = std::max (1, w);
                h = std::max (1, h);
                ++m_nmiplevels;
            }
        }
    }

    // Deal with all other params
    for (size_t p = 0;  p < m_spec.extra_attribs.size();  ++p)
        put_parameter (m_spec.extra_attribs[p].name().string(),
                       m_spec.extra_attribs[p].type(),
                       m_spec.extra_attribs[p].data());

    try {
        if (m_spec.tile_width) {
            m_header->setTileDescription (
                Imf::TileDescription (m_spec.tile_width, m_spec.tile_height,
                                      Imf::LevelMode(m_levelmode),
                                      Imf::LevelRoundingMode(m_roundingmode)));
            m_output_tiled = new Imf::TiledOutputFile (name.c_str(), *m_header);
        } else {
            m_output_scanline = new Imf::OutputFile (name.c_str(), *m_header);
        }
    }
    catch (const std::exception &e) {
        error ("OpenEXR exception: %s", e.what());
        m_output_scanline = NULL;
        return false;
    }
    if (! m_output_scanline && ! m_output_tiled) {
        error ("Unknown error opening EXR file");
        return false;
    }

    return true;
}
Пример #19
0
bool
OpenEXROutput::put_parameter (const std::string &name, TypeDesc type,
                              const void *data)
{
    // Translate
    std::string xname = name;
    if (istarts_with (xname, "oiio:"))
        return false;
    else if (iequals(xname, "worldtocamera"))
        xname = "worldToCamera";
    else if (iequals(xname, "worldtoscreen"))
        xname = "worldToNDC";
    else if (iequals(xname, "DateTime"))
        xname = "capDate";
    else if (iequals(xname, "description") || iequals(xname, "ImageDescription"))
        xname = "comments";
    else if (iequals(xname, "Copyright"))
        xname = "owner";
    else if (iequals(xname, "PixelAspectRatio"))
        xname = "pixelAspectRatio";
    else if (iequals(xname, "ExposureTime"))
        xname = "expTime";
    else if (iequals(xname, "FNumber"))
        xname = "aperture";
    else if (istarts_with (xname, format_prefix))
        xname = std::string (xname.begin()+format_prefix.size(), xname.end());

//    std::cerr << "exr put '" << name << "' -> '" << xname << "'\n";

    // Special cases
    if (iequals(xname, "Compression") && type == TypeDesc::STRING) {
        const char *str = *(char **)data;
        m_header->compression() = Imf::ZIP_COMPRESSION;  // Default
        if (str) {
            if (iequals (str, "none"))
                m_header->compression() = Imf::NO_COMPRESSION;
            else if (iequals (str, "deflate") || iequals (str, "zip")) 
                m_header->compression() = Imf::ZIP_COMPRESSION;
            else if (iequals (str, "rle")) 
                m_header->compression() = Imf::RLE_COMPRESSION;
            else if (iequals (str, "zips")) 
                m_header->compression() = Imf::ZIPS_COMPRESSION;
            else if (iequals (str, "piz")) 
                m_header->compression() = Imf::PIZ_COMPRESSION;
            else if (iequals (str, "pxr24")) 
                m_header->compression() = Imf::PXR24_COMPRESSION;
#ifdef IMF_B44_COMPRESSION
            // The enum Imf::B44_COMPRESSION is not defined in older versions
            // of OpenEXR, and there are no explicit version numbers in the
            // headers.  BUT this other related #define is present only in
            // the newer version.
            else if (iequals (str, "b44"))
                m_header->compression() = Imf::B44_COMPRESSION;
            else if (iequals (str, "b44a"))
                m_header->compression() = Imf::B44A_COMPRESSION;
#endif
        }
        return true;
    }

    if (iequals (xname, "openexr:lineOrder") && type == TypeDesc::STRING) {
        const char *str = *(char **)data;
        m_header->lineOrder() = Imf::INCREASING_Y;   // Default
        if (str) {
            if (iequals (str, "randomY"))
                m_header->lineOrder() = Imf::RANDOM_Y;
            else if (iequals (str, "decreasingY"))
                m_header->lineOrder() = Imf::DECREASING_Y;
        }
        return true;
    }

    // Supress planarconfig!
    if (iequals (xname, "planarconfig") || iequals (xname, "tiff:planarconfig"))
        return true;

    // General handling of attributes
    // FIXME -- police this if we ever allow arrays
    if (type == TypeDesc::INT || type == TypeDesc::UINT) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(int*)data));
        return true;
    }
    if (type == TypeDesc::INT16) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(short*)data));
        return true;
    }
    if (type == TypeDesc::UINT16) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(unsigned short*)data));
        return true;
    }
    if (type == TypeDesc::FLOAT) {
        m_header->insert (xname.c_str(), Imf::FloatAttribute (*(float*)data));
        return true;
    }
    if (type == TypeDesc::HALF) {
        m_header->insert (xname.c_str(), Imf::FloatAttribute ((float)*(half*)data));
        return true;
    }
    if (type == TypeDesc::TypeMatrix) {
        m_header->insert (xname.c_str(), Imf::M44fAttribute (*(Imath::M44f*)data));
        return true;
    }
    if (type == TypeDesc::TypeString) {
        m_header->insert (xname.c_str(), Imf::StringAttribute (*(char**)data));
        return true;
    }
    if (type == TypeDesc::TypeVector) {
        m_header->insert (xname.c_str(), Imf::V3fAttribute (*(Imath::V3f*)data));
        return true;
    }

#ifdef DEBUG
    std::cerr << "Don't know what to do with " << type.c_str() << ' ' << xname << "\n";
#endif

    return false;
}