|
|
bf609b |
/* === S Y N F I G ========================================================= */
|
|
|
bf609b |
/*! \file synfig/rendering/software/task/taskpixelgammasw.cpp
|
|
|
bf609b |
** \brief TaskPixelGammaSW
|
|
|
bf609b |
**
|
|
|
bf609b |
** $Id$
|
|
|
bf609b |
**
|
|
|
bf609b |
** \legal
|
|
|
1911b2 |
** ......... ... 2016-2018 Ivan Mahonin
|
|
|
bf609b |
**
|
|
|
bf609b |
** This package is free software; you can redistribute it and/or
|
|
|
bf609b |
** modify it under the terms of the GNU General Public License as
|
|
|
bf609b |
** published by the Free Software Foundation; either version 2 of
|
|
|
bf609b |
** the License, or (at your option) any later version.
|
|
|
bf609b |
**
|
|
|
bf609b |
** This package is distributed in the hope that it will be useful,
|
|
|
bf609b |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
bf609b |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
bf609b |
** General Public License for more details.
|
|
|
bf609b |
** \endlegal
|
|
|
bf609b |
*/
|
|
|
bf609b |
/* ========================================================================= */
|
|
|
bf609b |
|
|
|
bf609b |
/* === H E A D E R S ======================================================= */
|
|
|
bf609b |
|
|
|
bf609b |
#ifdef USING_PCH
|
|
|
bf609b |
# include "pch.h"
|
|
|
bf609b |
#else
|
|
|
bf609b |
#ifdef HAVE_CONFIG_H
|
|
|
bf609b |
# include <config.h></config.h>
|
|
|
bf609b |
#endif
|
|
|
bf609b |
|
|
|
bf609b |
#include <synfig debug="" debugsurface.h=""></synfig>
|
|
|
bf609b |
#include <synfig general.h=""></synfig>
|
|
|
bf609b |
|
|
|
39c97b |
#include "../../common/task/taskpixelprocessor.h"
|
|
|
39c97b |
#include "tasksw.h"
|
|
|
bf609b |
|
|
|
bf609b |
#endif
|
|
|
bf609b |
|
|
|
bf609b |
using namespace synfig;
|
|
|
bf609b |
using namespace rendering;
|
|
|
bf609b |
|
|
|
bf609b |
/* === M A C R O S ========================================================= */
|
|
|
bf609b |
|
|
|
bf609b |
/* === G L O B A L S ======================================================= */
|
|
|
bf609b |
|
|
|
bf609b |
/* === P R O C E D U R E S ================================================= */
|
|
|
bf609b |
|
|
|
bf609b |
/* === M E T H O D S ======================================================= */
|
|
|
bf609b |
|
|
|
39c97b |
namespace {
|
|
|
c74fcf |
|
|
|
39c97b |
class TaskPixelGammaSW: public TaskPixelGamma, public TaskSW
|
|
|
39c97b |
{
|
|
|
39c97b |
public:
|
|
|
39c97b |
typedef etl::handle<taskpixelgammasw> Handle;</taskpixelgammasw>
|
|
|
39c97b |
static Token token;
|
|
|
5e2754 |
virtual Token::Handle get_token() const { return token.handle(); }
|
|
|
da4398 |
|
|
|
39c97b |
private:
|
|
|
39c97b |
typedef void Func(ColorReal &dst, const ColorReal &src, const ColorReal &gamma);
|
|
|
da4398 |
|
|
|
39c97b |
struct Params
|
|
|
bf609b |
{
|
|
|
39c97b |
ColorReal *dst;
|
|
|
39c97b |
int dst_stride;
|
|
|
39c97b |
const ColorReal *src;
|
|
|
39c97b |
int src_stride;
|
|
|
39c97b |
int width;
|
|
|
39c97b |
int height;
|
|
|
39c97b |
|
|
|
39c97b |
union {
|
|
|
a4bbdd |
ColorReal gamma[3];
|
|
|
39c97b |
struct {
|
|
|
a4bbdd |
ColorReal gamma_r, gamma_g, gamma_b;
|
|
|
28bbc1 |
};
|
|
|
28bbc1 |
};
|
|
|
bf609b |
|
|
|
39c97b |
Params():
|
|
|
39c97b |
dst(), dst_stride(),
|
|
|
39c97b |
src(), src_stride(),
|
|
|
39c97b |
width(), height(),
|
|
|
a4bbdd |
gamma_r(1.0), gamma_g(1.0), gamma_b(1.0)
|
|
|
39c97b |
{ }
|
|
|
39c97b |
|
|
|
39c97b |
Params(
|
|
|
39c97b |
Color *dst,
|
|
|
39c97b |
int dst_stride,
|
|
|
39c97b |
const Color *src,
|
|
|
39c97b |
int src_stride,
|
|
|
39c97b |
int width,
|
|
|
39c97b |
int height,
|
|
|
39c97b |
ColorReal gamma_r,
|
|
|
39c97b |
ColorReal gamma_g,
|
|
|
a4bbdd |
ColorReal gamma_b
|
|
|
39c97b |
):
|
|
|
39c97b |
dst((ColorReal*)dst), dst_stride(dst_stride),
|
|
|
39c97b |
src((const ColorReal*)src), src_stride(src_stride),
|
|
|
39c97b |
width(width), height(height),
|
|
|
a4bbdd |
gamma_r(gamma_r), gamma_g(gamma_g), gamma_b(gamma_b)
|
|
|
39c97b |
{ }
|
|
|
39c97b |
};
|
|
|
28bbc1 |
|
|
|
898f7c |
static inline ColorReal clamp(const ColorReal &x)
|
|
|
898f7c |
{
|
|
|
898f7c |
const ColorReal max = ColorReal(1.0)/real_low_precision<colorreal>();</colorreal>
|
|
|
898f7c |
return std::max(-max, std::min(max, x));
|
|
|
898f7c |
}
|
|
|
898f7c |
|
|
|
a4bbdd |
static inline ColorReal clamp_positive(const ColorReal &x)
|
|
|
898f7c |
{
|
|
|
a4bbdd |
const ColorReal max = ColorReal(1.0)/real_low_precision<colorreal>();</colorreal>
|
|
|
a4bbdd |
return std::max(real_low_precision<colorreal>(), std::min(max, x));</colorreal>
|
|
|
817417 |
}
|
|
|
817417 |
|
|
|
39c97b |
static inline void func_none(ColorReal&, const ColorReal&, const ColorReal&) { }
|
|
|
39c97b |
static inline void func_copy(ColorReal &dst, const ColorReal &src, const ColorReal&)
|
|
|
39c97b |
{ dst = src; }
|
|
|
39c97b |
static inline void func_one(ColorReal &dst, const ColorReal &, const ColorReal &)
|
|
|
39c97b |
{ dst = ColorReal(1.0); }
|
|
|
a4bbdd |
static inline void func_pow(ColorReal &dst, const ColorReal &src, const ColorReal &gamma)
|
|
|
a4bbdd |
{ dst = clamp(src < 0 ? -pow(-src, gamma) : pow(src, gamma)); }
|
|
|
a4bbdd |
|
|
|
a4bbdd |
template<func fb="" fg,="" fr,="" func=""></func>
|
|
|
a4bbdd |
static void process_rgb(const Params &p) {
|
|
|
a4bbdd |
if (p.src == p.dst)
|
|
|
39c97b |
{
|
|
|
39c97b |
assert(p.src_stride == p.dst_stride);
|
|
|
39c97b |
|
|
|
39c97b |
int dst_dr = 4*(p.dst_stride - p.width);
|
|
|
39c97b |
int row_size = 4*p.width;
|
|
|
39c97b |
ColorReal *dst = p.dst;
|
|
|
39c97b |
for(ColorReal *dst_end = dst + 4*p.dst_stride*p.height; dst != dst_end; dst += dst_dr)
|
|
|
39c97b |
{
|
|
|
39c97b |
for(ColorReal *dst_row_end = dst + row_size; dst != dst_row_end; dst += 4)
|
|
|
bf609b |
{
|
|
|
39c97b |
fr(dst[0], dst[0], p.gamma_r);
|
|
|
39c97b |
fg(dst[1], dst[1], p.gamma_g);
|
|
|
39c97b |
fb(dst[2], dst[2], p.gamma_b);
|
|
|
bf609b |
}
|
|
|
bf609b |
}
|
|
|
39c97b |
}
|
|
|
39c97b |
else
|
|
|
39c97b |
{
|
|
|
39c97b |
assert(p.src + 4*p.src_stride*p.height <= p.dst || p.dst + 4*p.dst_stride*p.height <= p.src);
|
|
|
39c97b |
|
|
|
39c97b |
int dst_dr = 4*(p.dst_stride - p.width);
|
|
|
39c97b |
int src_dr = 4*(p.src_stride - p.width);
|
|
|
39c97b |
int row_size = 4*p.width;
|
|
|
39c97b |
ColorReal *dst = p.dst;
|
|
|
39c97b |
const ColorReal *src = p.src;
|
|
|
39c97b |
for(ColorReal *dst_end = dst + 4*p.dst_stride*p.height; dst != dst_end; dst += dst_dr, src += src_dr)
|
|
|
bf609b |
{
|
|
|
39c97b |
for(ColorReal *dst_row_end = dst + row_size; dst != dst_row_end; dst += 4, src += 4)
|
|
|
bf609b |
{
|
|
|
39c97b |
fr(dst[0], src[0], p.gamma_r);
|
|
|
39c97b |
fg(dst[1], src[1], p.gamma_g);
|
|
|
39c97b |
fb(dst[2], src[2], p.gamma_b);
|
|
|
a4bbdd |
dst[3] = src[3];
|
|
|
bf609b |
}
|
|
|
bf609b |
}
|
|
|
bf609b |
}
|
|
|
39c97b |
}
|
|
|
bf609b |
|
|
|
39c97b |
template<func fg="" fr,="" func=""></func>
|
|
|
39c97b |
static void process_rg(const Params &p) {
|
|
|
a4bbdd |
if ( approximate_equal_lp(p.gamma_b, ColorReal(0.0))) process_rgb<fr, fg,="" func_one="">(p); else</fr,>
|
|
|
a4bbdd |
if (!approximate_equal_lp(p.gamma_b, ColorReal(1.0))) process_rgb<fr, fg,="" func_pow="">(p); else</fr,>
|
|
|
a4bbdd |
if (p.src == p.dst) process_rgb<fr, fg,="" func_none="">(p); else</fr,>
|
|
|
898f7c |
process_rgb<fr, fg,="" func_copy="">(p);</fr,>
|
|
|
39c97b |
}
|
|
|
bf609b |
|
|
|
39c97b |
template<func fr=""></func>
|
|
|
39c97b |
static void process_r(const Params &p) {
|
|
|
a4bbdd |
if ( approximate_equal_lp(p.gamma_g, ColorReal(0.0))) process_rg<fr, func_one="">(p); else</fr,>
|
|
|
a4bbdd |
if (!approximate_equal_lp(p.gamma_g, ColorReal(1.0))) process_rg<fr, func_pow="">(p); else</fr,>
|
|
|
a4bbdd |
if (p.src == p.dst) process_rg<fr, func_none="">(p); else</fr,>
|
|
|
898f7c |
process_rg<fr, func_copy="">(p);</fr,>
|
|
|
39c97b |
}
|
|
|
bf609b |
|
|
|
39c97b |
static void process(const Params &p) {
|
|
|
a4bbdd |
if ( approximate_equal_lp(p.gamma_r, ColorReal(0.0))) process_r<func_one>(p); else</func_one>
|
|
|
a4bbdd |
if (!approximate_equal_lp(p.gamma_r, ColorReal(1.0))) process_r<func_pow>(p); else</func_pow>
|
|
|
a4bbdd |
if (p.src == p.dst) process_r<func_none>(p); else</func_none>
|
|
|
898f7c |
process_r<func_copy>(p);</func_copy>
|
|
|
39c97b |
}
|
|
|
bf609b |
|
|
|
39c97b |
public:
|
|
|
5e2754 |
virtual bool run(RunParams&) const {
|
|
|
39c97b |
if (!is_valid() || !sub_task() || !sub_task()->is_valid())
|
|
|
39c97b |
return true;
|
|
|
39c97b |
|
|
|
39c97b |
RectInt rd = target_rect;
|
|
|
39c97b |
VectorInt offset = get_offset();
|
|
|
39c97b |
RectInt rs = sub_task()->target_rect + rd.get_min() + offset;
|
|
|
39c97b |
etl::set_intersect(rs, rs, rd);
|
|
|
39c97b |
if (rs.is_valid())
|
|
|
39c97b |
{
|
|
|
5e2754 |
LockWrite ldst(this);
|
|
|
5e2754 |
if (!ldst) return false;
|
|
|
5e2754 |
LockRead lsrc(sub_task());
|
|
|
5e2754 |
if (!lsrc) return false;
|
|
|
5e2754 |
|
|
|
39c97b |
synfig::Surface &dst = ldst->get_surface();
|
|
|
39c97b |
const synfig::Surface &src = lsrc->get_surface();
|
|
|
39c97b |
|
|
|
39c97b |
process(Params(
|
|
|
39c97b |
&dst[rs.miny][rs.minx],
|
|
|
39c97b |
dst.get_pitch()/sizeof(Color),
|
|
|
39c97b |
&src[rs.miny - rd.miny - offset[1]][rs.minx - rd.minx - offset[0]],
|
|
|
39c97b |
src.get_pitch()/sizeof(Color),
|
|
|
39c97b |
rs.get_width(),
|
|
|
39c97b |
rs.get_height(),
|
|
|
a4bbdd |
clamp_positive(gamma.get_r()),
|
|
|
a4bbdd |
clamp_positive(gamma.get_g()),
|
|
|
a4bbdd |
clamp_positive(gamma.get_b()) ));
|
|
|
39c97b |
}
|
|
|
bf609b |
|
|
|
da4398 |
return true;
|
|
|
39c97b |
}
|
|
|
39c97b |
};
|
|
|
da4398 |
|
|
|
bf609b |
|
|
|
5e2754 |
Task::Token TaskPixelGammaSW::token(
|
|
|
5e2754 |
DescReal<taskpixelgammasw, taskpixelgamma="">("PixelGammaSW") );</taskpixelgammasw,>
|
|
|
bf609b |
|
|
|
39c97b |
} // end of anonimous namespace
|
|
|
bf609b |
|
|
|
bf609b |
/* === E N T R Y P O I N T ================================================= */
|