19 #include <nori/bitmap.h>
20 #include <ImfInputFile.h>
21 #include <ImfOutputFile.h>
22 #include <ImfChannelList.h>
23 #include <ImfStringAttribute.h>
24 #include <ImfVersion.h>
28 #define STB_IMAGE_WRITE_IMPLEMENTATION
29 #include <stb_image_write.h>
34 Imf::InputFile file(filename.c_str());
35 const Imf::Header &header = file.header();
36 const Imf::ChannelList &channels = header.channels();
38 Imath::Box2i dw = file.header().dataWindow();
39 resize(dw.max.y - dw.min.y + 1, dw.max.x - dw.min.x + 1);
41 cout <<
"Reading a " << cols() <<
"x" << rows() <<
" OpenEXR file from \""
42 << filename <<
"\"" << endl;
44 const char *ch_r =
nullptr, *ch_g =
nullptr, *ch_b =
nullptr;
45 for (Imf::ChannelList::ConstIterator it = channels.begin(); it != channels.end(); ++it) {
46 std::string name = toLower(it.name());
48 if (it.channel().xSampling != 1 || it.channel().ySampling != 1) {
53 if (!ch_r && (name ==
"r" || name ==
"red" ||
54 endsWith(name,
".r") || endsWith(name,
".red"))) {
56 }
else if (!ch_g && (name ==
"g" || name ==
"green" ||
57 endsWith(name,
".g") || endsWith(name,
".green"))) {
59 }
else if (!ch_b && (name ==
"b" || name ==
"blue" ||
60 endsWith(name,
".b") || endsWith(name,
".blue"))) {
65 if (!ch_r || !ch_g || !ch_b)
66 throw NoriException(
"This is not a standard RGB OpenEXR file!");
68 size_t compStride =
sizeof(float),
69 pixelStride = 3 * compStride,
70 rowStride = pixelStride * cols();
72 char *ptr =
reinterpret_cast<char *
>(data());
74 Imf::FrameBuffer frameBuffer;
75 frameBuffer.insert(ch_r, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
76 frameBuffer.insert(ch_g, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
77 frameBuffer.insert(ch_b, Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride));
78 file.setFrameBuffer(frameBuffer);
79 file.readPixels(dw.min.y, dw.max.y);
83 std::cout <<
"Saving " << filenameStem;
89 std::string filename = filenameStem +
".exr";
90 cout <<
"Writing a " << cols() <<
"x" << rows()
91 <<
" OpenEXR file to \"" << filename <<
"\"" << endl;
93 Imf::Header header((
int) cols(), (
int) rows());
94 header.insert(
"comments", Imf::StringAttribute(
"Generated by Nori"));
96 Imf::ChannelList &channels = header.channels();
97 channels.insert(
"R", Imf::Channel(Imf::FLOAT));
98 channels.insert(
"G", Imf::Channel(Imf::FLOAT));
99 channels.insert(
"B", Imf::Channel(Imf::FLOAT));
101 Imf::FrameBuffer frameBuffer;
102 size_t compStride =
sizeof(float),
103 pixelStride = 3 * compStride,
104 rowStride = pixelStride * cols();
106 char *ptr =
reinterpret_cast<char *
>(data());
107 frameBuffer.insert(
"R", Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
108 frameBuffer.insert(
"G", Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride)); ptr += compStride;
109 frameBuffer.insert(
"B", Imf::Slice(Imf::FLOAT, ptr, pixelStride, rowStride));
111 Imf::OutputFile file(filename.c_str(), header);
112 file.setFrameBuffer(frameBuffer);
113 file.writePixels((
int) rows());
116 static float GammaCorrect(
float value) {
117 if (value <= 0.0031308f)
return 12.92f * value;
118 return 1.055f * std::pow(value, 1.f/2.4f) - 0.055f;
120 static float Clamp(
float val,
float low,
float high) {
130 std::string filename = filenameStem +
".png";
131 cout <<
"Writing a " << cols() <<
"x" << rows()
132 <<
" PNG file to \"" << filename <<
"\"" << endl;
134 std::unique_ptr<uint8_t[]> rgb8(
new uint8_t[3 * cols() * rows()]);
135 uint8_t *dst = rgb8.get();
136 for (
int y = 0; y < rows(); ++y) {
137 for (
int x = 0; x < cols(); ++x) {
138 #define TO_BYTE(v) (uint8_t) Clamp(255.f * GammaCorrect(v) + 0.5f, 0.f, 255.f)
139 dst[0] = TO_BYTE(coeff(y,x).r());
140 dst[1] = TO_BYTE(coeff(y,x).g());
141 dst[2] = TO_BYTE(coeff(y,x).b());
146 int ret = stbi_write_png(filename.c_str(),cols(),rows(),3,rgb8.get(),3*cols());
148 cout <<
"Bitmap::savePNG(): Could not save PNG file \"" << filename <<
"%s\"" << endl;
void save(const std::string &filenameStem)
Save the bitmap as an EXR and PNG file with the specified filename.
void saveEXR(const std::string &filenameStem)
Save the bitmap as an EXR file with the specified filename.
void savePNG(const std::string &filenameStem)
Save the bitmap as a PNG file with the specified filename.
Bitmap(const Vector2i &size=Vector2i(0, 0))
Allocate a new bitmap of the specified size.
Simple exception class, which stores a human-readable error description.