Color Management: remove hardcoded ACES ODT tonemap
This tonemap was added as a temporary option only and if it'll be needed again, it'll be better to implement is as either a spline in OCIO or as a film response curve (as some of such curves were added as a presets for RGB curves in Mango production SVN). Also revert changes made to IMB_buffer_byte_from_float since it's not actually needed anymore and makes it's clearer changes against trunk.
This commit is contained in:
@@ -392,15 +392,6 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to, const unsigned char *rect
|
||||
int width, int height, int stride_to, int stride_from);
|
||||
void IMB_buffer_float_clamp(float *buf, int width, int height);
|
||||
|
||||
/* converting pixel buffers using tonecurve */
|
||||
|
||||
typedef void (*imb_tonecurveCb) (float rgbOut[3], const float rgbIn[3]);
|
||||
|
||||
void IMB_buffer_byte_from_float_tonecurve(unsigned char *rect_to, const float *rect_from,
|
||||
int channels_from, float dither, int profile_to, int profile_from, int predivide,
|
||||
int width, int height, int stride_to, int stride_from,
|
||||
imb_tonecurveCb tonecurve_func);
|
||||
|
||||
/**
|
||||
* Change the ordering of the color bytes pointed to by rect from
|
||||
* rgba to abgr. size * 4 color bytes are reordered.
|
||||
|
||||
@@ -75,9 +75,6 @@ typedef struct ConstProcessorRcPtr {
|
||||
|
||||
/* define this to allow byte buffers be color managed */
|
||||
#undef COLORMANAGE_BYTE_BUFFER
|
||||
#undef COLORMANAGE_USE_ACES_ODT
|
||||
|
||||
#define ACES_ODT_TONECORVE "ACES"
|
||||
|
||||
/* ** list of all supported color spaces, displays and views */
|
||||
#ifdef WITH_OCIO
|
||||
@@ -582,11 +579,6 @@ void IMB_colormanagement_init(void)
|
||||
|
||||
OCIO_configRelease(config);
|
||||
|
||||
#ifdef COLORMANAGE_USE_ACES_ODT
|
||||
/* special views, which does not depend on OCIO */
|
||||
colormanage_view_add(ACES_ODT_TONECORVE);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
BLI_init_srgb_conversion();
|
||||
@@ -737,44 +729,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle)
|
||||
return linear_buffer;
|
||||
}
|
||||
|
||||
#ifdef COLORMANAGE_USE_ACES_ODT
|
||||
static void *do_display_buffer_apply_tonemap_thread(void *handle_v)
|
||||
{
|
||||
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
|
||||
imb_tonecurveCb tonecurve_func = (imb_tonecurveCb) handle->processor;
|
||||
|
||||
float *buffer = handle->buffer;
|
||||
unsigned char *display_buffer = handle->display_buffer;
|
||||
|
||||
int channels = handle->channels;
|
||||
int width = handle->width;
|
||||
int height = handle->tot_line;
|
||||
int dither = handle->dither;
|
||||
int predivide = handle->predivide;
|
||||
|
||||
float *linear_buffer = display_buffer_apply_get_linear_buffer(handle);
|
||||
|
||||
IMB_buffer_byte_from_float_tonecurve(display_buffer, linear_buffer, channels, dither,
|
||||
IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
|
||||
predivide, width, height, width, width,
|
||||
tonecurve_func);
|
||||
|
||||
if (linear_buffer != buffer)
|
||||
MEM_freeN(linear_buffer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void display_buffer_apply_tonemap(ImBuf *ibuf, unsigned char *display_buffer,
|
||||
imb_tonecurveCb tonecurve_func)
|
||||
{
|
||||
display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *)ibuf->rect,
|
||||
display_buffer, tonecurve_func,
|
||||
do_display_buffer_apply_tonemap_thread);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *do_display_buffer_apply_ocio_thread(void *handle_v)
|
||||
static void *do_display_buffer_apply_thread(void *handle_v)
|
||||
{
|
||||
DisplayBufferThread *handle = (DisplayBufferThread *) handle_v;
|
||||
ConstProcessorRcPtr *processor = (ConstProcessorRcPtr *) handle->processor;
|
||||
@@ -856,9 +811,9 @@ static ConstProcessorRcPtr *create_display_buffer_processor(const char *view_tra
|
||||
return processor;
|
||||
}
|
||||
|
||||
static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer,
|
||||
const ColorManagedViewSettings *view_settings,
|
||||
const ColorManagedDisplaySettings *display_settings)
|
||||
static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer,
|
||||
const ColorManagedViewSettings *view_settings,
|
||||
const ColorManagedDisplaySettings *display_settings)
|
||||
{
|
||||
ConstProcessorRcPtr *processor;
|
||||
const float gamma = view_settings->gamma;
|
||||
@@ -870,33 +825,12 @@ static void display_buffer_apply_ocio(ImBuf *ibuf, unsigned char *display_buffer
|
||||
|
||||
if (processor) {
|
||||
display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect,
|
||||
display_buffer, processor, do_display_buffer_apply_ocio_thread);
|
||||
display_buffer, processor, do_display_buffer_apply_thread);
|
||||
}
|
||||
|
||||
OCIO_processorRelease(processor);
|
||||
}
|
||||
|
||||
static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *display_buffer,
|
||||
const ColorManagedViewSettings *view_settings,
|
||||
const ColorManagedDisplaySettings *display_settings)
|
||||
{
|
||||
#ifdef COLORMANAGE_USE_ACES_ODT
|
||||
const char *view_transform = view_settings->view_transform;
|
||||
|
||||
if (!strcmp(view_transform, ACES_ODT_TONECORVE)) {
|
||||
/* special case for Mango team, this does not actually apply
|
||||
* any input space -> display space conversion and just applies
|
||||
* a tonecurve for better linear float -> sRGB byte conversion
|
||||
*/
|
||||
display_buffer_apply_tonemap(ibuf, display_buffer, IMB_ratio_preserving_odt_tonecurve);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
display_buffer_apply_ocio(ibuf, display_buffer, view_settings, display_settings);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************** Threaded color space transform routines *************************/
|
||||
|
||||
typedef struct ColorspaceTransformThread {
|
||||
@@ -1845,14 +1779,6 @@ void IMB_colormanagement_view_items_add(EnumPropertyItem **items, int *totitem,
|
||||
ColorManagedDisplay *display = colormanage_display_get_named(display_name);
|
||||
ColorManagedView *view;
|
||||
|
||||
#ifdef COLORMANAGE_USE_ACES_ODT
|
||||
/* OCIO_TODO: try to get rid of such a hackish stuff */
|
||||
view = colormanage_view_get_named(ACES_ODT_TONECORVE);
|
||||
if (view) {
|
||||
colormanagement_view_item_add(items, totitem, view);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display) {
|
||||
LinkData *display_view;
|
||||
|
||||
@@ -1901,8 +1827,7 @@ void IMB_colormanagement_colorspace_items_add(EnumPropertyItem **items, int *tot
|
||||
static void partial_buffer_update_rect(unsigned char *display_buffer, const float *linear_buffer, int display_stride,
|
||||
int linear_stride, int linear_offset_x, int linear_offset_y,
|
||||
int channels, int dither, int predivide, int profile_from,
|
||||
ConstProcessorRcPtr *processor, imb_tonecurveCb tonecurve_func,
|
||||
int xmin, int ymin, int xmax, int ymax)
|
||||
ConstProcessorRcPtr *processor, int xmin, int ymin, int xmax, int ymax)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
@@ -1928,12 +1853,7 @@ static void partial_buffer_update_rect(unsigned char *display_buffer, const floa
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (tonecurve_func) {
|
||||
IMB_buffer_byte_from_float_tonecurve(display_buffer + display_index, linear_buffer + linear_index,
|
||||
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB,
|
||||
predivide, 1, 1, 1, 1, tonecurve_func);
|
||||
}
|
||||
else {
|
||||
{
|
||||
IMB_buffer_byte_from_float(display_buffer + display_index, linear_buffer + linear_index, channels,
|
||||
dither, IB_PROFILE_SRGB, profile_from, predivide, 1, 1, 1, 1);
|
||||
}
|
||||
@@ -1948,23 +1868,22 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
int predivide = ibuf->flags & IB_cm_predivide;
|
||||
int dither = ibuf->dither;
|
||||
int profile_from = ibuf->profile;
|
||||
int display;
|
||||
int *display_buffer_flags;
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
int display;
|
||||
|
||||
int *display_buffer_flags;
|
||||
|
||||
BLI_lock_thread(LOCK_COLORMANAGE);
|
||||
|
||||
if (ibuf->rect && ibuf->rect_float) {
|
||||
/* update byte buffer created by legacy color management */
|
||||
partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y,
|
||||
channels, dither, predivide, profile_from, NULL, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
if (!ibuf->display_buffer_flags) {
|
||||
/* there's no cached display buffers, so no need to iterate though bit fields */
|
||||
|
||||
if (ibuf->rect && ibuf->rect_float) {
|
||||
/* update byte buffer created by legacy color management */
|
||||
partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y,
|
||||
channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
BLI_unlock_thread(LOCK_COLORMANAGE);
|
||||
|
||||
return;
|
||||
@@ -2011,21 +1930,12 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
if (display_buffer) {
|
||||
const char *view_name = IMB_colormanagement_view_get_indexed_name(view_index);
|
||||
ConstProcessorRcPtr *processor = NULL;
|
||||
imb_tonecurveCb tonecurve_func = NULL;
|
||||
|
||||
#ifdef COLORMANAGE_USE_ACES_ODT
|
||||
if (!strcmp(view_name, ACES_ODT_TONECORVE)) {
|
||||
tonecurve_func = IMB_ratio_preserving_odt_tonecurve;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
processor = create_display_buffer_processor(view_name, display_name, exposure, gamma);
|
||||
}
|
||||
processor = create_display_buffer_processor(view_name, display_name, exposure, gamma);
|
||||
|
||||
partial_buffer_update_rect(display_buffer, linear_buffer, buffer_width, stride,
|
||||
offset_x, offset_y, channels, dither, predivide, profile_from,
|
||||
processor, tonecurve_func, xmin, ymin, xmax, ymax);
|
||||
processor, xmin, ymin, xmax, ymax);
|
||||
|
||||
if (processor)
|
||||
OCIO_processorRelease(processor);
|
||||
@@ -2040,13 +1950,8 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer,
|
||||
}
|
||||
|
||||
MEM_freeN(display_buffer_flags);
|
||||
#else
|
||||
(void) display;
|
||||
(void) display_buffer_flags;
|
||||
#endif
|
||||
|
||||
BLI_lock_thread(LOCK_COLORMANAGE);
|
||||
if (ibuf->rect && ibuf->rect_float) {
|
||||
/* update byte buffer created by legacy color management */
|
||||
partial_buffer_update_rect((unsigned char *) ibuf->rect, linear_buffer, ibuf->x, stride, offset_x, offset_y,
|
||||
channels, dither, predivide, profile_from, NULL, NULL, xmin, ymin, xmax, ymax);
|
||||
}
|
||||
BLI_unlock_thread(LOCK_COLORMANAGE);
|
||||
}
|
||||
|
||||
@@ -38,15 +38,10 @@
|
||||
#include "imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_filter.h"
|
||||
#include "IMB_allocimbuf.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
#include <ocio_capi.h>
|
||||
#endif
|
||||
|
||||
/**************************** Interlace/Deinterlace **************************/
|
||||
|
||||
void IMB_de_interlace(ImBuf *ibuf)
|
||||
@@ -190,13 +185,11 @@ MINLINE void float_to_byte_dither_v4(uchar b[4], const float f[4], DitherContext
|
||||
}
|
||||
|
||||
/* float to byte pixels, output 4-channel RGBA */
|
||||
void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from,
|
||||
int channels_from, float dither, int profile_to, int profile_from, int predivide,
|
||||
int width, int height, int stride_to, int stride_from,
|
||||
imb_tonecurveCb tonecurve_func)
|
||||
void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
|
||||
int channels_from, float dither, int profile_to, int profile_from, int predivide,
|
||||
int width, int height, int stride_to, int stride_from)
|
||||
{
|
||||
float tmp[4];
|
||||
float corrected[4];
|
||||
int x, y;
|
||||
DitherContext *di;
|
||||
|
||||
@@ -207,9 +200,6 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from
|
||||
if (dither)
|
||||
di = create_dither_context(width, dither);
|
||||
|
||||
if (!tonecurve_func)
|
||||
tonecurve_func = copy_v3_v3;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
if (channels_from == 1) {
|
||||
/* single channel input */
|
||||
@@ -234,8 +224,7 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from
|
||||
else if (profile_to == IB_PROFILE_SRGB) {
|
||||
/* convert from linear to sRGB */
|
||||
for (x = 0; x < width; x++, from += 3, to += 4) {
|
||||
tonecurve_func(corrected, from);
|
||||
linearrgb_to_srgb_v3_v3(tmp, corrected);
|
||||
linearrgb_to_srgb_v3_v3(tmp, from);
|
||||
rgb_float_to_uchar(to, tmp);
|
||||
to[3] = 255;
|
||||
}
|
||||
@@ -271,37 +260,25 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from
|
||||
|
||||
if (dither && predivide) {
|
||||
for (x = 0; x < width; x++, from += 4, to += 4) {
|
||||
tonecurve_func(corrected, from);
|
||||
corrected[3] = from[3];
|
||||
|
||||
linearrgb_to_srgb_ushort4_predivide(us, corrected);
|
||||
linearrgb_to_srgb_ushort4_predivide(us, from);
|
||||
ushort_to_byte_dither_v4(to, us, di);
|
||||
}
|
||||
}
|
||||
else if (dither) {
|
||||
for (x = 0; x < width; x++, from += 4, to += 4) {
|
||||
tonecurve_func(corrected, from);
|
||||
corrected[3] = from[3];
|
||||
|
||||
linearrgb_to_srgb_ushort4(us, corrected);
|
||||
linearrgb_to_srgb_ushort4(us, from);
|
||||
ushort_to_byte_dither_v4(to, us, di);
|
||||
}
|
||||
}
|
||||
else if (predivide) {
|
||||
for (x = 0; x < width; x++, from += 4, to += 4) {
|
||||
tonecurve_func(corrected, from);
|
||||
corrected[3] = from[3];
|
||||
|
||||
linearrgb_to_srgb_ushort4_predivide(us, corrected);
|
||||
linearrgb_to_srgb_ushort4_predivide(us, from);
|
||||
ushort_to_byte_v4(to, us);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (x = 0; x < width; x++, from += 4, to += 4) {
|
||||
tonecurve_func(corrected, from);
|
||||
corrected[3] = from[3];
|
||||
|
||||
linearrgb_to_srgb_ushort4(us, corrected);
|
||||
linearrgb_to_srgb_ushort4(us, from);
|
||||
ushort_to_byte_v4(to, us);
|
||||
}
|
||||
}
|
||||
@@ -343,15 +320,6 @@ void IMB_buffer_byte_from_float_tonecurve(uchar *rect_to, const float *rect_from
|
||||
clear_dither_context(di);
|
||||
}
|
||||
|
||||
void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from,
|
||||
int channels_from, float dither, int profile_to, int profile_from, int predivide,
|
||||
int width, int height, int stride_to, int stride_from)
|
||||
{
|
||||
IMB_buffer_byte_from_float_tonecurve(rect_to, rect_from, channels_from, dither, profile_to, profile_from, predivide,
|
||||
width, height, stride_to, stride_from, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* byte to float pixels, input and output 4-channel RGBA */
|
||||
void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from,
|
||||
int profile_to, int profile_from, int predivide,
|
||||
|
||||
@@ -31,11 +31,8 @@
|
||||
* \ingroup imbuf
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
@@ -602,217 +599,3 @@ void IMB_premultiply_alpha(ImBuf *ibuf)
|
||||
IMB_premultiply_rect_float(ibuf->rect_float, ibuf->planes, ibuf->x, ibuf->y);
|
||||
}
|
||||
|
||||
/* Tonecurve corrections */
|
||||
|
||||
/* code of rdt_shaper_fwd and ratio_preserving_odt_tonecurve belongs to
|
||||
* ACES project (https://github.com/ampas/aces-dev)
|
||||
*/
|
||||
|
||||
/* === ODT SPLINE === */
|
||||
/*
|
||||
* Algorithm for applying ODT tone curve in forward direction.
|
||||
*
|
||||
* vers 1.0 Doug Walker 2012-01-23
|
||||
* modified by Scott Dyer 2012-02-28
|
||||
*/
|
||||
|
||||
/* Input and output are in linear (not log) units. */
|
||||
static float rdt_shaper_fwd(float x)
|
||||
{
|
||||
/* B-spline coefficients.
|
||||
* The units are density of the output.
|
||||
*/
|
||||
const float COEFS0 = -0.008f;
|
||||
const float COEFS1 = -0.00616f;
|
||||
const float COEFS2 = 0.026f;
|
||||
const float COEFS3 = 0.185f;
|
||||
const float COEFS4 = 0.521f;
|
||||
const float COEFS5 = 0.993f;
|
||||
const float COEFS6 = 1.563f;
|
||||
const float COEFS7 = 2.218f;
|
||||
const float COEFS8 = 2.795f;
|
||||
const float COEFS9 = 3.36f;
|
||||
const float COEFS10 = 4.0f; /* NB: keep this less than or equal to -log10(FLARE) */
|
||||
/* The locations of these control points in OCES density space are:
|
||||
* -1., -0.79, -0.44, -0.01, 0.48, 1.01, 1.58, 2.18, 2.82, 3.47, 4.15, 4.85
|
||||
*/
|
||||
|
||||
/* The flare term allows the spline to more rapidly approach zero
|
||||
* while keeping the shape of the curve well-behaved in density space.
|
||||
*/
|
||||
const float FLARE = 1e-4f;
|
||||
|
||||
/* The last control point is fixed to yield a specific density at the
|
||||
* end of the knot domain.
|
||||
*/
|
||||
/* const float COEFS11 = 2. * (-log10(FLARE) - 0.001) - COEFS10; */
|
||||
|
||||
/* Note: Apparently a CTL bug prevents calling log10() here, so
|
||||
* you'll need to update this manually if you change FLARE.
|
||||
*/
|
||||
const float COEFS11 = COEFS10 + 2.0f * (4.0f - COEFS10);
|
||||
|
||||
/* The knots are in units of OCES density. */
|
||||
const unsigned int KNOT_LEN = 11;
|
||||
const float KNOT_START = -0.9f;
|
||||
const float KNOT_END = 4.484256f;
|
||||
|
||||
/* The KNOT_POW adjusts the spacing to put more knots near the toe (highlights). */
|
||||
const float KNOT_POW = 1.0f / 1.3f;
|
||||
const float OFFS = KNOT_START;
|
||||
const float SC = KNOT_END - KNOT_START;
|
||||
|
||||
/* KNOT_DENS is density of the spline at the knots. */
|
||||
const float KNOT_DENS[11] = {
|
||||
(COEFS0 + COEFS1) / 2.0f,
|
||||
(COEFS1 + COEFS2) / 2.0f,
|
||||
(COEFS2 + COEFS3) / 2.0f,
|
||||
(COEFS3 + COEFS4) / 2.0f,
|
||||
(COEFS4 + COEFS5) / 2.0f,
|
||||
(COEFS5 + COEFS6) / 2.0f,
|
||||
(COEFS6 + COEFS7) / 2.0f,
|
||||
(COEFS7 + COEFS8) / 2.0f,
|
||||
(COEFS8 + COEFS9) / 2.0f,
|
||||
(COEFS9 + COEFS10) / 2.0f,
|
||||
(COEFS10 + COEFS11) / 2.0f
|
||||
};
|
||||
|
||||
/* Parameters controlling linear extrapolation. */
|
||||
const float LIGHT_SLOPE = 0.023;
|
||||
const float CROSSOVER = pow(10,-KNOT_END);
|
||||
const float REV_CROSSOVER = pow(10.0f, -KNOT_DENS[ KNOT_LEN - 1]) - FLARE;
|
||||
const float DARK_SLOPE = REV_CROSSOVER / CROSSOVER;
|
||||
|
||||
/* Textbook monomial to basis-function conversion matrix. */
|
||||
/*const*/ float M[3][3] = {
|
||||
{ 0.5f, -1.0f, 0.5f},
|
||||
{-1.0f, 1.0f, 0.5f},
|
||||
{ 0.5f, 0.0f, 0.0f}
|
||||
};
|
||||
|
||||
float y;
|
||||
|
||||
/* Linear extrapolation in linear space for negative & very dark values. */
|
||||
if (x <= CROSSOVER) {
|
||||
y = x * DARK_SLOPE;
|
||||
}
|
||||
else {
|
||||
float in_dens = -log10(x);
|
||||
float out_dens;
|
||||
float knot_coord = (in_dens - OFFS) / SC;
|
||||
|
||||
if (knot_coord <= 0.0f) {
|
||||
/* Linear extrapolation in log space for very light values. */
|
||||
|
||||
out_dens = KNOT_DENS[0] - (KNOT_START - in_dens) * LIGHT_SLOPE;
|
||||
}
|
||||
else {
|
||||
/* For typical OCES values, apply a B-spline curve. */
|
||||
|
||||
int j;
|
||||
float t;
|
||||
float cf[3], monomials[3], v[3];
|
||||
|
||||
knot_coord = ( KNOT_LEN - 1) * pow( knot_coord, KNOT_POW);
|
||||
|
||||
j = knot_coord;
|
||||
t = knot_coord - j;
|
||||
|
||||
/* Would like to do this: */
|
||||
/* float cf[ 3] = { COEFS[ j], COEFS[ j + 1], COEFS[ j + 2]}; */
|
||||
/* or at least: */
|
||||
/* cf[0] = COEFS[j]; */
|
||||
/* cf[1] = COEFS[j + 1]; */
|
||||
/* cf[2] = COEFS[j + 2]; */
|
||||
/* But apparently CTL bugs prevent it, so we do the following: */
|
||||
if (j <= 0) {
|
||||
cf[0] = COEFS0; cf[1] = COEFS1; cf[2] = COEFS2;
|
||||
}
|
||||
else if (j == 1) {
|
||||
cf[0] = COEFS1; cf[1] = COEFS2; cf[2] = COEFS3;
|
||||
}
|
||||
else if (j == 2) {
|
||||
cf[0] = COEFS2; cf[1] = COEFS3; cf[2] = COEFS4;
|
||||
}
|
||||
else if (j == 3) {
|
||||
cf[0] = COEFS3; cf[1] = COEFS4; cf[2] = COEFS5;
|
||||
}
|
||||
else if (j == 4) {
|
||||
cf[0] = COEFS4; cf[1] = COEFS5; cf[2] = COEFS6;
|
||||
}
|
||||
else if (j == 5) {
|
||||
cf[0] = COEFS5; cf[1] = COEFS6; cf[2] = COEFS7;
|
||||
}
|
||||
else if (j == 6) {
|
||||
cf[0] = COEFS6; cf[1] = COEFS7; cf[2] = COEFS8;
|
||||
}
|
||||
else if (j == 7) {
|
||||
cf[0] = COEFS7; cf[1] = COEFS8; cf[2] = COEFS9;
|
||||
}
|
||||
else if (j == 8) {
|
||||
cf[0] = COEFS8; cf[1] = COEFS9; cf[2] = COEFS10;
|
||||
}
|
||||
else {
|
||||
cf[0] = COEFS9; cf[1] = COEFS10; cf[2] = COEFS11;
|
||||
}
|
||||
|
||||
monomials[0] = t * t;
|
||||
monomials[1] = t;
|
||||
monomials[2] = 1.0f;
|
||||
|
||||
mul_v3_m3v3(v, M, cf);
|
||||
out_dens = dot_v3v3( monomials, v);
|
||||
}
|
||||
|
||||
y = pow(10.0f, -out_dens) - FLARE;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
void IMB_ratio_preserving_odt_tonecurve(float rgbOut[3], const float rgbIn[3])
|
||||
{
|
||||
float acesIn[3], acesOut[3];
|
||||
|
||||
float rec709_to_aces[3][3] = {{0.4395770431f, 0.0895979404f, 0.0174174830f},
|
||||
{0.3839148879f, 0.8147120476f, 0.1087378338f},
|
||||
{0.1765103489f, 0.0956883803f, 0.8738504052f}};
|
||||
|
||||
float aces_to_rec709[3][3] = {{ 2.5219228268f, -0.2754705548f, -0.0159884077f},
|
||||
{-1.1370280981f, 1.3698303699f, -0.1477921605f},
|
||||
{-0.3849000633f, -0.0943564922f, 1.1637737751f}};
|
||||
|
||||
/* The "ratio preserving tonecurve" is used to avoid hue/chroma shifts.
|
||||
* It sends a norm through the tonecurve and scales the RGB values based on the output.
|
||||
*/
|
||||
|
||||
const float NTH_POWER = 2.0f;
|
||||
const float TINY = 1e-12f;
|
||||
float numerator, denominator;
|
||||
float normRGB, normRGBo;
|
||||
|
||||
mul_v3_m3v3(acesIn, rec709_to_aces, (float *) rgbIn);
|
||||
|
||||
numerator = pow(acesIn[0], NTH_POWER) + pow(acesIn[1], NTH_POWER) + pow(acesIn[2], NTH_POWER);
|
||||
|
||||
denominator = pow(acesIn[0], NTH_POWER - 1) +
|
||||
pow(acesIn[1], NTH_POWER - 1) +
|
||||
pow(acesIn[2], NTH_POWER - 1);
|
||||
|
||||
/* use of max function to avoid divide by zero */
|
||||
denominator = MAX2(TINY, denominator);
|
||||
|
||||
normRGB = numerator / denominator;
|
||||
|
||||
if (normRGB <= 0.0f) {
|
||||
normRGB = TINY;
|
||||
}
|
||||
|
||||
normRGBo = rdt_shaper_fwd(normRGB);
|
||||
|
||||
acesOut[0] = acesIn[0] * normRGBo / normRGB;
|
||||
acesOut[1] = acesIn[1] * normRGBo / normRGB;
|
||||
acesOut[2] = acesIn[2] * normRGBo / normRGB;
|
||||
|
||||
mul_v3_m3v3(rgbOut, aces_to_rec709, (float *) acesOut);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user