HDRUtils.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @class  HDRUtils.h
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @date   January 2009
00005    
00006    @brief
00007       Utilities for reading and writing HDR, OpenEXR, and PFM high dynamic 
00008    range image formats
00009    
00010    @note
00011       This code is based on similar code found in exrtools, by Billy Biggs 
00012    (http://scanline.ca/exrtools/)
00013    <!-------------------------------------------------------------------->**/
00014 
00015 #include "HDRUtils.h"
00016 #include "HDRImage.h"
00017 #include "RgbaImage.h"
00018 
00019 // third-party
00020 #include "rgbe.h"
00021 
00022 #ifdef HAVE_OPENEXR
00023 #  include "exrinput.h"
00024 #  include <ImfRgbaFile.h>
00025 #endif
00026 
00027 using namespace std;
00028 
00029 HDRImage *HDRUtils::loadHDR(const string &filename) {
00030    FILE *f = fopen(filename.c_str(), "r");
00031    unsigned width = 0, height = 0;
00032    
00033    if (NULL == f)
00034       return NULL;
00035    
00036    if (RGBE_ReadHeader(f, (int*)&width, (int*)&height, NULL) || 
00037        width == 0 || height == 0)
00038    {
00039       return NULL;
00040    }
00041    
00042    HDRImage *image = new HDRImage(width, height);
00043    float   *buffer = new float[3 * width];
00044    
00045    for(unsigned i = 0; i < height; ++i) {
00046       if (RGBE_ReadPixels_RLE(f, buffer, width, 1)) {
00047          safeDelete(image);
00048          safeDeleteArray(buffer);
00049          return NULL;
00050       }
00051       
00052       for(unsigned j = width; j--;) {
00053          const float *q = buffer + j * 3;
00054          
00055          image->setPixel<RgbaHDR>(i, j, RgbaHDR(q[0], q[1], q[2]));
00056       }
00057    }
00058    
00059    fclose(f);
00060    safeDeleteArray(buffer);
00061    
00062    return image;
00063 }
00064 
00065 HDRImage *HDRUtils::loadEXR(const string &filename) {
00066 #ifndef HAVE_OPENEXR
00067    HDRUtils::_warnMissingEXR(__FUNCTION__, filename);
00068    
00069    return NULL;
00070 #else
00071    unsigned width, height;
00072    exrinput_t *exrin;
00073    
00074    if (!(exrin = exrinput_new(filename.c_str())))
00075       return NULL;
00076    
00077    width  = exrinput_get_width(exrin);
00078    height = exrinput_get_height(exrin);
00079    
00080    HDRImage *image = new HDRImage(width, height);
00081    if (!image) {
00082       exrinput_delete(exrin);
00083       return NULL;
00084    }
00085    
00086    for(unsigned i = 0; i < height; ++i) {
00087       double *inscanline = exrinput_get_scanline(exrin, i);
00088       
00089       for(unsigned j = width; j--;) {
00090          const double *q = inscanline + 4 * j;
00091          
00092          image->setPixel<RgbaHDR>(i, j, RgbaHDR(q[0], q[1], q[2], q[3]));
00093       }
00094    }
00095    
00096    exrinput_delete(exrin);
00097    return image;
00098 #endif
00099 }
00100 
00101 HDRImage *HDRUtils::loadPFM(const string &filename) {
00102    NYI(); // TODO
00103    
00104    return NULL;
00105 }
00106 
00107 bool HDRUtils::saveHDR(const string &filename, const Image *image) {
00108    const string &filenameExt = HDRUtils::_toFullName(filename, ".hdr");
00109    const unsigned width  = image->getWidth();
00110    const unsigned height = image->getHeight();
00111    FILE *f = fopen(filenameExt.c_str(), "wb");
00112    
00113    if (NULL == f)
00114       return false;
00115    
00116    if (RGBE_WriteHeader(f, width, height, NULL))
00117       return false;
00118    
00119    float *buffer = new float[3 * width];
00120    
00121    for(unsigned i = 0; i < height; ++i) {
00122       for(unsigned j = width; j--;) {
00123          const RgbaHDR &p = image->getPixel<RgbaHDR>(i, j);
00124          float *q = buffer + j * 3;
00125          
00126          q[0] = MAX(0, p.r);
00127          q[1] = MAX(0, p.g);
00128          q[2] = MAX(0, p.b);
00129       }
00130       
00131       if (RGBE_WritePixels_RLE(f, buffer, width, 1)) {
00132          safeDeleteArray(buffer);
00133          return false;
00134       }
00135    }
00136    
00137    fclose(f);
00138    safeDeleteArray(buffer);
00139    
00140    return true;
00141 }
00142 
00143 bool HDRUtils::saveEXR(const string &filename, const Image *image) {
00144 #ifndef HAVE_OPENEXR
00145    HDRUtils::_warnMissingEXR(__FUNCTION__, filename);
00146    
00147    return false;
00148 #else
00149    const string &filenameExt = HDRUtils::_toFullName(filename, ".exr");
00150    const unsigned width  = image->getWidth();
00151    const unsigned height = image->getHeight();
00152    vector<Imf::Rgba> rgba(width * height);
00153    
00154    for(unsigned i = height; i--;) {
00155       for(unsigned j = width; j--;) {
00156          const RgbaHDR &p = image->getPixel<RgbaHDR>(i, j);
00157          
00158          Imf::Rgba &q = rgba[i * width + j];
00159          q.r = p.r;
00160          q.g = p.g;
00161          q.b = p.b;
00162          q.a = p.a;
00163       }
00164    }
00165    
00166    Imf::RgbaOutputFile file(filename.c_str(), width, height, Imf::WRITE_RGBA);
00167    file.setFrameBuffer((const Imf::Rgba*)&rgb[0], 1, width);
00168    file.writePixels(height);
00169    
00170    return true;
00171 #endif
00172 }
00173 
00174 bool HDRUtils::savePFM(const string &filename, const Image *image) {
00175    NYI(); // TODO
00176    
00177    return false;
00178 }
00179 
00180 HDRImage  *HDRUtils::toHDRImage (const RgbaImage *in) {
00181    ASSERT(in);
00182    
00183    HDRImage *out = new HDRImage(in->getWidth(), in->getHeight());
00184    out->setData(in->getData());
00185    
00186    return out;
00187 }
00188 
00189 RgbaImage *HDRUtils::toRgbaImage(const HDRImage *in) {
00190    ASSERT(in);
00191    
00192    RgbaImage *out  = new RgbaImage(in->getWidth(), in->getHeight());
00193    out->setData(in->getData());
00194    
00195    return out;
00196 }
00197 
00198 string HDRUtils::_toFullName(const string &filename, 
00199                              const string &ext)
00200 {
00201    const string::size_type extPos = filename.find_last_of('.');
00202    
00203    if (extPos == string::npos)
00204       return filename + ext;
00205    
00206    return filename;
00207 }
00208 
00209 void HDRUtils::_warnMissingEXR(const char *function, 
00210                                const string &filename)
00211 {
00212    cerr << (function ? function : "") << ": " 
00213         << "This build of Milton does not support OpenEXR" 
00214         << endl;
00215 }
00216 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6