2023-06-15 13:09:04 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2005 `Gernot Ziegler <gz@lysator.liu.se>`. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup openexr
|
2012-03-09 18:28:30 +00:00
|
|
|
*/
|
|
|
|
|
|
2025-03-25 14:52:31 +01:00
|
|
|
#include "IMB_filetype.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <algorithm>
|
2023-11-02 11:08:35 +01:00
|
|
|
#include <cctype>
|
2020-12-04 11:28:09 +01:00
|
|
|
#include <cerrno>
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstdlib>
|
2022-05-19 14:55:04 -07:00
|
|
|
#include <fcntl.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <set>
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
#include <string>
|
2016-05-05 21:39:10 +02:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
/* The OpenEXR version can reliably be found in this header file from OpenEXR,
|
|
|
|
|
* for both 2.x and 3.x:
|
|
|
|
|
*/
|
|
|
|
|
#include <OpenEXR/OpenEXRConfig.h>
|
|
|
|
|
#define COMBINED_OPENEXR_VERSION \
|
|
|
|
|
((10000 * OPENEXR_VERSION_MAJOR) + (100 * OPENEXR_VERSION_MINOR) + OPENEXR_VERSION_PATCH)
|
|
|
|
|
|
|
|
|
|
#if COMBINED_OPENEXR_VERSION >= 20599
|
|
|
|
|
/* >=2.5.99 -> OpenEXR >=3.0 */
|
|
|
|
|
# include <Imath/half.h>
|
|
|
|
|
# include <OpenEXR/ImfFrameBuffer.h>
|
|
|
|
|
# define exr_file_offset_t uint64_t
|
|
|
|
|
#else
|
|
|
|
|
/* OpenEXR 2.x, use the old locations. */
|
|
|
|
|
# include <OpenEXR/half.h>
|
|
|
|
|
# define exr_file_offset_t Int64
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <OpenEXR/Iex.h>
|
|
|
|
|
#include <OpenEXR/ImfArray.h>
|
2025-03-11 21:21:23 +01:00
|
|
|
#include <OpenEXR/ImfAttribute.h>
|
2022-02-16 17:36:47 +01:00
|
|
|
#include <OpenEXR/ImfChannelList.h>
|
2025-03-11 21:21:23 +01:00
|
|
|
#include <OpenEXR/ImfChromaticities.h>
|
2022-02-16 17:36:47 +01:00
|
|
|
#include <OpenEXR/ImfCompression.h>
|
|
|
|
|
#include <OpenEXR/ImfCompressionAttribute.h>
|
|
|
|
|
#include <OpenEXR/ImfIO.h>
|
|
|
|
|
#include <OpenEXR/ImfInputFile.h>
|
2025-03-24 12:00:07 +01:00
|
|
|
#include <OpenEXR/ImfIntAttribute.h>
|
2022-02-16 17:36:47 +01:00
|
|
|
#include <OpenEXR/ImfOutputFile.h>
|
|
|
|
|
#include <OpenEXR/ImfPixelType.h>
|
2022-05-19 14:55:04 -07:00
|
|
|
#include <OpenEXR/ImfPreviewImage.h>
|
2022-05-20 09:59:46 +10:00
|
|
|
#include <OpenEXR/ImfRgbaFile.h>
|
2022-02-16 17:36:47 +01:00
|
|
|
#include <OpenEXR/ImfStandardAttributes.h>
|
|
|
|
|
#include <OpenEXR/ImfStringAttribute.h>
|
|
|
|
|
#include <OpenEXR/ImfVersion.h>
|
2016-05-05 21:39:10 +02:00
|
|
|
|
|
|
|
|
/* multiview/multipart */
|
2022-02-16 17:36:47 +01:00
|
|
|
#include <OpenEXR/ImfInputPart.h>
|
|
|
|
|
#include <OpenEXR/ImfMultiPartInputFile.h>
|
|
|
|
|
#include <OpenEXR/ImfMultiPartOutputFile.h>
|
|
|
|
|
#include <OpenEXR/ImfMultiView.h>
|
|
|
|
|
#include <OpenEXR/ImfOutputPart.h>
|
|
|
|
|
#include <OpenEXR/ImfPartHelper.h>
|
|
|
|
|
#include <OpenEXR/ImfPartType.h>
|
|
|
|
|
#include <OpenEXR/ImfTiledOutputPart.h>
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2015-03-12 14:02:33 +01:00
|
|
|
#include "DNA_scene_types.h" /* For OpenEXR compression constants */
|
|
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
#include <openexr_api.h>
|
|
|
|
|
|
2017-05-27 15:34:55 -04:00
|
|
|
#if defined(WIN32)
|
2023-10-19 17:07:56 +02:00
|
|
|
# include "utfconv.hh"
|
2022-05-19 14:55:04 -07:00
|
|
|
# include <io.h>
|
|
|
|
|
#else
|
|
|
|
|
# include <unistd.h>
|
2012-08-24 12:10:35 +00:00
|
|
|
#endif
|
|
|
|
|
|
2020-01-26 16:38:18 +01:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2022-05-19 14:55:04 -07:00
|
|
|
#include "BLI_fileops.h"
|
2025-02-11 16:59:42 +01:00
|
|
|
#include "BLI_listbase.h"
|
2024-10-09 12:34:49 +02:00
|
|
|
#include "BLI_math_base.hh"
|
2010-07-12 11:28:16 +00:00
|
|
|
#include "BLI_math_color.h"
|
2022-05-19 14:55:04 -07:00
|
|
|
#include "BLI_mmap.h"
|
2025-01-26 20:07:58 +01:00
|
|
|
#include "BLI_path_utils.hh"
|
|
|
|
|
#include "BLI_string.h"
|
2012-04-02 11:04:24 +00:00
|
|
|
#include "BLI_threads.h"
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
2024-03-26 12:57:30 -04:00
|
|
|
#include "BKE_idprop.hh"
|
2024-11-12 15:21:59 +01:00
|
|
|
#include "BKE_image.hh"
|
2015-01-31 17:15:43 +01:00
|
|
|
|
2024-01-18 22:50:23 +02:00
|
|
|
#include "IMB_allocimbuf.hh"
|
|
|
|
|
#include "IMB_colormanagement.hh"
|
|
|
|
|
#include "IMB_imbuf.hh"
|
|
|
|
|
#include "IMB_imbuf_types.hh"
|
|
|
|
|
#include "IMB_metadata.hh"
|
|
|
|
|
#include "IMB_openexr.hh"
|
2016-01-26 09:57:25 +01:00
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
using namespace Imf;
|
|
|
|
|
using namespace Imath;
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* prototype */
|
2024-08-26 13:53:02 +08:00
|
|
|
static struct ExrPass *imb_exr_get_pass(ListBase *lb, const char *passname);
|
2015-04-06 10:40:12 -03:00
|
|
|
static bool exr_has_multiview(MultiPartInputFile &file);
|
|
|
|
|
static bool exr_has_multipart_file(MultiPartInputFile &file);
|
2015-04-20 23:37:04 +10:00
|
|
|
static bool exr_has_alpha(MultiPartInputFile &file);
|
2020-09-04 20:59:13 +02:00
|
|
|
static void exr_printf(const char *__restrict fmt, ...);
|
2015-04-06 10:40:12 -03:00
|
|
|
static void imb_exr_type_by_channels(ChannelList &channels,
|
|
|
|
|
StringVector &views,
|
|
|
|
|
bool *r_singlelayer,
|
|
|
|
|
bool *r_multilayer,
|
|
|
|
|
bool *r_multiview);
|
|
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
/* XYZ with Illuminant E */
|
|
|
|
|
static Imf::Chromaticities CHROMATICITIES_XYZ_E{
|
|
|
|
|
{1.0f, 0.0f}, {0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f / 3.0f, 1.0f / 3.0f}};
|
|
|
|
|
/* Values matching ChromaticitiesForACES in https://github.com/ampas/aces_container */
|
|
|
|
|
static Imf::Chromaticities CHROMATICITIES_ACES_2065_1{
|
|
|
|
|
{0.7347f, 0.2653f}, {0.0f, 1.0f}, {0.0001f, -0.077f}, {0.32168f, 0.33767f}};
|
|
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
/* Memory Input Stream */
|
|
|
|
|
|
2016-02-20 14:52:36 +01:00
|
|
|
class IMemStream : public Imf::IStream {
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
public:
|
2022-09-13 16:29:06 +10:00
|
|
|
IMemStream(uchar *exrbuf, size_t exrsize) : IStream("<memory>"), _exrpos(0), _exrsize(exrsize)
|
2013-07-19 16:44:17 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
_exrbuf = exrbuf;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-04 12:02:52 +01:00
|
|
|
bool read(char c[], int n) override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
if (n + _exrpos <= _exrsize) {
|
|
|
|
|
memcpy(c, (void *)(&_exrbuf[_exrpos]), n);
|
|
|
|
|
_exrpos += n;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-08-07 12:39:50 +02:00
|
|
|
|
2025-03-11 19:55:28 +01:00
|
|
|
/* OpenEXR requests chunks of 4096 bytes even if the file is smaller than that. Return
|
|
|
|
|
* zeros when reading up to 2x that amount past the end of the file.
|
|
|
|
|
* This was fixed after the OpenEXR 3.3.2 release, but not in an official release yet. */
|
|
|
|
|
if (n + _exrpos < _exrsize + 8192) {
|
|
|
|
|
const size_t remainder = _exrsize - _exrpos;
|
|
|
|
|
if (remainder > 0) {
|
|
|
|
|
memcpy(c, (void *)(&_exrbuf[_exrpos]), remainder);
|
|
|
|
|
memset(c + remainder, 0, n - remainder);
|
|
|
|
|
_exrpos += n;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-07 12:39:50 +02:00
|
|
|
return false;
|
2016-02-20 14:52:36 +01:00
|
|
|
}
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t tellg() override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
return _exrpos;
|
2011-10-06 22:04:01 +00:00
|
|
|
}
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
void seekg(exr_file_offset_t pos) override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
_exrpos = pos;
|
|
|
|
|
}
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2023-03-29 16:50:54 +02:00
|
|
|
void clear() override {}
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2016-02-20 14:52:36 +01:00
|
|
|
private:
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t _exrpos;
|
|
|
|
|
exr_file_offset_t _exrsize;
|
2022-09-13 16:29:06 +10:00
|
|
|
uchar *_exrbuf;
|
2016-02-20 14:52:36 +01:00
|
|
|
};
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2022-05-19 14:55:04 -07:00
|
|
|
/* Memory-Mapped Input Stream */
|
|
|
|
|
|
|
|
|
|
class IMMapStream : public Imf::IStream {
|
|
|
|
|
public:
|
|
|
|
|
IMMapStream(const char *filepath) : IStream(filepath)
|
|
|
|
|
{
|
2023-10-10 14:47:01 +11:00
|
|
|
const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
|
2022-05-19 14:55:04 -07:00
|
|
|
if (file < 0) {
|
|
|
|
|
throw IEX_NAMESPACE::InputExc("file not found");
|
|
|
|
|
}
|
|
|
|
|
_exrpos = 0;
|
|
|
|
|
imb_mmap_lock();
|
|
|
|
|
_mmap_file = BLI_mmap_open(file);
|
|
|
|
|
imb_mmap_unlock();
|
2023-10-10 14:16:04 +11:00
|
|
|
close(file);
|
2022-06-10 10:29:35 +02:00
|
|
|
if (_mmap_file == nullptr) {
|
2022-05-19 14:55:04 -07:00
|
|
|
throw IEX_NAMESPACE::InputExc("BLI_mmap_open failed");
|
|
|
|
|
}
|
2022-09-13 16:29:06 +10:00
|
|
|
_exrbuf = (uchar *)BLI_mmap_get_pointer(_mmap_file);
|
2023-10-10 15:37:35 +11:00
|
|
|
_exrsize = BLI_mmap_get_length(_mmap_file);
|
2022-05-19 14:55:04 -07:00
|
|
|
}
|
|
|
|
|
|
2022-06-10 10:29:35 +02:00
|
|
|
~IMMapStream() override
|
2022-05-19 14:55:04 -07:00
|
|
|
{
|
|
|
|
|
imb_mmap_lock();
|
|
|
|
|
BLI_mmap_free(_mmap_file);
|
|
|
|
|
imb_mmap_unlock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is implementing regular `read`, not `readMemoryMapped`, because DWAA and DWAB
|
|
|
|
|
* decompressors load on unaligned offsets. Therefore we can't avoid the memory copy. */
|
|
|
|
|
|
|
|
|
|
bool read(char c[], int n) override
|
|
|
|
|
{
|
|
|
|
|
if (_exrpos + n > _exrsize) {
|
|
|
|
|
throw Iex::InputExc("Unexpected end of file.");
|
|
|
|
|
}
|
|
|
|
|
memcpy(c, _exrbuf + _exrpos, n);
|
|
|
|
|
_exrpos += n;
|
|
|
|
|
|
|
|
|
|
return _exrpos < _exrsize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exr_file_offset_t tellg() override
|
|
|
|
|
{
|
|
|
|
|
return _exrpos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void seekg(exr_file_offset_t pos) override
|
|
|
|
|
{
|
|
|
|
|
_exrpos = pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
BLI_mmap_file *_mmap_file;
|
|
|
|
|
exr_file_offset_t _exrpos;
|
|
|
|
|
exr_file_offset_t _exrsize;
|
2022-09-13 16:29:06 +10:00
|
|
|
uchar *_exrbuf;
|
2022-05-19 14:55:04 -07:00
|
|
|
};
|
|
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
/* File Input Stream */
|
|
|
|
|
|
2012-08-26 07:27:51 +00:00
|
|
|
class IFileStream : public Imf::IStream {
|
2012-08-24 14:04:21 +00:00
|
|
|
public:
|
2022-03-24 16:33:32 +11:00
|
|
|
IFileStream(const char *filepath) : IStream(filepath)
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
2025-05-17 09:18:03 +10:00
|
|
|
/* UTF8 file path support on windows. */
|
2017-05-27 15:34:55 -04:00
|
|
|
#if defined(WIN32)
|
2022-03-24 16:33:32 +11:00
|
|
|
wchar_t *wfilepath = alloc_utf16_from_8(filepath, 0);
|
|
|
|
|
ifs.open(wfilepath, std::ios_base::binary);
|
|
|
|
|
free(wfilepath);
|
2012-08-24 14:04:21 +00:00
|
|
|
#else
|
2022-03-24 16:33:32 +11:00
|
|
|
ifs.open(filepath, std::ios_base::binary);
|
2012-08-24 14:04:21 +00:00
|
|
|
#endif
|
|
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (!ifs) {
|
2012-08-24 14:04:21 +00:00
|
|
|
Iex::throwErrnoExc();
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2012-08-24 14:04:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-04 12:02:52 +01:00
|
|
|
bool read(char c[], int n) override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
2019-04-23 11:01:30 +10:00
|
|
|
if (!ifs) {
|
2012-08-24 14:04:21 +00:00
|
|
|
throw Iex::InputExc("Unexpected end of file.");
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
errno = 0;
|
|
|
|
|
ifs.read(c, n);
|
|
|
|
|
return check_error();
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t tellg() override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
return std::streamoff(ifs.tellg());
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
void seekg(exr_file_offset_t pos) override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
ifs.seekg(pos);
|
|
|
|
|
check_error();
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-04 12:02:52 +01:00
|
|
|
void clear() override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
ifs.clear();
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
private:
|
|
|
|
|
bool check_error()
|
|
|
|
|
{
|
|
|
|
|
if (!ifs) {
|
2019-04-23 11:01:30 +10:00
|
|
|
if (errno) {
|
2012-08-24 14:04:21 +00:00
|
|
|
Iex::throwErrnoExc();
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
std::ifstream ifs;
|
|
|
|
|
};
|
|
|
|
|
|
2016-02-20 14:52:36 +01:00
|
|
|
/* Memory Output Stream */
|
|
|
|
|
|
|
|
|
|
class OMemStream : public OStream {
|
|
|
|
|
public:
|
2023-03-29 16:50:54 +02:00
|
|
|
OMemStream(ImBuf *ibuf_) : OStream("<memory>"), ibuf(ibuf_), offset(0) {}
|
2016-02-20 14:52:36 +01:00
|
|
|
|
2020-12-04 12:02:52 +01:00
|
|
|
void write(const char c[], int n) override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
ensure_size(offset + n);
|
2023-05-18 10:19:01 +02:00
|
|
|
memcpy(ibuf->encoded_buffer.data + offset, c, n);
|
2016-02-20 14:52:36 +01:00
|
|
|
offset += n;
|
2023-05-18 10:19:01 +02:00
|
|
|
ibuf->encoded_size += n;
|
2016-02-20 14:52:36 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t tellp() override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
void seekp(exr_file_offset_t pos) override
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
offset = pos;
|
|
|
|
|
ensure_size(offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
2022-02-16 17:36:47 +01:00
|
|
|
void ensure_size(exr_file_offset_t size)
|
2016-02-20 14:52:36 +01:00
|
|
|
{
|
|
|
|
|
/* if buffer is too small increase it. */
|
2023-05-18 10:19:01 +02:00
|
|
|
while (size > ibuf->encoded_buffer_size) {
|
2016-02-20 14:52:36 +01:00
|
|
|
if (!imb_enlargeencodedbufferImBuf(ibuf)) {
|
|
|
|
|
throw Iex::ErrnoExc("Out of memory.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImBuf *ibuf;
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t offset;
|
2016-02-20 14:52:36 +01:00
|
|
|
};
|
|
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
/* File Output Stream */
|
|
|
|
|
|
|
|
|
|
class OFileStream : public OStream {
|
|
|
|
|
public:
|
2022-03-24 16:33:32 +11:00
|
|
|
OFileStream(const char *filepath) : OStream(filepath)
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
2025-05-17 09:18:03 +10:00
|
|
|
/* UTF8 file path support on windows. */
|
2017-05-27 15:34:55 -04:00
|
|
|
#if defined(WIN32)
|
2022-03-24 16:33:32 +11:00
|
|
|
wchar_t *wfilepath = alloc_utf16_from_8(filepath, 0);
|
|
|
|
|
ofs.open(wfilepath, std::ios_base::binary);
|
|
|
|
|
free(wfilepath);
|
2012-08-24 14:04:21 +00:00
|
|
|
#else
|
2022-03-24 16:33:32 +11:00
|
|
|
ofs.open(filepath, std::ios_base::binary);
|
2012-08-24 14:04:21 +00:00
|
|
|
#endif
|
|
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (!ofs) {
|
2012-08-24 14:04:21 +00:00
|
|
|
Iex::throwErrnoExc();
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2012-08-24 14:04:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-04 12:02:52 +01:00
|
|
|
void write(const char c[], int n) override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
errno = 0;
|
|
|
|
|
ofs.write(c, n);
|
|
|
|
|
check_error();
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
exr_file_offset_t tellp() override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
return std::streamoff(ofs.tellp());
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-02-16 17:36:47 +01:00
|
|
|
void seekp(exr_file_offset_t pos) override
|
2012-08-24 14:04:21 +00:00
|
|
|
{
|
|
|
|
|
ofs.seekp(pos);
|
|
|
|
|
check_error();
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
private:
|
|
|
|
|
void check_error()
|
|
|
|
|
{
|
|
|
|
|
if (!ofs) {
|
2019-04-23 11:01:30 +10:00
|
|
|
if (errno) {
|
2012-08-24 14:04:21 +00:00
|
|
|
Iex::throwErrnoExc();
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
throw Iex::ErrnoExc("File output failed.");
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
std::ofstream ofs;
|
|
|
|
|
};
|
|
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
struct _RGBAZ {
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
half r;
|
|
|
|
|
half g;
|
|
|
|
|
half b;
|
|
|
|
|
half a;
|
|
|
|
|
half z;
|
|
|
|
|
};
|
|
|
|
|
|
2020-12-09 16:29:11 +01:00
|
|
|
using RGBAZ = _RGBAZ;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
|
2021-01-13 14:20:26 +01:00
|
|
|
static half float_to_half_safe(const float value)
|
|
|
|
|
{
|
|
|
|
|
return half(clamp_f(value, -HALF_MAX, HALF_MAX));
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 16:29:06 +10:00
|
|
|
bool imb_is_a_openexr(const uchar *mem, const size_t size)
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
{
|
2020-11-11 16:14:09 +11:00
|
|
|
/* No define is exposed for this size. */
|
|
|
|
|
if (size < 4) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
return Imf::isImfMagic((const char *)mem);
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
|
|
|
|
|
2024-10-09 12:34:49 +02:00
|
|
|
static int openexr_jpg_like_quality_to_dwa_quality(int q)
|
|
|
|
|
{
|
|
|
|
|
q = blender::math::clamp(q, 0, 100);
|
|
|
|
|
|
2025-02-28 10:33:36 +01:00
|
|
|
/* Map default JPG quality of 90 to default DWA level of 45,
|
2024-10-09 12:34:49 +02:00
|
|
|
* "lossless" JPG quality of 100 to DWA level of 0, and everything else
|
|
|
|
|
* linearly based on those. */
|
|
|
|
|
constexpr int x0 = 100, y0 = 0;
|
2025-02-28 10:33:36 +01:00
|
|
|
constexpr int x1 = 90, y1 = 45;
|
2024-10-09 12:34:49 +02:00
|
|
|
q = y0 + (q - x0) * (y1 - y0) / (x1 - x0);
|
|
|
|
|
return q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void openexr_header_compression(Header *header, int compression, int quality)
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
{
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (compression) {
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_NONE:
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
header->compression() = NO_COMPRESSION;
|
|
|
|
|
break;
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_PXR24:
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
header->compression() = PXR24_COMPRESSION;
|
|
|
|
|
break;
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_ZIP:
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
header->compression() = ZIP_COMPRESSION;
|
|
|
|
|
break;
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_PIZ:
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
header->compression() = PIZ_COMPRESSION;
|
|
|
|
|
break;
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_RLE:
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
header->compression() = RLE_COMPRESSION;
|
|
|
|
|
break;
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_ZIPS:
|
|
|
|
|
header->compression() = ZIPS_COMPRESSION;
|
|
|
|
|
break;
|
|
|
|
|
case R_IMF_EXR_CODEC_B44:
|
|
|
|
|
header->compression() = B44_COMPRESSION;
|
|
|
|
|
break;
|
|
|
|
|
case R_IMF_EXR_CODEC_B44A:
|
|
|
|
|
header->compression() = B44A_COMPRESSION;
|
|
|
|
|
break;
|
2022-05-18 09:51:11 +02:00
|
|
|
#if OPENEXR_VERSION_MAJOR > 2 || (OPENEXR_VERSION_MAJOR >= 2 && OPENEXR_VERSION_MINOR >= 2)
|
2015-03-12 14:02:33 +01:00
|
|
|
case R_IMF_EXR_CODEC_DWAA:
|
|
|
|
|
header->compression() = DWAA_COMPRESSION;
|
2024-10-09 12:34:49 +02:00
|
|
|
header->dwaCompressionLevel() = openexr_jpg_like_quality_to_dwa_quality(quality);
|
2015-03-12 14:02:33 +01:00
|
|
|
break;
|
|
|
|
|
case R_IMF_EXR_CODEC_DWAB:
|
|
|
|
|
header->compression() = DWAB_COMPRESSION;
|
2024-10-09 12:34:49 +02:00
|
|
|
header->dwaCompressionLevel() = openexr_jpg_like_quality_to_dwa_quality(quality);
|
2015-03-12 14:02:33 +01:00
|
|
|
break;
|
|
|
|
|
#endif
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
default:
|
2006-12-21 10:41:43 +00:00
|
|
|
header->compression() = ZIP_COMPRESSION;
|
2012-06-13 17:27:49 +00:00
|
|
|
break;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-26 21:35:20 +01:00
|
|
|
static int openexr_header_get_compression(const Header &header)
|
|
|
|
|
{
|
|
|
|
|
switch (header.compression()) {
|
|
|
|
|
case NO_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_NONE;
|
|
|
|
|
case RLE_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_RLE;
|
|
|
|
|
case ZIPS_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_ZIPS;
|
|
|
|
|
case ZIP_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_ZIP;
|
|
|
|
|
case PIZ_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_PIZ;
|
|
|
|
|
case PXR24_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_PXR24;
|
|
|
|
|
case B44_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_B44;
|
|
|
|
|
case B44A_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_B44A;
|
|
|
|
|
case DWAA_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_DWAA;
|
|
|
|
|
case DWAB_COMPRESSION:
|
|
|
|
|
return R_IMF_EXR_CODEC_DWAB;
|
|
|
|
|
case NUM_COMPRESSION_METHODS:
|
|
|
|
|
return R_IMF_EXR_CODEC_NONE;
|
|
|
|
|
}
|
|
|
|
|
return R_IMF_EXR_CODEC_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
static void openexr_header_metadata(Header *header, ImBuf *ibuf)
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
{
|
2015-01-31 17:15:43 +01:00
|
|
|
if (ibuf->metadata) {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (IDProperty *, prop, &ibuf->metadata->data.group) {
|
2023-03-14 04:42:17 +01:00
|
|
|
if (prop->type == IDP_STRING && !STREQ(prop->name, "compression")) {
|
2015-01-31 17:15:43 +01:00
|
|
|
header->insert(prop->name, StringAttribute(IDP_String(prop)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-04-08 00:14:32 +00:00
|
|
|
if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
|
2020-06-11 14:56:09 +10:00
|
|
|
/* Convert meters to inches. */
|
|
|
|
|
addXDensity(*header, ibuf->ppm[0] * 0.0254);
|
2025-04-08 00:14:32 +00:00
|
|
|
header->pixelAspectRatio() = blender::math::safe_divide(ibuf->ppm[1], ibuf->ppm[0]);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2025-03-24 12:00:07 +01:00
|
|
|
|
|
|
|
|
/* Write chromaticities for ACES-2065-1, as required by ACES container format. */
|
Refactor: OpenColorIO integration
Briefly about this change:
- OpenColorIO C-API is removed.
- The information about color spaces in ImBuf module is removed.
It was stored in global ListBase in colormanagement.cc.
- Both OpenColorIO and fallback implementation supports GPU drawing.
- Fallback implementation supports white point, RGB curves, etc.
- Removed check for support of GPU drawing in IMB.
Historically it was implemented in a separate library with C-API, this
is because way back C++ code needed to stay in intern. This causes all
sort of overheads, and even calls that are strictly considered bad
level.
This change moves OpenColorIO integration into a module within imbuf,
next to movie, and next to IMB_colormanagement which is the main user
of it. This allows to avoid copy of color spaces, displays, views etc
in the ImBuf: they were used to help quickly querying information to
be shown on the interface. With this change it can be stored in the
same data structures as what is used by the OpenColorIO integration.
While it might not be fully avoiding duplication it is now less, and
there is no need in the user code to maintain the copies.
In a lot of cases this change also avoids allocations done per access
to the OpenColorIO. For example, it is not needed anymore to allocate
image descriptor in a heap.
The bigger user-visible change is that the fallback implementation now
supports GLSL drawing, with the whole list of supported features, such
as curve mapping and white point. This should help simplifying code
which relies on color space conversion on GPU: there is no need to
figure out fallback solution in such cases. The only case when drawing
will not work is when there is some actual bug, or driver issue, and
shader has failed to compile.
The change avoids having an opaque type for color space, and instead
uses forward declaration. It is a bit verbose on declaration, but helps
avoiding unsafe type-casts. There are ways to solve this in the future,
like having a header for forward declaration, or to flatten the name
space a bit.
There should be no user-level changes under normal operation.
When building without OpenColorIO or the configuration has a typo or
is missing a fuller set of color management tools is applies (such as the
white point correction).
Pull Request: https://projects.blender.org/blender/blender/pulls/138433
2025-05-09 14:01:43 +02:00
|
|
|
const ColorSpace *colorspace = (ibuf->float_buffer.data) ? ibuf->float_buffer.colorspace :
|
|
|
|
|
(ibuf->byte_buffer.data) ? ibuf->byte_buffer.colorspace :
|
|
|
|
|
nullptr;
|
2025-03-24 12:00:07 +01:00
|
|
|
if (colorspace) {
|
|
|
|
|
const char *aces_colorspace = IMB_colormanagement_role_colorspace_name_get(
|
|
|
|
|
COLOR_ROLE_ACES_INTERCHANGE);
|
|
|
|
|
const char *ibuf_colorspace = IMB_colormanagement_colorspace_get_name(colorspace);
|
|
|
|
|
|
|
|
|
|
if (aces_colorspace && STREQ(aces_colorspace, ibuf_colorspace)) {
|
|
|
|
|
header->insert("chromaticities", TypedAttribute<Chromaticities>(CHROMATICITIES_ACES_2065_1));
|
|
|
|
|
header->insert("adoptedNeutral", TypedAttribute<V2f>(CHROMATICITIES_ACES_2065_1.white));
|
|
|
|
|
}
|
|
|
|
|
}
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-07-01 15:23:09 +02:00
|
|
|
static void openexr_header_metadata_callback(void *data,
|
|
|
|
|
const char *propname,
|
|
|
|
|
char *prop,
|
2022-10-03 17:37:25 -05:00
|
|
|
int /*len*/)
|
2015-05-26 12:02:14 +02:00
|
|
|
{
|
|
|
|
|
Header *header = (Header *)data;
|
|
|
|
|
header->insert(propname, StringAttribute(prop));
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-03 16:58:46 +10:00
|
|
|
static bool imb_save_openexr_half(ImBuf *ibuf, const char *filepath, const int flags)
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
{
|
2012-06-14 11:44:05 +00:00
|
|
|
const int channels = ibuf->channels;
|
2015-04-20 23:37:04 +10:00
|
|
|
const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
|
2012-06-14 11:44:05 +00:00
|
|
|
const int width = ibuf->x;
|
|
|
|
|
const int height = ibuf->y;
|
2020-11-06 17:49:09 +01:00
|
|
|
OStream *file_stream = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
try {
|
2012-06-13 17:27:49 +00:00
|
|
|
Header header(width, height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-10-09 12:34:49 +02:00
|
|
|
openexr_header_compression(
|
2024-10-10 08:45:55 +02:00
|
|
|
&header, ibuf->foptions.flag & OPENEXR_CODEC_MASK, ibuf->foptions.quality);
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
openexr_header_metadata(&header, ibuf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
/* create channels */
|
|
|
|
|
header.channels().insert("R", Channel(HALF));
|
|
|
|
|
header.channels().insert("G", Channel(HALF));
|
|
|
|
|
header.channels().insert("B", Channel(HALF));
|
2019-04-23 11:01:30 +10:00
|
|
|
if (is_alpha) {
|
2017-10-20 15:18:26 +02:00
|
|
|
header.channels().insert("A", Channel(HALF));
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
FrameBuffer frameBuffer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* Manually create `ofstream`, so we can handle UTF8 file-paths on windows. */
|
2019-04-23 11:01:30 +10:00
|
|
|
if (flags & IB_mem) {
|
2016-02-20 14:52:36 +01:00
|
|
|
file_stream = new OMemStream(ibuf);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2023-05-03 16:58:46 +10:00
|
|
|
file_stream = new OFileStream(filepath);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2016-02-20 14:52:36 +01:00
|
|
|
OutputFile file(*file_stream, header);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
/* we store first everything in half array */
|
2025-03-10 22:01:33 +01:00
|
|
|
std::unique_ptr<RGBAZ[]> pixels = std::unique_ptr<RGBAZ[]>(new RGBAZ[int64_t(height) * width]);
|
|
|
|
|
RGBAZ *to = pixels.get();
|
2012-06-14 11:44:05 +00:00
|
|
|
int xstride = sizeof(RGBAZ);
|
2012-06-13 17:27:49 +00:00
|
|
|
int ystride = xstride * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
/* indicate used buffers */
|
|
|
|
|
frameBuffer.insert("R", Slice(HALF, (char *)&to->r, xstride, ystride));
|
|
|
|
|
frameBuffer.insert("G", Slice(HALF, (char *)&to->g, xstride, ystride));
|
|
|
|
|
frameBuffer.insert("B", Slice(HALF, (char *)&to->b, xstride, ystride));
|
2017-11-18 17:22:54 +11:00
|
|
|
if (is_alpha) {
|
2017-10-20 15:18:26 +02:00
|
|
|
frameBuffer.insert("A", Slice(HALF, (char *)&to->a, xstride, ystride));
|
2017-11-18 17:22:54 +11:00
|
|
|
}
|
2023-05-18 10:19:01 +02:00
|
|
|
if (ibuf->float_buffer.data) {
|
2017-10-20 15:18:26 +02:00
|
|
|
float *from;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
for (int i = ibuf->y - 1; i >= 0; i--) {
|
2025-03-10 22:01:33 +01:00
|
|
|
from = ibuf->float_buffer.data + int64_t(channels) * i * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
for (int j = ibuf->x; j > 0; j--) {
|
2021-01-13 14:20:26 +01:00
|
|
|
to->r = float_to_half_safe(from[0]);
|
|
|
|
|
to->g = float_to_half_safe((channels >= 2) ? from[1] : from[0]);
|
|
|
|
|
to->b = float_to_half_safe((channels >= 3) ? from[2] : from[0]);
|
|
|
|
|
to->a = float_to_half_safe((channels >= 4) ? from[3] : 1.0f);
|
2017-10-20 15:18:26 +02:00
|
|
|
to++;
|
|
|
|
|
from += channels;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2017-10-20 15:18:26 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2017-10-20 15:18:26 +02:00
|
|
|
else {
|
2022-09-13 16:29:06 +10:00
|
|
|
uchar *from;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
for (int i = ibuf->y - 1; i >= 0; i--) {
|
2025-03-10 22:01:33 +01:00
|
|
|
from = ibuf->byte_buffer.data + int64_t(4) * i * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
for (int j = ibuf->x; j > 0; j--) {
|
2022-09-25 18:33:28 +10:00
|
|
|
to->r = srgb_to_linearrgb(float(from[0]) / 255.0f);
|
|
|
|
|
to->g = srgb_to_linearrgb(float(from[1]) / 255.0f);
|
|
|
|
|
to->b = srgb_to_linearrgb(float(from[2]) / 255.0f);
|
|
|
|
|
to->a = channels >= 4 ? float(from[3]) / 255.0f : 1.0f;
|
2017-10-20 15:18:26 +02:00
|
|
|
to++;
|
|
|
|
|
from += 4;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
exr_printf("OpenEXR-save: Writing OpenEXR file of height %d.\n", height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 12:10:35 +00:00
|
|
|
file.setFrameBuffer(frameBuffer);
|
|
|
|
|
file.writePixels(height);
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
catch (const std::exception &exc) {
|
2016-02-20 14:52:36 +01:00
|
|
|
delete file_stream;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
printf("OpenEXR-save: ERROR: %s\n", exc.what());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
return false;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
delete file_stream;
|
|
|
|
|
printf("OpenEXR-save: UNKNOWN ERROR\n");
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-20 14:52:36 +01:00
|
|
|
delete file_stream;
|
2015-04-06 10:40:12 -03:00
|
|
|
return true;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-03 16:58:46 +10:00
|
|
|
static bool imb_save_openexr_float(ImBuf *ibuf, const char *filepath, const int flags)
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
{
|
2012-06-14 11:44:05 +00:00
|
|
|
const int channels = ibuf->channels;
|
2015-04-20 23:37:04 +10:00
|
|
|
const bool is_alpha = (channels >= 4) && (ibuf->planes == 32);
|
2012-06-14 11:44:05 +00:00
|
|
|
const int width = ibuf->x;
|
|
|
|
|
const int height = ibuf->y;
|
2020-11-06 17:49:09 +01:00
|
|
|
OStream *file_stream = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
try {
|
2012-06-13 17:27:49 +00:00
|
|
|
Header header(width, height);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-10-09 12:34:49 +02:00
|
|
|
openexr_header_compression(
|
2024-10-10 08:45:55 +02:00
|
|
|
&header, ibuf->foptions.flag & OPENEXR_CODEC_MASK, ibuf->foptions.quality);
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
openexr_header_metadata(&header, ibuf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
/* create channels */
|
|
|
|
|
header.channels().insert("R", Channel(Imf::FLOAT));
|
|
|
|
|
header.channels().insert("G", Channel(Imf::FLOAT));
|
|
|
|
|
header.channels().insert("B", Channel(Imf::FLOAT));
|
2019-04-23 11:01:30 +10:00
|
|
|
if (is_alpha) {
|
2017-10-20 15:18:26 +02:00
|
|
|
header.channels().insert("A", Channel(Imf::FLOAT));
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
FrameBuffer frameBuffer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* Manually create `ofstream`, so we can handle UTF8 file-paths on windows. */
|
2019-04-23 11:01:30 +10:00
|
|
|
if (flags & IB_mem) {
|
2016-02-20 14:52:36 +01:00
|
|
|
file_stream = new OMemStream(ibuf);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2023-05-03 16:58:46 +10:00
|
|
|
file_stream = new OFileStream(filepath);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2016-02-20 14:52:36 +01:00
|
|
|
OutputFile file(*file_stream, header);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-20 12:15:39 +00:00
|
|
|
int xstride = sizeof(float) * channels;
|
2012-06-13 17:27:49 +00:00
|
|
|
int ystride = -xstride * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-24 11:31:23 +10:00
|
|
|
/* Last scan-line, stride negative. */
|
2020-11-06 17:49:09 +01:00
|
|
|
float *rect[4] = {nullptr, nullptr, nullptr, nullptr};
|
2025-03-10 22:01:33 +01:00
|
|
|
rect[0] = ibuf->float_buffer.data + int64_t(channels) * (height - 1) * width;
|
2017-10-20 15:18:26 +02:00
|
|
|
rect[1] = (channels >= 2) ? rect[0] + 1 : rect[0];
|
|
|
|
|
rect[2] = (channels >= 3) ? rect[0] + 2 : rect[0];
|
|
|
|
|
rect[3] = (channels >= 4) ?
|
|
|
|
|
rect[0] + 3 :
|
|
|
|
|
rect[0]; /* red as alpha, is this needed since alpha isn't written? */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
frameBuffer.insert("R", Slice(Imf::FLOAT, (char *)rect[0], xstride, ystride));
|
|
|
|
|
frameBuffer.insert("G", Slice(Imf::FLOAT, (char *)rect[1], xstride, ystride));
|
|
|
|
|
frameBuffer.insert("B", Slice(Imf::FLOAT, (char *)rect[2], xstride, ystride));
|
2017-11-18 17:22:54 +11:00
|
|
|
if (is_alpha) {
|
2017-10-20 15:18:26 +02:00
|
|
|
frameBuffer.insert("A", Slice(Imf::FLOAT, (char *)rect[3], xstride, ystride));
|
2017-11-18 17:22:54 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 12:10:35 +00:00
|
|
|
file.setFrameBuffer(frameBuffer);
|
|
|
|
|
file.writePixels(height);
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
catch (const std::exception &exc) {
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
printf("OpenEXR-save: ERROR: %s\n", exc.what());
|
2016-02-20 14:52:36 +01:00
|
|
|
delete file_stream;
|
2015-04-06 10:40:12 -03:00
|
|
|
return false;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
printf("OpenEXR-save: UNKNOWN ERROR\n");
|
|
|
|
|
delete file_stream;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-02-20 14:52:36 +01:00
|
|
|
delete file_stream;
|
2015-04-06 10:40:12 -03:00
|
|
|
return true;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
bool imb_save_openexr(ImBuf *ibuf, const char *filepath, int flags)
|
2006-01-09 10:55:41 +00:00
|
|
|
{
|
2012-04-28 06:31:57 +00:00
|
|
|
if (flags & IB_mem) {
|
2006-01-09 10:55:41 +00:00
|
|
|
imb_addencodedbufferImBuf(ibuf);
|
2023-05-18 10:19:01 +02:00
|
|
|
ibuf->encoded_size = 0;
|
2012-06-13 17:27:49 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (ibuf->foptions.flag & OPENEXR_HALF) {
|
2023-05-03 16:58:46 +10:00
|
|
|
return imb_save_openexr_half(ibuf, filepath, flags);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2020-08-07 12:39:50 +02:00
|
|
|
|
|
|
|
|
/* when no float rect, we save as half (16 bits is sufficient) */
|
2023-05-18 10:19:01 +02:00
|
|
|
if (ibuf->float_buffer.data == nullptr) {
|
2023-05-03 16:58:46 +10:00
|
|
|
return imb_save_openexr_half(ibuf, filepath, flags);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2020-08-07 12:39:50 +02:00
|
|
|
|
2023-05-03 16:58:46 +10:00
|
|
|
return imb_save_openexr_float(ibuf, filepath, flags);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
|
2019-04-22 01:18:55 +10:00
|
|
|
/* ******* Nicer API, MultiLayer and with Tile file support ************************************ */
|
2006-12-20 17:57:56 +00:00
|
|
|
|
|
|
|
|
/* naming rules:
|
2012-03-09 18:28:30 +00:00
|
|
|
* - parse name from right to left
|
|
|
|
|
* - last character is channel ID, 1 char like 'A' 'R' 'G' 'B' 'X' 'Y' 'Z' 'W' 'U' 'V'
|
|
|
|
|
* - separated with a dot; the Pass name (like "Depth", "Color", "Diffuse" or "Combined")
|
2019-02-27 12:02:02 +11:00
|
|
|
* - separated with a dot: the Layer name (like "Light1" or "Walls" or "Characters")
|
2012-03-09 18:28:30 +00:00
|
|
|
*/
|
2006-12-20 17:57:56 +00:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
static ListBase exrhandles = {nullptr, nullptr};
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
2020-12-04 12:46:43 +01:00
|
|
|
struct ExrHandle {
|
2023-06-03 08:36:28 +10:00
|
|
|
ExrHandle *next, *prev;
|
2015-04-06 10:40:12 -03:00
|
|
|
char name[FILE_MAX];
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2015-06-03 16:23:32 +10:00
|
|
|
IStream *ifile_stream;
|
2015-04-06 10:40:12 -03:00
|
|
|
MultiPartInputFile *ifile;
|
2012-08-24 12:10:35 +00:00
|
|
|
|
2012-08-24 14:04:21 +00:00
|
|
|
OFileStream *ofile_stream;
|
2015-04-06 10:40:12 -03:00
|
|
|
MultiPartOutputFile *mpofile;
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
OutputFile *ofile;
|
2012-08-24 12:10:35 +00:00
|
|
|
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
int tilex, tiley;
|
|
|
|
|
int width, height;
|
2008-02-06 13:45:07 +00:00
|
|
|
int mipmap;
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2019-04-22 01:18:55 +10:00
|
|
|
/** It needs to be a pointer due to Windows release builds of EXR2.0
|
|
|
|
|
* segfault when opening EXR bug. */
|
|
|
|
|
StringVector *multiView;
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
int parts;
|
|
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
ListBase channels; /* flattened out, ExrChannel */
|
|
|
|
|
ListBase layers; /* hierarchical, pointing in end to ExrChannel */
|
2015-06-19 13:00:18 +02:00
|
|
|
|
2022-09-16 18:13:19 +10:00
|
|
|
/** Used during file save, allows faster temporary buffers allocation. */
|
|
|
|
|
int num_half_channels;
|
2020-12-04 12:46:43 +01:00
|
|
|
};
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* flattened out channel */
|
2020-12-04 12:46:43 +01:00
|
|
|
struct ExrChannel {
|
2023-06-03 08:36:28 +10:00
|
|
|
ExrChannel *next, *prev;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
char name[EXR_TOT_MAXNAME + 1]; /* full name with everything */
|
2023-06-03 08:36:28 +10:00
|
|
|
MultiViewChannelName *m; /* struct to store all multipart channel info */
|
2021-09-24 11:31:23 +10:00
|
|
|
int xstride, ystride; /* step to next pixel, to next scan-line. */
|
2012-06-13 17:27:49 +00:00
|
|
|
float *rect; /* first pointer to write in */
|
|
|
|
|
char chan_id; /* quick lookup of channel char */
|
2015-04-06 10:40:12 -03:00
|
|
|
int view_id; /* quick lookup of channel view */
|
2015-06-19 13:00:18 +02:00
|
|
|
bool use_half_float; /* when saving use half float for file storage */
|
2020-12-04 12:46:43 +01:00
|
|
|
};
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* hierarchical; layers -> passes -> channels[] */
|
2020-12-04 12:46:43 +01:00
|
|
|
struct ExrPass {
|
2023-06-03 08:36:28 +10:00
|
|
|
ExrPass *next, *prev;
|
2006-12-20 17:57:56 +00:00
|
|
|
char name[EXR_PASS_MAXNAME];
|
|
|
|
|
int totchan;
|
|
|
|
|
float *rect;
|
2023-06-03 08:36:28 +10:00
|
|
|
ExrChannel *chan[EXR_PASS_MAXCHAN];
|
2006-12-20 17:57:56 +00:00
|
|
|
char chan_id[EXR_PASS_MAXCHAN];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
char internal_name[EXR_PASS_MAXNAME]; /* name with no view */
|
|
|
|
|
char view[EXR_VIEW_MAXNAME];
|
|
|
|
|
int view_id;
|
2020-12-04 12:46:43 +01:00
|
|
|
};
|
2006-12-20 17:57:56 +00:00
|
|
|
|
2020-12-04 12:46:43 +01:00
|
|
|
struct ExrLayer {
|
2023-06-03 08:36:28 +10:00
|
|
|
ExrLayer *next, *prev;
|
2012-06-13 17:27:49 +00:00
|
|
|
char name[EXR_LAY_MAXNAME + 1];
|
2006-12-20 17:57:56 +00:00
|
|
|
ListBase passes;
|
2020-12-04 12:46:43 +01:00
|
|
|
};
|
2006-12-20 17:57:56 +00:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data);
|
|
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* ********************** */
|
|
|
|
|
|
2023-07-02 19:37:22 +10:00
|
|
|
void *IMB_exr_get_handle()
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2025-03-05 16:35:09 +01:00
|
|
|
ExrHandle *data = MEM_callocN<ExrHandle>("exr handle");
|
2015-04-06 10:40:12 -03:00
|
|
|
data->multiView = new StringVector();
|
|
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
BLI_addtail(&exrhandles, data);
|
|
|
|
|
return data;
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
void *IMB_exr_get_handle_name(const char *name)
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)BLI_rfindstring(&exrhandles, name, offsetof(ExrHandle, name));
|
|
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
if (data == nullptr) {
|
2015-04-06 10:40:12 -03:00
|
|
|
data = (ExrHandle *)IMB_exr_get_handle();
|
2023-05-24 12:21:51 +10:00
|
|
|
STRNCPY(data->name, name);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* multiview functions */
|
|
|
|
|
|
|
|
|
|
void IMB_exr_add_view(void *handle, const char *name)
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
2025-01-26 20:07:58 +01:00
|
|
|
data->multiView->emplace_back(name);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imb_exr_get_multiView_id(StringVector &views, const std::string &name)
|
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
2019-09-08 03:31:49 +10:00
|
|
|
for (StringVector::const_iterator i = views.begin(); count < views.size(); ++i) {
|
2019-04-23 11:01:30 +10:00
|
|
|
if (name == *i) {
|
2015-04-06 10:40:12 -03:00
|
|
|
return count;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2020-08-07 12:39:50 +02:00
|
|
|
|
|
|
|
|
count++;
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* no views or wrong name */
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imb_exr_get_views(MultiPartInputFile &file, StringVector &views)
|
|
|
|
|
{
|
|
|
|
|
if (exr_has_multipart_file(file) == false) {
|
|
|
|
|
if (exr_has_multiview(file)) {
|
|
|
|
|
StringVector sv = multiView(file.header(0));
|
2020-12-07 12:21:11 +01:00
|
|
|
for (const std::string &view_name : sv) {
|
|
|
|
|
views.push_back(view_name);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
else {
|
|
|
|
|
for (int p = 0; p < file.parts(); p++) {
|
2020-08-07 12:17:29 +02:00
|
|
|
std::string view;
|
2019-04-23 11:01:30 +10:00
|
|
|
if (file.header(p).hasView()) {
|
2015-04-06 10:40:12 -03:00
|
|
|
view = file.header(p).view();
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (imb_exr_get_multiView_id(views, view) == -1) {
|
2015-04-06 10:40:12 -03:00
|
|
|
views.push_back(view);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-10 11:34:10 +11:00
|
|
|
/* Multi-layer Blender files have the view name in all the passes (even the default view one). */
|
2023-05-24 12:21:51 +10:00
|
|
|
static void imb_exr_insert_view_name(char name_full[EXR_TOT_MAXNAME + 1],
|
|
|
|
|
const char *passname,
|
|
|
|
|
const char *viewname)
|
2015-04-06 10:40:12 -03:00
|
|
|
{
|
2023-05-24 12:21:51 +10:00
|
|
|
/* Match: `sizeof(ExrChannel::name)`. */
|
|
|
|
|
const size_t name_full_maxncpy = EXR_TOT_MAXNAME + 1;
|
2015-07-12 01:43:32 +10:00
|
|
|
BLI_assert(!ELEM(name_full, passname, viewname));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
if (viewname == nullptr || viewname[0] == '\0') {
|
2023-05-24 12:21:51 +10:00
|
|
|
BLI_strncpy(name_full, passname, name_full_maxncpy);
|
2015-07-12 01:43:32 +10:00
|
|
|
return;
|
2015-07-12 01:43:32 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-27 10:24:00 +02:00
|
|
|
const char delims[] = {'.', '\0'};
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *sep;
|
|
|
|
|
const char *token;
|
2015-06-27 10:24:00 +02:00
|
|
|
size_t len;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-27 10:24:00 +02:00
|
|
|
len = BLI_str_rpartition(passname, delims, &sep, &token);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-27 10:24:00 +02:00
|
|
|
if (sep) {
|
2023-05-24 12:21:51 +10:00
|
|
|
BLI_snprintf(name_full, name_full_maxncpy, "%.*s.%s.%s", int(len), passname, viewname, token);
|
2015-06-27 10:24:00 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2023-05-24 12:21:51 +10:00
|
|
|
BLI_snprintf(name_full, name_full_maxncpy, "%s.%s", passname, viewname);
|
2015-06-27 10:24:00 +02:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
|
2015-06-19 13:00:18 +02:00
|
|
|
void IMB_exr_add_channel(void *handle,
|
|
|
|
|
const char *layname,
|
|
|
|
|
const char *passname,
|
|
|
|
|
const char *viewname,
|
|
|
|
|
int xstride,
|
|
|
|
|
int ystride,
|
|
|
|
|
float *rect,
|
|
|
|
|
bool use_half_float)
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
ExrChannel *echan;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-05 16:35:09 +01:00
|
|
|
echan = MEM_callocN<ExrChannel>("exr channel");
|
2015-04-06 10:40:12 -03:00
|
|
|
echan->m = new MultiViewChannelName();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (layname && layname[0] != '\0') {
|
|
|
|
|
echan->m->name = layname;
|
|
|
|
|
echan->m->name.append(".");
|
|
|
|
|
echan->m->name.append(passname);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
echan->m->name.assign(passname);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
echan->m->internal_name = echan->m->name;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
echan->m->view.assign(viewname ? viewname : "");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* quick look up */
|
|
|
|
|
echan->view_id = std::max(0, imb_exr_get_multiView_id(*data->multiView, echan->m->view));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* name has to be unique, thus it's a combination of layer, pass, view, and channel */
|
|
|
|
|
if (layname && layname[0] != '\0') {
|
2015-07-12 01:43:32 +10:00
|
|
|
imb_exr_insert_view_name(echan->name, echan->m->name.c_str(), echan->m->view.c_str());
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2020-07-03 14:59:27 +02:00
|
|
|
else if (!data->multiView->empty()) {
|
2015-04-06 10:40:12 -03:00
|
|
|
std::string raw_name = insertViewName(echan->m->name, *data->multiView, echan->view_id);
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(echan->name, raw_name.c_str());
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
else {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(echan->name, echan->m->name.c_str());
|
2012-06-13 17:27:49 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
echan->xstride = xstride;
|
|
|
|
|
echan->ystride = ystride;
|
|
|
|
|
echan->rect = rect;
|
2015-06-19 13:00:18 +02:00
|
|
|
echan->use_half_float = use_half_float;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-06-19 13:00:18 +02:00
|
|
|
if (echan->use_half_float) {
|
|
|
|
|
data->num_half_channels++;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
exr_printf("added channel %s\n", echan->name);
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
BLI_addtail(&data->channels, echan);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
bool IMB_exr_begin_write(void *handle,
|
2022-03-24 16:33:32 +11:00
|
|
|
const char *filepath,
|
2021-09-23 19:22:15 +02:00
|
|
|
int width,
|
|
|
|
|
int height,
|
2025-04-05 08:49:22 +00:00
|
|
|
const double ppm[2],
|
2021-09-23 19:22:15 +02:00
|
|
|
int compress,
|
2024-10-09 12:34:49 +02:00
|
|
|
int quality,
|
2021-09-23 19:22:15 +02:00
|
|
|
const StampData *stamp)
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
|
|
|
|
Header header(width, height);
|
|
|
|
|
|
|
|
|
|
data->width = width;
|
|
|
|
|
data->height = height;
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
bool is_singlelayer, is_multilayer, is_multiview;
|
|
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrChannel *, echan, &data->channels) {
|
2015-06-19 13:00:18 +02:00
|
|
|
header.channels().insert(echan->name, Channel(echan->use_half_float ? Imf::HALF : Imf::FLOAT));
|
|
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2024-10-09 12:34:49 +02:00
|
|
|
openexr_header_compression(&header, compress, quality);
|
2015-07-01 15:23:09 +02:00
|
|
|
BKE_stamp_info_callback(
|
|
|
|
|
&header, const_cast<StampData *>(stamp), openexr_header_metadata_callback, false);
|
2007-01-24 15:03:20 +00:00
|
|
|
/* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
imb_exr_type_by_channels(
|
|
|
|
|
header.channels(), *data->multiView, &is_singlelayer, &is_multilayer, &is_multiview);
|
|
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (is_multilayer) {
|
2015-04-06 10:40:12 -03:00
|
|
|
header.insert("BlenderMultiChannel", StringAttribute("Blender V2.55.1 and newer"));
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (is_multiview) {
|
2015-04-06 10:40:12 -03:00
|
|
|
addMultiView(header, *data->multiView);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2011-08-30 23:08:38 +00:00
|
|
|
|
2025-04-05 08:49:22 +00:00
|
|
|
if (ppm[0] != 0.0 && ppm[1] != 0.0) {
|
|
|
|
|
addXDensity(header, ppm[0] * 0.0254);
|
|
|
|
|
header.pixelAspectRatio() = blender::math::safe_divide(ppm[1], ppm[0]);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-17 09:18:03 +10:00
|
|
|
/* Avoid crash/abort when we don't have permission to write here. */
|
|
|
|
|
/* Manually create `ofstream`, so we can handle UTF8 file-paths on windows. */
|
2011-08-30 23:08:38 +00:00
|
|
|
try {
|
2022-03-24 16:33:32 +11:00
|
|
|
data->ofile_stream = new OFileStream(filepath);
|
2012-08-24 14:04:21 +00:00
|
|
|
data->ofile = new OutputFile(*(data->ofile_stream), header);
|
2011-08-30 23:08:38 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
catch (const std::exception &exc) {
|
2011-08-30 23:08:38 +00:00
|
|
|
std::cerr << "IMB_exr_begin_write: ERROR: " << exc.what() << std::endl;
|
2012-08-24 12:10:35 +00:00
|
|
|
|
|
|
|
|
delete data->ofile;
|
2012-08-24 14:04:21 +00:00
|
|
|
delete data->ofile_stream;
|
2012-08-24 12:10:35 +00:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
data->ofile = nullptr;
|
|
|
|
|
data->ofile_stream = nullptr;
|
2011-08-30 23:08:38 +00:00
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
std::cerr << "IMB_exr_begin_write: UNKNOWN ERROR" << std::endl;
|
|
|
|
|
|
|
|
|
|
delete data->ofile;
|
|
|
|
|
delete data->ofile_stream;
|
|
|
|
|
|
|
|
|
|
data->ofile = nullptr;
|
|
|
|
|
data->ofile_stream = nullptr;
|
|
|
|
|
}
|
2011-08-30 23:08:38 +00:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
return (data->ofile != nullptr);
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
bool IMB_exr_begin_read(
|
2022-03-24 16:33:32 +11:00
|
|
|
void *handle, const char *filepath, int *width, int *height, const bool parse_channels)
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
2015-04-06 10:40:12 -03:00
|
|
|
ExrChannel *echan;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
/* 32 is arbitrary, but zero length files crashes exr. */
|
2022-03-24 16:33:32 +11:00
|
|
|
if (!(BLI_exists(filepath) && BLI_file_size(filepath) > 32)) {
|
2021-09-23 19:22:15 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
/* avoid crash/abort when we don't have permission to write here */
|
|
|
|
|
try {
|
2022-03-24 16:33:32 +11:00
|
|
|
data->ifile_stream = new IFileStream(filepath);
|
2021-09-23 19:22:15 +02:00
|
|
|
data->ifile = new MultiPartInputFile(*(data->ifile_stream));
|
|
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
2021-09-23 19:22:15 +02:00
|
|
|
delete data->ifile;
|
|
|
|
|
delete data->ifile_stream;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
data->ifile = nullptr;
|
|
|
|
|
data->ifile_stream = nullptr;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
if (!data->ifile) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
Box2i dw = data->ifile->header(0).dataWindow();
|
|
|
|
|
data->width = *width = dw.max.x - dw.min.x + 1;
|
|
|
|
|
data->height = *height = dw.max.y - dw.min.y + 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
if (parse_channels) {
|
|
|
|
|
/* Parse channels into view/layer/pass. */
|
|
|
|
|
if (!imb_exr_multilayer_parse_channels_from_file(data)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Read view and channels without parsing. */
|
|
|
|
|
imb_exr_get_views(*data->ifile, *data->multiView);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
std::vector<MultiViewChannelName> channels;
|
|
|
|
|
GetChannelsInMultiPartFile(*data->ifile, channels);
|
|
|
|
|
|
|
|
|
|
for (const MultiViewChannelName &channel : channels) {
|
|
|
|
|
IMB_exr_add_channel(
|
|
|
|
|
data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
echan = (ExrChannel *)data->channels.last;
|
|
|
|
|
echan->m->name = channel.name;
|
|
|
|
|
echan->m->view = channel.view;
|
|
|
|
|
echan->m->part_number = channel.part_number;
|
|
|
|
|
echan->m->internal_name = channel.internal_name;
|
Memory saving for large renders:
New option "Save Buffers", in first Output panel of renderbuttons, will not
allocate all render buffers, but instead save the rendered tiles to exr.
For each scene rendered, a single exr file then is created.
After rendering, the files get read, and only then the memory allocation is
done.
The exr files are saved in the temp dir (from user settings), and have
names derived from the filename+scene name. That way these buffers remain
relatively unique, and can be re-used later too.
Saving all render-layers and passes in a single file (as F3 command) will
be done later. Also reading back the current muli-layer exr files is not
supported yet (will read black). The purpose is that these files then can
be used as input for the Compositor.
One fun thing I added; after rendering once with this option, close
Blender, and restart it. If you have a Composite set up press 'R' on an
active RenderResult node. This will refresh the node(s) and load the exr,
so you can composite again without a re-render.
2006-03-14 21:29:42 +00:00
|
|
|
}
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
2021-09-23 19:22:15 +02:00
|
|
|
|
|
|
|
|
return true;
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
2023-06-16 18:41:44 +02:00
|
|
|
bool IMB_exr_set_channel(
|
2010-12-03 17:05:21 +00:00
|
|
|
void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
2006-12-20 17:57:56 +00:00
|
|
|
char name[EXR_TOT_MAXNAME + 1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-05-16 12:40:04 +02:00
|
|
|
if (layname && layname[0] != '\0') {
|
2012-06-13 17:27:49 +00:00
|
|
|
char lay[EXR_LAY_MAXNAME + 1], pass[EXR_PASS_MAXNAME + 1];
|
2006-12-20 17:57:56 +00:00
|
|
|
BLI_strncpy(lay, layname, EXR_LAY_MAXNAME);
|
|
|
|
|
BLI_strncpy(pass, passname, EXR_PASS_MAXNAME);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
SNPRINTF(name, "%s.%s", lay, pass);
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
2017-05-16 12:40:04 +02:00
|
|
|
else {
|
2012-06-13 17:27:49 +00:00
|
|
|
BLI_strncpy(name, passname, EXR_TOT_MAXNAME - 1);
|
2017-05-16 12:40:04 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-16 18:41:44 +02:00
|
|
|
ExrChannel *echan = (ExrChannel *)BLI_findstring(
|
|
|
|
|
&data->channels, name, offsetof(ExrChannel, name));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-06-16 18:41:44 +02:00
|
|
|
if (echan == nullptr) {
|
|
|
|
|
return false;
|
2017-05-16 12:40:04 +02:00
|
|
|
}
|
2023-06-16 18:41:44 +02:00
|
|
|
|
|
|
|
|
echan->xstride = xstride;
|
|
|
|
|
echan->ystride = ystride;
|
|
|
|
|
echan->rect = rect;
|
|
|
|
|
return true;
|
2006-12-21 19:37:53 +00:00
|
|
|
}
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
void IMB_exr_write_channels(void *handle)
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
FrameBuffer frameBuffer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 07:52:14 +00:00
|
|
|
if (data->channels.first) {
|
2022-09-25 18:33:28 +10:00
|
|
|
const size_t num_pixels = size_t(data->width) * data->height;
|
2020-11-06 17:49:09 +01:00
|
|
|
half *rect_half = nullptr, *current_rect_half = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* We allocate temporary storage for half pixels for all the channels at once. */
|
2015-06-19 13:00:18 +02:00
|
|
|
if (data->num_half_channels != 0) {
|
2025-03-14 18:16:13 +01:00
|
|
|
rect_half = MEM_malloc_arrayN<half>(size_t(data->num_half_channels) * num_pixels, __func__);
|
2015-06-19 13:00:18 +02:00
|
|
|
current_rect_half = rect_half;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrChannel *, echan, &data->channels) {
|
2021-09-24 11:31:23 +10:00
|
|
|
/* Writing starts from last scan-line, stride negative. */
|
2015-06-19 13:00:18 +02:00
|
|
|
if (echan->use_half_float) {
|
2024-08-21 19:18:55 +10:00
|
|
|
const float *rect = echan->rect;
|
2015-06-19 13:00:18 +02:00
|
|
|
half *cur = current_rect_half;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (size_t i = 0; i < num_pixels; i++, cur++) {
|
2021-01-13 14:20:26 +01:00
|
|
|
*cur = float_to_half_safe(rect[i * echan->xstride]);
|
2015-06-19 13:00:18 +02:00
|
|
|
}
|
2018-01-15 12:53:17 +01:00
|
|
|
half *rect_to_write = current_rect_half + (data->height - 1L) * data->width;
|
2015-06-19 13:00:18 +02:00
|
|
|
frameBuffer.insert(
|
|
|
|
|
echan->name,
|
|
|
|
|
Slice(Imf::HALF, (char *)rect_to_write, sizeof(half), -data->width * sizeof(half)));
|
|
|
|
|
current_rect_half += num_pixels;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2018-01-15 12:53:17 +01:00
|
|
|
float *rect = echan->rect + echan->xstride * (data->height - 1L) * data->width;
|
2015-06-19 13:00:18 +02:00
|
|
|
frameBuffer.insert(echan->name,
|
|
|
|
|
Slice(Imf::FLOAT,
|
|
|
|
|
(char *)rect,
|
|
|
|
|
echan->xstride * sizeof(float),
|
|
|
|
|
-echan->ystride * sizeof(float)));
|
2010-11-27 19:33:40 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
data->ofile->setFrameBuffer(frameBuffer);
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
try {
|
2012-06-13 17:27:49 +00:00
|
|
|
data->ofile->writePixels(data->height);
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
catch (const std::exception &exc) {
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
std::cerr << "OpenEXR-writePixels: ERROR: " << exc.what() << std::endl;
|
|
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
std::cerr << "OpenEXR-writePixels: UNKNOWN ERROR" << std::endl;
|
|
|
|
|
}
|
2015-06-19 13:00:18 +02:00
|
|
|
/* Free temporary buffers. */
|
2020-11-06 17:49:09 +01:00
|
|
|
if (rect_half != nullptr) {
|
2015-06-19 13:00:18 +02:00
|
|
|
MEM_freeN(rect_half);
|
|
|
|
|
}
|
2009-06-08 20:08:19 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("Error: attempt to save MultiLayer without layers.\n");
|
|
|
|
|
}
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
void IMB_exr_read_channels(void *handle)
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
|
|
|
|
int numparts = data->ifile->parts();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-19 17:12:48 +10:00
|
|
|
/* Check if EXR was saved with previous versions of blender which flipped images. */
|
2015-04-06 10:40:12 -03:00
|
|
|
const StringAttribute *ta = data->ifile->header(0).findTypedAttribute<StringAttribute>(
|
|
|
|
|
"BlenderMultiChannel");
|
2019-08-14 23:29:46 +10:00
|
|
|
|
|
|
|
|
/* 'previous multilayer attribute, flipped. */
|
2020-11-06 15:56:03 +11:00
|
|
|
short flip = (ta && STRPREFIX(ta->value().c_str(), "Blender V2.43"));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
exr_printf(
|
|
|
|
|
"\nIMB_exr_read_channels\n%s %-6s %-22s "
|
|
|
|
|
"\"%s\"\n---------------------------------------------------------------------\n",
|
|
|
|
|
"p",
|
|
|
|
|
"view",
|
|
|
|
|
"name",
|
|
|
|
|
"internal_name");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
for (int i = 0; i < numparts; i++) {
|
|
|
|
|
/* Read part header. */
|
|
|
|
|
InputPart in(*data->ifile, i);
|
|
|
|
|
Header header = in.header();
|
|
|
|
|
Box2i dw = header.dataWindow();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-02-05 16:23:34 +11:00
|
|
|
/* Insert all matching channel into frame-buffer. */
|
2017-10-19 03:55:11 +02:00
|
|
|
FrameBuffer frameBuffer;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrChannel *, echan, &data->channels) {
|
2017-11-18 17:22:54 +11:00
|
|
|
if (echan->m->part_number != i) {
|
2017-10-19 03:55:11 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
exr_printf("%d %-6s %-22s \"%s\"\n",
|
|
|
|
|
echan->m->part_number,
|
|
|
|
|
echan->m->view.c_str(),
|
|
|
|
|
echan->m->name.c_str(),
|
|
|
|
|
echan->m->internal_name.c_str());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
if (echan->rect) {
|
|
|
|
|
float *rect = echan->rect;
|
|
|
|
|
size_t xstride = echan->xstride * sizeof(float);
|
|
|
|
|
size_t ystride = echan->ystride * sizeof(float);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
if (!flip) {
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Inverse correct first pixel for data-window coordinates. */
|
2017-10-19 03:55:11 +02:00
|
|
|
rect -= echan->xstride * (dw.min.x - dw.min.y * data->width);
|
2021-09-24 11:31:23 +10:00
|
|
|
/* Move to last scan-line to flip to Blender convention. */
|
2017-10-19 03:55:11 +02:00
|
|
|
rect += echan->xstride * (data->height - 1) * data->width;
|
|
|
|
|
ystride = -ystride;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Inverse correct first pixel for data-window coordinates. */
|
2017-10-19 03:55:11 +02:00
|
|
|
rect -= echan->xstride * (dw.min.x + dw.min.y * data->width);
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
frameBuffer.insert(echan->m->internal_name,
|
|
|
|
|
Slice(Imf::FLOAT, (char *)rect, xstride, ystride));
|
|
|
|
|
}
|
2010-11-27 19:33:40 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2017-10-19 03:55:11 +02:00
|
|
|
/* Read pixels. */
|
|
|
|
|
try {
|
|
|
|
|
in.setFrameBuffer(frameBuffer);
|
|
|
|
|
exr_printf("readPixels:readPixels[%d]: min.y: %d, max.y: %d\n", i, dw.min.y, dw.max.y);
|
|
|
|
|
in.readPixels(dw.min.y, dw.max.y);
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception &exc) {
|
|
|
|
|
std::cerr << "OpenEXR-readPixels: ERROR: " << exc.what() << std::endl;
|
|
|
|
|
break;
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
std::cerr << "OpenEXR-readPixels: UNKNOWN ERROR: " << std::endl;
|
|
|
|
|
break;
|
|
|
|
|
}
|
Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
editing the code directly.
* Functions removed that were only used for sequencer plugin API:
IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
2010-05-07 15:18:04 +00:00
|
|
|
}
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
void IMB_exr_multilayer_convert(void *handle,
|
|
|
|
|
void *base,
|
2015-04-06 10:40:12 -03:00
|
|
|
void *(*addview)(void *base, const char *str),
|
2012-07-08 00:04:41 +00:00
|
|
|
void *(*addlayer)(void *base, const char *str),
|
|
|
|
|
void (*addpass)(void *base,
|
|
|
|
|
void *lay,
|
|
|
|
|
const char *str,
|
2015-04-06 10:40:12 -03:00
|
|
|
float *rect,
|
|
|
|
|
int totchan,
|
|
|
|
|
const char *chan_id,
|
|
|
|
|
const char *view))
|
2006-12-20 17:57:56 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-23 18:16:33 -03:00
|
|
|
/* RenderResult needs at least one RenderView */
|
2020-07-03 14:59:27 +02:00
|
|
|
if (data->multiView->empty()) {
|
2015-04-23 18:16:33 -03:00
|
|
|
addview(base, "");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* add views to RenderResult */
|
2020-12-07 12:21:11 +01:00
|
|
|
for (const std::string &view_name : *data->multiView) {
|
|
|
|
|
addview(base, view_name.c_str());
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-04-23 18:16:33 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-02-08 06:07:10 +11:00
|
|
|
if (BLI_listbase_is_empty(&data->layers)) {
|
2006-12-20 17:57:56 +00:00
|
|
|
printf("cannot convert multilayer, no layers in handle\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrLayer *, lay, &data->layers) {
|
2012-06-13 17:27:49 +00:00
|
|
|
void *laybase = addlayer(base, lay->name);
|
2012-03-24 07:52:14 +00:00
|
|
|
if (laybase) {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrPass *, pass, &lay->passes) {
|
2015-04-06 10:40:12 -03:00
|
|
|
addpass(base,
|
|
|
|
|
laybase,
|
|
|
|
|
pass->internal_name,
|
|
|
|
|
pass->rect,
|
|
|
|
|
pass->totchan,
|
|
|
|
|
pass->chan_id,
|
|
|
|
|
pass->view);
|
2020-11-06 17:49:09 +01:00
|
|
|
pass->rect = nullptr;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Work in progress commit on saving OpenEXR with all render-layers and
passes in single file. Code is currently disabled, commit is mainly to
have a nicer method of excluding OpenEXR dependency from render module.
This should compile with disabled WITH_OPENEXR too.
Reason why EXR is great to include by default in Blender is its feature
to store unlimited layers and channels, and write this tile based. I
need the feature for saving memory; while rendering tiles, all full-size
buffers for all layers and passes are kept in memory now, which can go
into 100s of MB easily.
The code I commit now doesn't allocate these buffers while rendering, but
saves the tiles to disk. In the end is it read back. Overhead for large
renders (like 300 meg buffers) is 10-15 seconds, not bad.
Two more interesting aspects:
- Blender can save such multi-layer files in the temp directory, storing
it with .blend file name and scene name. That way, on each restart of Blender,
or on switching scenes, these buffers can be read. So you always see what was
rendered last. Also great for compositing work.
- This can also become an output image type for rendering. There's plenty of
cases where you want specific layers or passes saved to disk for later use.
Anyhoo, finishing it is another days of work, and I got more urgent stuff
now!
2006-02-23 20:57:31 +00:00
|
|
|
void IMB_exr_close(void *handle)
|
|
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-08-24 12:10:35 +00:00
|
|
|
delete data->ifile;
|
2012-08-24 14:04:21 +00:00
|
|
|
delete data->ifile_stream;
|
2012-08-24 12:10:35 +00:00
|
|
|
delete data->ofile;
|
2015-04-06 10:40:12 -03:00
|
|
|
delete data->mpofile;
|
2012-08-24 14:04:21 +00:00
|
|
|
delete data->ofile_stream;
|
2015-06-02 22:42:51 +05:00
|
|
|
delete data->multiView;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
data->ifile = nullptr;
|
|
|
|
|
data->ifile_stream = nullptr;
|
|
|
|
|
data->ofile = nullptr;
|
|
|
|
|
data->mpofile = nullptr;
|
|
|
|
|
data->ofile_stream = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrChannel *, chan, &data->channels) {
|
2015-04-06 10:40:12 -03:00
|
|
|
delete chan->m;
|
|
|
|
|
}
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
BLI_freelistN(&data->channels);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrLayer *, lay, &data->layers) {
|
|
|
|
|
LISTBASE_FOREACH (ExrPass *, pass, &lay->passes) {
|
2019-04-23 11:01:30 +10:00
|
|
|
if (pass->rect) {
|
2006-12-20 17:57:56 +00:00
|
|
|
MEM_freeN(pass->rect);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
BLI_freelistN(&lay->passes);
|
|
|
|
|
}
|
|
|
|
|
BLI_freelistN(&data->layers);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
BLI_remlink(&exrhandles, data);
|
|
|
|
|
MEM_freeN(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ********* */
|
|
|
|
|
|
2022-09-23 14:33:43 +10:00
|
|
|
/** Get a sub-string from the end of the name, separated by '.'. */
|
2015-06-27 10:24:00 +02:00
|
|
|
static int imb_exr_split_token(const char *str, const char *end, const char **token)
|
2006-12-20 17:57:56 +00:00
|
|
|
{
|
2015-06-27 10:24:00 +02:00
|
|
|
const char delims[] = {'.', '\0'};
|
2015-06-27 11:00:47 +02:00
|
|
|
const char *sep;
|
2015-06-27 10:24:00 +02:00
|
|
|
|
2015-06-27 11:00:47 +02:00
|
|
|
BLI_str_partition_ex(str, end, delims, &sep, token, true);
|
2015-06-27 10:24:00 +02:00
|
|
|
|
|
|
|
|
if (!sep) {
|
|
|
|
|
*token = str;
|
2012-08-22 16:44:32 +00:00
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2022-09-25 18:33:28 +10:00
|
|
|
return int(end - *token);
|
2012-05-11 08:06:01 +00:00
|
|
|
}
|
|
|
|
|
|
2024-02-29 13:50:18 +01:00
|
|
|
static void imb_exr_pass_name_from_channel(char *passname,
|
|
|
|
|
const ExrChannel *echan,
|
|
|
|
|
const char *channelname,
|
|
|
|
|
const bool has_xyz_channels)
|
|
|
|
|
{
|
|
|
|
|
const int passname_maxncpy = EXR_TOT_MAXNAME;
|
|
|
|
|
|
|
|
|
|
if (echan->chan_id == 'Z' && (!has_xyz_channels || BLI_strcaseeq(channelname, "depth"))) {
|
|
|
|
|
BLI_strncpy(passname, "Depth", passname_maxncpy);
|
|
|
|
|
}
|
|
|
|
|
else if (echan->chan_id == 'Y' && !has_xyz_channels) {
|
|
|
|
|
BLI_strncpy(passname, channelname, passname_maxncpy);
|
|
|
|
|
}
|
|
|
|
|
else if (ELEM(echan->chan_id, 'R', 'G', 'B', 'A', 'V', 'X', 'Y', 'Z')) {
|
|
|
|
|
BLI_strncpy(passname, "Combined", passname_maxncpy);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_strncpy(passname, channelname, passname_maxncpy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-11 11:04:08 +02:00
|
|
|
static void imb_exr_pass_name_from_channel_name(char *passname,
|
|
|
|
|
const ExrChannel * /*echan*/,
|
|
|
|
|
const char *channelname,
|
|
|
|
|
const bool /*has_xyz_channels*/)
|
|
|
|
|
{
|
|
|
|
|
const int passname_maxncpy = EXR_TOT_MAXNAME;
|
|
|
|
|
|
|
|
|
|
/* TODO: Are special tricks similar to imb_exr_pass_name_from_channel() needed here?
|
|
|
|
|
* Note that unknown passes are default to chan_id='X'. The place where this function is called
|
|
|
|
|
* is when the channel name is more than 1 character, so perhaps using just channel ID is not
|
|
|
|
|
* fully correct here. */
|
|
|
|
|
|
|
|
|
|
BLI_strncpy(passname, channelname, passname_maxncpy);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 10:01:10 +01:00
|
|
|
static int imb_exr_split_channel_name(ExrChannel *echan,
|
|
|
|
|
char *layname,
|
|
|
|
|
char *passname,
|
|
|
|
|
bool has_xyz_channels)
|
2012-05-11 08:06:01 +00:00
|
|
|
{
|
2023-06-19 20:06:55 +10:00
|
|
|
const int layname_maxncpy = EXR_TOT_MAXNAME;
|
2015-04-06 10:40:12 -03:00
|
|
|
const char *name = echan->m->name.c_str();
|
2012-05-11 08:06:01 +00:00
|
|
|
const char *end = name + strlen(name);
|
|
|
|
|
const char *token;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-13 10:01:10 +01:00
|
|
|
/* Some multi-layers have the combined buffer with names V, RGBA, or XYZ saved. Additionally, the
|
|
|
|
|
* Z channel can be interpreted as a Depth channel, but we only detect it as such if no X and Y
|
|
|
|
|
* channels exists, since the Z in this case is part of XYZ. The same goes for the Y channel,
|
|
|
|
|
* which can be detected as a luminance channel with the same name. */
|
2013-02-09 16:54:10 +00:00
|
|
|
if (name[1] == 0) {
|
2023-12-13 10:01:10 +01:00
|
|
|
/* Notice that we will be comparing with this upper-case version of the channel name, so the
|
|
|
|
|
* below comparisons are effectively not case sensitive, and would also consider lowercase
|
|
|
|
|
* versions of the listed channels. */
|
2022-05-09 17:17:03 +02:00
|
|
|
echan->chan_id = BLI_toupper_ascii(name[0]);
|
2013-03-12 10:34:14 +00:00
|
|
|
layname[0] = '\0';
|
2024-02-29 13:50:18 +01:00
|
|
|
imb_exr_pass_name_from_channel(passname, echan, name, has_xyz_channels);
|
2013-02-09 16:54:10 +00:00
|
|
|
return 1;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-02-23 14:32:17 +01:00
|
|
|
/* last token is channel identifier */
|
2022-05-09 17:17:03 +02:00
|
|
|
size_t len = imb_exr_split_token(name, end, &token);
|
2012-05-11 08:06:01 +00:00
|
|
|
if (len == 0) {
|
|
|
|
|
printf("multilayer read: bad channel name: %s\n", name);
|
2006-12-20 17:57:56 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
|
|
|
|
|
char channelname[EXR_TOT_MAXNAME];
|
|
|
|
|
BLI_strncpy(channelname, token, std::min(len + 1, sizeof(channelname)));
|
|
|
|
|
|
2020-08-07 12:39:50 +02:00
|
|
|
if (len == 1) {
|
2022-05-09 17:17:03 +02:00
|
|
|
echan->chan_id = BLI_toupper_ascii(channelname[0]);
|
2013-06-10 13:54:09 +00:00
|
|
|
}
|
2025-02-05 14:31:16 +11:00
|
|
|
else {
|
|
|
|
|
BLI_assert(len > 1); /* Checks above ensure. */
|
2013-06-10 13:54:09 +00:00
|
|
|
if (len == 2) {
|
2022-09-19 14:47:27 +10:00
|
|
|
/* Some multi-layers are using two-letter channels name,
|
2013-06-10 13:54:09 +00:00
|
|
|
* like, MX or NZ, which is basically has structure of
|
|
|
|
|
* <pass_prefix><component>
|
|
|
|
|
*
|
2023-02-12 14:37:16 +11:00
|
|
|
* This is a bit silly, but see file from #35658.
|
2013-06-10 13:54:09 +00:00
|
|
|
*
|
|
|
|
|
* Here we do some magic to distinguish such cases.
|
|
|
|
|
*/
|
2022-05-09 17:17:03 +02:00
|
|
|
const char chan_id = BLI_toupper_ascii(channelname[1]);
|
|
|
|
|
if (ELEM(chan_id, 'X', 'Y', 'Z', 'R', 'G', 'B', 'U', 'V', 'A')) {
|
|
|
|
|
echan->chan_id = chan_id;
|
2023-06-14 17:06:48 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
echan->chan_id = 'X'; /* Default to X if unknown. */
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2013-06-10 13:54:09 +00:00
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
else if (BLI_strcaseeq(channelname, "red")) {
|
2018-02-23 14:32:17 +01:00
|
|
|
echan->chan_id = 'R';
|
|
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
else if (BLI_strcaseeq(channelname, "green")) {
|
2018-02-23 14:32:17 +01:00
|
|
|
echan->chan_id = 'G';
|
|
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
else if (BLI_strcaseeq(channelname, "blue")) {
|
2018-02-23 14:32:17 +01:00
|
|
|
echan->chan_id = 'B';
|
|
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
else if (BLI_strcaseeq(channelname, "alpha")) {
|
2018-02-23 14:32:17 +01:00
|
|
|
echan->chan_id = 'A';
|
|
|
|
|
}
|
2022-05-09 17:17:03 +02:00
|
|
|
else if (BLI_strcaseeq(channelname, "depth")) {
|
2018-02-23 14:32:17 +01:00
|
|
|
echan->chan_id = 'Z';
|
|
|
|
|
}
|
2023-06-14 17:06:48 +02:00
|
|
|
else {
|
|
|
|
|
echan->chan_id = 'X'; /* Default to X if unknown. */
|
2013-06-10 13:54:09 +00:00
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
end -= len + 1; /* +1 to skip '.' separator */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-02-29 13:50:18 +01:00
|
|
|
if (end > name) {
|
|
|
|
|
/* second token is pass name */
|
|
|
|
|
len = imb_exr_split_token(name, end, &token);
|
|
|
|
|
if (len == 0) {
|
|
|
|
|
printf("multilayer read: bad channel name: %s\n", name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
BLI_strncpy(passname, token, len + 1);
|
|
|
|
|
end -= len + 1; /* +1 to skip '.' separator */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Single token, determine pass name from channel name. */
|
2024-07-11 11:04:08 +02:00
|
|
|
imb_exr_pass_name_from_channel_name(passname, echan, channelname, has_xyz_channels);
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-11 08:06:01 +00:00
|
|
|
/* all preceding tokens combined as layer name */
|
2019-04-23 11:01:30 +10:00
|
|
|
if (end > name) {
|
2023-06-19 20:06:55 +10:00
|
|
|
BLI_strncpy(layname, name, std::min(layname_maxncpy, int(end - name) + 1));
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2012-05-11 08:06:01 +00:00
|
|
|
layname[0] = '\0';
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 21:34:20 +00:00
|
|
|
return 1;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-26 11:34:42 +10:00
|
|
|
static ExrLayer *imb_exr_get_layer(ListBase *lb, const char *layname)
|
2006-12-20 17:57:56 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrLayer *lay = (ExrLayer *)BLI_findstring(lb, layname, offsetof(ExrLayer, name));
|
2010-05-17 16:42:53 +00:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
if (lay == nullptr) {
|
2025-03-05 16:35:09 +01:00
|
|
|
lay = MEM_callocN<ExrLayer>("exr layer");
|
2010-05-17 16:42:53 +00:00
|
|
|
BLI_addtail(lb, lay);
|
|
|
|
|
BLI_strncpy(lay->name, layname, EXR_LAY_MAXNAME);
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2010-05-17 16:42:53 +00:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
return lay;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-26 11:34:42 +10:00
|
|
|
static ExrPass *imb_exr_get_pass(ListBase *lb, const char *passname)
|
2006-12-20 17:57:56 +00:00
|
|
|
{
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrPass *pass = (ExrPass *)BLI_findstring(lb, passname, offsetof(ExrPass, name));
|
2010-05-17 16:42:53 +00:00
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
if (pass == nullptr) {
|
2025-03-05 16:35:09 +01:00
|
|
|
pass = MEM_callocN<ExrPass>("exr pass");
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (STREQ(passname, "Combined")) {
|
2010-05-17 16:42:53 +00:00
|
|
|
BLI_addhead(lb, pass);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2010-05-17 16:42:53 +00:00
|
|
|
BLI_addtail(lb, pass);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(pass->name, passname);
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
return pass;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 10:01:10 +01:00
|
|
|
static bool exr_has_xyz_channels(ExrHandle *exr_handle)
|
|
|
|
|
{
|
|
|
|
|
bool x_found = false;
|
|
|
|
|
bool y_found = false;
|
|
|
|
|
bool z_found = false;
|
|
|
|
|
LISTBASE_FOREACH (ExrChannel *, channel, &exr_handle->channels) {
|
2023-12-17 16:24:36 +11:00
|
|
|
if (ELEM(channel->m->name, "X", "x")) {
|
2023-12-13 10:01:10 +01:00
|
|
|
x_found = true;
|
|
|
|
|
}
|
2023-12-17 16:24:36 +11:00
|
|
|
if (ELEM(channel->m->name, "Y", "y")) {
|
2023-12-13 10:01:10 +01:00
|
|
|
y_found = true;
|
|
|
|
|
}
|
2023-12-17 16:24:36 +11:00
|
|
|
if (ELEM(channel->m->name, "Z", "z")) {
|
2023-12-13 10:01:10 +01:00
|
|
|
z_found = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return x_found && y_found && z_found;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-29 13:50:18 +01:00
|
|
|
/* Replacement for OpenEXR GetChannelsInMultiPartFile, that also handles the
|
|
|
|
|
* case where parts are used for passes instead of multiview. */
|
|
|
|
|
static std::vector<MultiViewChannelName> exr_channels_in_multi_part_file(
|
|
|
|
|
const MultiPartInputFile &file)
|
2006-12-20 17:57:56 +00:00
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
std::vector<MultiViewChannelName> channels;
|
2024-02-29 13:50:18 +01:00
|
|
|
|
|
|
|
|
/* Detect if file has multiview. */
|
|
|
|
|
StringVector multiview;
|
|
|
|
|
bool has_multiview = false;
|
|
|
|
|
if (file.parts() == 1) {
|
|
|
|
|
if (hasMultiView(file.header(0))) {
|
|
|
|
|
multiview = multiView(file.header(0));
|
|
|
|
|
has_multiview = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get channels from each part. */
|
|
|
|
|
for (int p = 0; p < file.parts(); p++) {
|
|
|
|
|
const ChannelList &c = file.header(p).channels();
|
|
|
|
|
|
2025-01-26 20:07:58 +01:00
|
|
|
std::string part_view;
|
2024-02-29 13:50:18 +01:00
|
|
|
if (file.header(p).hasView()) {
|
|
|
|
|
part_view = file.header(p).view();
|
|
|
|
|
}
|
2025-01-26 20:07:58 +01:00
|
|
|
std::string part_name;
|
2024-02-29 13:50:18 +01:00
|
|
|
if (file.header(p).hasName()) {
|
|
|
|
|
part_name = file.header(p).name();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (ChannelList::ConstIterator i = c.begin(); i != c.end(); i++) {
|
|
|
|
|
MultiViewChannelName m;
|
|
|
|
|
m.name = std::string(i.name());
|
|
|
|
|
m.internal_name = m.name;
|
|
|
|
|
|
|
|
|
|
if (has_multiview) {
|
|
|
|
|
m.view = viewFromChannelName(m.name, multiview);
|
|
|
|
|
m.name = removeViewName(m.internal_name, m.view);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
m.view = part_view;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Prepend part name as potential layer or pass name. */
|
|
|
|
|
if (!part_name.empty()) {
|
|
|
|
|
m.name = part_name + "." + m.name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.part_number = p;
|
|
|
|
|
channels.push_back(m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return channels;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool imb_exr_multilayer_parse_channels_from_file(ExrHandle *data)
|
|
|
|
|
{
|
|
|
|
|
std::vector<MultiViewChannelName> channels = exr_channels_in_multi_part_file(*data->ifile);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
imb_exr_get_views(*data->ifile, *data->multiView);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-07 12:21:11 +01:00
|
|
|
for (const MultiViewChannelName &channel : channels) {
|
2015-06-19 13:00:18 +02:00
|
|
|
IMB_exr_add_channel(
|
2020-12-07 12:21:11 +01:00
|
|
|
data, nullptr, channel.name.c_str(), channel.view.c_str(), 0, 0, nullptr, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
ExrChannel *echan = (ExrChannel *)data->channels.last;
|
2020-12-07 12:21:11 +01:00
|
|
|
echan->m->name = channel.name;
|
|
|
|
|
echan->m->view = channel.view;
|
|
|
|
|
echan->m->part_number = channel.part_number;
|
|
|
|
|
echan->m->internal_name = channel.internal_name;
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-12-13 10:01:10 +01:00
|
|
|
const bool has_xyz_channels = exr_has_xyz_channels(data);
|
|
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* now try to sort out how to assign memory to the channels */
|
|
|
|
|
/* first build hierarchical layer list */
|
2021-09-23 19:22:15 +02:00
|
|
|
ExrChannel *echan = (ExrChannel *)data->channels.first;
|
|
|
|
|
for (; echan; echan = echan->next) {
|
|
|
|
|
char layname[EXR_TOT_MAXNAME], passname[EXR_TOT_MAXNAME];
|
2023-12-13 10:01:10 +01:00
|
|
|
if (imb_exr_split_channel_name(echan, layname, passname, has_xyz_channels)) {
|
2015-04-06 10:40:12 -03:00
|
|
|
const char *view = echan->m->view.c_str();
|
|
|
|
|
char internal_name[EXR_PASS_MAXNAME];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(internal_name, passname);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
if (view[0] != '\0') {
|
|
|
|
|
char tmp_pass[EXR_PASS_MAXNAME];
|
2023-05-09 12:50:37 +10:00
|
|
|
SNPRINTF(tmp_pass, "%s.%s", passname, view);
|
|
|
|
|
STRNCPY(passname, tmp_pass);
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
ExrLayer *lay = imb_exr_get_layer(&data->layers, layname);
|
|
|
|
|
ExrPass *pass = imb_exr_get_pass(&lay->passes, passname);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-13 17:27:49 +00:00
|
|
|
pass->chan[pass->totchan] = echan;
|
2006-12-20 17:57:56 +00:00
|
|
|
pass->totchan++;
|
2015-04-06 10:40:12 -03:00
|
|
|
pass->view_id = echan->view_id;
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(pass->view, view);
|
|
|
|
|
STRNCPY(pass->internal_name, internal_name);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (pass->totchan >= EXR_PASS_MAXCHAN) {
|
2006-12-20 17:57:56 +00:00
|
|
|
break;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2012-03-24 07:52:14 +00:00
|
|
|
if (echan) {
|
2015-04-06 10:40:12 -03:00
|
|
|
printf("error, too many channels in one pass: %s\n", echan->m->name.c_str());
|
2021-09-23 19:22:15 +02:00
|
|
|
return false;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* with some heuristics, try to merge the channels in buffers */
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (ExrLayer *, lay, &data->layers) {
|
|
|
|
|
LISTBASE_FOREACH (ExrPass *, pass, &lay->passes) {
|
2012-03-24 07:52:14 +00:00
|
|
|
if (pass->totchan) {
|
2025-03-14 18:16:13 +01:00
|
|
|
pass->rect = MEM_calloc_arrayN<float>(
|
|
|
|
|
size_t(data->width) * size_t(data->height) * size_t(pass->totchan), "pass rect");
|
2012-06-13 17:27:49 +00:00
|
|
|
if (pass->totchan == 1) {
|
2021-09-23 19:22:15 +02:00
|
|
|
ExrChannel *echan = pass->chan[0];
|
2012-06-13 17:27:49 +00:00
|
|
|
echan->rect = pass->rect;
|
|
|
|
|
echan->xstride = 1;
|
2021-09-23 19:22:15 +02:00
|
|
|
echan->ystride = data->width;
|
2012-06-13 17:27:49 +00:00
|
|
|
pass->chan_id[0] = echan->chan_id;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
char lookup[256];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
memset(lookup, 0, sizeof(lookup));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* we can have RGB(A), XYZ(W), UVA */
|
2020-11-06 12:30:59 +11:00
|
|
|
if (ELEM(pass->totchan, 3, 4)) {
|
2012-06-13 17:27:49 +00:00
|
|
|
if (pass->chan[0]->chan_id == 'B' || pass->chan[1]->chan_id == 'B' ||
|
|
|
|
|
pass->chan[2]->chan_id == 'B')
|
|
|
|
|
{
|
2022-09-25 18:33:28 +10:00
|
|
|
lookup[uint('R')] = 0;
|
|
|
|
|
lookup[uint('G')] = 1;
|
|
|
|
|
lookup[uint('B')] = 2;
|
|
|
|
|
lookup[uint('A')] = 3;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
else if (pass->chan[0]->chan_id == 'Y' || pass->chan[1]->chan_id == 'Y' ||
|
|
|
|
|
pass->chan[2]->chan_id == 'Y')
|
|
|
|
|
{
|
2022-09-25 18:33:28 +10:00
|
|
|
lookup[uint('X')] = 0;
|
|
|
|
|
lookup[uint('Y')] = 1;
|
|
|
|
|
lookup[uint('Z')] = 2;
|
|
|
|
|
lookup[uint('W')] = 3;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2022-09-25 18:33:28 +10:00
|
|
|
lookup[uint('U')] = 0;
|
|
|
|
|
lookup[uint('V')] = 1;
|
|
|
|
|
lookup[uint('A')] = 2;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2021-09-23 19:22:15 +02:00
|
|
|
for (int a = 0; a < pass->totchan; a++) {
|
2012-06-13 17:27:49 +00:00
|
|
|
echan = pass->chan[a];
|
2022-09-25 18:33:28 +10:00
|
|
|
echan->rect = pass->rect + lookup[uint(echan->chan_id)];
|
2012-06-13 17:27:49 +00:00
|
|
|
echan->xstride = pass->totchan;
|
2021-09-23 19:22:15 +02:00
|
|
|
echan->ystride = data->width * pass->totchan;
|
2022-09-25 18:33:28 +10:00
|
|
|
pass->chan_id[uint(lookup[uint(echan->chan_id)])] = echan->chan_id;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
else { /* unknown */
|
2021-09-23 19:22:15 +02:00
|
|
|
for (int a = 0; a < pass->totchan; a++) {
|
|
|
|
|
ExrChannel *echan = pass->chan[a];
|
2012-06-13 17:27:49 +00:00
|
|
|
echan->rect = pass->rect + a;
|
|
|
|
|
echan->xstride = pass->totchan;
|
2021-09-23 19:22:15 +02:00
|
|
|
echan->ystride = data->width * pass->totchan;
|
2012-06-13 17:27:49 +00:00
|
|
|
pass->chan_id[a] = echan->chan_id;
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-09-23 19:22:15 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* creates channels, makes a hierarchy and assigns memory to channels */
|
|
|
|
|
static ExrHandle *imb_exr_begin_read_mem(IStream &file_stream,
|
|
|
|
|
MultiPartInputFile &file,
|
|
|
|
|
int width,
|
|
|
|
|
int height)
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)IMB_exr_get_handle();
|
|
|
|
|
|
|
|
|
|
data->ifile_stream = &file_stream;
|
|
|
|
|
data->ifile = &file;
|
|
|
|
|
|
|
|
|
|
data->width = width;
|
|
|
|
|
data->height = height;
|
|
|
|
|
|
|
|
|
|
if (!imb_exr_multilayer_parse_channels_from_file(data)) {
|
|
|
|
|
IMB_exr_close(data);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
return data;
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ********************************************************* */
|
2006-01-09 19:17:37 +00:00
|
|
|
|
2008-07-09 10:51:03 +00:00
|
|
|
/* debug only */
|
2015-04-06 10:40:12 -03:00
|
|
|
static void exr_printf(const char *fmt, ...)
|
2006-01-09 19:17:37 +00:00
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
#if 0
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2023-06-27 15:27:34 +10:00
|
|
|
vprintf(fmt, args);
|
2015-04-06 10:40:12 -03:00
|
|
|
va_end(args);
|
|
|
|
|
#else
|
|
|
|
|
(void)fmt;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2012-06-13 17:27:49 +00:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static void exr_print_filecontents(MultiPartInputFile &file)
|
|
|
|
|
{
|
|
|
|
|
int numparts = file.parts();
|
|
|
|
|
if (numparts == 1 && hasMultiView(file.header(0))) {
|
|
|
|
|
const StringVector views = multiView(file.header(0));
|
|
|
|
|
printf("OpenEXR-load: MultiView file\n");
|
|
|
|
|
printf("OpenEXR-load: Default view: %s\n", defaultViewName(views).c_str());
|
2020-12-07 12:21:11 +01:00
|
|
|
for (const std::string &view : views) {
|
|
|
|
|
printf("OpenEXR-load: Found view %s\n", view.c_str());
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (numparts > 1) {
|
|
|
|
|
printf("OpenEXR-load: MultiPart file\n");
|
|
|
|
|
for (int i = 0; i < numparts; i++) {
|
2019-04-23 11:01:30 +10:00
|
|
|
if (file.header(i).hasView()) {
|
2015-04-06 10:40:12 -03:00
|
|
|
printf("OpenEXR-load: Part %d: view = \"%s\"\n", i, file.header(i).view().c_str());
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
for (int j = 0; j < numparts; j++) {
|
|
|
|
|
const ChannelList &channels = file.header(j).channels();
|
2019-09-08 03:31:49 +10:00
|
|
|
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
|
2015-04-06 10:40:12 -03:00
|
|
|
const Channel &channel = i.channel();
|
|
|
|
|
printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
|
|
|
|
|
}
|
2006-01-09 19:17:37 +00:00
|
|
|
}
|
2006-01-10 21:41:37 +00:00
|
|
|
}
|
2008-07-09 10:51:03 +00:00
|
|
|
|
2021-07-23 16:56:00 +10:00
|
|
|
/* For non-multi-layer, map R G B A channel names to something that's in this file. */
|
2015-04-06 10:40:12 -03:00
|
|
|
static const char *exr_rgba_channelname(MultiPartInputFile &file, const char *chan)
|
2008-07-09 10:51:03 +00:00
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
const ChannelList &channels = file.header(0).channels();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-08 03:31:49 +10:00
|
|
|
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
|
2021-08-12 14:34:41 +10:00
|
|
|
// const Channel &channel = i.channel(); /* Not used yet. */
|
2012-06-13 17:27:49 +00:00
|
|
|
const char *str = i.name();
|
|
|
|
|
int len = strlen(str);
|
2012-03-24 07:52:14 +00:00
|
|
|
if (len) {
|
2012-06-13 17:27:49 +00:00
|
|
|
if (BLI_strcasecmp(chan, str + len - 1) == 0) {
|
2008-07-09 10:51:03 +00:00
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return chan;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 17:08:40 +02:00
|
|
|
static int exr_has_rgb(MultiPartInputFile &file, const char *rgb_channels[3])
|
2014-06-09 16:41:28 +06:00
|
|
|
{
|
2023-11-02 11:08:35 +01:00
|
|
|
/* Common names for RGB-like channels in order. The V channel name is used by convention for BW
|
|
|
|
|
* images, which will be broadcast to RGB channel at the end. */
|
2020-07-28 17:08:40 +02:00
|
|
|
static const char *channel_names[] = {
|
2023-11-02 11:08:35 +01:00
|
|
|
"V", "R", "Red", "G", "Green", "B", "Blue", "AR", "RA", "AG", "GA", "AB", "BA", nullptr};
|
2020-07-28 17:08:40 +02:00
|
|
|
|
|
|
|
|
const Header &header = file.header(0);
|
|
|
|
|
int num_channels = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; channel_names[i]; i++) {
|
2023-12-07 12:15:45 +11:00
|
|
|
/* Also try to match lower case variant of the channel names. */
|
2023-11-02 11:08:35 +01:00
|
|
|
std::string lower_case_name = std::string(channel_names[i]);
|
|
|
|
|
std::transform(lower_case_name.begin(),
|
|
|
|
|
lower_case_name.end(),
|
|
|
|
|
lower_case_name.begin(),
|
2023-11-07 11:31:07 +11:00
|
|
|
[](uchar c) { return std::tolower(c); });
|
2023-11-02 11:08:35 +01:00
|
|
|
|
|
|
|
|
if (header.channels().findChannel(channel_names[i]) ||
|
|
|
|
|
header.channels().findChannel(lower_case_name))
|
|
|
|
|
{
|
2020-07-28 17:08:40 +02:00
|
|
|
rgb_channels[num_channels++] = channel_names[i];
|
|
|
|
|
if (num_channels == 3) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return num_channels;
|
2014-06-09 16:41:28 +06:00
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static bool exr_has_luma(MultiPartInputFile &file)
|
2014-06-09 16:41:28 +06:00
|
|
|
{
|
|
|
|
|
/* Y channel is the luma and should always present fir luma space images,
|
|
|
|
|
* optionally it could be also channels for chromas called BY and RY.
|
|
|
|
|
*/
|
2020-07-28 17:08:40 +02:00
|
|
|
const Header &header = file.header(0);
|
2020-11-06 17:49:09 +01:00
|
|
|
return header.channels().findChannel("Y") != nullptr;
|
2014-06-09 16:41:28 +06:00
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static bool exr_has_chroma(MultiPartInputFile &file)
|
2014-06-09 16:41:28 +06:00
|
|
|
{
|
2020-07-28 17:08:40 +02:00
|
|
|
const Header &header = file.header(0);
|
2020-11-06 17:49:09 +01:00
|
|
|
return header.channels().findChannel("BY") != nullptr &&
|
|
|
|
|
header.channels().findChannel("RY") != nullptr;
|
2014-06-09 16:41:28 +06:00
|
|
|
}
|
|
|
|
|
|
2015-04-20 23:37:04 +10:00
|
|
|
static bool exr_has_alpha(MultiPartInputFile &file)
|
2012-06-14 12:05:38 +00:00
|
|
|
{
|
2020-07-28 17:08:40 +02:00
|
|
|
const Header &header = file.header(0);
|
2020-11-06 17:49:09 +01:00
|
|
|
return !(header.channels().findChannel("A") == nullptr);
|
2012-06-14 12:05:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-13 10:01:10 +01:00
|
|
|
static bool exr_has_xyz(MultiPartInputFile &file)
|
|
|
|
|
{
|
|
|
|
|
const Header &header = file.header(0);
|
|
|
|
|
return (header.channels().findChannel("X") != nullptr ||
|
|
|
|
|
header.channels().findChannel("x") != nullptr) &&
|
|
|
|
|
(header.channels().findChannel("Y") != nullptr ||
|
|
|
|
|
header.channels().findChannel("y") != nullptr) &&
|
|
|
|
|
(header.channels().findChannel("Z") != nullptr ||
|
|
|
|
|
header.channels().findChannel("z") != nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-25 15:05:53 +01:00
|
|
|
static bool exr_is_half_float(MultiPartInputFile &file)
|
|
|
|
|
{
|
|
|
|
|
const ChannelList &channels = file.header(0).channels();
|
|
|
|
|
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
|
|
|
|
|
const Channel &channel = i.channel();
|
|
|
|
|
if (channel.type != HALF) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
static bool imb_exr_is_multilayer_file(MultiPartInputFile &file)
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
{
|
2015-04-06 10:40:12 -03:00
|
|
|
const ChannelList &channels = file.header(0).channels();
|
2012-04-03 11:53:38 +00:00
|
|
|
std::set<std::string> layerNames;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-17 20:46:04 +02:00
|
|
|
/* This will not include empty layer names, so files with just R/G/B/A
|
|
|
|
|
* channels without a layer name will be single layer. */
|
2012-04-03 11:53:38 +00:00
|
|
|
channels.layers(layerNames);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-10-07 22:52:53 +11:00
|
|
|
return !layerNames.empty();
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imb_exr_type_by_channels(ChannelList &channels,
|
|
|
|
|
StringVector &views,
|
|
|
|
|
bool *r_singlelayer,
|
|
|
|
|
bool *r_multilayer,
|
|
|
|
|
bool *r_multiview)
|
|
|
|
|
{
|
|
|
|
|
std::set<std::string> layerNames;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
*r_singlelayer = true;
|
|
|
|
|
*r_multilayer = *r_multiview = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
/* will not include empty layer names */
|
|
|
|
|
channels.layers(layerNames);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 14:59:27 +02:00
|
|
|
if (!views.empty() && !views[0].empty()) {
|
2015-04-06 10:40:12 -03:00
|
|
|
*r_multiview = true;
|
2015-10-28 13:41:01 -02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_singlelayer = false;
|
2018-03-10 04:33:14 +01:00
|
|
|
*r_multilayer = (layerNames.size() > 1);
|
2015-10-28 13:41:01 -02:00
|
|
|
*r_multiview = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-03 14:59:27 +02:00
|
|
|
if (!layerNames.empty()) {
|
2020-07-19 17:12:48 +10:00
|
|
|
/* If `layerNames` is not empty, it means at least one layer is non-empty,
|
2015-04-06 10:40:12 -03:00
|
|
|
* but it also could be layers without names in the file and such case
|
2020-07-19 17:12:48 +10:00
|
|
|
* shall be considered a multi-layer EXR.
|
2015-04-06 10:40:12 -03:00
|
|
|
*
|
2020-07-19 17:12:48 +10:00
|
|
|
* That's what we do here: test whether there are empty layer names together
|
|
|
|
|
* with non-empty ones in the file.
|
2015-04-06 10:40:12 -03:00
|
|
|
*/
|
2019-04-23 11:01:30 +10:00
|
|
|
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) {
|
2020-12-07 12:21:11 +01:00
|
|
|
for (const std::string &layer_name : layerNames) {
|
2023-05-24 20:27:13 +10:00
|
|
|
/* see if any layer_name differs from a view_name. */
|
2020-12-07 12:21:11 +01:00
|
|
|
if (imb_exr_get_multiView_id(views, layer_name) == -1) {
|
|
|
|
|
std::string layerName = layer_name;
|
2015-04-06 10:40:12 -03:00
|
|
|
size_t pos = layerName.rfind('.');
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-10-28 13:41:01 -02:00
|
|
|
if (pos == std::string::npos) {
|
2015-04-06 10:40:12 -03:00
|
|
|
*r_multilayer = true;
|
|
|
|
|
*r_singlelayer = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
|
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_singlelayer = true;
|
|
|
|
|
*r_multilayer = false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
BLI_assert(r_singlelayer != r_multilayer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool exr_has_multiview(MultiPartInputFile &file)
|
|
|
|
|
{
|
2017-10-20 15:18:26 +02:00
|
|
|
for (int p = 0; p < file.parts(); p++) {
|
|
|
|
|
if (hasMultiView(file.header(p))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2015-04-06 10:40:12 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool exr_has_multipart_file(MultiPartInputFile &file)
|
|
|
|
|
{
|
|
|
|
|
return file.parts() > 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* it returns true if the file is multilayer or multiview */
|
|
|
|
|
static bool imb_exr_is_multi(MultiPartInputFile &file)
|
|
|
|
|
{
|
2019-04-22 01:18:55 +10:00
|
|
|
/* Multipart files are treated as multilayer in blender -
|
|
|
|
|
* even if they are single layer openexr with multiview. */
|
2019-04-23 11:01:30 +10:00
|
|
|
if (exr_has_multipart_file(file)) {
|
2015-04-06 10:40:12 -03:00
|
|
|
return true;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (exr_has_multiview(file)) {
|
2015-04-06 10:40:12 -03:00
|
|
|
return true;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (imb_exr_is_multilayer_file(file)) {
|
2015-04-06 10:40:12 -03:00
|
|
|
return true;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
|
|
|
|
|
return false;
|
Four-in-one commit:
(NOTE: new include dependency in Render module, might need MSVC update!
It has to include the imbuf/intern/openexr/ directory in search path)
-> New Composite node: "Hue Saturation".
Works like the former 'post process' menu. There's no gamma, brightness or
multiply needed in this node, for that the Curves Node functions better.
-> Enabled Toolbox in Node editor
This now also replaces the SHIFT+A for adding nodes. The nodes are
automatically added to the menus, using the 'class' category from the
type definition.
Current classes are (compositor examples):
Inputs: RenderResult, Image
Outputs: Composite, Viewer
Color Ops: RGB Curves, Mix, Hue Saturation, AlphaOver
Vector Ops: Normal, Vector Curves, Map Value
Filters: Filter, Blur, VectorBlur
Convertors: ColorRamp, RGBtoBW, Separate RGBA, Separate HSVA, Set Alpha
Generators: RGB, Value, Time
Groups: the list of custom defined nodes
-> OpenEXR tile saving support
Created an API for for saving tile-based Images with an unlimited amount
of layers/channels. I've tested it for 'render result' now, with the idea
that this can (optionally) replace the current inserting of tiles in the
main result buffers. Especially with a lot of layers, the used memory for
these buffers can easily go into the 100s of megs.
Two other advantages:
- all 'render result' layers can be saved entirely in a single file, for
later use in compositing, also for animation output.
- on each render, per scene, a unique temp file can be stored, allowing
to re-use these temp files on starting Blender or loading files, showing
the last result of a render command.
The option is currently disabled, needs more work... but I had to commit
this because of the rest of the work I did!
-> Bug fix
The Image node didn't call an execute event when browsing another image.
2006-02-18 13:28:44 +00:00
|
|
|
}
|
2006-01-10 21:41:37 +00:00
|
|
|
|
2017-10-20 15:18:26 +02:00
|
|
|
bool IMB_exr_has_multilayer(void *handle)
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
|
|
|
|
return imb_exr_is_multi(*data->ifile);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
static bool imb_check_chromaticity_val(float test_v, float ref_v)
|
|
|
|
|
{
|
|
|
|
|
const float tolerance_v = 0.000001f;
|
|
|
|
|
return (test_v < (ref_v + tolerance_v)) && (test_v > (ref_v - tolerance_v));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* https://openexr.com/en/latest/TechnicalIntroduction.html#recommendations */
|
|
|
|
|
static bool imb_check_chromaticity_matches(const Imf::Chromaticities &a,
|
|
|
|
|
const Imf::Chromaticities &b)
|
|
|
|
|
{
|
|
|
|
|
return imb_check_chromaticity_val(a.red.x, b.red.x) &&
|
|
|
|
|
imb_check_chromaticity_val(a.red.y, b.red.y) &&
|
|
|
|
|
imb_check_chromaticity_val(a.green.x, b.green.x) &&
|
|
|
|
|
imb_check_chromaticity_val(a.green.y, b.green.y) &&
|
|
|
|
|
imb_check_chromaticity_val(a.blue.x, b.blue.x) &&
|
|
|
|
|
imb_check_chromaticity_val(a.blue.y, b.blue.y) &&
|
|
|
|
|
imb_check_chromaticity_val(a.white.x, b.white.x) &&
|
|
|
|
|
imb_check_chromaticity_val(a.white.y, b.white.y);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-25 14:52:31 +01:00
|
|
|
static void imb_exr_set_known_colorspace(const Header &header, ImFileColorSpace &r_colorspace)
|
2025-03-11 21:21:23 +01:00
|
|
|
{
|
2025-03-25 14:52:31 +01:00
|
|
|
r_colorspace.is_hdr_float = true;
|
2025-03-11 21:21:23 +01:00
|
|
|
|
2025-03-24 12:00:07 +01:00
|
|
|
/* Read ACES container format metadata. */
|
|
|
|
|
const IntAttribute *header_aces_container = header.findTypedAttribute<IntAttribute>(
|
|
|
|
|
"acesImageContainerFlag");
|
2025-03-11 21:21:23 +01:00
|
|
|
const ChromaticitiesAttribute *header_chromaticities =
|
|
|
|
|
header.findTypedAttribute<ChromaticitiesAttribute>("chromaticities");
|
2025-03-24 12:00:07 +01:00
|
|
|
|
|
|
|
|
if ((header_aces_container && header_aces_container->value() == 1) ||
|
|
|
|
|
(header_chromaticities &&
|
|
|
|
|
imb_check_chromaticity_matches(header_chromaticities->value(), CHROMATICITIES_ACES_2065_1)))
|
|
|
|
|
{
|
|
|
|
|
const char *known_colorspace = IMB_colormanagement_role_colorspace_name_get(
|
|
|
|
|
COLOR_ROLE_ACES_INTERCHANGE);
|
|
|
|
|
if (known_colorspace) {
|
2025-03-25 14:52:31 +01:00
|
|
|
STRNCPY(r_colorspace.metadata_colorspace, known_colorspace);
|
2025-03-11 21:21:23 +01:00
|
|
|
}
|
2025-03-24 12:00:07 +01:00
|
|
|
}
|
|
|
|
|
else if (header_chromaticities &&
|
|
|
|
|
(imb_check_chromaticity_matches(header_chromaticities->value(), CHROMATICITIES_XYZ_E)))
|
|
|
|
|
{
|
|
|
|
|
/* Only works for the Blender default configuration due to fixed name. */
|
2025-03-25 14:52:31 +01:00
|
|
|
STRNCPY(r_colorspace.metadata_colorspace, "Linear CIE-XYZ E");
|
2025-03-11 21:21:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-05 08:49:22 +00:00
|
|
|
static bool exr_get_ppm(MultiPartInputFile &file, double ppm[2])
|
|
|
|
|
{
|
|
|
|
|
const Header &header = file.header(0);
|
|
|
|
|
if (!hasXDensity(header)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ppm[0] = double(xDensity(header)) / 0.0254;
|
|
|
|
|
ppm[1] = ppm[0] * double(header.pixelAspectRatio());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IMB_exr_get_ppm(void *handle, double ppm[2])
|
|
|
|
|
{
|
|
|
|
|
ExrHandle *data = (ExrHandle *)handle;
|
|
|
|
|
return exr_get_ppm(*data->ifile, ppm);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-25 14:52:31 +01:00
|
|
|
ImBuf *imb_load_openexr(const uchar *mem, size_t size, int flags, ImFileColorSpace &r_colorspace)
|
2012-06-14 12:05:38 +00:00
|
|
|
{
|
2023-06-03 08:36:28 +10:00
|
|
|
ImBuf *ibuf = nullptr;
|
2020-11-06 17:49:09 +01:00
|
|
|
IMemStream *membuf = nullptr;
|
|
|
|
|
MultiPartInputFile *file = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-11 16:14:06 +11:00
|
|
|
if (imb_is_a_openexr(mem, size) == 0) {
|
2020-11-06 17:49:09 +01:00
|
|
|
return nullptr;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
try {
|
2014-02-05 22:36:15 +11:00
|
|
|
bool is_multi;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-09-13 16:29:06 +10:00
|
|
|
membuf = new IMemStream((uchar *)mem, size);
|
2015-04-06 10:40:12 -03:00
|
|
|
file = new MultiPartInputFile(*membuf);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
const Header &file_header = file->header(0);
|
|
|
|
|
Box2i dw = file_header.dataWindow();
|
2021-12-10 15:38:46 +01:00
|
|
|
const size_t width = dw.max.x - dw.min.x + 1;
|
|
|
|
|
const size_t height = dw.max.y - dw.min.y + 1;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-01 11:09:22 +10:00
|
|
|
// printf("OpenEXR-load: image data window %d %d %d %d\n",
|
2006-01-11 10:41:04 +00:00
|
|
|
// dw.min.x, dw.min.y, dw.max.x, dw.max.y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-11-06 14:25:30 +01:00
|
|
|
if (false) { /* debug */
|
2015-04-06 10:40:12 -03:00
|
|
|
exr_print_filecontents(*file);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
is_multi = imb_exr_is_multi(*file);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-20 17:57:56 +00:00
|
|
|
/* do not make an ibuf when */
|
2012-04-28 06:31:57 +00:00
|
|
|
if (is_multi && !(flags & IB_test) && !(flags & IB_multilayer)) {
|
2006-12-20 17:57:56 +00:00
|
|
|
printf("Error: can't process EXR multilayer file\n");
|
|
|
|
|
}
|
|
|
|
|
else {
|
2022-08-26 15:57:43 +10:00
|
|
|
const bool is_alpha = exr_has_alpha(*file);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-14 12:05:38 +00:00
|
|
|
ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0);
|
2025-03-26 21:35:20 +01:00
|
|
|
ibuf->foptions.flag |= exr_is_half_float(*file) ? OPENEXR_HALF : 0;
|
|
|
|
|
ibuf->foptions.flag |= openexr_header_get_compression(file_header);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-04-05 08:49:22 +00:00
|
|
|
exr_get_ppm(*file, ibuf->ppm);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-03-25 14:52:31 +01:00
|
|
|
imb_exr_set_known_colorspace(file_header, r_colorspace);
|
2025-03-11 21:21:23 +01:00
|
|
|
|
2015-07-13 13:58:17 +02:00
|
|
|
ibuf->ftype = IMB_FTYPE_OPENEXR;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
if (!(flags & IB_test)) {
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-05-26 12:02:14 +02:00
|
|
|
if (flags & IB_metadata) {
|
|
|
|
|
Header::ConstIterator iter;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-05 16:27:15 +02:00
|
|
|
IMB_metadata_ensure(&ibuf->metadata);
|
2025-03-11 21:21:23 +01:00
|
|
|
for (iter = file_header.begin(); iter != file_header.end(); iter++) {
|
|
|
|
|
const StringAttribute *attr = file_header.findTypedAttribute<StringAttribute>(
|
2015-05-26 12:02:14 +02:00
|
|
|
iter.name());
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-05-26 12:02:14 +02:00
|
|
|
/* not all attributes are string attributes so we might get some NULLs here */
|
2020-04-03 16:59:34 +11:00
|
|
|
if (attr) {
|
|
|
|
|
IMB_metadata_set_field(ibuf->metadata, iter.name(), attr->value().c_str());
|
2015-05-26 12:02:14 +02:00
|
|
|
ibuf->flags |= IB_metadata;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-05-26 12:02:14 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-07-10 14:41:19 +10:00
|
|
|
/* Only enters with IB_multilayer flag set. */
|
|
|
|
|
if (is_multi && ((flags & IB_thumbnail) == 0)) {
|
2006-12-20 17:57:56 +00:00
|
|
|
/* constructs channels for reading, allocates memory in channels */
|
2015-06-03 16:23:32 +10:00
|
|
|
ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height);
|
2012-03-24 07:52:14 +00:00
|
|
|
if (handle) {
|
2006-12-20 17:57:56 +00:00
|
|
|
IMB_exr_read_channels(handle);
|
2012-06-13 17:27:49 +00:00
|
|
|
ibuf->userdata = handle; /* potential danger, the caller has to check for this! */
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2006-12-20 17:57:56 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-07-28 17:08:40 +02:00
|
|
|
const char *rgb_channels[3];
|
|
|
|
|
const int num_rgb_channels = exr_has_rgb(*file, rgb_channels);
|
2015-04-06 10:40:12 -03:00
|
|
|
const bool has_luma = exr_has_luma(*file);
|
2023-12-13 10:01:10 +01:00
|
|
|
const bool has_xyz = exr_has_xyz(*file);
|
2006-12-20 17:57:56 +00:00
|
|
|
FrameBuffer frameBuffer;
|
|
|
|
|
float *first;
|
2021-12-10 15:38:46 +01:00
|
|
|
size_t xstride = sizeof(float[4]);
|
|
|
|
|
size_t ystride = -xstride * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-09-11 12:38:31 +02:00
|
|
|
/* No need to clear image memory, it will be fully written below. */
|
2025-03-03 17:11:45 +01:00
|
|
|
IMB_alloc_float_pixels(ibuf, 4, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-06-12 09:04:10 +10:00
|
|
|
/* Inverse correct first pixel for data-window
|
2019-04-22 01:18:55 +10:00
|
|
|
* coordinates (- dw.min.y because of y flip). */
|
2023-05-18 10:19:01 +02:00
|
|
|
first = ibuf->float_buffer.data - 4 * (dw.min.x - dw.min.y * width);
|
2021-09-24 11:31:23 +10:00
|
|
|
/* But, since we read y-flipped (negative y stride) we move to last scan-line. */
|
2012-06-13 17:27:49 +00:00
|
|
|
first += 4 * (height - 1) * width;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-28 17:08:40 +02:00
|
|
|
if (num_rgb_channels > 0) {
|
|
|
|
|
for (int i = 0; i < num_rgb_channels; i++) {
|
|
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, rgb_channels[i]),
|
|
|
|
|
Slice(Imf::FLOAT, (char *)(first + i), xstride, ystride));
|
|
|
|
|
}
|
2014-06-09 16:41:28 +06:00
|
|
|
}
|
2023-12-13 10:01:10 +01:00
|
|
|
else if (has_xyz) {
|
|
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, "X"),
|
|
|
|
|
Slice(Imf::FLOAT, (char *)first, xstride, ystride));
|
|
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, "Y"),
|
|
|
|
|
Slice(Imf::FLOAT, (char *)(first + 1), xstride, ystride));
|
|
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, "Z"),
|
|
|
|
|
Slice(Imf::FLOAT, (char *)(first + 2), xstride, ystride));
|
|
|
|
|
}
|
2014-06-09 16:41:28 +06:00
|
|
|
else if (has_luma) {
|
2015-04-06 10:40:12 -03:00
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, "Y"),
|
2014-06-09 16:41:28 +06:00
|
|
|
Slice(Imf::FLOAT, (char *)first, xstride, ystride));
|
2015-04-06 10:40:12 -03:00
|
|
|
frameBuffer.insert(
|
|
|
|
|
exr_rgba_channelname(*file, "BY"),
|
2014-06-09 16:41:28 +06:00
|
|
|
Slice(Imf::FLOAT, (char *)(first + 1), xstride, ystride, 1, 1, 0.5f));
|
2015-04-06 10:40:12 -03:00
|
|
|
frameBuffer.insert(
|
|
|
|
|
exr_rgba_channelname(*file, "RY"),
|
2014-06-09 16:41:28 +06:00
|
|
|
Slice(Imf::FLOAT, (char *)(first + 2), xstride, ystride, 1, 1, 0.5f));
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-11-12 07:33:01 +00:00
|
|
|
/* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */
|
2015-04-06 10:40:12 -03:00
|
|
|
frameBuffer.insert(exr_rgba_channelname(*file, "A"),
|
2012-06-14 12:05:38 +00:00
|
|
|
Slice(Imf::FLOAT, (char *)(first + 3), xstride, ystride, 1, 1, 1.0f));
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-04-06 10:40:12 -03:00
|
|
|
InputPart in(*file, 0);
|
|
|
|
|
in.setFrameBuffer(frameBuffer);
|
|
|
|
|
in.readPixels(dw.min.y, dw.max.y);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2010-07-12 13:35:00 +00:00
|
|
|
/* XXX, ImBuf has no nice way to deal with this.
|
|
|
|
|
* ideally IM_rect would be used when the caller wants a rect BUT
|
|
|
|
|
* at the moment all functions use IM_rect.
|
2019-04-22 01:18:55 +10:00
|
|
|
* Disabling this is ok because all functions should check
|
|
|
|
|
* if a rect exists and create one on demand.
|
2020-10-10 18:19:55 +11:00
|
|
|
*
|
2010-07-12 13:35:00 +00:00
|
|
|
* Disabling this because the sequencer frees immediate. */
|
2020-10-10 18:19:55 +11:00
|
|
|
#if 0
|
2019-04-23 11:01:30 +10:00
|
|
|
if (flag & IM_rect) {
|
2025-03-03 17:11:45 +01:00
|
|
|
IMB_byte_from_float(ibuf);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2020-10-10 18:19:55 +11:00
|
|
|
#endif
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-07-28 17:08:40 +02:00
|
|
|
if (num_rgb_channels == 0 && has_luma && exr_has_chroma(*file)) {
|
2022-09-25 18:33:28 +10:00
|
|
|
for (size_t a = 0; a < size_t(ibuf->x) * ibuf->y; a++) {
|
2023-05-18 10:19:01 +02:00
|
|
|
float *color = ibuf->float_buffer.data + a * 4;
|
2020-07-28 17:08:40 +02:00
|
|
|
ycc_to_rgb(color[0] * 255.0f,
|
|
|
|
|
color[1] * 255.0f,
|
|
|
|
|
color[2] * 255.0f,
|
|
|
|
|
&color[0],
|
|
|
|
|
&color[1],
|
|
|
|
|
&color[2],
|
|
|
|
|
BLI_YCC_ITU_BT709);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2020-07-28 17:08:40 +02:00
|
|
|
}
|
2023-12-13 10:01:10 +01:00
|
|
|
else if (!has_xyz && num_rgb_channels <= 1) {
|
2020-07-28 17:08:40 +02:00
|
|
|
/* Convert 1 to 3 channels. */
|
2022-09-25 18:33:28 +10:00
|
|
|
for (size_t a = 0; a < size_t(ibuf->x) * ibuf->y; a++) {
|
2023-05-18 10:19:01 +02:00
|
|
|
float *color = ibuf->float_buffer.data + a * 4;
|
2023-12-13 10:01:10 +01:00
|
|
|
color[1] = color[0];
|
|
|
|
|
color[2] = color[0];
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-29 11:59:29 +02:00
|
|
|
/* file is no longer needed */
|
|
|
|
|
delete membuf;
|
|
|
|
|
delete file;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-07-29 11:59:29 +02:00
|
|
|
else {
|
|
|
|
|
delete membuf;
|
|
|
|
|
delete file;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-23 11:01:30 +10:00
|
|
|
if (flags & IB_alphamode_detect) {
|
2012-12-31 13:52:13 +00:00
|
|
|
ibuf->flags |= IB_alphamode_premul;
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2006-01-09 19:17:37 +00:00
|
|
|
}
|
2020-08-08 11:02:11 +10:00
|
|
|
return ibuf;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
2015-04-06 10:40:12 -03:00
|
|
|
catch (const std::exception &exc) {
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
std::cerr << exc.what() << std::endl;
|
2019-04-23 11:01:30 +10:00
|
|
|
if (ibuf) {
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
IMB_freeImBuf(ibuf);
|
2019-04-23 11:01:30 +10:00
|
|
|
}
|
2007-03-27 10:13:57 +00:00
|
|
|
delete file;
|
2015-06-03 16:07:27 +10:00
|
|
|
delete membuf;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-04-20 18:40:07 +02:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
std::cerr << "OpenEXR-Load: UNKNOWN ERROR" << std::endl;
|
|
|
|
|
if (ibuf) {
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
}
|
|
|
|
|
delete file;
|
|
|
|
|
delete membuf;
|
|
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
return nullptr;
|
Orange branch: OpenEXR finally in Blender!
Credits go to Gernot Ziegler, who originally coded EXR support, and to
Austin Benesh for bringing it further. Kent Mein provided a lot of code
for integrating float buffers in Blender imbuf and ImBuf API cleanup,
and provided Make and Scons and static linking.
At this moment; the EXR libraries are a *dependency*, so you cannot get
the Orange branch compiled without having OpenEXR installed. Get the
(precompiled or sources) stuff from www.openexr.com. Current default is
that the headers and lib resides in /user/local/
Several changes/additions/fixes were added:
- EXR code only supported 'half' format (16 bits per channel). I've added
float writing, but for reading it I need tomorrow. :)
- Quite some clumsy copying of data happened in EXR code.
- cleaned up the api calls already a bit, preparing for more advanced
support
- Zbuffers were saved 16 bits, now 32 bits
- automatic adding of .exr extensions went wrong
Imbuf:
- added proper imbuf->flags and imbuf->mall support for float buffers, it
was created for *each* imbuf. :)
- found bugs for float buffers in scaling and flipping. Code there will
need more checks still
- imbuf also needs to be verified to behave properly when no 32 bits
rect exists (for saving for example)
TODO:
- support internal float images for textures, backbuf, AO probes, and
display in Image window
Hope this commit won't screwup syncing with bf-blender... :/
2006-01-09 00:40:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
2006-01-09 10:55:41 +00:00
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
ImBuf *imb_load_filepath_thumbnail_openexr(const char *filepath,
|
|
|
|
|
const int /*flags*/,
|
|
|
|
|
const size_t max_thumb_size,
|
2025-03-25 14:52:31 +01:00
|
|
|
ImFileColorSpace &r_colorspace,
|
2023-06-03 08:36:28 +10:00
|
|
|
size_t *r_width,
|
|
|
|
|
size_t *r_height)
|
2012-04-02 11:04:24 +00:00
|
|
|
{
|
2022-05-19 14:55:04 -07:00
|
|
|
IStream *stream = nullptr;
|
|
|
|
|
Imf::RgbaInputFile *file = nullptr;
|
|
|
|
|
|
|
|
|
|
/* OpenExr uses exceptions for error-handling. */
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
/* The memory-mapped stream is faster, but don't use for huge files as it requires contiguous
|
|
|
|
|
* address space and we are processing multiple files at once (typically one per processor
|
|
|
|
|
* core). The 100 MB limit here is arbitrary, but seems reasonable and conservative. */
|
|
|
|
|
if (BLI_file_size(filepath) < 100 * 1024 * 1024) {
|
|
|
|
|
stream = new IMMapStream(filepath);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
stream = new IFileStream(filepath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* imb_initopenexr() creates a global pool of worker threads. But we thumbnail multiple images
|
|
|
|
|
* at once, and by default each file will attempt to use the entire pool for itself, stalling
|
|
|
|
|
* the others. So each thumbnail should use a single thread of the pool. */
|
|
|
|
|
file = new RgbaInputFile(*stream, 1);
|
|
|
|
|
|
|
|
|
|
if (!file->isComplete()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Imath::Box2i dw = file->dataWindow();
|
|
|
|
|
int source_w = dw.max.x - dw.min.x + 1;
|
|
|
|
|
int source_h = dw.max.y - dw.min.y + 1;
|
|
|
|
|
*r_width = source_w;
|
|
|
|
|
*r_height = source_h;
|
|
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
const Header &file_header = file->header();
|
|
|
|
|
|
2022-05-19 14:55:04 -07:00
|
|
|
/* If there is an embedded thumbnail, return that instead of making a new one. */
|
2025-03-11 21:21:23 +01:00
|
|
|
if (file_header.hasPreviewImage()) {
|
2022-05-19 14:55:04 -07:00
|
|
|
const Imf::PreviewImage &preview = file->header().previewImage();
|
|
|
|
|
ImBuf *ibuf = IMB_allocFromBuffer(
|
2023-05-18 10:19:01 +02:00
|
|
|
(uint8_t *)preview.pixels(), nullptr, preview.width(), preview.height(), 4);
|
2022-05-19 14:55:04 -07:00
|
|
|
delete file;
|
|
|
|
|
delete stream;
|
|
|
|
|
IMB_flipy(ibuf);
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
/* No effect yet for thumbnails, but will work once it is supported. */
|
2025-03-25 14:52:31 +01:00
|
|
|
imb_exr_set_known_colorspace(file_header, r_colorspace);
|
2022-05-19 14:55:04 -07:00
|
|
|
|
2025-03-11 21:21:23 +01:00
|
|
|
/* Create a new thumbnail. */
|
2023-11-07 16:33:19 +11:00
|
|
|
float scale_factor = std::min(float(max_thumb_size) / float(source_w),
|
2023-11-07 08:04:17 +01:00
|
|
|
float(max_thumb_size) / float(source_h));
|
2023-11-07 16:33:19 +11:00
|
|
|
int dest_w = std::max(int(source_w * scale_factor), 1);
|
|
|
|
|
int dest_h = std::max(int(source_h * scale_factor), 1);
|
2022-05-19 14:55:04 -07:00
|
|
|
|
2025-03-03 17:11:45 +01:00
|
|
|
ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_float_data);
|
2022-05-19 14:55:04 -07:00
|
|
|
|
|
|
|
|
/* A single row of source pixels. */
|
|
|
|
|
Imf::Array<Imf::Rgba> pixels(source_w);
|
|
|
|
|
|
|
|
|
|
/* Loop through destination thumbnail rows. */
|
|
|
|
|
for (int h = 0; h < dest_h; h++) {
|
|
|
|
|
|
|
|
|
|
/* Load the single source row that corresponds with destination row. */
|
2022-09-25 18:33:28 +10:00
|
|
|
int source_y = int(float(h) / scale_factor) + dw.min.y;
|
2022-05-19 14:55:04 -07:00
|
|
|
file->setFrameBuffer(&pixels[0] - dw.min.x - source_y * source_w, 1, source_w);
|
|
|
|
|
file->readPixels(source_y);
|
|
|
|
|
|
|
|
|
|
for (int w = 0; w < dest_w; w++) {
|
|
|
|
|
/* For each destination pixel find single corresponding source pixel. */
|
2024-01-22 15:58:18 +01:00
|
|
|
int source_x = int(std::min<int>((w / scale_factor), dw.max.x - 1));
|
2023-05-18 10:19:01 +02:00
|
|
|
float *dest_px = &ibuf->float_buffer.data[(h * dest_w + w) * 4];
|
2022-05-19 14:55:04 -07:00
|
|
|
dest_px[0] = pixels[source_x].r;
|
|
|
|
|
dest_px[1] = pixels[source_x].g;
|
|
|
|
|
dest_px[2] = pixels[source_x].b;
|
|
|
|
|
dest_px[3] = pixels[source_x].a;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-02 11:04:24 +00:00
|
|
|
|
2022-05-19 14:55:04 -07:00
|
|
|
if (file->lineOrder() == INCREASING_Y) {
|
|
|
|
|
IMB_flipy(ibuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete file;
|
|
|
|
|
delete stream;
|
|
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
catch (const std::exception &exc) {
|
|
|
|
|
std::cerr << exc.what() << std::endl;
|
|
|
|
|
delete file;
|
|
|
|
|
delete stream;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2023-04-20 18:40:07 +02:00
|
|
|
catch (...) { /* Catch-all for edge cases or compiler bugs. */
|
|
|
|
|
std::cerr << "OpenEXR-Thumbnail: UNKNOWN ERROR" << std::endl;
|
|
|
|
|
delete file;
|
|
|
|
|
delete stream;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2022-05-19 14:55:04 -07:00
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-02 19:37:22 +10:00
|
|
|
void imb_initopenexr()
|
2022-05-19 14:55:04 -07:00
|
|
|
{
|
|
|
|
|
/* In a multithreaded program, staticInitialize() must be called once during startup, before the
|
|
|
|
|
* program accesses any other functions or classes in the IlmImf library. */
|
|
|
|
|
Imf::staticInitialize();
|
|
|
|
|
Imf::setGlobalThreadCount(BLI_system_thread_count());
|
2012-04-02 11:04:24 +00:00
|
|
|
}
|
2006-01-09 10:55:41 +00:00
|
|
|
|
2023-07-02 19:37:22 +10:00
|
|
|
void imb_exitopenexr()
|
2018-09-18 11:10:49 +02:00
|
|
|
{
|
2022-05-19 14:55:04 -07:00
|
|
|
/* Tells OpenEXR to free thread pool, also ensures there is no running tasks. */
|
|
|
|
|
Imf::setGlobalThreadCount(0);
|
2018-09-18 11:10:49 +02:00
|
|
|
}
|