bool Bitmap::loadEXR(const char* filename) { try { Imf::RgbaInputFile exr(filename); Imf::Array2D<Imf::Rgba> pixels; Imath::Box2i dw = exr.dataWindow(); width = dw.max.x - dw.min.x + 1; height = dw.max.y - dw.min.y + 1; pixels.resizeErase(height, width); exr.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); exr.readPixels(dw.min.y, dw.max.y); data = new Color[width * height]; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { Color& pixel = data[y * width + x]; pixel.r = pixels[y + dw.min.y][x + dw.min.x].r; pixel.g = pixels[y + dw.min.y][x + dw.min.x].g; pixel.b = pixels[y + dw.min.y][x + dw.min.x].b; } return true; } catch (Iex::BaseExc ex) { width = height = 0; data = NULL; return false; } }
//////////////////////////////////////////////////////////////////////////// // 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; }
template<class T> Array<Vector<T,3>,2> ExrFile<T>:: read(const std::string& filename) { Imf::RgbaInputFile file(filename.c_str()); Imath::Box2i dw = file.dataWindow(); int width = dw.max.x - dw.min.x + 1; int height = dw.max.y - dw.min.y + 1; Imf::Array2D<Imf::Rgba> pixels; pixels.resizeErase(height, width); file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width); file.readPixels(dw.min.y, dw.max.y); Array<Vector<T,3>,2> image(width, height); for (int i = 0; i < image.m; ++i) { for (int j = 0; j < image.n; ++j) { image(i,j) = from_rgba<T>(pixels[j][i]); } } return image; }
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); } } }
/*! 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 }
int main(int argc, char** argv) { //clock_t start = clock(); //glutInit(&argc, argv); //glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); std::cout << argc << endl; if (argc == 3) { name = argv[2]; } else if (argc == 2) { name = argv[1]; name = name.substr(0, name.find_last_of('.')) + ".exr"; } else { /*clock_t start = clock(); srand(time(NULL)); #define __R rand() / (double)RAND_MAX #define __VR Vector3d(__R, __R, __R) Sphere* ss = new Sphere(Vector3d(__R, __R, __R), __R, new Material(Vector3d::Ones, Vector3d::Ones, Vector3d::Ones, 0, Vector3d::Ones, 0, Vector3d::Ones)); bool result = false; hitRecord r; for (int i = 0; i < 1e6; i++) { result = ss->hit(Ray(__VR, __VR, std::vector<double>(), std::vector<Vector3d>(), Ray::VIEW), nINF, INF, r); } clock_t ends = clock(); double runtime = (double) (ends - start) / CLOCKS_PER_SEC; cout << runtime << " seconds" << endl; return result;*/ /* Interval i(0, 1); cout << i << endl; cout << "should be true: " << Interval::intersects(i, Interval(-1, 0.5)) << endl; cout << "============= binary Intersects ============" << endl; cout << "should be (0, 0.5): " << i.intersect(Interval(-1, 0.5)) << endl; cout << "should be (0.2, 0.8): " << i.intersect(Interval(0.2, 0.8)) << endl; cout << "should be (0.5, 1): " << i.intersect(Interval(0.5, 4)) << endl; cout << "should be (): " << i.intersect(Interval(9, 10)) << endl; cout << "should be (): " << i.intersect(Interval()) << endl; cout << "============= binary Unions ================" << endl; cout << "should be (0, 4) and (0, 4): " << i.unionize(Interval(1, 4)) << " " << i.unionize(Interval(0.5, 4)) << endl; cout << "should be {(0, 1), (5, 6)}: " << i.unionize(Interval(5, 6)) << endl; cout << "should be {(-5, -3), (0, 1)}: " << i.unionize(Interval(-5, -3)) << endl; cout << "should be (-5, 5): " << i.unionize(Interval(-5, 5)) << endl; cout << "should be (0, 1): " << i.unionize(Interval()) << endl; cout << "============= binary Differences ===========" << endl; Interval k(-5, 5); cout << "should be {(-5, -2), (2, 5)}: " << k.difference(Interval(-2, 2)) << endl; cout << "should be (0, 5): " << k.difference(Interval(-5, 0)) << endl; cout << "should be (-5, 0): " << k.difference(Interval(0, 5)) << endl; cout << "should be (): " << k.difference(k) << endl; cout << "should be (): " << k.difference(Interval(-10, 10)) << endl; cout << "should be (-5, 5): " << k.difference(Interval(10, 20)) << endl; cout << "should be (-5, 5): " << k.difference(Interval(-20, -10)) << endl; cout << "should be (-5, 5): " << k.difference(Interval()) << endl; cout << "should be (): " << Interval().difference(k) << endl; cout << "============= Multiple Unions ==============" << endl; Intervals j; j.push_back(Interval(-1, 1)); j.push_back(Interval(1.5, 2)); j.push_back(Interval(2.5, 3)); //j = Interval::unionize(j); cout << "{(-1, 1), (1.5, 2), (2.5, 3)}: " << j << endl; Intervals x = j; x.push_back(Interval(2, 4)); //x = Interval::unionize(x); cout << "{(-1, 1), (1.5, 4)}: " << x << endl; x = j; x.push_back(Interval(-5, 5)); //cout << "{(-5, 5)}: " << Interval::unionize(x) << endl; Intervals y; y.push_back(Interval(0, 2)); y.push_back(Interval(3, 4)); y.push_back(Interval(-3, -2)); x.pop_back(); x.insert(x.end(), y.begin(), y.end()); //cout << x << endl << Interval::unionize(x) << endl; exit(0);*/ } tracer.parse(argv[1]); width = tracer.width; height = tracer.height; pixels = new unsigned int[width * height]; for (int i = 0; i < width * height; i++) { pixels[i] = 0; } o.resizeErase (height, width); cout << endl << width << " " << height << endl; clock_t start = clock(); tracer.render(o); clock_t ends = clock(); double runtime = (double) (ends - start) / CLOCKS_PER_SEC; cout << runtime << " seconds" << endl; writeRgba(name.c_str(), &o[0][0], width, height); return 0; //glutInitWindowPosition(0,0); //glutInitWindowSize(width,height); //glWindow = glutCreateWindow("RayTra"); //glViewport(0, 0, width, height); //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); //gluOrtho2D(0, width, 0, height); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); //glClearColor(0.0, 0.0, 0.0, 0.0); //glutDisplayFunc(display); //glutIdleFunc(idle); //glutKeyboardFunc(keylistener); //glDisable(GL_DEPTH_TEST); //glutMainLoop(); //clock_t ends = clock(); //double runtime = (double) (ends - start) / CLOCKS_PER_SEC; //std::cout << "Elapsed: " << runtime << std::endl; }
ChannelInfo( int inStride, int inDim1, int inDim2) { stride = inStride; array2d.resizeErase( inDim1 * stride, inDim2); }