/*! load an EXR file from disk */ Ref<Image> loadExr(const FileName& filename) { Imf::RgbaInputFile file (filename.c_str()); Imath::Box2i dw = file.dataWindow(); ssize_t width = dw.max.x - dw.min.x + 1; ssize_t height = dw.max.y - dw.min.y + 1; Imf::Array2D<Imf::Rgba> pixels(height, width); file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels (dw.min.y, dw.max.y); Ref<Image> img = new Image3f(width,height,filename); if (file.lineOrder() == Imf::INCREASING_Y) { for (ssize_t y=0; y<height; y++) { for (ssize_t x=0; x<width; x++) { Imf::Rgba c = pixels[y][x]; img->set(x,y,Color4(c.r,c.g,c.b,c.a)); } } } else { for (ssize_t y=0; y<height; y++) { for (ssize_t x=0; x<width; x++) { Imf::Rgba c = pixels[y][x]; img->set(x,height-y-1,Color4(c.r,c.g,c.b,c.a)); } } } return img; }
//////////////////////////////////////////////////////////////////////////// // Take a file name/location and load an OpenEXR // Load the image into the "texture" texture object and pass back the texture sizes // bool LoadOpenEXRImage(char *fileName, GLint textureName, GLuint &texWidth, GLuint &texHeight) { // The OpenEXR uses exception handling to report errors or failures // Do all work in a try block to catch any thrown exceptions. try { Imf::Array2D<Imf::Rgba> pixels; Imf::RgbaInputFile file (fileName); Imath::Box2i dw = file.dataWindow(); texWidth = dw.max.x - dw.min.x + 1; texHeight = dw.max.y - dw.min.y + 1; pixels.resizeErase (texHeight, texWidth); file.setFrameBuffer (&pixels[0][0] - dw.min.x - dw.min.y * texWidth, 1, texWidth); file.readPixels (dw.min.y, dw.max.y); GLfloat* texels = (GLfloat*)malloc(texWidth * texHeight * 3 * sizeof(GLfloat)); GLfloat* pTex = texels; // Copy OpenEXR into local buffer for loading into a texture for (unsigned int v = 0; v < texHeight; v++) { for (unsigned int u = 0; u < texWidth; u++) { Imf::Rgba texel = pixels[texHeight - v - 1][u]; pTex[0] = texel.r; pTex[1] = texel.g; pTex[2] = texel.b; pTex += 3; } } // Bind texture, load image, set tex state glBindTexture(GL_TEXTURE_2D, textureName); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, texWidth, texHeight, 0, GL_RGB, GL_FLOAT, texels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); free(texels); } catch(Iex::BaseExc & e) { std::cerr << e.what() << std::endl; // // Handle exception. // } return true; }
void make_preview(Imf::RgbaInputFile &in, float exposure, int previewWidth, int previewHeight, Imf::Array2D <Imf::PreviewRgba> &previewPixels) { // // Read image // Box2i dw = in.dataWindow(); int w = dw.max.x - dw.min.x + 1; int h = dw.max.y - dw.min.y + 1; Array2D <Rgba> pixels (h, w); in.setFrameBuffer (&pixels[0][0] - dw.min.y * w - dw.min.x, 1, w); in.readPixels (dw.min.y, dw.max.y); // // Make a preview image // previewPixels.resizeErase (previewHeight, previewWidth); float fx = (previewWidth > 0)? (float (w - 1) / (previewWidth - 1)): 1; float fy = (previewHeight > 0)? (float (h - 1) / (previewHeight - 1)): 1; float m = Math<float>::pow (2.f, clamp (exposure + 2.47393f, -20.f, 20.f)); for (int y = 0; y < previewHeight; ++y) { for (int x = 0; x < previewWidth; ++x) { PreviewRgba &preview = previewPixels[y][x]; const Rgba &pixel = pixels[int (y * fy + .5f)][int (x * fx + .5f)]; preview.r = gamma (pixel.r, m); preview.g = gamma (pixel.g, m); preview.b = gamma (pixel.b, m); preview.a = int (clamp (pixel.a * 255.f, 0.f, 255.f) + .5f); } } }
int main (int argc, char * argv[]) { int status = 0; try { clo::parser parser; parser.parse (argc, argv); const clo::options & options = parser.get_options (); const vector<string> & nonopts = parser.get_non_options (); if (nonopts.size () != 4) { clo::option_error e ("illegal syntax."); throw e; } const std::string & exrA = nonopts[0]; const std::string & op = nonopts[1]; const std::string & exrB = nonopts[2]; const std::string & exrC = nonopts[3]; if (op != "over" && op != "in" && op != "out") { clo::option_error e ("unknown operation"); throw e; } // // Open A and B for reading. // // The images must have the same data and display window, // but this requirement should be relaxed. // Imf::RgbaInputFile inA (exrA.c_str ()); Imf::RgbaInputFile inB (exrB.c_str ()); Imath::Box2i dataWinA = inA.dataWindow (); Imath::Box2i dataWinB = inB.dataWindow (); if ((dataWinA.min.x != dataWinB.min.x) || (dataWinA.min.y != dataWinB.min.y) || (dataWinA.max.x != dataWinB.max.x) || (dataWinA.max.y != dataWinB.max.y)) { THROW (Iex::BaseExc, "both images must have the same data window"); } Imath::Box2i dpyWinA = inA.displayWindow (); Imath::Box2i dpyWinB = inB.displayWindow (); if ((dpyWinA.min.x != dpyWinB.min.x) || (dpyWinA.min.y != dpyWinB.min.y) || (dpyWinA.max.x != dpyWinB.max.x) || (dpyWinA.max.y != dpyWinB.max.y)) { THROW (Iex::BaseExc, "both images must have the same display " << "window"); } // // Open C for writing, preserving the data window and display // window of the original images. // Imf::RgbaOutputFile outC (exrC.c_str (), dpyWinA, dataWinA, Imf::WRITE_RGBA); // // Read A and B. // Imath::V2i dim (dataWinA.max.x - dataWinA.min.x + 1, dataWinA.max.y - dataWinA.min.y + 1); int dx = dataWinA.min.x; int dy = dataWinA.min.y; Imf::Array<Imf::Rgba> imgA (dim.x * dim.y); Imf::Array<Imf::Rgba> imgB (dim.x * dim.y); inA.setFrameBuffer (imgA - dx - dy * dim.x, 1, dim.x); inA.readPixels (dataWinA.min.y, dataWinA.max.y); inB.setFrameBuffer (imgB - dx - dy * dim.x, 1, dim.x); inB.readPixels (dataWinB.min.y, dataWinB.max.y); // // Do the comp, overwrite image B with the result. // if (op == "over") Comp::over (dim, imgA, imgB, imgB); else if (op == "in") Comp::in (dim, imgA, imgB, imgB); else Comp::out (dim, imgA, imgB, imgB); // // Write comp'ed image. // outC.setFrameBuffer (imgB - dx - dy * dim.x, 1, dim.x); outC.writePixels (dim.y); } catch (clo::autoexcept & e) { switch (e.get_autothrow_id ()) { case clo::autothrow_help: cout << "Usage: exrcomp [options] <a.exr> <over|in|out> " << "<b.exr> <output.exr>" << endl; cout << e.what (); break; case clo::autothrow_version: cout << "exrcomp version 1.0" << endl; break; default: cerr << "Internal error (illegal autothrow)" << endl; cerr << e.what () << endl; status = 1; } } catch (clo::option_error & e) { cerr << "exrcomp: " << e.what () << endl; cerr << "Use -h for help." << endl; status = 1; } catch (exception & e) { cerr << "exrcomp: " << e.what () << endl; status = 1; } catch (...) { cerr << "exrcomp: caught unhandled exception" << endl; status = 1; } return status; }