chalk

kis_filter_strategy.cpp
1/*
2 * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
3 * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19#include <kdebug.h>
20#include <tdelocale.h>
21#include "kis_debug_areas.h"
22#include "kis_filter_strategy.h"
23#include <math.h>
24
25double KisHermiteFilterStrategy::valueAt(double t) const {
26 /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
27 if(t < 0.0) t = -t;
28 if(t < 1.0) return((2.0 * t - 3.0) * t * t + 1.0);
29 return(0.0);
30}
31
32TQ_UINT32 KisHermiteFilterStrategy::intValueAt(TQ_INT32 t) const {
33 /* f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 */
34 if(t < 0) t = -t;
35 if(t < 256)
36 {
37 t =(2 * t - 3*256) * t * t +(256<<16);
38
39 //go from .24 fixed point to .8 fixedpoint (hack only works with positve numbers, which it is)
40 t = (t + 0x8000) >> 16;
41
42 // go from .8 fixed point to 8bitscale. ie t = (t*255)/256;
43 if(t >= 128)
44 return t - 1;
45 return t;
46 }
47 return(0);
48}
49
50double KisCubicFilterStrategy::valueAt(double x) const {
51 if (x < -2.0)
52 return(0.0);
53 if (x < -1.0)
54 return((2.0+x)*(2.0+x)*(2.0+x)/6.0);
55 if (x < 0.0)
56 return((4.0+x*x*(-6.0-3.0*x))/6.0);
57 if (x < 1.0)
58 return((4.0+x*x*(-6.0+3.0*x))/6.0);
59 if (x < 2.0)
60 return((2.0-x)*(2.0-x)*(2.0-x)/6.0);
61 return(0.0);
62}
63
64TQ_UINT32 KisCubicFilterStrategy::intValueAt(TQ_INT32 x) const {
65 if (x < 2)
66 return 0;
67 if (x < -1)
68 return (2 + x) * (2 + x) * ( 2 + x) / 6;
69 if ( x < 0)
70 return (4 + x * x * ( -6 - 3 * x)) / 6;
71 if (x < 1)
72 return (4 + x * x * ( -6 + 3 * x)) / 6;
73 if (x < 2)
74 return (2 - x) * ( 2 - x) * (2 - x) / 6;
75 return 0;
76}
77
78double KisBoxFilterStrategy::valueAt(double t) const {
79 if((t > -0.5) && (t <= 0.5)) return(1.0);
80 return(0.0);
81}
82
83TQ_UINT32 KisBoxFilterStrategy::intValueAt(TQ_INT32 t) const {
84 /* f(t) = 1, -0.5 < t <= 0.5 */
85 if((t > -128) && (t <= 128))
86 return 255;
87 return 0;
88}
89
90double KisTriangleFilterStrategy::valueAt(double t) const {
91 if(t < 0.0) t = -t;
92 if(t < 1.0) return(1.0 - t);
93 return(0.0);
94}
95
96TQ_UINT32 KisTriangleFilterStrategy::intValueAt(TQ_INT32 t) const {
97 /* f(t) = |t|, -1 <= t <= 1 */
98 if(t < 0) t = -t;
99 if(t < 256)
100 {
101 // calc 256-1 but also go from .8 fixed point to 8bitscale. ie t = (t*255)/256; ie: if(t>=128) return t-1;
102 if(t>=128) return 256 - t;
103 return 255 - t;
104 }
105 return(0);
106}
107
108
109double KisBellFilterStrategy::valueAt(double t) const {
110 if(t < 0) t = -t;
111 if(t < .5) return(.75 - (t * t));
112 if(t < 1.5) {
113 t = (t - 1.5);
114 return(.5 * (t * t));
115 }
116 return(0.0);
117}
118
119double KisBSplineFilterStrategy::valueAt(double t) const {
120 double tt;
121
122 if(t < 0) t = -t;
123 if(t < 1) {
124 tt = t * t;
125 return((.5 * tt * t) - tt + (2.0 / 3.0));
126 } else if(t < 2) {
127 t = 2 - t;
128 return((1.0 / 6.0) * (t * t * t));
129 }
130 return(0.0);
131}
132
133double KisLanczos3FilterStrategy::valueAt(double t) const {
134 if(t < 0) t = -t;
135 if(t < 3.0) return(sinc(t) * sinc(t/3.0));
136 return(0.0);
137}
138
139double KisLanczos3FilterStrategy::sinc(double x) const {
140 const double pi=3.1415926535897932385;
141 x *= pi;
142 if(x != 0) return(sin(x) / x);
143 return(1.0);
144}
145
146double KisMitchellFilterStrategy::valueAt(double t) const {
147 const double B=1.0/3.0;
148 const double C=1.0/3.0;
149 double tt;
150
151 tt = t * t;
152 if(t < 0) t = -t;
153 if(t < 1.0) {
154 t = (((12.0 - 9.0 * B - 6.0 * C) * (t * tt)) + ((-18.0 + 12.0 * B + 6.0 * C) * tt) + (6.0 - 2 * B));
155 return(t / 6.0);
156 } else if(t < 2.0) {
157 t = (((-1.0 * B - 6.0 * C) * (t * tt)) + ((6.0 * B + 30.0 * C) * tt) + ((-12.0 * B - 48.0 * C) * t) + (8.0 * B + 24 * C));
158 return(t / 6.0);
159 }
160 return(0.0);
161}
162
163KisFilterStrategyRegistry *KisFilterStrategyRegistry::m_singleton = 0;
164
165KisFilterStrategyRegistry::KisFilterStrategyRegistry()
166{
167 Q_ASSERT(KisFilterStrategyRegistry::m_singleton == 0);
168 KisFilterStrategyRegistry::m_singleton = this;
169}
170
171KisFilterStrategyRegistry::~KisFilterStrategyRegistry()
172{
173}
174
175KisFilterStrategyRegistry* KisFilterStrategyRegistry::instance()
176{
177 if(KisFilterStrategyRegistry::m_singleton == 0)
178 {
179 KisFilterStrategyRegistry::m_singleton = new KisFilterStrategyRegistry();
180 TQ_CHECK_PTR(KisFilterStrategyRegistry::m_singleton);
181 m_singleton->add(new KisHermiteFilterStrategy);
182 m_singleton->add(new KisBoxFilterStrategy);
183 m_singleton->add(new KisTriangleFilterStrategy);
184 m_singleton->add(new KisBellFilterStrategy);
185 m_singleton->add(new KisBSplineFilterStrategy);
186// m_singleton->add(new KisLanczos3FilterStrategy);
187 m_singleton->add(new KisMitchellFilterStrategy);
188// m_singleton->add(new KisCubicFilterStrategy);
189 }
190 return KisFilterStrategyRegistry::m_singleton;
191}
192