import '../color.dart'; | |
import '../image.dart'; | |
/** | |
* A kernel object to use with [seperableConvolution] filtering. | |
*/ | |
class SeperableKernel { | |
final List<double> coefficients; | |
final int size; | |
/** | |
* Create a seperable convolution kernel for the given [radius]. | |
*/ | |
SeperableKernel(int radius) : | |
coefficients = new List<double>(2 * radius + 1), | |
this.size = radius; | |
/** | |
* Get the number of coefficients in the kernel. | |
*/ | |
int get length => coefficients.length; | |
/** | |
* Get a coefficient from the kernel. | |
*/ | |
double operator[](int index) => coefficients[index]; | |
/** | |
* Set a coefficient in the kernel. | |
*/ | |
void operator[]=(int index, double c) { | |
coefficients[index] = c; | |
} | |
/** | |
* Apply the kernel to the [src] image, storing the results in [dst], | |
* for a single dimension. If [horizontal is true, the filter will be | |
* applied to the horizontal axis, otherwise it will be appied to the | |
* vertical axis. | |
*/ | |
void apply(Image src, Image dst, {bool horizontal: true}) { | |
if (horizontal) { | |
for (int y = 0; y < src.height; ++y) { | |
_applyCoeffsLine(src, dst, y, src.width, horizontal); | |
} | |
} else { | |
for (int x = 0; x < src.width; ++x) { | |
_applyCoeffsLine(src, dst, x, src.height, horizontal); | |
} | |
} | |
} | |
/** | |
* Scale all of the coefficients by [s]. | |
*/ | |
void scaleCoefficients(double s) { | |
for (int i = 0; i < coefficients.length; ++i) { | |
coefficients[i] *= s; | |
} | |
} | |
int _reflect(int max, int x) { | |
if (x < 0) { | |
return -x; | |
} | |
if (x >= max) { | |
return max - (x - max) - 1; | |
} | |
return x; | |
} | |
void _applyCoeffsLine(Image src, Image dst, int y, int width, | |
bool horizontal) { | |
for (int x = 0; x < width; x++) { | |
double r = 0.0; | |
double g = 0.0; | |
double b = 0.0; | |
double a = 0.0; | |
for (int j = -size, j2 = 0; j <= size; ++j, ++j2) { | |
double coeff = coefficients[j2]; | |
int gr = _reflect(width, x + j); | |
int sc = (horizontal) ? | |
src.getPixel(gr, y) : | |
src.getPixel(y, gr); | |
r += coeff * getRed(sc); | |
g += coeff * getGreen(sc); | |
b += coeff * getBlue(sc); | |
a += coeff * getAlpha(sc); | |
} | |
int c = getColor((r > 255.0 ? 255.0 : r).toInt(), | |
(g > 255.0 ? 255.0 : g).toInt(), | |
(b > 255.0 ? 255.0 : b).toInt(), | |
(a > 255.0 ? 255.0 : a).toInt()); | |
if (horizontal) { | |
dst.setPixel(x, y, c); | |
} else { | |
dst.setPixel(y, x, c); | |
} | |
} | |
} | |
} |