24#include <ImfOutputFile.h>
25#include <ImfChannelList.h>
26#include <ImfVersion.h>
28#include <ImfFrameBuffer.h>
33#ifndef IMATH_NAMESPACE
34#define IMATH_NAMESPACE Imath
43static const char *
const extensions_exr[] = {
46static const int num_extensions_exr =
sizeof(extensions_exr) /
sizeof(
const char *);
49class ImfStdOstream :
public IMF::OStream {
51 ImfStdOstream(std::ostream &strm) : IMF::OStream(
"ostream"), _strm(strm) {}
53 virtual void write(
const char c[],
int n) {
57#if OPENEXR_VERSION_MAJOR >= 3
58 virtual uint64_t tellp() {
62 virtual void seekp(uint64_t pos) {
66 virtual IMF::Int64 tellp() {
70 virtual void seekp(IMF::Int64 pos) {
80class ImfStdIstream :
public IMF::IStream {
82 ImfStdIstream(std::istream &strm,
const std::string &magic_number) : IMF::IStream(
"istream"), _strm(strm) {
84 for (std::string::const_reverse_iterator mi = magic_number.rbegin();
85 mi != magic_number.rend();
91 virtual bool isMemoryMapped ()
const {
95 virtual bool read (
char c[],
int n) {
97 if (_strm.gcount() != n) {
98 throw std::exception();
101 bool not_eof = !_strm.eof();
105#if OPENEXR_VERSION_MAJOR >= 3
106 virtual uint64_t tellg() {
107 return _strm.tellg();
110 virtual void seekg(uint64_t pos) {
114 virtual IMF::Int64 tellg() {
115 return _strm.tellg();
118 virtual void seekg(IMF::Int64 pos) {
123 virtual void clear() {
138string PNMFileTypeEXR::
148get_num_extensions()
const {
149 return num_extensions_exr;
156string PNMFileTypeEXR::
157get_extension(
int n)
const {
158 nassertr(n >= 0 && n < num_extensions_exr,
string());
159 return extensions_exr[n];
166string PNMFileTypeEXR::
167get_suggested_extension()
const {
176has_magic_number()
const {
186matches_magic_number(
const string &magic_number)
const {
187 nassertr(magic_number.size() >= 2,
false);
189 if (magic_number.size() >= 4) {
192 return IMF::isImfMagic(magic_number.data());
195 return magic_number[0] == ((IMF::MAGIC >> 0) & 0x00ff) &&
196 magic_number[1] == ((IMF::MAGIC >> 8) & 0x00ff);
206make_reader(istream *file,
bool owns_file,
const string &magic_number) {
208 return new Reader(
this, file, owns_file, magic_number);
217make_writer(ostream *file,
bool owns_file) {
219 return new Writer(
this, file, owns_file);
225PNMFileTypeEXR::Reader::
226Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
228 _strm(new ImfStdIstream(*_file, magic_number)),
231 const IMF::Header &header = _imf_file.header();
233 IMATH_NAMESPACE::Box2i dw = header.dataWindow();
234 _x_size = dw.max.x - dw.min.x + 1;
235 _y_size = dw.max.y - dw.min.y + 1;
239 _channel_names.clear();
241 const IMF::ChannelList &channels = header.channels();
247 const char *possible_channel_names[] = {
"R",
"G",
"B",
"Y",
"A",
nullptr };
248 for (
const char **pni = possible_channel_names; *pni !=
nullptr; ++pni) {
249 std::string name = *pni;
250 IMF::ChannelList::ConstIterator ci = channels.find(name.c_str());
251 if (ci != channels.end()) {
253 if (name ==
"Y" && !_channel_names.empty()) {
257 _channel_names.push_back(name);
262 if (_channel_names.empty()) {
267 _channel_names.push_back(
"R");
268 _channel_names.push_back(
"G");
269 _channel_names.push_back(
"B");
272 _num_channels = (int)_channel_names.size();
273 if (_num_channels == 0 || _num_channels > 4) {
287PNMFileTypeEXR::Reader::
297bool PNMFileTypeEXR::Reader::
309bool PNMFileTypeEXR::Reader::
311 pfm.
clear(_x_size, _y_size, _num_channels);
315 PN_float32 *table_data = table.data();
317 size_t y_stride = x_stride * pfm.
get_x_size();
318 nassertr(y_stride * pfm.
get_y_size() <= table.size() *
sizeof(PN_float32),
false);
320 const IMF::Header &header = _imf_file.header();
321 IMATH_NAMESPACE::Box2i dw = header.dataWindow();
323 IMF::FrameBuffer frameBuffer;
326 frameBuffer.insert(_channel_names[ci].c_str(),
327 IMF::Slice(IMF::FLOAT, base, x_stride, y_stride,
331 _imf_file.setFrameBuffer(frameBuffer);
334 _imf_file.readPixels(dw.min.y, dw.max.y);
335 }
catch (
const std::exception &exc) {
336 pnmimage_exr_cat.error()
337 << exc.what() <<
"\n";
354int PNMFileTypeEXR::Reader::
355read_data(
xel *array, xelval *alpha) {
365PNMFileTypeEXR::Writer::
366Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
376bool PNMFileTypeEXR::Writer::
377supports_floating_point() {
386bool PNMFileTypeEXR::Writer::
395bool PNMFileTypeEXR::Writer::
397 const vector_float &table = pfm.
get_table();
398 const PN_float32 *table_data = table.data();
400 size_t y_stride = x_stride * pfm.
get_x_size();
401 nassertr(y_stride * pfm.
get_y_size() <= table.size() *
sizeof(PN_float32),
false);
403 const char *channel_names_1[] = {
"G" };
404 const char *channel_names_2[] = {
"G",
"A" };
405 const char *channel_names_3[] = {
"R",
"G",
"B" };
406 const char *channel_names_4[] = {
"R",
"G",
"B",
"A" };
407 const char **channel_names =
nullptr;
411 channel_names = channel_names_1;
415 channel_names = channel_names_2;
419 channel_names = channel_names_3;
423 channel_names = channel_names_4;
432 header.channels().insert(channel_names[ci], IMF::Channel(IMF::FLOAT));
435 IMF::FrameBuffer frameBuffer;
437 const char *base = (
const char *)(table_data + ci);
438 frameBuffer.insert(channel_names[ci],
439 IMF::Slice(IMF::FLOAT, (
char *)base, x_stride, y_stride));
442 ImfStdOstream strm(*_file);
443 IMF::OutputFile file(strm, header);
444 file.setFrameBuffer(frameBuffer);
448 }
catch (
const std::exception &exc) {
449 pnmimage_exr_cat.error()
450 << exc.what() <<
"\n";
473int PNMFileTypeEXR::Writer::
474write_data(
xel *array, xelval *alpha) {
485register_with_read_factory() {
487 register_factory(get_class_type(), make_PNMFileTypeEXR);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
This is the base class of a family of classes that represent particular image file types that PNMImag...
This is an abstract base class that defines the interface for reading image files of various types.
This is an abstract base class that defines the interface for writing image files of various types.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component,...
void swap_table(vector_float &table)
This is a very low-level function that completely exchanges the PfmFile's internal table of floating-...
const vector_float & get_table() const
This is a very low-level function that returns a read-only reference to the internal table of floatin...
void clear()
Eliminates all data in the file.
TypeHandle is the identifier used to differentiate C++ class types.
Base class for objects that can be written to and read from Bam files.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.