mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-01 05:46:06 -04:00
--User changes
-Allow for saving EXR as full 31-bit float per component per pixel. -Allow for saving the output from the final render dialog as a different image format without starting the rendering process over. --Code changes: -Make StripsRender() handle memsetting the final output image so calling code no longer has to. -Make FinalRenderEmberController<T>::SaveCurrentRender() return the path that the image was actually saved to.
This commit is contained in:
@ -263,12 +263,12 @@ static void Rgba32ToRgba16(v4F* rgba, glm::uint16* rgb, size_t width, size_t hei
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an EXR RGBA 32-bit float buffer.
|
||||
/// Convert an RGBA 32-bit float buffer to an EXR RGBA 16-bit float buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// Note that this squares the values coming in, for some reason EXR expects that.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The EXR RGBA 32-bit float buffer</param>
|
||||
/// <param name="ilmfRgba">The EXR RGBA 16-bit float buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
/// <param name="doAlpha">True to use alpha transparency, false to assign the max alpha value to make each pixel fully visible</param>
|
||||
@ -283,6 +283,30 @@ static void Rgba32ToRgbaExr(v4F* rgba, Rgba* ilmfRgba, size_t width, size_t heig
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an EXR RGBA 32-bit float buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// Note that this squares the values coming in, for some reason EXR expects that.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="r">The EXR red 32-bit float buffer</param>
|
||||
/// <param name="g">The EXR green 32-bit float buffer</param>
|
||||
/// <param name="b">The EXR blue 32-bit float buffer</param>
|
||||
/// <param name="a">The EXR alpha 32-bit float buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
/// <param name="doAlpha">True to use alpha transparency, false to assign the max alpha value to make each pixel fully visible</param>
|
||||
static void Rgba32ToRgba32Exr(v4F* rgba, float* r, float* g, float* b, float* a, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0; i < (width * height); i++)
|
||||
{
|
||||
r[i] = Clamp<float>(Sqr(rgba[i].r), 0.0f, 1.0f);
|
||||
g[i] = Clamp<float>(Sqr(rgba[i].g), 0.0f, 1.0f);
|
||||
b[i] = Clamp<float>(Sqr(rgba[i].b), 0.0f, 1.0f);
|
||||
a[i] = doAlpha ? Clamp<float>(rgba[i].a * 1.0f, 0.0f, 1.0f) : 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a filename for a single render. This is used in EmberRender.
|
||||
/// </summary>
|
||||
@ -599,6 +623,7 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<v4F>& f
|
||||
vector<QTIsaac<ISAAC_SIZE, ISAAC_INT>> randVec;
|
||||
ember.m_Quality *= strips;
|
||||
ember.m_FinalRasH = size_t(ceil(floatStripH));
|
||||
Memset(finalImage);
|
||||
|
||||
if (strips > 1)
|
||||
randVec = renderer->RandVec();
|
||||
@ -654,7 +679,6 @@ static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<v4F>& f
|
||||
if (success)
|
||||
allStripsFinished(ember);
|
||||
|
||||
Memset(finalImage);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -67,11 +67,15 @@
|
||||
#include <OpenEXR/ImfRgbaFile.h>
|
||||
#include <OpenEXR/ImfStringAttribute.h>
|
||||
#include <OpenEXR/half.h>
|
||||
#define ENUM_DYLD_BOOL
|
||||
#include <mach-o/dyld.h>
|
||||
#include <OpenEXR/ImfChannelList.h>
|
||||
#include <OpenEXR/ImfOutputFile.h>
|
||||
#define ENUM_DYLD_BOOL
|
||||
#include <mach-o/dyld.h>
|
||||
#else
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <ImfChannelList.h>
|
||||
#include <ImfOutputFile.h>
|
||||
#include <half.h>
|
||||
#endif
|
||||
|
||||
|
@ -364,9 +364,9 @@ static bool WriteBmp(const char* filename, byte* image, size_t width, size_t hei
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an EXR file.
|
||||
/// This is used for extreme color precision because it uses
|
||||
/// floats for each color channel.
|
||||
/// Write an EXR file which will use the 16 bit half float format for each pixel channel.
|
||||
/// This is used for high color precision because it uses
|
||||
/// HALFS for each color channel.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and name of the file</param>
|
||||
/// <param name="image">Pointer to the image data to write</param>
|
||||
@ -378,7 +378,7 @@ static bool WriteBmp(const char* filename, byte* image, size_t width, size_t hei
|
||||
/// <param name="url">Url of the author</param>
|
||||
/// <param name="nick">Nickname of the author</param>
|
||||
/// <returns>True if success, else false</returns>
|
||||
static bool WriteExr(const char* filename, Rgba* image, size_t width, size_t height, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
|
||||
static bool WriteExr16(const char* filename, Rgba* image, size_t width, size_t height, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -419,3 +419,89 @@ static bool WriteExr(const char* filename, Rgba* image, size_t width, size_t hei
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an EXR file which will use the 32 bit half float format for each pixel channel.
|
||||
/// This is used for extreme color precision because it uses
|
||||
/// floats for each color channel.
|
||||
/// </summary>
|
||||
/// <param name="filename">The full path and name of the file</param>
|
||||
/// <param name="r">Pointer to the red image data to write</param>
|
||||
/// <param name="g">Pointer to the green image data to write</param>
|
||||
/// <param name="b">Pointer to the blue image data to write</param>
|
||||
/// <param name="a">Pointer to the alpha image data to write</param>
|
||||
/// <param name="width">Width of the image in pixels</param>
|
||||
/// <param name="height">Height of the image in pixels</param>
|
||||
/// <param name="enableComments">True to embed comments, else false</param>
|
||||
/// <param name="comments">The comment string to embed</param>
|
||||
/// <param name="id">Id of the author</param>
|
||||
/// <param name="url">Url of the author</param>
|
||||
/// <param name="nick">Nickname of the author</param>
|
||||
/// <returns>True if success, else false</returns>
|
||||
static bool WriteExr32(const char* filename, float* r, float* g, float* b, float* a, size_t width, size_t height, bool enableComments, const EmberImageComments& comments, const string& id, const string& url, const string& nick)
|
||||
{
|
||||
try
|
||||
{
|
||||
int iw = int(width);
|
||||
int ih = int(height);
|
||||
std::unique_ptr<OutputFile> file;
|
||||
|
||||
try
|
||||
{
|
||||
rlg l(fileCs);
|
||||
Header header(iw, ih);
|
||||
header.channels().insert("R", Channel(PixelType::FLOAT));
|
||||
header.channels().insert("G", Channel(PixelType::FLOAT));
|
||||
header.channels().insert("B", Channel(PixelType::FLOAT));
|
||||
header.channels().insert("A", Channel(PixelType::FLOAT));
|
||||
file = std::make_unique<OutputFile>(filename, header);
|
||||
}
|
||||
catch (std::exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (enableComments)
|
||||
{
|
||||
auto& header = const_cast<Imf::Header&>(file->header());
|
||||
header.insert("ember_version", StringAttribute(EmberVersion()));
|
||||
header.insert("ember_nickname", StringAttribute(nick));
|
||||
header.insert("ember_url", StringAttribute(url));
|
||||
header.insert("ember_id", StringAttribute(id));
|
||||
header.insert("ember_error_rate", StringAttribute(comments.m_Badvals));
|
||||
header.insert("ember_samples", StringAttribute(comments.m_NumIters));
|
||||
header.insert("ember_time", StringAttribute(comments.m_Runtime));
|
||||
header.insert("ember_genome", StringAttribute(comments.m_Genome));
|
||||
}
|
||||
|
||||
FrameBuffer frameBuffer;
|
||||
frameBuffer.insert("R",
|
||||
Slice(PixelType::FLOAT,
|
||||
(char*)r,
|
||||
sizeof(*r) * 1,
|
||||
sizeof(*r) * width));
|
||||
frameBuffer.insert("G",
|
||||
Slice(PixelType::FLOAT,
|
||||
(char*)g,
|
||||
sizeof(*g) * 1,
|
||||
sizeof(*g) * width));
|
||||
frameBuffer.insert("B",
|
||||
Slice(PixelType::FLOAT,
|
||||
(char*)b,
|
||||
sizeof(*b) * 1,
|
||||
sizeof(*b) * width));
|
||||
frameBuffer.insert("A",
|
||||
Slice(PixelType::FLOAT,
|
||||
(char*)a,
|
||||
sizeof(*a) * 1,
|
||||
sizeof(*a) * width));
|
||||
file->setFrameBuffer(frameBuffer);
|
||||
file->writePixels(ih);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user