Code

feColorMatrix filter primitive implementation
authorjucablues <jucablues@users.sourceforge.net>
Sun, 5 Aug 2007 05:07:59 +0000 (05:07 +0000)
committerjucablues <jucablues@users.sourceforge.net>
Sun, 5 Aug 2007 05:07:59 +0000 (05:07 +0000)
src/display/nr-filter-colormatrix.cpp
src/display/nr-filter-colormatrix.h
src/helper-fns.h
src/sp-fecolormatrix.cpp

index 417a106c1f8c980fb7d5a5d41b4849c21b433d74..94f8ee9624eb6f1a960b84bd3245d8ce8cf2c25f 100644 (file)
  */
 
 #include "display/nr-filter-colormatrix.h"
+#include "display/nr-filter-utils.h"
+#include<math.h>
+
 namespace NR {
 
 FilterColorMatrix::FilterColorMatrix()
 {
-    g_warning("FilterColorMatrix::render not implemented.");
 }
 
 FilterPrimitive * FilterColorMatrix::create() {
@@ -34,17 +36,92 @@ int FilterColorMatrix::render(FilterSlot &slot, Matrix const &trans) {
 
     unsigned char *in_data = NR_PIXBLOCK_PX(in);
     unsigned char *out_data = NR_PIXBLOCK_PX(out);
+    unsigned char r,g,b,a;
+    int x,y,x0,y0,x1,y1,i;
+    double a00,a01,a02,a10,a11,a12,a20,a21,a22, coshue, sinhue;
+    x0=in->area.x0;
+    y0=in->area.y0;
+    x1=in->area.x1;
+    y1=in->area.y1;    
 
-//IMPLEMENT ME!
-        printf("type = %d\n", type);
-        if (type==0){
-            for (int i=0;i<20;i++){
-                printf("values[%d]=%f\n", i, values[i]);
+    switch(type){
+        case 0: //matrix
+            if (values.size()!=20) {
+                g_warning("ColorMatrix: values parameter error. Wrong size.");
+                return -1;
+            }
+            for (x=x0;x<x1;x++){
+                for (y=y0;y<y1;y++){
+                    i = ((x-x0) + (x1-x0)*(y-y0))*4;
+                    r = in_data[i];
+                    g = in_data[i+1];
+                    b = in_data[i+2];
+                    a = in_data[i+3];
+                    out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + values[4] );
+                    out_data[i+1] = CLAMP_D_TO_U8( r*values[5] + g*values[6] + b*values[7] + a*values[8] + values[9] );
+                    out_data[i+2] = CLAMP_D_TO_U8( r*values[10] + g*values[11] + b*values[12] + a*values[13] + values[14] );
+                    out_data[i+3] = CLAMP_D_TO_U8( r*values[15] + g*values[16] + b*values[17] + a*values[18] + values[19] );
+                }
+            }
+            break;
+        case 1: //saturate
+            for (x=x0;x<x1;x++){
+                for (y=y0;y<y1;y++){
+                    i = ((x-x0) + (x1-x0)*(y-y0))*4;
+                    r = in_data[i];
+                    g = in_data[i+1];
+                    b = in_data[i+2];
+                    a = in_data[i+3];
+                    out_data[i] = CLAMP_D_TO_U8( r*(0.213+0.787*value) + g*(0.715-0.715*value) + b*(0.072-0.072*value) );
+                    out_data[i+1] = CLAMP_D_TO_U8( r*(0.213-0.213*value) + g*(0.715+0.285*value) + b*(0.072-0.072*value) );
+                    out_data[i+2] = CLAMP_D_TO_U8( r*(0.213-0.213*value) + g*(0.715-0.715*value) + b*(0.072+0.928*value) );
+                    out_data[i+3] = a;
+                }
+            }
+            break;
+        case 2: //hueRotate
+            coshue = cos(value);
+            sinhue = sin(value);
+            a00 = 0.213 + coshue*( 0.787) + sinhue*(-0.213);
+            a01 = 0.715 + coshue*(-0.715) + sinhue*(-0.715);
+            a02 = 0.072 + coshue*(-0.072) + sinhue*( 0.928);
+            a10 = 0.213 + coshue*(-0.213) + sinhue*( 0.143);
+            a11 = 0.715 + coshue*( 0.285) + sinhue*( 0.140);
+            a12 = 0.072 + coshue*(-0.072) + sinhue*(-0.283);
+            a20 = 0.213 + coshue*(-0.213) + sinhue*(-0.787);
+            a21 = 0.715 + coshue*(-0.715) + sinhue*( 0.715);
+            a22 = 0.072 + coshue*( 0.928) + sinhue*( 0.072);
+                                    
+            for (x=x0;x<x1;x++){
+                for (y=y0;y<y1;y++){
+                    i = ((x-x0) + (x1-x0)*(y-y0))*4;
+                    r = in_data[i];
+                    g = in_data[i+1];
+                    b = in_data[i+2];
+                    a = in_data[i+3];
+                    
+                    out_data[i] = CLAMP_D_TO_U8( r*a00 + g*a01 + b*a02 );
+                    out_data[i+1] = CLAMP_D_TO_U8( r*a10 + g*a11 + b*a12 );
+                    out_data[i+2] = CLAMP_D_TO_U8( r*a20 + g*a21 + b*a22 );
+                    out_data[i+3] = a;
+                }
+            }
+            break;
+        case 3: //luminanceToAlpha
+            for (x=x0;x<x1;x++){
+                for (y=y0;y<y1;y++){
+                    i = ((x-x0) + (x1-x0)*(y-y0))*4;
+                    r = in_data[i];
+                    g = in_data[i+1];
+                    b = in_data[i+2];
+                    out_data[i] = 0;
+                    out_data[i+1] = 0;
+                    out_data[i+2] = 0;
+                    out_data[i+3] = CLAMP_D_TO_U8( r*0.2125 + g*0.7154 + b*0.0721);
+                }
             }
-        } else {
-                printf("value = %f\n", value);
-        }
-        
+            break;
+    }
     out->empty = FALSE;
     slot.set(_output, out);
     return 0;
@@ -62,7 +139,7 @@ void FilterColorMatrix::set_value(gdouble v){
         value = v;
 }
 
-void FilterColorMatrix::set_values(std::vector<gdouble> v){
+void FilterColorMatrix::set_values(std::vector<gdouble> &v){
         values = v;
 }
 
index e87145c009dad4b0e2e13256408a003940373ccc..9cb628d50c7b58f1fdbc627014516cdf6d875876 100644 (file)
@@ -28,7 +28,7 @@ public:
     virtual void area_enlarge(NRRectL &area, Matrix const &trans);
     virtual void set_type(int type);
     virtual void set_value(gdouble value);
-    virtual void set_values(std::vector<gdouble> values);
+    virtual void set_values(std::vector<gdouble> &values);
 private:
     std::vector<gdouble> values;
     gdouble value;
index f588b9905970fd355fc6485b644e0011a9f3fad9..29fd2ebec7aabf49e70148d8e4fa39283aa0f83c 100644 (file)
@@ -44,8 +44,8 @@ static std::vector<gdouble> helperfns_read_vector(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);
+        for (i=0;i<size && values[i];i++)
+            v[i] = g_ascii_strtod(values[i], NULL);
         return v;
 }
 
index cc7ee61381e447c106be6a01e8ab665df965a108..d20c1145696ad375574cbdaebedd6bd5193b1cc7 100644 (file)
@@ -94,7 +94,8 @@ sp_feColorMatrix_build(SPObject *object, SPDocument *document, Inkscape::XML::No
     }
 
     /*LOAD ATTRIBUTES FROM REPR HERE*/
-    
+    sp_object_read_attr(object, "type");
+    sp_object_read_attr(object, "values");
 }
 
 /**
@@ -130,7 +131,7 @@ static int sp_feColorMatrix_read_type(gchar const *value){
  * Sets a specific value in the SPFeColorMatrix.
  */
 static void
-sp_feColorMatrix_set(SPObject *object, unsigned int key, gchar const *value)
+sp_feColorMatrix_set(SPObject *object, unsigned int key, gchar const *str)
 {
     SPFeColorMatrix *feColorMatrix = SP_FECOLORMATRIX(object);
     (void)feColorMatrix;
@@ -140,39 +141,22 @@ sp_feColorMatrix_set(SPObject *object, unsigned int key, gchar const *value)
        /*DEAL WITH SETTING ATTRIBUTES HERE*/
     switch(key) {
         case SP_ATTR_TYPE:
-            read_int =  sp_feColorMatrix_read_type(value);
+            read_int =  sp_feColorMatrix_read_type(str);
             if (feColorMatrix->type != read_int){
                 feColorMatrix->type = read_int;
                 object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
             }
             break;
         case SP_ATTR_VALUES:
-            switch(feColorMatrix->type){
-                case '0': //matrix
-                    feColorMatrix->values = helperfns_read_vector(value, 20);
-                    object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
-                    break;
-                case '1': //saturate
-                    read_num = helperfns_read_number(value);
-                    if (feColorMatrix->value != read_num){ //TODO: check if it is a real number between 0 and 1;
-                        feColorMatrix->value = read_num;
-                        object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
-                    }
-                    break;
-                case '2': //hueRotate
-                    read_num = helperfns_read_number(value);
-                    if (feColorMatrix->value != read_num){
-                        feColorMatrix->value = read_num;
-                        object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
-                    }
-                    break;                
-                case '3': //luminanceToAlpha
-                 g_warning("value attribute is not applicable for feColorMatrix type='luminanceToAlpha'.");
-                    break;
+            if (str){     
+                feColorMatrix->values = helperfns_read_vector(str, 20);
+                feColorMatrix->value = helperfns_read_number(str);
+                object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
             }
+            break;
         default:
             if (((SPObjectClass *) feColorMatrix_parent_class)->set)
-                ((SPObjectClass *) feColorMatrix_parent_class)->set(object, key, value);
+                ((SPObjectClass *) feColorMatrix_parent_class)->set(object, key, str);
             break;
     }
 }