OpenEXR: add support for writing EXR files to memory.

This commit is contained in:
Brecht Van Lommel 2016-02-20 14:52:36 +01:00
parent 624d010fe5
commit 8326d59dbb
2 changed files with 92 additions and 42 deletions

View File

@ -116,19 +116,42 @@ static void imb_exr_type_by_channels(ChannelList &channels,
/* Memory Input Stream */
class Mem_IStream : public Imf::IStream {
class IMemStream : public Imf::IStream {
public:
Mem_IStream(unsigned char *exrbuf, size_t exrsize)
: IStream("dummy"), _exrpos(0), _exrsize(exrsize)
IMemStream(unsigned char *exrbuf, size_t exrsize)
: IStream("<memory>"), _exrpos(0), _exrsize(exrsize)
{
_exrbuf = exrbuf;
}
virtual bool read(char c[], int n);
virtual Int64 tellg();
virtual void seekg(Int64 pos);
virtual void clear();
//virtual ~Mem_IStream() {}; // unused
virtual ~IMemStream()
{
}
virtual bool read(char c[], int n)
{
if (n + _exrpos <= _exrsize) {
memcpy(c, (void *)(&_exrbuf[_exrpos]), n);
_exrpos += n;
return true;
}
else
return false;
}
virtual Int64 tellg()
{
return _exrpos;
}
virtual void seekg(Int64 pos)
{
_exrpos = pos;
}
virtual void clear()
{
}
private:
Int64 _exrpos;
@ -136,31 +159,6 @@ class Mem_IStream : public Imf::IStream {
unsigned char *_exrbuf;
};
bool Mem_IStream::read(char c[], int n)
{
if (n + _exrpos <= _exrsize) {
memcpy(c, (void *)(&_exrbuf[_exrpos]), n);
_exrpos += n;
return true;
}
else
return false;
}
Int64 Mem_IStream::tellg()
{
return _exrpos;
}
void Mem_IStream::seekg(Int64 pos)
{
_exrpos = pos;
}
void Mem_IStream::clear()
{
}
/* File Input Stream */
class IFileStream : public Imf::IStream {
@ -222,6 +220,48 @@ class IFileStream : public Imf::IStream {
std::ifstream ifs;
};
/* Memory Output Stream */
class OMemStream : public OStream {
public:
OMemStream(ImBuf *ibuf_) : OStream("<memory>"), ibuf(ibuf_), offset(0)
{
}
virtual void write(const char c[], int n)
{
ensure_size(offset + n);
memcpy(ibuf->encodedbuffer + offset, c, n);
offset += n;
ibuf->encodedsize += n;
}
virtual Int64 tellp()
{
return offset;
}
virtual void seekp(Int64 pos)
{
offset = pos;
ensure_size(offset);
}
private:
void ensure_size(Int64 size)
{
/* if buffer is too small increase it. */
while (size > ibuf->encodedbuffersize) {
if (!imb_enlargeencodedbufferImBuf(ibuf)) {
throw Iex::ErrnoExc("Out of memory.");
}
}
}
ImBuf *ibuf;
Int64 offset;
};
/* File Output Stream */
class OFileStream : public OStream {
@ -367,6 +407,7 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags
const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
OStream *file_stream = NULL;
try {
Header header(width, height);
@ -386,8 +427,11 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags
FrameBuffer frameBuffer;
/* manually create ofstream, so we can handle utf-8 filepaths on windows */
OFileStream file_stream(name);
OutputFile file(file_stream, header);
if (flags & IB_mem)
file_stream = new OMemStream(ibuf);
else
file_stream = new OFileStream(name);
OutputFile file(*file_stream, header);
/* we store first everything in half array */
std::vector<RGBAZ> pixels(height * width);
@ -448,11 +492,13 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags
file.writePixels(height);
}
catch (const std::exception &exc) {
delete file_stream;
printf("OpenEXR-save: ERROR: %s\n", exc.what());
return false;
}
delete file_stream;
return true;
}
@ -463,6 +509,7 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag
const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */
const int width = ibuf->x;
const int height = ibuf->y;
OStream *file_stream = NULL;
try {
Header header(width, height);
@ -482,8 +529,11 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag
FrameBuffer frameBuffer;
/* manually create ofstream, so we can handle utf-8 filepaths on windows */
OFileStream file_stream(name);
OutputFile file(file_stream, header);
if (flags & IB_mem)
file_stream = new OMemStream(ibuf);
else
file_stream = new OFileStream(name);
OutputFile file(*file_stream, header);
int xstride = sizeof(float) * channels;
int ystride = -xstride * width;
@ -516,19 +566,19 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag
}
catch (const std::exception &exc) {
printf("OpenEXR-save: ERROR: %s\n", exc.what());
delete file_stream;
return false;
}
delete file_stream;
return true;
}
int imb_save_openexr(struct ImBuf *ibuf, const char *name, int flags)
{
if (flags & IB_mem) {
printf("OpenEXR-save: Create EXR in memory CURRENTLY NOT SUPPORTED !\n");
imb_addencodedbufferImBuf(ibuf);
ibuf->encodedsize = 0;
return (0);
}
if (ibuf->foptions.flag & OPENEXR_HALF)
@ -1792,7 +1842,7 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem,
char colorspace[IM_MAX_SPACE])
{
struct ImBuf *ibuf = NULL;
Mem_IStream *membuf = NULL;
IMemStream *membuf = NULL;
MultiPartInputFile *file = NULL;
if (imb_is_a_openexr(mem) == 0)
@ -1803,7 +1853,7 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem,
try {
bool is_multi;
membuf = new Mem_IStream((unsigned char *)mem, size);
membuf = new IMemStream((unsigned char *)mem, size);
file = new MultiPartInputFile(*membuf);
Box2i dw = file->header(0).dataWindow();

View File

@ -83,7 +83,7 @@ static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length)
{
ImBuf *ibuf = (ImBuf *)png_get_io_ptr(png_ptr);
/* if buffer is to small increase it. */
/* if buffer is too small increase it. */
while (ibuf->encodedsize + length > ibuf->encodedbuffersize) {
imb_enlargeencodedbufferImBuf(ibuf);
}