/** \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())); }
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(); }
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(); }
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; }
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; }
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; }
// 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; }
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; }