24 #include <ImfOutputFile.h>
25 #include <ImfChannelList.h>
26 #include <ImfVersion.h>
28 #include <ImfFrameBuffer.h>
29 #include <ImfHeader.h>
33 #ifndef IMATH_NAMESPACE
34 #define IMATH_NAMESPACE Imath
43 static const char *
const extensions_exr[] = {
46 static const int num_extensions_exr =
sizeof(extensions_exr) /
sizeof(
const char *);
49 class 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) {
80 class 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() {
138 string PNMFileTypeEXR::
148 get_num_extensions()
const {
149 return num_extensions_exr;
156 string PNMFileTypeEXR::
157 get_extension(
int n)
const {
158 nassertr(n >= 0 && n < num_extensions_exr,
string());
159 return extensions_exr[n];
166 string PNMFileTypeEXR::
167 get_suggested_extension()
const {
175 bool PNMFileTypeEXR::
176 has_magic_number()
const {
185 bool PNMFileTypeEXR::
186 matches_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);
206 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
208 return new Reader(
this, file, owns_file, magic_number);
217 make_writer(ostream *file,
bool owns_file) {
219 return new Writer(
this, file, owns_file);
225 PNMFileTypeEXR::Reader::
226 Reader(
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) {
287 PNMFileTypeEXR::Reader::
297 bool PNMFileTypeEXR::Reader::
298 is_floating_point() {
309 bool 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";
354 int PNMFileTypeEXR::Reader::
355 read_data(
xel *array, xelval *alpha) {
365 PNMFileTypeEXR::Writer::
366 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
376 bool PNMFileTypeEXR::Writer::
377 supports_floating_point() {
386 bool PNMFileTypeEXR::Writer::
395 bool PNMFileTypeEXR::Writer::
396 write_pfm(
const PfmFile &pfm) {
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";
473 int PNMFileTypeEXR::Writer::
474 write_data(
xel *array, xelval *alpha) {
484 void PNMFileTypeEXR::
485 register_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.