Changeset View
Changeset View
Standalone View
Standalone View
libs/image/kis_filter_strategy.cc
Show All 20 Lines | |||||
21 | #include "kis_filter_strategy.h" | 21 | #include "kis_filter_strategy.h" | ||
22 | 22 | | |||
23 | #include <math.h> | 23 | #include <math.h> | ||
24 | 24 | | |||
25 | #include <klocalizedstring.h> | 25 | #include <klocalizedstring.h> | ||
26 | #include <QGlobalStatic> | 26 | #include <QGlobalStatic> | ||
27 | 27 | | |||
28 | #include "kis_debug.h" | 28 | #include "kis_debug.h" | ||
29 | #include <QtMath> | ||||
29 | 30 | | |||
30 | Q_GLOBAL_STATIC(KisFilterStrategyRegistry, s_instance) | 31 | Q_GLOBAL_STATIC(KisFilterStrategyRegistry, s_instance) | ||
31 | 32 | | |||
32 | qreal KisHermiteFilterStrategy::valueAt(qreal t) const | 33 | qreal KisHermiteFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
33 | { | 34 | { | ||
35 | Q_UNUSED(weightsPositionScale); | ||||
34 | /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ | 36 | /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ | ||
35 | if (t < 0.0) t = -t; | 37 | if (t < 0.0) t = -t; | ||
36 | if (t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); | 38 | if (t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0); | ||
37 | return(0.0); | 39 | return(0.0); | ||
38 | } | 40 | } | ||
39 | 41 | | |||
40 | qint32 KisHermiteFilterStrategy::intValueAt(qint32 t) const | 42 | qint32 KisHermiteFilterStrategy::intValueAt(qint32 t, qreal weightsPositionScale) const | ||
41 | { | 43 | { | ||
44 | Q_UNUSED(weightsPositionScale); | ||||
42 | /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ | 45 | /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */ | ||
43 | if (t < 0) t = -t; | 46 | if (t < 0) t = -t; | ||
44 | if (t < 256) { | 47 | if (t < 256) { | ||
45 | t = (2 * t - 3 * 256) * t * t + (256 << 16); | 48 | t = (2 * t - 3 * 256) * t * t + (256 << 16); | ||
46 | 49 | | |||
47 | //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) | 50 | //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) | ||
48 | t = (t + 0x8000) >> 16; | 51 | t = (t + 0x8000) >> 16; | ||
49 | 52 | | |||
50 | // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; | 53 | // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; | ||
51 | if (t >= 128) | 54 | if (t >= 128) | ||
52 | return t - 1; | 55 | return t - 1; | ||
53 | return t; | 56 | return t; | ||
54 | } | 57 | } | ||
55 | return(0); | 58 | return(0); | ||
56 | } | 59 | } | ||
57 | 60 | | |||
58 | qint32 KisBicubicFilterStrategy::intValueAt(qint32 t) const | 61 | qint32 KisBicubicFilterStrategy::intValueAt(qint32 t, qreal weightsPositionScale) const | ||
59 | { | 62 | { | ||
63 | Q_UNUSED(weightsPositionScale); | ||||
60 | /* f(t) = 1.5|t|^3 - 2.5|t|^2 + 1, -1 <= t <= 1 */ | 64 | /* f(t) = 1.5|t|^3 - 2.5|t|^2 + 1, -1 <= t <= 1 */ | ||
61 | if (t < 0) t = -t; | 65 | if (t < 0) t = -t; | ||
62 | if (t < 256) { | 66 | if (t < 256) { | ||
63 | t = (3 * t - 5 * 256) * t * t / 2 + (256 << 16); | 67 | t = (3 * t - 5 * 256) * t * t / 2 + (256 << 16); | ||
64 | 68 | | |||
65 | //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) | 69 | //go from .24 fixed point to .8 fixedpoint (hack only works with positive numbers, which it is) | ||
66 | t = (t + 0x8000) >> 16; | 70 | t = (t + 0x8000) >> 16; | ||
67 | 71 | | |||
Show All 12 Lines | 77 | if (t < 512) { | |||
80 | // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; | 84 | // go from .8 fixed point to 8bitscale. ie t = (t*255)/256; | ||
81 | if (t >= 128) | 85 | if (t >= 128) | ||
82 | return t - 1; | 86 | return t - 1; | ||
83 | return t; | 87 | return t; | ||
84 | } | 88 | } | ||
85 | return(0); | 89 | return(0); | ||
86 | } | 90 | } | ||
87 | 91 | | |||
88 | qreal KisBoxFilterStrategy::valueAt(qreal t) const | 92 | qreal KisBoxFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
89 | { | 93 | { | ||
90 | if ((t > -0.5) && (t <= 0.5)) return(1.0); | 94 | if ((t >= -0.5 * weightsPositionScale) && (t < 0.5 * weightsPositionScale)) return(1.0); | ||
91 | return(0.0); | 95 | return(0.0); | ||
92 | } | 96 | } | ||
93 | 97 | | |||
94 | qint32 KisBoxFilterStrategy::intValueAt(qint32 t) const | 98 | qint32 KisBoxFilterStrategy::intValueAt(qint32 t, qreal weightsPositionScale) const | ||
95 | { | 99 | { | ||
96 | /* f(t) = 1, -0.5 < t <= 0.5 */ | 100 | /* f(t) = 1, -0.5 < t <= 0.5 */ | ||
97 | if ((t > -128) && (t <= 128)) | 101 | if ((t >= -128 * weightsPositionScale) && (t < 128 * weightsPositionScale)) | ||
98 | return 255; | 102 | return 255; | ||
99 | return 0; | 103 | return 0; | ||
100 | } | 104 | } | ||
101 | 105 | | |||
102 | qreal KisBilinearFilterStrategy::valueAt(qreal t) const | 106 | | ||
107 | qreal KisBoxFilterStrategy::support(qreal weightsPositionScale) | ||||
108 | { | ||||
109 | return supportVal*weightsPositionScale; | ||||
110 | } | ||||
111 | | ||||
112 | qint32 KisBoxFilterStrategy::intSupport(qreal weightsPositionScale) | ||||
113 | { | ||||
114 | return qCeil(intSupportVal*weightsPositionScale); | ||||
115 | } | ||||
116 | | ||||
117 | qreal KisBilinearFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||||
103 | { | 118 | { | ||
119 | Q_UNUSED(weightsPositionScale); | ||||
104 | if (t < 0.0) t = -t; | 120 | if (t < 0.0) t = -t; | ||
105 | if (t < 1.0) return(1.0 - t); | 121 | if (t < 1.0) return(1.0 - t); | ||
106 | return(0.0); | 122 | return(0.0); | ||
107 | } | 123 | } | ||
108 | 124 | | |||
109 | qint32 KisBilinearFilterStrategy::intValueAt(qint32 t) const | 125 | qint32 KisBilinearFilterStrategy::intValueAt(qint32 t, qreal weightsPositionScale) const | ||
110 | { | 126 | { | ||
127 | Q_UNUSED(weightsPositionScale); | ||||
111 | /* f(t) = |t|, -1 <= t <= 1 */ | 128 | /* f(t) = |t|, -1 <= t <= 1 */ | ||
112 | if (t < 0) t = -t; | 129 | if (t < 0) t = -t; | ||
113 | if (t < 256) { | 130 | if (t < 256) { | ||
114 | // calc 256-1 but also go from .8 fixed point to 8bitscale. ie t = (t*255)/256; ie: if(t>=128) return t-1; | 131 | // calc 256-1 but also go from .8 fixed point to 8bitscale. ie t = (t*255)/256; ie: if(t>=128) return t-1; | ||
115 | if (t >= 128) return 256 - t; | 132 | if (t >= 128) return 256 - t; | ||
116 | return 255 - t; | 133 | return 255 - t; | ||
117 | } | 134 | } | ||
118 | return(0); | 135 | return(0); | ||
119 | } | 136 | } | ||
120 | 137 | | |||
121 | 138 | | |||
122 | qreal KisBellFilterStrategy::valueAt(qreal t) const | 139 | qreal KisBellFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
123 | { | 140 | { | ||
141 | Q_UNUSED(weightsPositionScale); | ||||
124 | if (t < 0) t = -t; | 142 | if (t < 0) t = -t; | ||
125 | if (t < .5) return(.75 - (t * t)); | 143 | if (t < .5) return(.75 - (t * t)); | ||
126 | if (t < 1.5) { | 144 | if (t < 1.5) { | ||
127 | t = (t - 1.5); | 145 | t = (t - 1.5); | ||
128 | return(.5 *(t * t)); | 146 | return(.5 *(t * t)); | ||
129 | } | 147 | } | ||
130 | return(0.0); | 148 | return(0.0); | ||
131 | } | 149 | } | ||
132 | 150 | | |||
133 | qreal KisBSplineFilterStrategy::valueAt(qreal t) const | 151 | qreal KisBSplineFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
134 | { | 152 | { | ||
153 | Q_UNUSED(weightsPositionScale); | ||||
135 | qreal tt; | 154 | qreal tt; | ||
136 | 155 | | |||
137 | if (t < 0) t = -t; | 156 | if (t < 0) t = -t; | ||
138 | if (t < 1) { | 157 | if (t < 1) { | ||
139 | tt = t * t; | 158 | tt = t * t; | ||
140 | return((.5 * tt * t) - tt + (2.0 / 3.0)); | 159 | return((.5 * tt * t) - tt + (2.0 / 3.0)); | ||
141 | } else if (t < 2) { | 160 | } else if (t < 2) { | ||
142 | t = 2 - t; | 161 | t = 2 - t; | ||
143 | return((1.0 / 6.0) *(t * t * t)); | 162 | return((1.0 / 6.0) *(t * t * t)); | ||
144 | } | 163 | } | ||
145 | return(0.0); | 164 | return(0.0); | ||
146 | } | 165 | } | ||
147 | 166 | | |||
148 | qreal KisLanczos3FilterStrategy::valueAt(qreal t) const | 167 | qreal KisLanczos3FilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
149 | { | 168 | { | ||
169 | Q_UNUSED(weightsPositionScale); | ||||
150 | if (t < 0) t = -t; | 170 | if (t < 0) t = -t; | ||
151 | if (t < 3.0) return(sinc(t) * sinc(t / 3.0)); | 171 | if (t < 3.0) return(sinc(t) * sinc(t / 3.0)); | ||
152 | return(0.0); | 172 | return(0.0); | ||
153 | } | 173 | } | ||
154 | 174 | | |||
155 | qreal KisLanczos3FilterStrategy::sinc(qreal x) const | 175 | qreal KisLanczos3FilterStrategy::sinc(qreal x) const | ||
156 | { | 176 | { | ||
157 | const qreal pi = 3.1415926535897932385; | 177 | const qreal pi = 3.1415926535897932385; | ||
158 | x *= pi; | 178 | x *= pi; | ||
159 | if (x != 0) return(sin(x) / x); | 179 | if (x != 0) return(sin(x) / x); | ||
160 | return(1.0); | 180 | return(1.0); | ||
161 | } | 181 | } | ||
162 | 182 | | |||
163 | qreal KisMitchellFilterStrategy::valueAt(qreal t) const | 183 | qreal KisMitchellFilterStrategy::valueAt(qreal t, qreal weightsPositionScale) const | ||
164 | { | 184 | { | ||
185 | Q_UNUSED(weightsPositionScale); | ||||
165 | const qreal B = 1.0 / 3.0; | 186 | const qreal B = 1.0 / 3.0; | ||
166 | const qreal C = 1.0 / 3.0; | 187 | const qreal C = 1.0 / 3.0; | ||
167 | qreal tt; | 188 | qreal tt; | ||
168 | 189 | | |||
169 | tt = t * t; | 190 | tt = t * t; | ||
170 | if (t < 0) t = -t; | 191 | if (t < 0) t = -t; | ||
171 | if (t < 1.0) { | 192 | if (t < 1.0) { | ||
172 | t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); | 193 | t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B)); | ||
▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines |