Code

feMorphology filter primitive implementation
authorjucablues <jucablues@users.sourceforge.net>
Thu, 9 Aug 2007 05:06:49 +0000 (05:06 +0000)
committerjucablues <jucablues@users.sourceforge.net>
Thu, 9 Aug 2007 05:06:49 +0000 (05:06 +0000)
src/display/nr-filter-morphology.cpp
src/display/nr-filter-morphology.h
src/sp-femorphology.cpp
src/sp-femorphology.h

index 9660d61ef36cb37681369fe501adc42c28efc0ce..bbf26c87cba000485311174779972185f3119fe2 100644 (file)
@@ -14,7 +14,6 @@ namespace NR {
 
 FilterMorphology::FilterMorphology()
 {
-    g_warning("FilterMorphology::render not implemented.");
 }
 
 FilterPrimitive * FilterMorphology::create() {
@@ -28,15 +27,53 @@ int FilterMorphology::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);
+    int x0=in->area.x0;
+    int y0=in->area.y0;
+    int x1=in->area.x1;
+    int y1=in->area.y1;            
+    int w=x1-x0, h=y1-y0;
+    int x,y,i,j;
+    int rmax,gmax,bmax,amax;
+    int rmin,gmin,bmin,amin;
+    
+    nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true);
 
     unsigned char *in_data = NR_PIXBLOCK_PX(in);
     unsigned char *out_data = NR_PIXBLOCK_PX(out);
 
-//IMPLEMENT ME!
-    
+    for(x=xradius; x<w-xradius; x++){
+        for(y=yradius; y<h-yradius; y++){
+            rmin=rmax=in_data[4*(x + w*y)];
+            gmin=gmax=in_data[4*(x + w*y)+1];
+            bmin=bmax=in_data[4*(x + w*y)+2];
+            amin=amax=in_data[4*(x + w*y)+3];
+            for(i=x-xradius;i<x+xradius;i++){
+                for(j=y-yradius;j<y+yradius;j++){
+                    if(in_data[4*(i + w*j)]>rmax) rmax = in_data[4*(i + w*j)];
+                    if(in_data[4*(i + w*j)+1]>gmax) gmax = in_data[4*(i + w*j)+1];
+                    if(in_data[4*(i + w*j)+2]>bmax) bmax = in_data[4*(i + w*j)+2];
+                    if(in_data[4*(i + w*j)+3]>amax) amax = in_data[4*(i + w*j)+3];
+                                                            
+                    if(in_data[4*(i + w*j)]<rmin) rmin = in_data[4*(i + w*j)];
+                    if(in_data[4*(i + w*j)+1]<gmin) gmin = in_data[4*(i + w*j)+1];
+                    if(in_data[4*(i + w*j)+2]<bmin) bmin = in_data[4*(i + w*j)+2];
+                    if(in_data[4*(i + w*j)+3]<amin) amin = in_data[4*(i + w*j)+3];                    
+                }
+            }
+            if (Operator==MORPHOLOGY_OPERATOR_ERODE){
+                out_data[4*(x + w*y)]=rmax;
+                out_data[4*(x + w*y)+1]=gmax;
+                out_data[4*(x + w*y)+2]=bmax;
+                out_data[4*(x + w*y)+3]=amax;
+            } else {
+                out_data[4*(x + w*y)]=rmin;
+                out_data[4*(x + w*y)+1]=gmin;
+                out_data[4*(x + w*y)+2]=bmin;
+                out_data[4*(x + w*y)+3]=amin;
+            }
+        }
+    }
+   
     out->empty = FALSE;
     slot.set(_output, out);
     return 0;
@@ -44,6 +81,22 @@ int FilterMorphology::render(FilterSlot &slot, Matrix const &trans) {
 
 void FilterMorphology::area_enlarge(NRRectL &area, Matrix const &trans)
 {
+    area.x0-=xradius;
+    area.x1+=xradius;
+    area.y0-=yradius;
+    area.y1+=yradius;            
+}
+
+void FilterMorphology::set_operator(FilterMorphologyOperator &o){
+    Operator = o;
+}
+
+void FilterMorphology::set_xradius(int x){
+    xradius = x;
+}
+
+void FilterMorphology::set_yradius(int y){
+    yradius = y;
 }
 
 } /* namespace NR */
index 5f89688d0cb2caaa65a310755e1acac53a99dea1..be9ad20310f43465ebead48e1ebe66dbf1565175 100644 (file)
 
 namespace NR {
 
+enum FilterMorphologyOperator {
+    MORPHOLOGY_OPERATOR_ERODE,
+    MORPHOLOGY_OPERATOR_DILATE
+};
+
 class FilterMorphology : public FilterPrimitive {
 public:
     FilterMorphology();
@@ -25,6 +30,14 @@ public:
 
     virtual int render(FilterSlot &slot, Matrix const &trans);
     virtual void area_enlarge(NRRectL &area, Matrix const &trans);
+    void set_operator(FilterMorphologyOperator &o);
+    void set_xradius(int x);
+    void set_yradius(int y);
+
+private:
+    FilterMorphologyOperator Operator;
+    int xradius;
+    int yradius;
 };
 
 } /* namespace NR */
index 980d77968e2163a74e5936630b151fa9a67e3467..22c6de038e48b0a1442060792fd6f941aa9b2d41 100644 (file)
@@ -6,7 +6,8 @@
  */
 /*
  * Authors:
- *   hugo Rodrigues <haa.rodrigues@gmail.com>
+ *   Felipe Sanches <felipe.sanches@gmail.com>
+ *   Hugo Rodrigues <haa.rodrigues@gmail.com>
  *
  * Copyright (C) 2006 Hugo Rodrigues
  *
@@ -21,7 +22,7 @@
 #include "svg/svg.h"
 #include "sp-femorphology.h"
 #include "xml/repr.h"
-
+#include "display/nr-filter-morphology.h"
 
 /* FeMorphology base class */
 
@@ -77,6 +78,8 @@ sp_feMorphology_class_init(SPFeMorphologyClass *klass)
 static void
 sp_feMorphology_init(SPFeMorphology *feMorphology)
 {
+    //Setting default values:
+    feMorphology->radius.set("0");
 }
 
 /**
@@ -92,6 +95,8 @@ sp_feMorphology_build(SPObject *object, SPDocument *document, Inkscape::XML::Nod
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
+    sp_object_read_attr(object, "operator");
+    sp_object_read_attr(object, "radius");
 }
 
 /**
@@ -104,6 +109,19 @@ sp_feMorphology_release(SPObject *object)
         ((SPObjectClass *) feMorphology_parent_class)->release(object);
 }
 
+static NR::FilterMorphologyOperator sp_feMorphology_read_operator(gchar const *value){
+    if (!value) return NR::MORPHOLOGY_OPERATOR_ERODE; //erode is default
+    switch(value[0]){
+        case 'e':
+            if (strncmp(value, "erode", 5) == 0) return NR::MORPHOLOGY_OPERATOR_ERODE;
+            break;
+        case 'd':
+            if (strncmp(value, "dilate", 6) == 0) return NR::MORPHOLOGY_OPERATOR_DILATE;
+            break;
+    }
+    return NR::MORPHOLOGY_OPERATOR_ERODE; //erode is default
+}
+
 /**
  * Sets a specific value in the SPFeMorphology.
  */
@@ -112,9 +130,24 @@ sp_feMorphology_set(SPObject *object, unsigned int key, gchar const *value)
 {
     SPFeMorphology *feMorphology = SP_FEMORPHOLOGY(object);
     (void)feMorphology;
-
+    
+    NR::FilterMorphologyOperator read_operator;
     switch(key) {
-       /*DEAL WITH SETTING ATTRIBUTES HERE*/
+    /*DEAL WITH SETTING ATTRIBUTES HERE*/
+        case SP_ATTR_OPERATOR:
+            read_operator = sp_feMorphology_read_operator(value);
+            if (read_operator != feMorphology->Operator){
+                feMorphology->Operator = read_operator;
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            }
+            break;
+        case SP_ATTR_RADIUS:
+            feMorphology->radius.set(value);
+            //From SVG spec: If <y-radius> is not provided, it defaults to <x-radius>.
+            if (feMorphology->radius.optNumIsSet() == false)
+                feMorphology->radius.setOptNumber(feMorphology->radius.getNumber());
+            object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
+            break;
         default:
             if (((SPObjectClass *) feMorphology_parent_class)->set)
                 ((SPObjectClass *) feMorphology_parent_class)->set(object, key, value);
@@ -175,7 +208,11 @@ static void sp_feMorphology_build_renderer(SPFilterPrimitive *primitive, NR::Fil
     NR::FilterMorphology *nr_morphology = dynamic_cast<NR::FilterMorphology*>(nr_primitive);
     g_assert(nr_morphology != NULL);
 
-    sp_filter_primitive_renderer_common(primitive, nr_primitive);
+    sp_filter_primitive_renderer_common(primitive, nr_primitive); 
+    
+    nr_morphology->set_operator(sp_morphology->Operator);
+    nr_morphology->set_xradius( (int)sp_morphology->radius.getNumber() );
+    nr_morphology->set_yradius( (int)sp_morphology->radius.getOptNumber() );
 }
 
 /*
index 11206b2da7d5540d81cbf9fe338b1724ad2439b7..1229c90d187934824f55e9d3851045e7a7cb4a30 100644 (file)
@@ -15,7 +15,7 @@
 
 #include "sp-filter.h"
 #include "sp-femorphology-fns.h"
-
+#include "number-opt-number.h"
 #include "display/nr-filter.h"
 #include "display/nr-filter-morphology.h"
 
@@ -25,7 +25,8 @@ class SPFeMorphologyClass;
 
 struct SPFeMorphology : public SPFilterPrimitive {
     /** MORPHOLOGY ATTRIBUTES HERE */
-    
+    NR::FilterMorphologyOperator Operator;
+    NumberOptNumber radius;
 };
 
 struct SPFeMorphologyClass {