index 6bdb3306e86a6b925e8d369872f16b5ed5a11d07..e23a8b32f8a34621328e88ae14f2a7206aa5e5ff 100644 (file)
*/
#include "display/nr-filter-convolve-matrix.h"
+#include "display/nr-filter-units.h"
+#include "display/nr-filter-utils.h"
#include <vector>
+
namespace NR {
FilterConvolveMatrix::FilterConvolveMatrix()
return true;
}
-int FilterConvolveMatrix::render(FilterSlot &slot, Matrix const &trans) {
+int FilterConvolveMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
NRPixBlock *in = slot.get(_input);
+ if (!in) {
+ g_warning("Missing source image for feConvolveMatrix (in=%d)", _input);
+ return 1;
+ }
+
NRPixBlock *out = new NRPixBlock;
nr_pixblock_setup_fast(out, in->mode,
int width = in->area.x1 - in->area.x0;
int height = in->area.y1 - in->area.y0;
- double div=0;
-
- if (divisor != 0){
- div = divisor;
- } else {
- for (i=0;i<orderX*orderY;i++){
- div += kernelMatrix[i];
- }
- }
-
- for (x=0; x < width; x++){
- for (y=0; y < height; y++){
+ unsigned int index;
+ unsigned int kernel_index;
+
+ for (x=targetX; x < width - (orderX - targetX); x++){
+ for (y=targetY; y < height - (orderY - targetY); y++){
result_R = 0;
result_G = 0;
result_B = 0;
for (i=0; i < orderY; i++){
for (j=0; j < orderX; j++){
if (inside_area(x - targetX + j, y - targetY + i, width, height)){
- result_R += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
- result_G += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+1] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
- result_B += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+2] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
- result_A += ( (double) in_data[4*( x - targetX + j + width*(y - targetY + i) )+3] * kernelMatrix[orderX-j-1 + orderX*(orderY-i-1)] );
+ index = 4*( x - targetX + j + width*(y - targetY + i) );
+ kernel_index = orderX-j-1 + orderX*(orderY-i-1);
+ result_R += ( (double) in_data[index++] * kernelMatrix[kernel_index] );
+ result_G += ( (double) in_data[index++] * kernelMatrix[kernel_index] );
+ result_B += ( (double) in_data[index++] * kernelMatrix[kernel_index] );
+ result_A += ( (double) in_data[index] * kernelMatrix[kernel_index] );
}
}
}
- result_R = result_R / div + bias;
- result_G = result_G / div + bias;
- result_B = result_B / div + bias;
- result_A = result_A / div + bias;
-
- result_R = (result_R > 0 ? result_R : 0);
- result_G = (result_G > 0 ? result_G : 0);
- result_B = (result_B > 0 ? result_B : 0);
- result_A = (result_A > 0 ? result_A : 0);
-
- out_data[4*( x + width*y )] = (result_R < 255 ? (unsigned char)result_R : 255);
- out_data[4*( x + width*y )+1] = (result_G < 255 ? (unsigned char)result_G : 255);
- out_data[4*( x + width*y )+2] = (result_B < 255 ? (unsigned char)result_B : 255);
- out_data[4*( x + width*y )+3] = (result_A < 255 ? (unsigned char)result_A : 255);
+ unsigned int out_index = 4*( x + width*y );
+ out_data[out_index++] = CLAMP_D_TO_U8(result_R / divisor + bias);
+ out_data[out_index++] = CLAMP_D_TO_U8(result_G / divisor + bias);
+ out_data[out_index++] = CLAMP_D_TO_U8(result_B / divisor + bias);
+
+ if( preserveAlpha ) {
+ out_data[out_index] = in_data[out_index];
+ } else {
+ out_data[out_index] = CLAMP_D_TO_U8(result_A / divisor + bias);
+ }
}
}
kernelMatrix = km;
}
-void FilterConvolveMatrix::area_enlarge(NRRectL &area, Matrix const &trans)
+void FilterConvolveMatrix::set_edgeMode(FilterConvolveMatrixEdgeMode mode){
+ edgeMode = mode;
+}
+
+void FilterConvolveMatrix::set_preserveAlpha(bool pa){
+ preserveAlpha = pa;
+}
+
+void FilterConvolveMatrix::area_enlarge(NRRectL &area, Matrix const &/*trans*/)
{
+ //Seems to me that since this filter's operation is resolution dependent,
+ // some spurious pixels may still appear at the borders when low zooming or rotating. Needs a better fix.
+ area.x0 -= targetX;
+ area.y0 -= targetY;
+ area.x1 += orderX - targetX;
+ area.y1 += orderY - targetY;
+}
+
+FilterTraits FilterConvolveMatrix::get_input_traits() {
+ return TRAIT_PARALLER;
}
} /* namespace NR */