Code

enable safe support for motion hints
[inkscape.git] / src / display / nr-filter-colormatrix.cpp
1 /*
2  * feColorMatrix filter primitive renderer
3  *
4  * Authors:
5  *   Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include "display/nr-filter-colormatrix.h"
13 #include "display/nr-filter-units.h"
14 #include "display/nr-filter-utils.h"
15 #include "libnr/nr-blit.h"
16 #include <math.h>
18 namespace NR {
20 FilterColorMatrix::FilterColorMatrix()
21 {
22 }
24 FilterPrimitive * FilterColorMatrix::create() {
25     return new FilterColorMatrix();
26 }
28 FilterColorMatrix::~FilterColorMatrix()
29 {}
31 int FilterColorMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
32     NRPixBlock *in = slot.get(_input);
33     if (!in) {
34         g_warning("Missing source image for feColorMatrix (in=%d)", _input);
35         return 1;
36     }
38     NRPixBlock *out = new NRPixBlock;
40     nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N,
41                            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
42                            true);
44     // this primitive is defined for non-premultiplied RGBA values,
45     // thus convert them to that format
46     bool free_in_on_exit = false;
47     if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N) {
48         NRPixBlock *original_in = in;
49         in = new NRPixBlock;
50         nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8N,
51                                original_in->area.x0, original_in->area.y0,
52                                original_in->area.x1, original_in->area.y1,
53                                true);
54         nr_blit_pixblock_pixblock(in, original_in);
55         free_in_on_exit = true;
56     }
58     unsigned char *in_data = NR_PIXBLOCK_PX(in);
59     unsigned char *out_data = NR_PIXBLOCK_PX(out);
60     unsigned char r,g,b,a;
61     int x,y,x0,y0,x1,y1,i;
62     double a00,a01,a02,a10,a11,a12,a20,a21,a22, coshue, sinhue;
63     x0=in->area.x0;
64     y0=in->area.y0;
65     x1=in->area.x1;
66     y1=in->area.y1;
68     switch(type){
69         case COLORMATRIX_MATRIX:
70             if (values.size()!=20) {
71                 g_warning("ColorMatrix: values parameter error. Wrong size: %i.", static_cast<int>(values.size()));
72                 return -1;
73             }
74             for (x=x0;x<x1;x++){
75                 for (y=y0;y<y1;y++){
76                     i = ((x-x0) + (x1-x0)*(y-y0))*4;
77                     r = in_data[i];
78                     g = in_data[i+1];
79                     b = in_data[i+2];
80                     a = in_data[i+3];
81                     out_data[i] = CLAMP_D_TO_U8( r*values[0] + g*values[1] + b*values[2] + a*values[3] + 255*values[4] );
82                     out_data[i+1] = CLAMP_D_TO_U8( r*values[5] + g*values[6] + b*values[7] + a*values[8] + 255*values[9] );
83                     out_data[i+2] = CLAMP_D_TO_U8( r*values[10] + g*values[11] + b*values[12] + a*values[13] + 255*values[14] );
84                     out_data[i+3] = CLAMP_D_TO_U8( r*values[15] + g*values[16] + b*values[17] + a*values[18] + 255*values[19] );
85                 }
86             }
87             break;
88         case COLORMATRIX_SATURATE:
89             for (x=x0;x<x1;x++){
90                 for (y=y0;y<y1;y++){
91                     i = ((x-x0) + (x1-x0)*(y-y0))*4;
92                     r = in_data[i];
93                     g = in_data[i+1];
94                     b = in_data[i+2];
95                     a = in_data[i+3];
96                     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) );
97                     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) );
98                     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) );
99                     out_data[i+3] = a;
100                 }
101             }
102             break;
103         case COLORMATRIX_HUEROTATE:
104             coshue = cos(value * M_PI/180.0);
105             sinhue = sin(value * M_PI/180.0);
106             a00 = 0.213 + coshue*( 0.787) + sinhue*(-0.213);
107             a01 = 0.715 + coshue*(-0.715) + sinhue*(-0.715);
108             a02 = 0.072 + coshue*(-0.072) + sinhue*( 0.928);
109             a10 = 0.213 + coshue*(-0.213) + sinhue*( 0.143);
110             a11 = 0.715 + coshue*( 0.285) + sinhue*( 0.140);
111             a12 = 0.072 + coshue*(-0.072) + sinhue*(-0.283);
112             a20 = 0.213 + coshue*(-0.213) + sinhue*(-0.787);
113             a21 = 0.715 + coshue*(-0.715) + sinhue*( 0.715);
114             a22 = 0.072 + coshue*( 0.928) + sinhue*( 0.072);
116             for (x=x0;x<x1;x++){
117                 for (y=y0;y<y1;y++){
118                     i = ((x-x0) + (x1-x0)*(y-y0))*4;
119                     r = in_data[i];
120                     g = in_data[i+1];
121                     b = in_data[i+2];
122                     a = in_data[i+3];
124                     out_data[i] = CLAMP_D_TO_U8( r*a00 + g*a01 + b*a02 );
125                     out_data[i+1] = CLAMP_D_TO_U8( r*a10 + g*a11 + b*a12 );
126                     out_data[i+2] = CLAMP_D_TO_U8( r*a20 + g*a21 + b*a22 );
127                     out_data[i+3] = a;
128                 }
129             }
130             break;
131         case COLORMATRIX_LUMINANCETOALPHA:
132             for (x=x0;x<x1;x++){
133                 for (y=y0;y<y1;y++){
134                     i = ((x-x0) + (x1-x0)*(y-y0))*4;
135                     r = in_data[i];
136                     g = in_data[i+1];
137                     b = in_data[i+2];
138                     out_data[i] = 0;
139                     out_data[i+1] = 0;
140                     out_data[i+2] = 0;
141                     out_data[i+3] = CLAMP_D_TO_U8( r*0.2125 + g*0.7154 + b*0.0721);
142                 }
143             }
144             break;
145         case COLORMATRIX_ENDTYPE:
146             break;
147     }
149     if (free_in_on_exit) {
150         nr_pixblock_release(in);
151         delete in;
152     }
154     out->empty = FALSE;
155     slot.set(_output, out);
156     return 0;
159 void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Matrix const &/*trans*/)
163 void FilterColorMatrix::set_type(FilterColorMatrixType t){
164         type = t;
167 void FilterColorMatrix::set_value(gdouble v){
168         value = v;
171 void FilterColorMatrix::set_values(std::vector<gdouble> &v){
172         values = v;
175 } /* namespace NR */
177 /*
178   Local Variables:
179   mode:c++
180   c-file-style:"stroustrup"
181   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
182   indent-tabs-mode:nil
183   fill-column:99
184   End:
185 */
186 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :