bool isTiledOpenExrFile (const char fileName[]) { bool exr, tiled; exr = isOpenExrFile (fileName, tiled); return exr && tiled; }
bool isTiledOpenExrFile (IStream &is) { bool exr, tiled; exr = isOpenExrFile (is, tiled); return exr && tiled; }
/*! Tries to fill the image object with the data read from the given input stream. Returns true on success. */ bool EXRImageFileType::read( Image *image, std::istream &is, const std::string &mimetype) { #ifdef OSG_WITH_IMF if (!is.good()) return false; const char *dummy = ""; StdIStream file(is, dummy); Imf::Int64 pos = file.tellg(); bool check = isOpenExrFile(is); file.seekg(pos); if (!check) { FFATAL(( "Wrong format, no %s image given!\n", mimetype.c_str() )); return false; } // just read the header and get the channel count int channel_count = 0; pos = file.tellg(); try { Imf::RgbaInputFile stream(file); const Imf::Header &header = stream.header(); const Imf::ChannelList &channels = header.channels(); for(Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it) { ++channel_count; } } catch(std::exception &e) { FFATAL(( "Error while trying to read OpenEXR Image from stream: %s\n", e.what() )); return false; } file.seekg(pos); if(channel_count <= 4) { // TODO: check for mipmap levels, // look if line order is s.th. else than INCREASING_Y try { Int32 width, height, numImg = 1; Imf::RgbaInputFile stream(file); Imath::Box2i dw = stream.dataWindow(); Imf::Array2D<Imf::Rgba> pixels; const Imf::Header &header = stream.header(); // const Imf::LineOrder &order = header.lineOrder(); const Imf::EnvmapAttribute *envmap = header.findTypedAttribute<Imf::EnvmapAttribute>("envmap"); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase(height, width); if(envmap && envmap->value() == Imf::ENVMAP_CUBE) { numImg = 6; height /= numImg; if (width != height) { FFATAL(( "Cubemaps must have squared size, " "but w=%d and h=%d!\n", width, height )); return false; } } stream.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); stream.readPixels(dw.min.y, dw.max.y); image->set( Image::OSG_RGBA_PF, width, height, 1, 1, 1, 0, 0, Image::OSG_FLOAT16_IMAGEDATA, true, numImg ); image->clearHalf(); // now add custom attributes for(Imf::Header::ConstIterator it = header.begin(); it != header.end(); ++it) { Imf::Attribute *copy = it.attribute().copy(); Imf::StringAttribute *sa = dynamic_cast<Imf::StringAttribute *>(copy); if(sa != NULL) image->setAttachmentField(it.name(), sa->value()); delete copy; } Real16 *data = reinterpret_cast<Real16*>(image->editData()); for (Int32 side=numImg-1; side >=0; side--) { Int32 i, j, size = side * width * height * 4; for (Int32 y=side*height; y<(side+1)*height; y++) { for (Int32 x=0; x<width; x++) { if (numImg == 1 || side == 2 || side == 3) { i = (2 * side + 1) * height - (y + 1); // new y j = x; } else { i = y; j = width - x - 1; // new x } *(data + size++) = Real16(pixels[i][j].r); *(data + size++) = Real16(pixels[i][j].g); *(data + size++) = Real16(pixels[i][j].b); *(data + size++) = Real16(pixels[i][j].a); } } } return true; } catch(std::exception &e) { FFATAL(( "Error while trying to read OpenEXR Image from stream: " "%s\n", e.what() )); return false; } } else { try { if(channel_count % 4 != 0) { FFATAL(( "Error while trying to read OpenEXR Image from " "stream, channel count of %d is not supported!\n", channel_count)); return false; } int num_img = channel_count / 4; Imf::InputFile stream(file); const Imf::Header &header = stream.header(); Imath::Box2i dw = header.dataWindow(); int width = dw.max.x - dw.min.x + 1; int height = dw.max.y - dw.min.y + 1; image->set(Image::OSG_RGBA_PF, width, height, 1, 1, 1, 0, 0, Image::OSG_FLOAT16_IMAGEDATA, true, num_img); image->clearHalf(); // now add custom attributes for(Imf::Header::ConstIterator it = header.begin(); it != header.end(); ++it ) { Imf::Attribute *copy = it.attribute().copy(); Imf::StringAttribute *sa = dynamic_cast<Imf::StringAttribute *>(copy); if(sa != NULL) image->setAttachmentField(it.name(), sa->value()); delete copy; } const Imf::ChannelList &channels = header.channels(); // do some channel name checks bool channel_error = false; for(Imf::ChannelList::ConstIterator it=channels.begin();it!=channels.end();++it) { for(int side=0;side>num_img;++side) { char cn[20]; sprintf(cn, "%d", side); char name[20]; sprintf(name, "R%s", side == 0 ? "" : cn); if(channels.findChannel(name) == NULL) channel_error = true; sprintf(name, "G%s", side == 0 ? "" : cn); if(channels.findChannel(name) == NULL) channel_error = true; sprintf(name, "B%s", side == 0 ? "" : cn); if(channels.findChannel(name) == NULL) channel_error = true; sprintf(name, "A%s", side == 0 ? "" : cn); if(channels.findChannel(name) == NULL) channel_error = true; } } if(channel_error) { FFATAL(( "Error while trying to read OpenEXR Image from " "stream, expected channel names 'R' 'G' 'B' 'A', " "'R1' 'G1', 'B1', 'A1', ...\n")); return false; } Imf::FrameBuffer frame_buffer; // we need to do a vertical flip so we read single scan lines in. int current_scan_line = 0; for(int i=height-1;i>=0;--i) { for(int side=0;side<num_img;++side) { char *data = (reinterpret_cast<char *>(image->editData(0, 0, side))) + i * (sizeof(Real16) * 4 * width); data -= current_scan_line * (sizeof(Real16) * 4 * width); char cn[20]; sprintf(cn, "%d", side); char name[20]; sprintf(name, "R%s", side == 0 ? "" : cn); frame_buffer.insert(name, Imf::Slice(Imf::HALF, data, sizeof(Real16) * 4, sizeof(Real16) * 4 * width)); sprintf(name, "G%s", side == 0 ? "" : cn); frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 1 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width)); sprintf(name, "B%s", side == 0 ? "" : cn); frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 2 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width)); sprintf(name, "A%s", side == 0 ? "" : cn); frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 3 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width)); } stream.setFrameBuffer(frame_buffer); stream.readPixels(current_scan_line, current_scan_line); ++current_scan_line; } return true; } catch(std::exception &e) { FFATAL(( "Error while trying to read OpenEXR Image from stream: %s\n", e.what() )); return false; } } #else SWARNING << getMimeType() << " read is not compiled into the current binary " << std::endl; return false; #endif }
bool isOpenExrFile (const char fileName[]) { bool tiled; return isOpenExrFile (fileName, tiled); }
bool isOpenExrFile (IStream &is) { bool tiled; return isOpenExrFile (is, tiled); }