blob: d254c22ccdd14657f380f506beba0b1c0221ae3b [file] [log] [blame]
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);
}
}
}
}