diff options
| author | Jasper van de Gronde <jasper.vandegronde@gmail.com> | 2011-04-02 15:31:36 +0000 |
|---|---|---|
| committer | Jasper van de Gronde <jasper.vandegronde@gmail.com> | 2011-04-02 15:31:36 +0000 |
| commit | 33ab199838791c9b3b7a29a342014ea4716fdd27 (patch) | |
| tree | b8edb66952ea4b42e66fe64199935ecba33ad8ff /src | |
| parent | use shape's curve before LPE as flash path in node tool. so now, you should s... (diff) | |
| download | inkscape-33ab199838791c9b3b7a29a342014ea4716fdd27.tar.gz inkscape-33ab199838791c9b3b7a29a342014ea4716fdd27.zip | |
Faster rounding for Gaussian blur
(bzr r10144)
Diffstat (limited to 'src')
| -rw-r--r-- | src/display/nr-filter-gaussian.cpp | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index 3f7bea35d..9b83c8647 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -78,15 +78,46 @@ template<typename T> static inline T clip(T const& v, T const& a, T const& b) { } template<typename Tt, typename Ts> -static inline Tt round_cast(Ts const& v) { +static inline Tt round_cast(Ts v) { static Ts const rndoffset(.5); return static_cast<Tt>(v+rndoffset); } +template<> +inline unsigned char round_cast(double v) { + // This (fast) rounding method is based on: + // http://stereopsis.com/sree/fpu2006.html +#if G_BYTE_ORDER==G_LITTLE_ENDIAN
+ double const dmr = 6755399441055744.0;
+ v = v + dmr;
+ return ((unsigned char*)&v)[0]; +#elif G_BYTE_ORDER==G_BIG_ENDIAN + double const dmr = 6755399441055744.0;
+ v = v + dmr;
+ return ((unsigned char*)&v)[7]; +#else + static double const rndoffset(.5); + return static_cast<unsigned char>(v+rndoffset);
+#endif
+} + +template<typename Tt, typename Ts> +static inline Tt clip_round_cast(Ts const v) { + Ts const minval = std::numeric_limits<Tt>::min(); + Ts const maxval = std::numeric_limits<Tt>::max(); + Tt const minval_rounded = std::numeric_limits<Tt>::min(); + Ts const maxval_rounded = std::numeric_limits<Tt>::max(); + if ( v < minval ) return minval_rounded; + if ( v > maxval ) return maxval_rounded; + return round_cast<Tt>(v); +} + template<typename Tt, typename Ts> -static inline Tt clip_round_cast(Ts const& v, Tt const minval=std::numeric_limits<Tt>::min(), Tt const maxval=std::numeric_limits<Tt>::max()) { - if ( v < minval ) return minval; - if ( v > maxval ) return maxval; +static inline Tt clip_round_cast_varmax(Ts const v, Ts const maxval, Tt const maxval_rounded) { + Ts const minval = std::numeric_limits<Tt>::min(); + Tt const minval_rounded = std::numeric_limits<Tt>::min(); + if ( v < minval ) return minval_rounded; + if ( v > maxval ) return maxval_rounded; return round_cast<Tt>(v); } @@ -320,7 +351,7 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2, dstimg -= dstr1; if ( PREMULTIPLIED_ALPHA ) { dstimg[PC-1] = clip_round_cast<PT>(v[0][PC-1]); - for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast<PT>(v[0][c], std::numeric_limits<PT>::min(), dstimg[PC-1]); + for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][PC-1], dstimg[PC-1]); } else { for(unsigned int c=0; c<PC; c++) dstimg[c] = clip_round_cast<PT>(v[0][c]); } @@ -335,7 +366,7 @@ filter2D_IIR(PT *const dest, int const dstr1, int const dstr2, dstimg -= dstr1; if ( PREMULTIPLIED_ALPHA ) { dstimg[PC-1] = clip_round_cast<PT>(v[0][PC-1]); - for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast<PT>(v[0][c], std::numeric_limits<PT>::min(), dstimg[PC-1]); + for(unsigned int c=0; c<PC-1; c++) dstimg[c] = clip_round_cast_varmax<PT>(v[0][c], v[0][PC-1], dstimg[PC-1]); } else { for(unsigned int c=0; c<PC; c++) dstimg[c] = clip_round_cast<PT>(v[0][c]); } |
