Esempio n. 1
0
NORI_NAMESPACE_BEGIN

Bitmap::Bitmap(const std::string &filename) {
    Imf::InputFile file(filename.c_str());
    const Imf::Header &header = file.header();
    const Imf::ChannelList &channels = header.channels();

    Imath::Box2i dw = file.header().dataWindow();
    resize(dw.max.y - dw.min.y + 1, dw.max.x - dw.min.x + 1);

    cout << "Reading a " << cols() << "x" << rows() << " OpenEXR file from \""
         << filename << "\"" << endl;

    const char *ch_r = nullptr, *ch_g = nullptr, *ch_b = nullptr;
    for (Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it) {
        std::string name = toLower(it.name());

        if (it.channel().xSampling != 1 || it.channel().ySampling != 1) {
            /* Sub-sampled layers are not supported */
            continue;
        }

        if (!ch_r && (name == "r" || name == "red" || 
                endsWith(name, ".r") || endsWith(name, ".red"))) {
            ch_r = it.name();
        } else if (!ch_g && (name == "g" || name == "green" || 
                endsWith(name, ".g") || endsWith(name, ".green"))) {
            ch_g = it.name();
        } else if (!ch_b && (name == "b" || name == "blue" || 
                endsWith(name, ".b") || endsWith(name, ".blue"))) {
            ch_b = it.name();
        }
    }

    if (!ch_r || !ch_g || !ch_b)
        throw NoriException("This is not a standard RGB OpenEXR file!");

    size_t compStride = sizeof(float),
           pixelStride = 3 * compStride,
           rowStride = pixelStride * cols();

    char *ptr = reinterpret_cast<char *>(data());

    Imf::FrameBuffer frameBuffer;
    frameBuffer.insert(ch_r, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
    frameBuffer.insert(ch_g, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
    frameBuffer.insert(ch_b, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); 
    file.setFrameBuffer(frameBuffer);
    file.readPixels(dw.min.y, dw.max.y);

    m_totalLuminance = getTotalLuminace();
}
Esempio n. 2
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()));
}
Esempio n. 3
0
void
OpenEXRInput::PartInfo::query_channels (const Imf::Header *header)
{
    ASSERT (! initialized);
    spec.nchannels = 0;
    const Imf::ChannelList &channels (header->channels());
    std::vector<std::string> channelnames;  // Order of channels in file
    std::vector<ChanNameHolder> cnh;
    int c = 0;
    for (Imf::ChannelList::ConstIterator ci = channels.begin();
         ci != channels.end();  ++c, ++ci) {
        cnh.emplace_back (ci.name(), c, ci.channel().type);
        ++spec.nchannels;
    }
    std::sort (cnh.begin(), cnh.end(), ChanNameHolder::compare_cnh);
    // Now we should have cnh sorted into the order that we want to present
    // to the OIIO client.
    spec.format = TypeDesc::UNKNOWN;
    bool all_one_format = true;
    for (int c = 0; c < spec.nchannels; ++c) {
        spec.channelnames.push_back (cnh[c].fullname);
        spec.channelformats.push_back (cnh[c].datatype);
        spec.format = TypeDesc(ImageBufAlgo::type_merge (TypeDesc::BASETYPE(spec.format.basetype),
                                                         TypeDesc::BASETYPE(cnh[c].datatype.basetype)));
        pixeltype.push_back (cnh[c].exr_data_type);
        chanbytes.push_back (cnh[c].datatype.size());
        all_one_format &= (cnh[c].datatype == cnh[0].datatype);
        if (spec.alpha_channel < 0 && (Strutil::iequals (cnh[c].suffix, "A") ||
                                       Strutil::iequals (cnh[c].suffix, "Alpha")))
            spec.alpha_channel = c;
        if (spec.z_channel < 0 && (Strutil::iequals (cnh[c].suffix, "Z") ||
                                   Strutil::iequals (cnh[c].suffix, "Depth")))
            spec.z_channel = c;
    }
    ASSERT ((int)spec.channelnames.size() == spec.nchannels);
    ASSERT (spec.format != TypeDesc::UNKNOWN);
    if (all_one_format)
        spec.channelformats.clear();
}
Esempio n. 4
0
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
    bool bUseRgbaInterface = false;
    FIBITMAP *dib = NULL;

    if(!handle) {
        return NULL;
    }

    try {
        BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;

        // save the stream starting point
        const long stream_start = io->tell_proc(handle);

        // wrap the FreeImage IO stream
        C_IStream istream(io, handle);

        // open the file
        Imf::InputFile file(istream);

        // get file info
        const Imath::Box2i &dataWindow = file.header().dataWindow();
        int width  = dataWindow.max.x - dataWindow.min.x + 1;
        int height = dataWindow.max.y - dataWindow.min.y + 1;

        //const Imf::Compression &compression = file.header().compression();

        const Imf::ChannelList &channels = file.header().channels();

        // check the number of components and check for a coherent format

        std::string exr_color_model;
        Imf::PixelType pixel_type = Imf::HALF;
        FREE_IMAGE_TYPE image_type = FIT_UNKNOWN;
        int components = 0;
        bool bMixedComponents = false;

        for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
            components++;
            if(components == 1) {
                exr_color_model += i.name();
                pixel_type = i.channel().type;
            } else {
                exr_color_model += "/";
                exr_color_model += i.name();
                if (i.channel().type != pixel_type) {
                    bMixedComponents = true;
                }
            }
        }

        if(bMixedComponents) {
            bool bHandled = false;
            // we may have a RGBZ or RGBAZ image ...
            if(components > 4) {
                if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B") && channels.findChannel("A")) {
                    std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model";
                    FreeImage_OutputMessageProc(s_format_id, msg.c_str());
                    bHandled = true;
                }
            }
            else if(components > 3) {
                if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) {
                    std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model";
                    FreeImage_OutputMessageProc(s_format_id, msg.c_str());
                    bHandled = true;
                }
            }
            if(!bHandled) {
                THROW (Iex::InputExc, "Unable to handle mixed component types (color model = " << exr_color_model << ")");
            }
        }

        switch(pixel_type) {
        case Imf::UINT:
            THROW (Iex::InputExc, "Unsupported format: UINT");
            break;
        case Imf::HALF:
        case Imf::FLOAT:
        default:
            break;
        }

        // check for supported image color models
        // --------------------------------------------------------------

        if((components == 1) || (components == 2)) {
            // if the image is gray-alpha (YA), ignore the alpha channel
            if((components == 1) && channels.findChannel("Y")) {
                image_type = FIT_FLOAT;
                components = 1;
            } else {
                std::string msg = "Warning: loading color model " + exr_color_model + " as Y color model";
                FreeImage_OutputMessageProc(s_format_id, msg.c_str());
                image_type = FIT_FLOAT;
                // ignore the other channel
                components = 1;
            }
        } else if(components == 3) {
            if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) {
                image_type = FIT_RGBF;
            }
            else if(channels.findChannel("BY") && channels.findChannel("RY") && channels.findChannel("Y")) {
                image_type = FIT_RGBF;
                bUseRgbaInterface = true;
            }
        } else if(components >= 4) {
            if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) {
                if(channels.findChannel("A")) {
                    if(components > 4) {
                        std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model";
                        FreeImage_OutputMessageProc(s_format_id, msg.c_str());
                    }
                    image_type = FIT_RGBAF;
                    // ignore other layers if there is more than one alpha layer
                    components = 4;
                } else {
                    std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model";
                    FreeImage_OutputMessageProc(s_format_id, msg.c_str());

                    image_type = FIT_RGBF;
                    // ignore other channels
                    components = 3;
                }
            }
        }

        if(image_type == FIT_UNKNOWN) {
            THROW (Iex::InputExc, "Unsupported color model: " << exr_color_model);
        }

        // allocate a new dib
        dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, 0);
        if(!dib) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);

        // try to load the preview image
        // --------------------------------------------------------------

        if(file.header().hasPreviewImage()) {
            const Imf::PreviewImage& preview = file.header().previewImage();
            const unsigned thWidth = preview.width();
            const unsigned thHeight = preview.height();

            FIBITMAP* thumbnail = FreeImage_Allocate(thWidth, thHeight, 32);
            if(thumbnail) {
                const Imf::PreviewRgba *src_line = preview.pixels();
                BYTE *dst_line = FreeImage_GetScanLine(thumbnail, thHeight - 1);
                const unsigned dstPitch = FreeImage_GetPitch(thumbnail);

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

                    for(unsigned x = 0; x < thWidth; ++x) {
                        dst_pixel->rgbRed = src_pixel->r;
                        dst_pixel->rgbGreen = src_pixel->g;
                        dst_pixel->rgbBlue = src_pixel->b;
                        dst_pixel->rgbReserved = src_pixel->a;
                        src_pixel++;
                        dst_pixel++;
                    }
                    src_line += thWidth;
                    dst_line -= dstPitch;
                }
                FreeImage_SetThumbnail(dib, thumbnail);
                FreeImage_Unload(thumbnail);
            }
        }

        if(header_only) {
            // header only mode
            return dib;
        }

        // load pixels
        // --------------------------------------------------------------

        const BYTE *bits = FreeImage_GetBits(dib);			// pointer to our pixel buffer
        const size_t bytespp = sizeof(float) * components;	// size of our pixel in bytes
        const unsigned pitch = FreeImage_GetPitch(dib);		// size of our yStride in bytes

        Imf::PixelType pixelType = Imf::FLOAT;	// load as float data type;

        if(bUseRgbaInterface) {
            // use the RGBA interface (used when loading RY BY Y images )

            const int chunk_size = 16;

            BYTE *scanline = (BYTE*)bits;

            // re-open using the RGBA interface
            io->seek_proc(handle, stream_start, SEEK_SET);
            Imf::RgbaInputFile rgbaFile(istream);

            // read the file in chunks
            Imath::Box2i dw = dataWindow;
            Imf::Array2D<Imf::Rgba> chunk(chunk_size, width);
            while (dw.min.y <= dw.max.y) {
                // read a chunk
                rgbaFile.setFrameBuffer (&chunk[0][0] - dw.min.x - dw.min.y * width, 1, width);
                rgbaFile.readPixels (dw.min.y, MIN(dw.min.y + chunk_size - 1, dw.max.y));
                // fill the dib
                const int y_max = ((dw.max.y - dw.min.y) <= chunk_size) ? (dw.max.y - dw.min.y) : chunk_size;
                for(int y = 0; y < y_max; y++) {
                    FIRGBF *pixel = (FIRGBF*)scanline;
                    const Imf::Rgba *half_rgba = chunk[y];
                    for(int x = 0; x < width; x++) {
                        // convert from half to float
                        pixel[x].red = half_rgba[x].r;
                        pixel[x].green = half_rgba[x].g;
                        pixel[x].blue = half_rgba[x].b;
                    }
                    // next line
                    scanline += pitch;
                }
                // next chunk
                dw.min.y += chunk_size;
            }

        } else {
            // use the low level interface

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

            // allow dataWindow with minimal bounds different form zero
            size_t offset = - dataWindow.min.x * bytespp - dataWindow.min.y * pitch;

            if(components == 1) {
                frameBuffer.insert ("Y",	// name
                                    Imf::Slice (pixelType,	// type
                                                (char*)(bits + offset), // base
                                                bytespp,				// xStride
                                                pitch,					// yStride
                                                1, 1,					// x/y sampling
                                                0.0));					// fillValue
            } else if((components == 3) || (components == 4)) {
                const char *channel_name[4] = { "R", "G", "B", "A" };

                for(int c = 0; c < components; c++) {
                    frameBuffer.insert (
                        channel_name[c],					// name
                        Imf::Slice (pixelType,				// type
                                    (char*)(bits + c * sizeof(float) + offset), // base
                                    bytespp,							// xStride
                                    pitch,								// yStride
                                    1, 1,								// x/y sampling
                                    0.0));								// fillValue
                }
            }

            // read the file
            file.setFrameBuffer(frameBuffer);
            file.readPixels(dataWindow.min.y, dataWindow.max.y);
        }

        // lastly, flip dib lines
        FreeImage_FlipVertical(dib);

    }
    catch(Iex::BaseExc & e) {
        if(dib != NULL) {
            FreeImage_Unload(dib);
        }
        FreeImage_OutputMessageProc(s_format_id, e.what());
        return NULL;
    }

    return dib;
}
Esempio n. 5
0
void
OpenEXRInput::PartInfo::query_channels (const Imf::Header *header)
{
    ASSERT (! initialized);
    spec.nchannels = 0;
    const Imf::ChannelList &channels (header->channels());
    std::vector<std::string> channelnames;  // Order of channels in file
    std::vector<ChanNameHolder> cnh;
    int c = 0;
    for (Imf::ChannelList::ConstIterator ci = channels.begin();
         ci != channels.end();  ++c, ++ci) {
        cnh.push_back (ChanNameHolder (ci.name(), c));
        ++spec.nchannels;
    }
    std::sort (cnh.begin(), cnh.end(), ChanNameHolder::compare_cnh);
    c = 0;
    for (Imf::ChannelList::ConstIterator ci = channels.begin();
         ci != channels.end();  ++c, ++ci) {
        spec.channelnames.push_back (cnh[c].fullname);
        if (spec.alpha_channel < 0 && (Strutil::iequals (cnh[c].suffix, "A") ||
                                       Strutil::iequals (cnh[c].suffix, "Alpha")))
            spec.alpha_channel = c;
        if (spec.z_channel < 0 && (Strutil::iequals (cnh[c].suffix, "Z") ||
                                   Strutil::iequals (cnh[c].suffix, "Depth")))
            spec.z_channel = c;
    }
    ASSERT ((int)spec.channelnames.size() == spec.nchannels);

    // Figure out data types -- choose the highest range
    spec.format = TypeDesc::UNKNOWN;
    std::vector<TypeDesc> chanformat;
    c = 0;
    for (Imf::ChannelList::ConstIterator 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 (spec.format == TypeDesc::UNKNOWN)
                spec.format = TypeDesc::UINT;
            break;
        case Imf::HALF :
            fmt = TypeDesc::HALF;
            if (spec.format != TypeDesc::FLOAT)
                spec.format = TypeDesc::HALF;
            break;
        case Imf::FLOAT :
            fmt = TypeDesc::FLOAT;
            spec.format = TypeDesc::FLOAT;
            break;
        default: ASSERT (0);
        }
        pixeltype.push_back (ptype);
        chanbytes.push_back (fmt.size());
        if (chanformat.size() == 0)
            chanformat.resize (spec.nchannels, fmt);
        for (int i = 0;  i < spec.nchannels;  ++i) {
            ASSERT ((int)spec.channelnames.size() > i);
            if (spec.channelnames[i] == ci.name()) {
                chanformat[i] = fmt;
                break;
            }
        }
    }
    ASSERT (spec.format != TypeDesc::UNKNOWN);
    bool differing_chanformats = false;
    for (int c = 1;  c < spec.nchannels;  ++c)
        differing_chanformats |= (chanformat[c] != chanformat[0]);
    if (differing_chanformats)
        spec.channelformats = chanformat;
}
Esempio n. 6
0
void
OpenEXRInput::PartInfo::query_channels (const Imf::Header *header)
{
    ASSERT (! initialized);
    spec.nchannels = 0;
    const Imf::ChannelList &channels (header->channels());
    std::vector<std::string> channelnames;  // Order of channels in file
    std::vector<int> userchannels;      // Map file chans to user chans
    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) {
        const char* name = ci.name();
        channelnames.push_back (name);
        if (red < 0 && (Strutil::iequals(name, "R") || Strutil::iequals(name, "Red") ||
                        Strutil::iends_with(name,".R") || Strutil::iends_with(name,".Red") ||
                        Strutil::iequals(name, "real")))
            red = c;
        if (green < 0 && (Strutil::iequals(name, "G") || Strutil::iequals(name, "Green") ||
                          Strutil::iends_with(name,".G") || Strutil::iends_with(name,".Green") ||
                          Strutil::iequals(name, "imag")))
            green = c;
        if (blue < 0 && (Strutil::iequals(name, "B") || Strutil::iequals(name, "Blue") ||
                         Strutil::iends_with(name,".B") || Strutil::iends_with(name,".Blue")))
            blue = c;
        if (alpha < 0 && (Strutil::iequals(name, "A") || Strutil::iequals(name, "Alpha") ||
                          Strutil::iends_with(name,".A") || Strutil::iends_with(name,".Alpha")))
            alpha = c;
        if (zee < 0 && (Strutil::iequals(name, "Z") || Strutil::iequals(name, "Depth") ||
                        Strutil::iends_with(name,".Z") || Strutil::iends_with(name,".Depth")))
            zee = c;
    }
    spec.nchannels = (int)channelnames.size();
    userchannels.resize (spec.nchannels);
    int nc = 0;
    if (red >= 0) {
        spec.channelnames.push_back (channelnames[red]);
        userchannels[red] = nc++;
    }
    if (green >= 0) {
        spec.channelnames.push_back (channelnames[green]);
        userchannels[green] = nc++;
    }
    if (blue >= 0) {
        spec.channelnames.push_back (channelnames[blue]);
        userchannels[blue] = nc++;
    }
    if (alpha >= 0) {
        spec.channelnames.push_back (channelnames[alpha]);
        spec.alpha_channel = nc;
        userchannels[alpha] = nc++;
    }
    if (zee >= 0) {
        spec.channelnames.push_back (channelnames[zee]);
        spec.z_channel = nc;
        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
        userchannels[c] = nc;
        spec.channelnames.push_back (ci.name());
        ++nc;
    }
    ASSERT ((int)spec.channelnames.size() == spec.nchannels);
    // FIXME: should we also figure out the layers?

    // Figure out data types -- choose the highest range
    spec.format = TypeDesc::UNKNOWN;
    std::vector<TypeDesc> chanformat;
    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 (spec.format == TypeDesc::UNKNOWN)
                spec.format = TypeDesc::UINT;
            break;
        case Imf::HALF :
            fmt = TypeDesc::HALF;
            if (spec.format != TypeDesc::FLOAT)
                spec.format = TypeDesc::HALF;
            break;
        case Imf::FLOAT :
            fmt = TypeDesc::FLOAT;
            spec.format = TypeDesc::FLOAT;
            break;
        default: ASSERT (0);
        }
        pixeltype.push_back (ptype);
        chanbytes.push_back (fmt.size());
        if (chanformat.size() == 0)
            chanformat.resize (spec.nchannels, fmt);
        for (int i = 0;  i < spec.nchannels;  ++i) {
            ASSERT ((int)spec.channelnames.size() > i);
            if (spec.channelnames[i] == ci.name()) {
                chanformat[i] = fmt;
                break;
            }
        }
    }
    ASSERT (spec.format != TypeDesc::UNKNOWN);
    bool differing_chanformats = false;
    for (int c = 1;  c < spec.nchannels;  ++c)
        differing_chanformats |= (chanformat[c] != chanformat[0]);
    if (differing_chanformats)
        spec.channelformats = chanformat;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}