24 #include <ImfOutputFile.h>
25 #include <ImfChannelList.h>
26 #include <ImfVersion.h>
29 #ifndef IMATH_NAMESPACE
30 #define IMATH_NAMESPACE Imath
39 static const char *
const extensions_exr[] = {
42 static const int num_extensions_exr =
sizeof(extensions_exr) /
sizeof(
const char *);
45 class ImfStdOstream :
public IMF::OStream {
47 ImfStdOstream(std::ostream &strm) : IMF::OStream(
"ostream"), _strm(strm) {}
49 virtual void write(
const char c[],
int n) {
53 virtual IMF::Int64 tellp() {
57 virtual void seekp(IMF::Int64 pos) {
66 class ImfStdIstream :
public IMF::IStream {
68 ImfStdIstream(std::istream &strm,
const std::string &magic_number) : IMF::IStream(
"istream"), _strm(strm) {
70 for (std::string::const_reverse_iterator mi = magic_number.rbegin();
71 mi != magic_number.rend();
77 virtual bool isMemoryMapped ()
const {
81 virtual bool read (
char c[],
int n) {
83 if (_strm.gcount() != n) {
84 throw std::exception();
87 bool not_eof = !_strm.eof();
91 virtual IMF::Int64 tellg() {
95 virtual void seekg(IMF::Int64 pos) {
99 virtual void clear() {
114 string PNMFileTypeEXR::
124 get_num_extensions()
const {
125 return num_extensions_exr;
132 string PNMFileTypeEXR::
133 get_extension(
int n)
const {
134 nassertr(n >= 0 && n < num_extensions_exr,
string());
135 return extensions_exr[n];
142 string PNMFileTypeEXR::
143 get_suggested_extension()
const {
151 bool PNMFileTypeEXR::
152 has_magic_number()
const {
161 bool PNMFileTypeEXR::
162 matches_magic_number(
const string &magic_number)
const {
163 nassertr(magic_number.size() >= 2,
false);
165 if (magic_number.size() >= 4) {
168 return IMF::isImfMagic(magic_number.data());
171 return magic_number[0] == ((IMF::MAGIC >> 0) & 0x00ff) &&
172 magic_number[1] == ((IMF::MAGIC >> 8) & 0x00ff);
182 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
184 return new Reader(
this, file, owns_file, magic_number);
193 make_writer(ostream *file,
bool owns_file) {
195 return new Writer(
this, file, owns_file);
201 PNMFileTypeEXR::Reader::
202 Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
204 _strm(new ImfStdIstream(*_file, magic_number)),
207 const IMF::Header &header = _imf_file.header();
209 IMATH_NAMESPACE::Box2i dw = header.dataWindow();
210 _x_size = dw.max.x - dw.min.x + 1;
211 _y_size = dw.max.y - dw.min.y + 1;
215 _channel_names.clear();
217 const IMF::ChannelList &channels = header.channels();
223 const char *possible_channel_names[] = {
"R",
"G",
"B",
"Y",
"A",
nullptr };
224 for (
const char **pni = possible_channel_names; *pni !=
nullptr; ++pni) {
225 std::string name = *pni;
226 IMF::ChannelList::ConstIterator ci = channels.find(name.c_str());
227 if (ci != channels.end()) {
229 if (name ==
"Y" && !_channel_names.empty()) {
233 _channel_names.push_back(name);
238 if (_channel_names.empty()) {
243 _channel_names.push_back(
"R");
244 _channel_names.push_back(
"G");
245 _channel_names.push_back(
"B");
248 _num_channels = (int)_channel_names.size();
249 if (_num_channels == 0 || _num_channels > 4) {
263 PNMFileTypeEXR::Reader::
273 bool PNMFileTypeEXR::Reader::
274 is_floating_point() {
285 bool PNMFileTypeEXR::Reader::
287 pfm.
clear(_x_size, _y_size, _num_channels);
291 PN_float32 *table_data = table.data();
293 size_t y_stride = x_stride * pfm.
get_x_size();
294 nassertr(y_stride * pfm.
get_y_size() <= table.size() *
sizeof(PN_float32),
false);
296 const IMF::Header &header = _imf_file.header();
297 IMATH_NAMESPACE::Box2i dw = header.dataWindow();
299 IMF::FrameBuffer frameBuffer;
302 frameBuffer.insert(_channel_names[ci].c_str(),
303 IMF::Slice(IMF::FLOAT, base, x_stride, y_stride,
307 _imf_file.setFrameBuffer(frameBuffer);
310 _imf_file.readPixels(dw.min.y, dw.max.y);
311 }
catch (
const std::exception &exc) {
312 pnmimage_exr_cat.error()
313 << exc.what() <<
"\n";
330 int PNMFileTypeEXR::Reader::
331 read_data(
xel *array, xelval *alpha) {
341 PNMFileTypeEXR::Writer::
342 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
352 bool PNMFileTypeEXR::Writer::
353 supports_floating_point() {
362 bool PNMFileTypeEXR::Writer::
371 bool PNMFileTypeEXR::Writer::
372 write_pfm(
const PfmFile &pfm) {
373 const vector_float &table = pfm.
get_table();
374 const PN_float32 *table_data = table.data();
376 size_t y_stride = x_stride * pfm.
get_x_size();
377 nassertr(y_stride * pfm.
get_y_size() <= table.size() *
sizeof(PN_float32),
false);
379 const char *channel_names_1[] = {
"G" };
380 const char *channel_names_2[] = {
"G",
"A" };
381 const char *channel_names_3[] = {
"R",
"G",
"B" };
382 const char *channel_names_4[] = {
"R",
"G",
"B",
"A" };
383 const char **channel_names =
nullptr;
387 channel_names = channel_names_1;
391 channel_names = channel_names_2;
395 channel_names = channel_names_3;
399 channel_names = channel_names_4;
408 header.channels().insert(channel_names[ci], IMF::Channel(IMF::FLOAT));
411 IMF::FrameBuffer frameBuffer;
413 const char *base = (
const char *)(table_data + ci);
414 frameBuffer.insert(channel_names[ci],
415 IMF::Slice(IMF::FLOAT, (
char *)base, x_stride, y_stride));
418 ImfStdOstream strm(*_file);
419 IMF::OutputFile file(strm, header);
420 file.setFrameBuffer(frameBuffer);
424 }
catch (
const std::exception &exc) {
425 pnmimage_exr_cat.error()
426 << exc.what() <<
"\n";
449 int PNMFileTypeEXR::Writer::
450 write_data(
xel *array, xelval *alpha) {
460 void PNMFileTypeEXR::
461 register_with_read_factory() {
463 register_factory(get_class_type(), make_PNMFileTypeEXR);
479 #endif // HAVE_OPENEXR