X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdisplay%2Fnr-filter-gaussian.cpp;h=5ef43039475e1570cb7c745693270805e98d3d79;hb=8f2afbd99dcbbe962be70bc574e356b33c8b9537;hp=ccbc018ef84b09da0e1b73aa4dd290b6536c54dc;hpb=724821145d62dee9f97465c706952582da6e432d;p=inkscape.git diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index ccbc018ef..5ef430394 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "isnan.h" @@ -24,8 +25,10 @@ #include "display/nr-filter-primitive.h" #include "display/nr-filter-gaussian.h" #include "display/nr-filter-types.h" +#include "display/nr-filter-units.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-matrix.h" +#include "libnr/nr-matrix-fns.h" #include "util/fixed_point.h" #include "prefs-utils.h" @@ -38,13 +41,13 @@ // Using the backwards-pass initialization procedure from: // Boundary Conditions for Young - van Vliet Recursive Filtering // Bill Triggs, Michael Sdika -// IEEE Transactions on Signal Processing, Volume 54, Number 5 - may 2006 +// IEEE Transactions on Signal Processing, Volume 54, Number 5 - may 2006 // Number of IIR filter coefficients used. Currently only 3 is supported. // "Recursive Gaussian Derivative Filters" says this is enough though (and // some testing indeed shows that the quality doesn't improve much if larger // filters are used). -const size_t N = 3; +static size_t const N = 3; template void copy_n(InIt beg_in, Size N, OutIt beg_out) { @@ -52,7 +55,7 @@ void copy_n(InIt beg_in, Size N, OutIt beg_out) { } // Type used for IIR filter coefficients (can be 10.21 signed fixed point, see Anisotropic Gaussian Filtering Using Fixed Point Arithmetic, Christoph H. Lampert & Oliver Wirjadi, 2006) -typedef double IIRValue; +typedef double IIRValue; // Type used for FIR filter coefficients (can be 16.16 unsigned fixed point, should have 8 or more bits in the fractional part, the integer part should be capable of storing approximately 20*255) typedef Inkscape::Util::FixedPoint FIRValue; @@ -67,15 +70,15 @@ template static inline T clip(T const& v, T const& a, T const& b) { template static inline Tt round_cast(Ts const& v) { - static Ts const rndoffset(.5); - return static_cast(v+rndoffset); + static Ts const rndoffset(.5); + return static_cast(v+rndoffset); } template static inline Tt clip_round_cast(Ts const& v, Tt const minval=std::numeric_limits::min(), Tt const maxval=std::numeric_limits::max()) { if ( v < minval ) return minval; if ( v > maxval ) return maxval; - return round_cast(v); + return round_cast(v); } namespace NR { @@ -95,12 +98,14 @@ FilterGaussian::~FilterGaussian() // Nothing to do here } -int _effect_area_scr(double deviation) +static int +_effect_area_scr(double const deviation) { return (int)std::ceil(deviation * 3.0); } -void _make_kernel(FIRValue *kernel, double deviation) +static void +_make_kernel(FIRValue *const kernel, double const deviation) { int const scr_len = _effect_area_scr(deviation); double const d_sq = sqr(deviation) * 2; @@ -134,7 +139,8 @@ void _make_kernel(FIRValue *kernel, double deviation) // 8<=32-2*v // 2*v<=24 // v<=12 -int _effect_subsample_step_log2(double deviation, int quality) +static int +_effect_subsample_step_log2(double const deviation, int const quality) { // To make sure FIR will always be used (unless the kernel is VERY big): // deviation/step <= 3 @@ -181,7 +187,8 @@ int _effect_subsample_step_log2(double deviation, int quality) * Catches reading and writing outside the pixblock area. * When enabled, decreases filter rendering speed massively. */ -inline void _check_index(NRPixBlock const * const pb, int const location, int const line) +static inline void +_check_index(NRPixBlock const * const pb, int const location, int const line) { if (false) { int max_loc = pb->rs * (pb->area.y1 - pb->area.y0); @@ -257,7 +264,12 @@ static void calcTriggsSdikaInitialization(double const M[N*N], IIRValue const uo // Filters over 1st dimension template -void filter2D_IIR(PT *dest, int dstr1, int dstr2, PT const *src, int sstr1, int sstr2, int n1, int n2, IIRValue const b[N+1], double const M[N*N], IIRValue *const tmpdata) { +static void +filter2D_IIR(PT *const dest, int const dstr1, int const dstr2, + PT const *const src, int const sstr1, int const sstr2, + int const n1, int const n2, IIRValue const b[N+1], double const M[N*N], + IIRValue *const tmpdata) +{ for ( int c2 = 0 ; c2 < n2 ; c2++ ) { // corresponding line in the source and output buffer PT const * srcimg = src + c2*sstr2; @@ -311,7 +323,11 @@ void filter2D_IIR(PT *dest, int dstr1, int dstr2, PT const *src, int sstr1, int // Assumes kernel is symmetric // scr_len should be size of kernel - 1 template -void filter2D_FIR(PT *dst, int dstr1, int dstr2, PT const *src, int sstr1, int sstr2, int n1, int n2, FIRValue const *const kernel, int scr_len) { +static void +filter2D_FIR(PT *const dst, int const dstr1, int const dstr2, + PT const *const src, int const sstr1, int const sstr2, + int const n1, int const n2, FIRValue const *const kernel, int const scr_len) +{ // Past pixels seen (to enable in-place operation) PT history[scr_len+1][PC]; @@ -385,8 +401,8 @@ void filter2D_FIR(PT *dst, int dstr1, int dstr2, PT const *src, int sstr1, int s // store the result in bufx dst[dst_disp + byte] = round_cast(sum); - // optimization: if there was no variation within this point's neighborhood, - // skip ahead while we keep seeing the same last_in byte: + // optimization: if there was no variation within this point's neighborhood, + // skip ahead while we keep seeing the same last_in byte: // blurring flat color would not change it anyway if (different_count <= 1) { int pos = c1 + 1; @@ -406,7 +422,11 @@ void filter2D_FIR(PT *dst, int dstr1, int dstr2, PT const *src, int sstr1, int s } template -void downsample(PT *dst, int dstr1, int dstr2, int dn1, int dn2, PT const *src, int sstr1, int sstr2, int sn1, int sn2, int step1_l2, int step2_l2) { +static void +downsample(PT *const dst, int const dstr1, int const dstr2, int const dn1, int const dn2, + PT const *const src, int const sstr1, int const sstr2, int const sn1, int const sn2, + int const step1_l2, int const step2_l2) +{ unsigned int const divisor_l2 = step1_l2+step2_l2; // step1*step2=2^(step1_l2+step2_l2) unsigned int const round_offset = (1< -void upsample(PT *dst, int dstr1, int dstr2, unsigned int dn1, unsigned int dn2, PT const *src, int sstr1, int sstr2, unsigned int sn1, unsigned int sn2, unsigned int step1_l2, unsigned int step2_l2) { +static void +upsample(PT *const dst, int const dstr1, int const dstr2, unsigned int const dn1, unsigned int const dn2, + PT const *const src, int const sstr1, int const sstr2, unsigned int const sn1, unsigned int const sn2, + unsigned int const step1_l2, unsigned int const step2_l2) +{ assert(((sn1-1)<=dn1 && ((sn2-1)<=dn2); // The last pixel of the source image should fall outside the destination image unsigned int const divisor_l2 = step1_l2+step2_l2; // step1*step2=2^(step1_l2+step2_l2) unsigned int const round_offset = (1<area.x1-in->area.x0, height_org = in->area.y1-in->area.y0; - double const deviation_x_org = _deviation_x * trans.expansionX(); - double const deviation_y_org = _deviation_y * trans.expansionY(); + double const deviation_x_org = _deviation_x * NR::expansionX(trans); + double const deviation_y_org = _deviation_y * NR::expansionY(trans); int const PC = NR_PIXBLOCK_BPP(in); // Subsampling constants @@ -745,8 +775,8 @@ int FilterGaussian::render(FilterSlot &slot, Matrix const &trans) void FilterGaussian::area_enlarge(NRRectL &area, Matrix const &trans) { - int area_x = _effect_area_scr(_deviation_x * trans.expansionX()); - int area_y = _effect_area_scr(_deviation_y * trans.expansionY()); + int area_x = _effect_area_scr(_deviation_x * NR::expansionX(trans)); + int area_y = _effect_area_scr(_deviation_y * NR::expansionY(trans)); // maximum is used because rotations can mix up these directions // TODO: calculate a more tight-fitting rendering area int area_max = std::max(area_x, area_y); @@ -756,6 +786,10 @@ void FilterGaussian::area_enlarge(NRRectL &area, Matrix const &trans) area.y1 += area_max; } +FilterTraits FilterGaussian::get_input_traits() { + return TRAIT_PARALLER; +} + void FilterGaussian::set_deviation(double deviation) { if(isFinite(deviation) && deviation >= 0) {