Code

Patch from Felipe Sanches: support for feConvolveMatrix filter primitive
authorkiirala <kiirala@users.sourceforge.net>
Fri, 20 Jul 2007 20:19:00 +0000 (20:19 +0000)
committerkiirala <kiirala@users.sourceforge.net>
Fri, 20 Jul 2007 20:19:00 +0000 (20:19 +0000)
AUTHORS
src/display/Makefile_insert
src/display/nr-filter-convolve-matrix.cpp [new file with mode: 0644]
src/display/nr-filter-convolve-matrix.h [new file with mode: 0644]
src/display/nr-filter.cpp
src/sp-feconvolvematrix.cpp
src/sp-feconvolvematrix.h

diff --git a/AUTHORS b/AUTHORS
index 527dae8d86683073b57af06af0bdd9ea29d7c2ff..989c3b7a7cedb37169991ea3d83496ccfe773edb 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -65,11 +65,13 @@ Marten Owens
 Jon Phillips
 Zdenko Podobny
 Alexandre Prokoudine
+Jean-René Reinhard
 Alexey Remizov
 Frederic Rodrigo
 Hugo Rodrigues
 Juarez Rudsatz
 Xavier Conde Rueda
+Felipe Sanches
 Christian Schaller
 Marco Scholten
 Tom von Schwerdtner
index bc6fb33369744069c54cc5abd89e63dd2db0b1f2..eaa2f584f311dbf8647e36235f2d3b575f689f9e 100644 (file)
@@ -81,6 +81,8 @@ display_libspdisplay_a_SOURCES = \
        display/nr-filter-specularlighting.h       \
        display/nr-filter-composite.h   \
        display/nr-filter-composite.cpp \
+       display/nr-filter-convolve-matrix.cpp   \
+       display/nr-filter-convolve-matrix.h     \
        display/nr-filter-slot.cpp      \
        display/nr-filter-slot.h        \
        display/nr-filter-getalpha.cpp  \
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
new file mode 100644 (file)
index 0000000..6bdb330
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * feConvolveMatrix filter primitive renderer
+ *
+ * Authors:
+ *   Felipe Corrêa da Silva Sanches <felipe.sanches@gmail.com>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-filter-convolve-matrix.h"
+#include <vector>
+namespace NR {
+
+FilterConvolveMatrix::FilterConvolveMatrix()
+{}
+
+FilterPrimitive * FilterConvolveMatrix::create() {
+    return new FilterConvolveMatrix();
+}
+
+FilterConvolveMatrix::~FilterConvolveMatrix()
+{}
+
+static bool inside_area(int px, int py, int w, int h){
+        if (px<0) return false;
+        if (py<0) return false;
+        if (px>w) return false;
+        if (py>h) return false;
+        return true;
+}
+
+int FilterConvolveMatrix::render(FilterSlot &slot, Matrix const &trans) {
+    NRPixBlock *in = slot.get(_input);
+    NRPixBlock *out = new NRPixBlock;
+
+    nr_pixblock_setup_fast(out, in->mode,
+                           in->area.x0, in->area.y0, in->area.x1, in->area.y1,
+                           true);
+
+    unsigned char *in_data = NR_PIXBLOCK_PX(in);
+    unsigned char *out_data = NR_PIXBLOCK_PX(out);
+
+    double result_R, result_G, result_B, result_A;
+    int i, j, x, y;
+    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++){
+            result_R = 0;
+            result_G = 0;
+            result_B = 0;
+            result_A = 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)] );
+                    }
+                }
+            }
+            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);
+        }
+    }
+
+    out->empty = FALSE;
+    slot.set(_output, out);
+    return 0;
+}
+
+void FilterConvolveMatrix::set_targetX(int coord) {
+    targetX = coord;
+}
+
+void FilterConvolveMatrix::set_targetY(int coord) {
+    targetY = coord;
+}
+
+void FilterConvolveMatrix::set_orderX(int coord) {
+    orderX = coord;
+}
+
+void FilterConvolveMatrix::set_orderY(int coord) {
+    orderY = coord;
+}
+
+void FilterConvolveMatrix::set_divisor(double d) {
+    divisor = d;
+}
+
+void FilterConvolveMatrix::set_bias(double b) {
+    bias = b;
+}
+
+void FilterConvolveMatrix::set_kernelMatrix(std::vector<gdouble> &km) {
+    kernelMatrix = km;
+}
+
+void FilterConvolveMatrix::area_enlarge(NRRectL &area, Matrix const &trans)
+{
+}
+
+} /* namespace NR */
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h
new file mode 100644 (file)
index 0000000..e5b72a7
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __NR_FILTER_CONVOLVE_MATRIX_H__
+#define __NR_FILTER_CONVOLVE_MATRIX_H__
+
+/*
+ * feConvolveMatrix filter primitive renderer
+ *
+ * Authors:
+ *   Felipe Corrêa da Silva Sanches <felipe.sanches@gmail.com>
+ *
+ * Copyright (C) 2007 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/nr-filter-primitive.h"
+#include "display/nr-filter-slot.h"
+#include "libnr/nr-matrix.h"
+#include "libnr/nr-rect-l.h"
+#include <vector>
+
+namespace NR {
+
+class FilterConvolveMatrix : public FilterPrimitive {
+public:
+    FilterConvolveMatrix();
+    static FilterPrimitive *create();
+    virtual ~FilterConvolveMatrix();
+
+    virtual int render(FilterSlot &slot, Matrix const &trans);
+    virtual void area_enlarge(NRRectL &area, Matrix const &trans);
+
+    void set_targetY(int coord);
+    void set_targetX(int coord);
+    void set_orderY(int coord);
+    void set_orderX(int coord);
+    void set_kernelMatrix(std::vector<gdouble>& km);
+    void set_bias(double b);
+    void set_divisor(double d);
+
+private:
+    std::vector<gdouble> kernelMatrix;
+    int targetX, targetY;
+    int orderX, orderY;
+    gdouble divisor, bias;
+    int dx, dy; //kernelUnitLength
+};
+
+} /* namespace NR */
+
+#endif /* __NR_FILTER_CONVOLVE_MATRIX_H__ */
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 8a22778a130566eaa57233496c5b2e7429f27fc1..73a3df415708214b241b5972e8f0ca24ffb06f20 100644 (file)
@@ -22,6 +22,7 @@
 #include "display/pixblock-transform.h"
 
 #include "display/nr-filter-gaussian.h"
+#include "display/nr-filter-convolve-matrix.h"
 #include "display/nr-filter-blend.h"
 #include "display/nr-filter-offset.h"
 #include "display/nr-filter-composite.h"
@@ -314,7 +315,7 @@ void Filter::_create_constructor_table()
     _constructor[NR_FILTER_COLORMATRIX] = NULL;
     _constructor[NR_FILTER_COMPONENTTRANSFER] = NULL;
     _constructor[NR_FILTER_COMPOSITE] = &FilterComposite::create;
-    _constructor[NR_FILTER_CONVOLVEMATRIX] = NULL;
+    _constructor[NR_FILTER_CONVOLVEMATRIX] = &FilterConvolveMatrix::create;
     _constructor[NR_FILTER_DIFFUSELIGHTING] = &FilterDiffuseLighting::create;
     _constructor[NR_FILTER_DISPLACEMENTMAP] = NULL;
     _constructor[NR_FILTER_FLOOD] = NULL;
index fe127900bd0d82504c576b55d3e611658dfe67f5..4191cceecfae0a2cf3ce0c8b49d1e37cd827f07e 100644 (file)
@@ -6,6 +6,7 @@
  */
 /*
  * Authors:
+ *   Felipe Corrêa da Silva Sanches <felipe.sanches@gmail.com>
  *   hugo Rodrigues <haa.rodrigues@gmail.com>
  *
  * Copyright (C) 2006 Hugo Rodrigues
 # include "config.h"
 #endif
 
+#include <vector>
 #include "attributes.h"
 #include "svg/svg.h"
 #include "sp-feconvolvematrix.h"
 #include "xml/repr.h"
-
+#include "display/nr-filter-convolve-matrix.h"
 
 /* FeConvolveMatrix base class */
 
@@ -33,6 +35,7 @@ static void sp_feConvolveMatrix_release(SPObject *object);
 static void sp_feConvolveMatrix_set(SPObject *object, unsigned int key, gchar const *value);
 static void sp_feConvolveMatrix_update(SPObject *object, SPCtx *ctx, guint flags);
 static Inkscape::XML::Node *sp_feConvolveMatrix_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static void sp_feConvolveMatrix_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter);
 
 static SPFilterPrimitiveClass *feConvolveMatrix_parent_class;
 
@@ -61,6 +64,7 @@ static void
 sp_feConvolveMatrix_class_init(SPFeConvolveMatrixClass *klass)
 {
     SPObjectClass *sp_object_class = (SPObjectClass *)klass;
+    SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass;
 
     feConvolveMatrix_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass);
 
@@ -69,11 +73,16 @@ sp_feConvolveMatrix_class_init(SPFeConvolveMatrixClass *klass)
     sp_object_class->write = sp_feConvolveMatrix_write;
     sp_object_class->set = sp_feConvolveMatrix_set;
     sp_object_class->update = sp_feConvolveMatrix_update;
+
+    sp_primitive_class->build_renderer = sp_feConvolveMatrix_build_renderer;
 }
 
 static void
 sp_feConvolveMatrix_init(SPFeConvolveMatrix *feConvolveMatrix)
 {
+        feConvolveMatrix->divisor=0;
+        feConvolveMatrix->preserveAlpha = false;
+        feConvolveMatrix->order.set("3 3");
 }
 
 /**
@@ -89,6 +98,16 @@ sp_feConvolveMatrix_build(SPObject *object, SPDocument *document, Inkscape::XML:
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
+    sp_object_read_attr(object, "order");
+    sp_object_read_attr(object, "kernelMatrix");
+    sp_object_read_attr(object, "divisor");
+    sp_object_read_attr(object, "bias");
+    sp_object_read_attr(object, "targetX");
+    sp_object_read_attr(object, "targetY");
+    sp_object_read_attr(object, "edgeMode");
+    sp_object_read_attr(object, "kernelUnitLength");
+    sp_object_read_attr(object, "preserveAlpha");
+
 }
 
 /**
@@ -101,6 +120,30 @@ sp_feConvolveMatrix_release(SPObject *object)
         ((SPObjectClass *) feConvolveMatrix_parent_class)->release(object);
 }
 
+
+static std::vector<gdouble> read_kernel_matrix(const gchar* value, int size){
+        std::vector<gdouble> v(size, (gdouble) 0);
+        int i;
+        gchar** values = g_strsplit(value , " ", size);
+        for (i=0;i<size;i++)
+                v[i] = g_ascii_strtod(values[i], NULL);
+        return v;
+}
+
+static double
+sp_feConvolveMatrix_read_number(gchar const *value) {
+    if (!value) return 0;
+    char *end;
+    double ret = g_ascii_strtod(value, &end);
+    if (*end) {
+        g_warning("Unable to convert \"%s\" to number", value);
+        // We could leave this out, too. If strtod can't convert
+        // anything, it will return zero.
+        ret = 0;
+    }
+    return ret;
+}
+
 /**
  * Sets a specific value in the SPFeConvolveMatrix.
  */
@@ -112,6 +155,41 @@ sp_feConvolveMatrix_set(SPObject *object, unsigned int key, gchar const *value)
 
     switch(key) {
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
+        case SP_ATTR_ORDER:
+            feConvolveMatrix->order.set(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_KERNELMATRIX:
+            feConvolveMatrix->kernelMatrix = read_kernel_matrix(value, (int) (feConvolveMatrix->order.getNumber() * feConvolveMatrix->order.getOptNumber()));
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_DIVISOR:
+            feConvolveMatrix->divisor = sp_feConvolveMatrix_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_BIAS:
+            feConvolveMatrix->bias = sp_feConvolveMatrix_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_TARGETX:
+            feConvolveMatrix->targetX = (int) sp_feConvolveMatrix_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_TARGETY:
+            feConvolveMatrix->targetY = (int) sp_feConvolveMatrix_read_number(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_EDGEMODE:
+                //TODO
+            break;
+        case SP_ATTR_KERNELUNITLENGTH:
+            feConvolveMatrix->kernelUnitLength.set(value);
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
+        case SP_ATTR_PRESERVEALPHA:
+                //TODO
+            break;
+
         default:
             if (((SPObjectClass *) feConvolveMatrix_parent_class)->set)
                 ((SPObjectClass *) feConvolveMatrix_parent_class)->set(object, key, value);
@@ -161,7 +239,28 @@ sp_feConvolveMatrix_write(SPObject *object, Inkscape::XML::Node *repr, guint fla
     return repr;
 }
 
+static void sp_feConvolveMatrix_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) {
+    g_assert(primitive != NULL);
+    g_assert(filter != NULL);
+
+    SPFeConvolveMatrix *sp_convolve = SP_FECONVOLVEMATRIX(primitive);
+
+    int primitive_n = filter->add_primitive(NR::NR_FILTER_CONVOLVEMATRIX);
+    NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n);
+    NR::FilterConvolveMatrix *nr_convolve = dynamic_cast<NR::FilterConvolveMatrix*>(nr_primitive);
+    g_assert(nr_convolve != NULL);
 
+    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+
+    nr_convolve->set_targetX(sp_convolve->targetX);
+    nr_convolve->set_targetY(sp_convolve->targetY);
+    nr_convolve->set_orderX( (int)sp_convolve->order.getNumber() );
+    nr_convolve->set_orderY( (int)sp_convolve->order.getOptNumber() );
+    nr_convolve->set_kernelMatrix(sp_convolve->kernelMatrix);
+    nr_convolve->set_divisor(sp_convolve->divisor);
+    nr_convolve->set_bias(sp_convolve->bias);
+
+}
 /*
   Local Variables:
   mode:c++
index d19666976947460c1e72aecc4cc118416357601c..53ed8b741e822c65e1439866ab8640f9bc16f7bb 100644 (file)
@@ -6,6 +6,7 @@
  */
 /*
  * Authors:
+ *   Felipe Corrêa da Silva Sanches <felipe.sanches@gmail.com>
  *   Hugo Rodrigues <haa.rodrigues@gmail.com>
  *
  * Copyright (C) 2006 Hugo Rodrigues
 
 #include "sp-filter.h"
 #include "sp-feconvolvematrix-fns.h"
+#include "number-opt-number.h"
+#include <vector>
+//#include <glib.h>
+
 
 /* FeConvolveMatrix base class */
 class SPFeConvolveMatrixClass;
 
 struct SPFeConvolveMatrix : public SPFilterPrimitive {
-    /** CONVOLVEMATRIX ATTRIBUTES HERE */
-    
+    /* CONVOLVEMATRIX ATTRIBUTES */
+    NumberOptNumber order;
+    std::vector<gdouble> kernelMatrix;
+    double divisor, bias;
+    int targetX, targetY;
+    unsigned short edgeMode;
+    NumberOptNumber kernelUnitLength;
+    bool preserveAlpha;
 };
 
 struct SPFeConvolveMatrixClass {