bool OpenEXRInput::read_native_scanlines (int ybegin, int yend, int z, int chbegin, int chend, void *data) { chend = clamp (chend, chbegin+1, m_spec.nchannels); // std::cerr << "openexr rns " << ybegin << ' ' << yend << ", channels " // << chbegin << "-" << (chend-1) << "\n"; if (m_input_scanline == NULL && m_scanline_input_part == NULL) { error ("called OpenEXRInput::read_native_scanlines without an open file"); return false; } // Compute where OpenEXR needs to think the full buffers starts. // OpenImageIO requires that 'data' points to where the client wants // to put the pixels being read, but OpenEXR's frameBuffer.insert() // wants where the address of the "virtual framebuffer" for the // whole image. const PartInfo &part (m_parts[m_subimage]); size_t pixelbytes = m_spec.pixel_bytes (chbegin, chend, true); size_t scanlinebytes = (size_t)m_spec.width * pixelbytes; char *buf = (char *)data - m_spec.x * pixelbytes - ybegin * scanlinebytes; try { Imf::FrameBuffer frameBuffer; size_t chanoffset = 0; for (int c = chbegin; c < chend; ++c) { size_t chanbytes = m_spec.channelformat(c).size(); frameBuffer.insert (m_spec.channelnames[c].c_str(), Imf::Slice (part.pixeltype[c], buf + chanoffset, pixelbytes, scanlinebytes)); chanoffset += chanbytes; } if (m_input_scanline) { m_input_scanline->setFrameBuffer (frameBuffer); m_input_scanline->readPixels (ybegin, yend-1); #ifdef USE_OPENEXR_VERSION2 } else if (m_scanline_input_part) { m_scanline_input_part->setFrameBuffer (frameBuffer); m_scanline_input_part->readPixels (ybegin, yend-1); #endif } else { error ("Attempted to read scanline from a non-scanline file."); return false; } } catch (const std::exception &e) { error ("Failed OpenEXR read: %s", e.what()); return false; } catch (...) { // catch-all for edge cases or compiler bugs error ("Failed OpenEXR read: unknown exception"); return false; } return true; }
bool OpenEXRInput::read_native_scanlines (int ybegin, int yend, int z, int firstchan, int nchans, void *data) { // std::cerr << "openexr rns " << ybegin << ' ' << yend << ", channels " // << firstchan << "-" << (firstchan+nchans-1) << "\n"; if (m_input_scanline == NULL) return false; // Compute where OpenEXR needs to think the full buffers starts. // OpenImageIO requires that 'data' points to where the client wants // to put the pixels being read, but OpenEXR's frameBuffer.insert() // wants where the address of the "virtual framebuffer" for the // whole image. size_t pixelbytes = m_spec.pixel_bytes (firstchan, nchans, true); size_t scanlinebytes = (size_t)m_spec.width * pixelbytes; char *buf = (char *)data - m_spec.x * pixelbytes - ybegin * scanlinebytes; try { Imf::FrameBuffer frameBuffer; size_t chanoffset = 0; for (int c = 0; c < nchans; ++c) { size_t chanbytes = m_spec.channelformats.size() ? m_spec.channelformats[c+firstchan].size() : m_spec.format.size(); frameBuffer.insert (m_spec.channelnames[c+firstchan].c_str(), Imf::Slice (m_pixeltype[c+firstchan], buf + chanoffset, pixelbytes, scanlinebytes)); chanoffset += chanbytes; } m_input_scanline->setFrameBuffer (frameBuffer); m_input_scanline->readPixels (ybegin, yend-1); } catch (const std::exception &e) { error ("Failed OpenEXR read: %s", e.what()); return false; } return true; }
bool EXRCreator::create(const TQString &path, int, int, TQImage &img) { Imf::InputFile in ( path.ascii() ); const Imf::Header &h = in.header(); if ( h.hasPreviewImage() ) { kdDebug() << "EXRcreator - using preview" << endl; const Imf::PreviewImage &preview = in.header().previewImage(); TQImage qpreview(preview.width(), preview.height(), 32, 0, TQImage::BigEndian); for ( unsigned int y=0; y < preview.height(); y++ ) { for ( unsigned int x=0; x < preview.width(); x++ ) { const Imf::PreviewRgba &q = preview.pixels()[x+(y*preview.width())]; qpreview.setPixel( x, y, tqRgba(q.r, q.g, q.b, q.a) ); } } img = qpreview; return true; } else { // do it the hard way // We ignore maximum size when just extracting the thumnail // from the header, but it is very expensive to render large // EXR images just to turn it into an icon, so we go back // to honouring it in here. kdDebug() << "EXRcreator - using original image" << endl; TDEConfig * config = TDEGlobal::config(); TDEConfigGroupSaver cgs( config, "PreviewSettings" ); unsigned long long maxSize = config->readNumEntry( "MaximumSize", 1024*1024 /* 1MB */ ); unsigned long long fileSize = TQFile( path ).size(); if ( (fileSize > 0) && (fileSize < maxSize) ) { if (!img.load( path )) { return false; } if (img.depth() != 32) img = img.convertDepth( 32 ); return true; } else { return false; } } }
void OpenEXRImpl :: load_channels(Imf::InputFile &file, Matrix& mat, int numChannels, const char *channelNames) { Imath::Box2i dw = file.header().dataWindow(); int width = dw.max.x - dw.min.x + 1; int height = dw.max.y - dw.min.y + 1; mat.create(numChannels, Matrix::FLOAT32, width, height); Imf::FrameBuffer frameBuffer; for(int i=0; i < numChannels; i++) { char c[2]; c[0] = channelNames[i]; c[1] = '\0'; frameBuffer.insert(c, Imf::Slice(Imf::FLOAT, (char *)(mat.data.fl + i), sizeof(float)*numChannels, sizeof(float)*numChannels*width)); } file.setFrameBuffer(frameBuffer); file.readPixels(dw.min.y, dw.max.y); }
bool OpenEXRInput::read_native_scanline (int y, int z, void *data) { ASSERT (m_input_scanline != NULL); // Compute where OpenEXR needs to think the full buffers starts. // OpenImageIO requires that 'data' points to where the client wants // to put the pixels being read, but OpenEXR's frameBuffer.insert() // wants where the address of the "virtual framebuffer" for the // whole image. size_t pixelbytes = m_spec.pixel_bytes (true); size_t scanlinebytes = m_spec.scanline_bytes (true); char *buf = (char *)data - m_spec.x * pixelbytes - y * scanlinebytes; try { Imf::FrameBuffer frameBuffer; size_t chanoffset = 0; for (int c = 0; c < m_spec.nchannels; ++c) { size_t chanbytes = m_spec.channelformats.size() ? m_spec.channelformats[c].size() : m_spec.format.size(); frameBuffer.insert (m_spec.channelnames[c].c_str(), Imf::Slice (m_pixeltype[c], buf + chanoffset, pixelbytes, scanlinebytes)); chanoffset += chanbytes; } m_input_scanline->setFrameBuffer (frameBuffer); m_input_scanline->readPixels (y, y); } catch (const std::exception &e) { error ("Failed OpenEXR read: %s", e.what()); return false; } return true; }
bool OpenEXRInput::seek_subimage (int subimage, int miplevel, ImageSpec &newspec) { if (subimage < 0 || subimage >= m_nsubimages) // out of range return false; if (subimage == m_subimage && miplevel == m_miplevel) { // no change newspec = m_spec; return true; } PartInfo &part (m_parts[subimage]); if (! part.initialized) { const Imf::Header *header = NULL; #ifdef USE_OPENEXR_VERSION2 if (m_input_multipart) header = &(m_input_multipart->header(subimage)); #else if (m_input_tiled) header = &(m_input_tiled->header()); if (m_input_scanline) header = &(m_input_scanline->header()); #endif part.parse_header (header); part.initialized = true; } #ifdef USE_OPENEXR_VERSION2 if (subimage != m_subimage) { delete m_scanline_input_part; m_scanline_input_part = NULL; delete m_tiled_input_part; m_tiled_input_part = NULL; delete m_deep_scanline_input_part; m_deep_scanline_input_part = NULL; delete m_deep_tiled_input_part; m_deep_tiled_input_part = NULL; try { if (part.spec.deep) { if (part.spec.tile_width) m_deep_tiled_input_part = new Imf::DeepTiledInputPart (*m_input_multipart, subimage); else m_deep_scanline_input_part = new Imf::DeepScanLineInputPart (*m_input_multipart, subimage); } else { if (part.spec.tile_width) m_tiled_input_part = new Imf::TiledInputPart (*m_input_multipart, subimage); else m_scanline_input_part = new Imf::InputPart (*m_input_multipart, subimage); } } catch (const std::exception &e) { error ("OpenEXR exception: %s", e.what()); m_scanline_input_part = NULL; m_tiled_input_part = NULL; m_deep_scanline_input_part = NULL; m_deep_tiled_input_part = NULL; ASSERT(0); return false; } } #endif m_subimage = subimage; if (miplevel < 0 || miplevel >= part.nmiplevels) // out of range return false; m_miplevel = miplevel; m_spec = part.spec; if (miplevel == 0 && part.levelmode == Imf::ONE_LEVEL) { newspec = m_spec; return true; } // Compute the resolution of the requested mip level. int w = part.topwidth, h = part.topheight; if (part.levelmode == Imf::MIPMAP_LEVELS) { while (miplevel--) { if (part.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 (part.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 = part.top_datawindow; Imath::Box2i displaywindow = part.top_displaywindow; m_spec.x = datawindow.min.x; m_spec.y = datawindow.min.y; if (m_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 (part.cubeface) { m_spec.full_width = w; m_spec.full_height = w; } newspec = m_spec; return true; }
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; }