summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJasper van de Gronde <jasper.vandegronde@gmail.com>2011-04-02 15:31:36 +0000
committerJasper van de Gronde <jasper.vandegronde@gmail.com>2011-04-02 15:31:36 +0000
commit33ab199838791c9b3b7a29a342014ea4716fdd27 (patch)
treeb8edb66952ea4b42e66fe64199935ecba33ad8ff /src
parentuse shape's curve before LPE as flash path in node tool. so now, you should s... (diff)
downloadinkscape-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.cpp43
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]);
}