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
1.5.6