mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-07-02 06:16:17 -04:00
Features:
--Add support for Exr files which use 32-bit floats for each RGBA channel. Seems to come out too washed out. --Allow for clearing an individual color curve. --Allow for saving multiple image types in EmberRender and EmberAnimate. All writes are threaded. --Remove --bpc command line argument. Add format png16 as a replacement. --Remove --enable_jpg_comments and --enable_png_comments command line arguments, and replace them with --enable_comments which applies to jpg, png and exr. --Add menu items to variations and affine spinners which allow for easy entry of specific numeric values like pi. --Make final render dialog be wider rather than so tall. Bug fixes: --Fix some OpenCL compile errors on Mac. --Remove ability to save bitmap files on all platforms but Windows. Code changes: --New dependency on OpenEXR. --Allow Curves class to interact with objects of a different template type. --Make m_Curves member of Ember always use float as template type. --Set the length of the curves array to always be 2^17 which should offer enough precision with new 32-bit float pixel types. --Set pixel types to always be 32-bit float. This results in a major reduction of code in the final accumulation part of Renderer.h/cpp. --Remove corresponding code from RendererCL and FinalAccumOpenCLKernelCreator. --Remove Transparency, NumChannels and BytesPerPixel setters from Renderer.h/cpp. --Add new global functions to format final image buffers and place all alpha calculation and scaling code in them. --Blending is no longer needed in OpenGLWidget because of the new pixel type. --Make new class, AffineDoubleSpinBox. --Attempt to make file save dialog code work the same on all OSes. --Remove some unused functions.
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "EmberCommonPch.h"
|
||||
#include "EmberOptions.h"
|
||||
|
||||
/// <summary>
|
||||
/// Global utility classes and functions that are common to all programs that use
|
||||
@ -168,26 +169,133 @@ void FormatName(Ember<T>& result, ostringstream& os, streamsize padding)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA buffer to an RGB buffer.
|
||||
/// Convert an RGBA 32-bit float buffer to an RGB 8-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA buffer</param>
|
||||
/// <param name="rgb">The RGB buffer</param>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGB 8-bit buffer</param>
|
||||
/// <param name="width">The width of the image in pixels</param>
|
||||
/// <param name="height">The height of the image in pixels</param>
|
||||
static void RgbaToRgb(vector<byte>& rgba, vector<byte>& rgb, size_t width, size_t height)
|
||||
static void Rgba32ToRgb8(v4F* rgba, byte* rgb, size_t width, size_t height)
|
||||
{
|
||||
if (rgba.data() != rgb.data())//Only resize the destination buffer if they are different.
|
||||
rgb.resize(width * height * 3);
|
||||
|
||||
for (size_t i = 0, j = 0; i < (width * height * 4); i += 4, j += 3)
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j] = rgba[i];
|
||||
rgb[j + 1] = rgba[i + 1];
|
||||
rgb[j + 2] = rgba[i + 2];
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].r * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].g * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].b * 255.0f, 0.0f, 255.0f));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an RGBA 8-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGBA 8-bit 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 Rgba32ToRgba8(v4F* rgba, byte* rgb, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].r * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].g * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = byte(Clamp<float>(rgba[i].b * 255.0f, 0.0f, 255.0f));
|
||||
rgb[j++] = doAlpha ? byte(Clamp<float>(rgba[i].a * 255.0f, 0.0f, 255.0f)) : 255;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert an RGBA 32-bit float buffer to an RGBA 16-bit buffer.
|
||||
/// The two buffers can point to the same memory location if needed.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The RGBA 16-bit 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 Rgba32ToRgba16(v4F* rgba, glm::uint16* rgb, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0, j = 0; i < (width * height); i++)
|
||||
{
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].r * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].g * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = glm::uint16(Clamp<float>(rgba[i].b * 65535.0f, 0.0f, 65535.0f));
|
||||
rgb[j++] = doAlpha ? glm::uint16(Clamp<float>(rgba[i].a * 65535.0f, 0.0f, 65535.0f)) : glm::uint16(65535);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.
|
||||
/// </summary>
|
||||
/// <param name="rgba">The RGBA 32-bit float buffer</param>
|
||||
/// <param name="rgb">The EXR RGBA 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 Rgba32ToRgbaExr(v4F* rgba, Rgba* ilmfRgba, size_t width, size_t height, bool doAlpha)
|
||||
{
|
||||
for (size_t i = 0; i < (width * height); i++)
|
||||
{
|
||||
ilmfRgba[i].r = Clamp<float>(rgba[i].r, 0.0f, 1.0f);
|
||||
ilmfRgba[i].g = Clamp<float>(rgba[i].g, 0.0f, 1.0f);
|
||||
ilmfRgba[i].b = Clamp<float>(rgba[i].b, 0.0f, 1.0f);
|
||||
ilmfRgba[i].a = 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>
|
||||
/// <param name="path">The path portion of where to save the file</param>
|
||||
/// <param name="out">The full name and path to override everything else</param>
|
||||
/// <param name="finalName">The name to use when useFinalName is true</param>
|
||||
/// <param name="prefix">The prefix to prepend to the filename</param>
|
||||
/// <param name="suffix">True suffix to append to the filename</param>
|
||||
/// <param name="format">The format extention. This must not contain a period.</param>
|
||||
/// <param name="padding">The width padding to use, which will be zero filled.</param>
|
||||
/// <param name="i">The numerical value to use for the filename when useFinalName is false and out is empty</param>
|
||||
/// <param name="useFinalName">Whether to use the name included in the flame. The i parameter is ignored in this case.</param>
|
||||
static string MakeSingleFilename(const string& path, const string& out, const string& finalName, const string& prefix, const string& suffix, const string& format, glm::uint padding, size_t i, bool useFinalName)
|
||||
{
|
||||
string filename;
|
||||
|
||||
if (!out.empty())
|
||||
{
|
||||
filename = out;
|
||||
}
|
||||
else if (useFinalName)
|
||||
{
|
||||
filename = path + prefix + finalName + suffix + "." + format;
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << path << prefix << setfill('0') << setprecision(0) << fixed << setw(padding) << i << suffix << "." << format;
|
||||
filename = fnstream.str();
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make a filename for a frame of an animation render. This is used in EmberAnimate.
|
||||
/// </summary>
|
||||
/// <param name="path">The path portion of where to save the file</param>
|
||||
/// <param name="prefix">The prefix to prepend to the filename</param>
|
||||
/// <param name="suffix">True suffix to append to the filename</param>
|
||||
/// <param name="format">The format extention. This must contain a period.</param>
|
||||
/// <param name="padding">The width padding to use, which will be zero filled.</param>
|
||||
/// <param name="ftime">The numerical value to use for the filename</param>
|
||||
static string MakeAnimFilename(const string& path, const string& prefix, const string& suffix, const string& format, glm::uint padding, size_t ftime)
|
||||
{
|
||||
ostringstream fnstream;
|
||||
fnstream << path << prefix << setfill('0') << setprecision(0) << fixed << setw(padding) << ftime << suffix << format;
|
||||
return fnstream.str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the number of strips required if the needed amount of memory
|
||||
/// is greater than the system memory, or greater than what the user wants to allow.
|
||||
@ -439,7 +547,7 @@ static vector<unique_ptr<Renderer<T, float>>> CreateRenderers(eRendererType rend
|
||||
/// <param name="allStripsFinished">Function called when all strips successfully finish rendering</param>
|
||||
/// <returns>True if all rendering was successful, else false.</returns>
|
||||
template <typename T>
|
||||
static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<byte>& finalImage, double time, size_t strips, bool yAxisUp,
|
||||
static bool StripsRender(RendererBase* renderer, Ember<T>& ember, vector<v4F>& finalImage, double time, size_t strips, bool yAxisUp,
|
||||
std::function<void(size_t strip)> perStripStart,
|
||||
std::function<void(size_t strip)> perStripFinish,
|
||||
std::function<void(size_t strip)> perStripError,
|
||||
|
@ -57,5 +57,17 @@
|
||||
#include "SimpleGlob.h"
|
||||
#include "SimpleOpt.h"
|
||||
|
||||
//Exr
|
||||
#ifdef _WIN32
|
||||
#define OPENEXR_DLL 1
|
||||
#endif
|
||||
|
||||
#include <ImfRgbaFile.h>
|
||||
#include <ImfStringAttribute.h>
|
||||
#include <half.h>
|
||||
|
||||
using namespace Imf;
|
||||
using namespace Imath;
|
||||
|
||||
using namespace EmberNs;
|
||||
using namespace EmberCLns;
|
||||
|
@ -58,8 +58,7 @@ enum class eOptionIDs : et
|
||||
OPT_INT_PALETTE,
|
||||
OPT_HEX_PALETTE,
|
||||
OPT_INSERT_PALETTE,
|
||||
OPT_JPEG_COMMENTS,
|
||||
OPT_PNG_COMMENTS,
|
||||
OPT_ENABLE_COMMENTS,
|
||||
OPT_WRITE_GENOME,
|
||||
OPT_THREADED_WRITE,
|
||||
OPT_ENCLOSED,
|
||||
@ -75,7 +74,6 @@ enum class eOptionIDs : et
|
||||
OPT_STRIPS,
|
||||
OPT_SUPERSAMPLE,
|
||||
OPT_TEMPSAMPLES,
|
||||
OPT_BPC,
|
||||
OPT_PRINT_EDIT_DEPTH,
|
||||
OPT_JPEG,
|
||||
OPT_BEGIN,
|
||||
@ -363,8 +361,7 @@ public:
|
||||
INITBOOLOPTION(NameEnable, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_NAME_ENABLE, _T("--name_enable"), false, SO_NONE, " --name_enable Use the name attribute contained in the Xml as the output filename [default: false].\n"));
|
||||
INITBOOLOPTION(HexPalette, Eob(eOptionUse::OPT_ANIM_GENOME, eOptionIDs::OPT_HEX_PALETTE, _T("--hex_palette"), true, SO_OPT, " --hex_palette Force palette RGB values to be hex when saving to Xml [default: true].\n"));
|
||||
INITBOOLOPTION(InsertPalette, Eob(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_INSERT_PALETTE, _T("--insert_palette"), false, SO_NONE, " --insert_palette Insert the palette into the image for debugging purposes. Disabled when running with OpenCL [default: false].\n"));
|
||||
INITBOOLOPTION(JpegComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG_COMMENTS, _T("--enable_jpg_comments"), false, SO_NONE, " --enable_jpg_comments Enables embedding the flame parameters and user identifying information in the jpeg header [default: false].\n"));
|
||||
INITBOOLOPTION(PngComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PNG_COMMENTS, _T("--enable_png_comments"), false, SO_NONE, " --enable_png_comments Enables embedding the flame parameters and user identifying information in the png header [default: false].\n"));
|
||||
INITBOOLOPTION(EnableComments, Eob(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_ENABLE_COMMENTS, _T("--enable_comments"), false, SO_NONE, " --enable_comments Enables embedding the flame parameters and user identifying information in the header of a jpg, png or exr [default: false].\n"));
|
||||
INITBOOLOPTION(WriteGenome, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_WRITE_GENOME, _T("--write_genome"), false, SO_NONE, " --write_genome Write out flame associated with center of motion blur window [default: false].\n"));
|
||||
INITBOOLOPTION(ThreadedWrite, Eob(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_THREADED_WRITE, _T("--threaded_write"), true, SO_OPT, " --threaded_write Use a separate thread to write images to disk. This gives better performance, but doubles the memory required for the final output buffer. [default: true].\n"));
|
||||
INITBOOLOPTION(Enclosed, Eob(eOptionUse::OPT_USE_GENOME, eOptionIDs::OPT_ENCLOSED, _T("--enclosed"), true, SO_OPT, " --enclosed Use enclosing Xml tags [default: true].\n"));
|
||||
@ -388,7 +385,6 @@ public:
|
||||
INITUINTOPTION(Strips, Eou(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_STRIPS, _T("--nstrips"), 1, SO_REQ_SEP, " --nstrips=<val> The number of fractions to split a single render frame into. Useful for print size renders or low memory systems [default: 1].\n"));
|
||||
INITUINTOPTION(Supersample, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUPERSAMPLE, _T("--supersample"), 0, SO_REQ_SEP, " --supersample=<val> The supersample value used to override the one specified in the file [default: 0 (use value from file), Range: 0 - 4].\n"));
|
||||
INITUINTOPTION(TemporalSamples, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_TEMPSAMPLES, _T("--ts"), 0, SO_REQ_SEP, " --ts=<val> The temporal samples value used to override all of the temporal sample values specified in the file when animating [default: 0 (use value from file)].\n"));
|
||||
INITUINTOPTION(BitsPerChannel, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_BPC, _T("--bpc"), 8, SO_REQ_SEP, " --bpc=<val> Bits per channel. 8 or 16 for PNG, 8 for all others, always 8 with OpenCL [default: 8].\n"));
|
||||
INITUINTOPTION(PrintEditDepth, Eou(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PRINT_EDIT_DEPTH, _T("--print_edit_depth"), 0, SO_REQ_SEP, " --print_edit_depth=<val> Depth to truncate <edit> tag structure when converting a flame to Xml. 0 prints all <edit> tags [default: 0].\n"));
|
||||
INITUINTOPTION(JpegQuality, Eou(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_JPEG, _T("--jpeg"), 95, SO_REQ_SEP, " --jpeg=<val> Jpeg quality 0-100 for compression [default: 95].\n"));
|
||||
INITUINTOPTION(FirstFrame, Eou(eOptionUse::OPT_USE_ANIMATE, eOptionIDs::OPT_BEGIN, _T("--begin"), UINT_MAX, SO_REQ_SEP, " --begin=<val> Time of first frame to render [default: first time specified in file].\n"));
|
||||
@ -431,7 +427,11 @@ public:
|
||||
INITSTRINGOPTION(Out, Eos(eOptionUse::OPT_USE_RENDER, eOptionIDs::OPT_OUT, _T("--out"), "", SO_REQ_SEP, " --out=<val> Name of a single output file. Not recommended when rendering more than one image.\n"));
|
||||
INITSTRINGOPTION(Prefix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_PREFIX, _T("--prefix"), "", SO_REQ_SEP, " --prefix=<val> Prefix to prepend to all output files.\n"));
|
||||
INITSTRINGOPTION(Suffix, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_SUFFIX, _T("--suffix"), "", SO_REQ_SEP, " --suffix=<val> Suffix to append to all output files.\n"));
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: bmp, jpg, png [default: png].\n"));
|
||||
#ifdef _WIN32
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: bmp, jpg, png or exr [default: png].\n"));
|
||||
#else
|
||||
INITSTRINGOPTION(Format, Eos(eOptionUse::OPT_RENDER_ANIM, eOptionIDs::OPT_FORMAT, _T("--format"), "png", SO_REQ_SEP, " --format=<val> Format of the output file. Valid values are: jpg, png or exr [default: png].\n"));
|
||||
#endif
|
||||
INITSTRINGOPTION(PalettePath, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_PALETTE_FILE, _T("--flam3_palettes"), "flam3-palettes.xml", SO_REQ_SEP, " --flam3_palettes=<val> Path and name of the palette file [default: flam3-palettes.xml].\n"));
|
||||
INITSTRINGOPTION(Id, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_ID, _T("--id"), "", SO_REQ_SEP, " --id=<val> ID to use in <edit> tags / image comments.\n"));
|
||||
INITSTRINGOPTION(Url, Eos(eOptionUse::OPT_USE_ALL, eOptionIDs::OPT_URL, _T("--url"), "", SO_REQ_SEP, " --url=<val> URL to use in <edit> tags / image comments.\n"));
|
||||
@ -519,8 +519,7 @@ public:
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_NAME_ENABLE, NameEnable);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_HEX_PALETTE, HexPalette);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_INSERT_PALETTE, InsertPalette);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_JPEG_COMMENTS, JpegComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_PNG_COMMENTS, PngComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_ENABLE_COMMENTS, EnableComments);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_WRITE_GENOME, WriteGenome);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_THREADED_WRITE, ThreadedWrite);
|
||||
PARSEBOOLOPTION(eOptionIDs::OPT_ENCLOSED, Enclosed);
|
||||
@ -538,7 +537,6 @@ public:
|
||||
PARSEOPTION(eOptionIDs::OPT_STRIPS, Strips);
|
||||
PARSEOPTION(eOptionIDs::OPT_SUPERSAMPLE, Supersample);
|
||||
PARSEOPTION(eOptionIDs::OPT_TEMPSAMPLES, TemporalSamples);
|
||||
PARSEOPTION(eOptionIDs::OPT_BPC, BitsPerChannel);
|
||||
PARSEOPTION(eOptionIDs::OPT_PRINT_EDIT_DEPTH, PrintEditDepth);
|
||||
PARSEOPTION(eOptionIDs::OPT_JPEG, JpegQuality);
|
||||
PARSEOPTION(eOptionIDs::OPT_BEGIN, FirstFrame);
|
||||
@ -723,18 +721,18 @@ public:
|
||||
{
|
||||
cout << "Usage:\n"
|
||||
#ifdef _WIN32
|
||||
"\tEmberRender.exe --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n";
|
||||
"\tEmberRender.exe --in=test.flame [--out=outfile --verbose --progress --opencl]\n\n";
|
||||
#else
|
||||
"\temberrender --in=test.flame [--out=outfile --format=png --verbose --progress --opencl]\n\n";
|
||||
"\temberrender --in=test.flame [--out=outfile --verbose --progress --opencl]\n\n";
|
||||
#endif
|
||||
}
|
||||
else if (optUsage == eOptionUse::OPT_USE_ANIMATE)
|
||||
{
|
||||
cout << "Usage:\n"
|
||||
#ifdef _WIN32
|
||||
"\tEmberAnimate.exe --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n";
|
||||
"\tEmberAnimate.exe --in=sequence.flame [--verbose --progress --opencl]\n\n";
|
||||
#else
|
||||
"\temberanimate --in=sequence.flame [--format=png --verbose --progress --opencl]\n\n";
|
||||
"\temberanimate --in=sequence.flame [--verbose --progress --opencl]\n\n";
|
||||
#endif
|
||||
}
|
||||
else if (optUsage == eOptionUse::OPT_USE_GENOME)
|
||||
@ -808,8 +806,7 @@ public:
|
||||
Eob NameEnable;
|
||||
Eob HexPalette;
|
||||
Eob InsertPalette;
|
||||
Eob JpegComments;
|
||||
Eob PngComments;
|
||||
Eob EnableComments;
|
||||
Eob WriteGenome;
|
||||
Eob ThreadedWrite;
|
||||
Eob Enclosed;
|
||||
@ -828,7 +825,6 @@ public:
|
||||
Eou Strips;
|
||||
Eou Supersample;
|
||||
Eou TemporalSamples;
|
||||
Eou BitsPerChannel;
|
||||
Eou Bits;
|
||||
Eou PrintEditDepth;
|
||||
Eou JpegQuality;
|
||||
|
@ -136,28 +136,28 @@ static bool WritePng(const char* filename, byte* image, size_t width, size_t hei
|
||||
glm::uint16 testbe = 1;
|
||||
vector<byte*> rows(height);
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[0].key = const_cast<png_charp>("flam3_version");
|
||||
text[0].key = const_cast<png_charp>("ember_version");
|
||||
text[0].text = const_cast<png_charp>(EmberVersion());
|
||||
text[1].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[1].key = const_cast<png_charp>("flam3_nickname");
|
||||
text[1].key = const_cast<png_charp>("ember_nickname");
|
||||
text[1].text = const_cast<png_charp>(nick.c_str());
|
||||
text[2].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[2].key = const_cast<png_charp>("flam3_url");
|
||||
text[2].key = const_cast<png_charp>("ember_url");
|
||||
text[2].text = const_cast<png_charp>(url.c_str());
|
||||
text[3].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[3].key = const_cast<png_charp>("flam3_id");
|
||||
text[3].key = const_cast<png_charp>("ember_id");
|
||||
text[3].text = const_cast<png_charp>(id.c_str());
|
||||
text[4].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[4].key = const_cast<png_charp>("flam3_error_rate");
|
||||
text[4].key = const_cast<png_charp>("ember_error_rate");
|
||||
text[4].text = const_cast<png_charp>(comments.m_Badvals.c_str());
|
||||
text[5].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[5].key = const_cast<png_charp>("flam3_samples");
|
||||
text[5].key = const_cast<png_charp>("ember_samples");
|
||||
text[5].text = const_cast<png_charp>(comments.m_NumIters.c_str());
|
||||
text[6].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
text[6].key = const_cast<png_charp>("flam3_time");
|
||||
text[6].key = const_cast<png_charp>("ember_time");
|
||||
text[6].text = const_cast<png_charp>(comments.m_Runtime.c_str());
|
||||
text[7].compression = PNG_TEXT_COMPRESSION_zTXt;
|
||||
text[7].key = const_cast<png_charp>("flam3_genome");
|
||||
text[7].key = const_cast<png_charp>("ember_genome");
|
||||
text[7].text = const_cast<png_charp>(comments.m_Genome.c_str());
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
@ -326,3 +326,50 @@ static bool WriteBmp(const char* filename, byte* image, size_t width, size_t hei
|
||||
b = SaveBmp(filename, bgrBuf.data(), width, height, newSize);
|
||||
return b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an EXR file.
|
||||
/// 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="image">Pointer to the 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 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)
|
||||
{
|
||||
try
|
||||
{
|
||||
int iw = int(width);
|
||||
int ih = int(height);
|
||||
RgbaOutputFile file(filename, iw, ih, WRITE_RGBA);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(image, 1, iw);
|
||||
file.writePixels(ih);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user