Code

User message context in extensions
[inkscape.git] / src / display / nr-filter-morphology.cpp
1 /*
2  * feMorphology filter primitive renderer
3  *
4  * Authors:
5  *   Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include <cmath>
13 #include "display/nr-filter-morphology.h"
14 #include "display/nr-filter-units.h"
15 #include "libnr/nr-blit.h"
17 namespace Inkscape {
18 namespace Filters {
20 FilterMorphology::FilterMorphology()
21 {
22 }
24 FilterPrimitive * FilterMorphology::create() {
25     return new FilterMorphology();
26 }
28 FilterMorphology::~FilterMorphology()
29 {}
31 int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) {
32     NRPixBlock *in = slot.get(_input);
33     if (!in) {
34         g_warning("Missing source image for feMorphology (in=%d)", _input);
35         return 1;
36     }
38     NRPixBlock *out = new NRPixBlock;
40     // this primitive is defined for premultiplied RGBA values,
41     // thus convert them to that format
42     bool free_in_on_exit = false;
43     if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
44         NRPixBlock *original_in = in;
45         in = new NRPixBlock;
46         nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8P,
47                                original_in->area.x0, original_in->area.y0,
48                                original_in->area.x1, original_in->area.y1,
49                                true);
50         nr_blit_pixblock_pixblock(in, original_in);
51         free_in_on_exit = true;
52     }
54     Geom::Matrix p2pb = units.get_matrix_primitiveunits2pb();
55     int const xradius = (int)round(this->xradius * p2pb.expansionX());
56     int const yradius = (int)round(this->yradius * p2pb.expansionY());
58     int x0=in->area.x0;
59     int y0=in->area.y0;
60     int x1=in->area.x1;
61     int y1=in->area.y1;
62     int w=x1-x0, h=y1-y0;
63     int x, y, i, j;
64     int rmax,gmax,bmax,amax;
65     int rmin,gmin,bmin,amin;
67     nr_pixblock_setup_fast(out, in->mode, x0, y0, x1, y1, true);
69     unsigned char *in_data = NR_PIXBLOCK_PX(in);
70     unsigned char *out_data = NR_PIXBLOCK_PX(out);
72     for(x = 0 ; x < w ; x++){
73         for(y = 0 ; y < h ; y++){
74             rmin = gmin = bmin = amin = 255;
75             rmax = gmax = bmax = amax = 0;
76             for(i = x - xradius ; i < x + xradius ; i++){
77                 if (i < 0 || i >= w) continue;
78                 for(j = y - yradius ; j < y + yradius ; j++){
79                     if (j < 0 || j >= h) continue;
80                     if(in_data[4*(i + w*j)]>rmax) rmax = in_data[4*(i + w*j)];
81                     if(in_data[4*(i + w*j)+1]>gmax) gmax = in_data[4*(i + w*j)+1];
82                     if(in_data[4*(i + w*j)+2]>bmax) bmax = in_data[4*(i + w*j)+2];
83                     if(in_data[4*(i + w*j)+3]>amax) amax = in_data[4*(i + w*j)+3];
85                     if(in_data[4*(i + w*j)]<rmin) rmin = in_data[4*(i + w*j)];
86                     if(in_data[4*(i + w*j)+1]<gmin) gmin = in_data[4*(i + w*j)+1];
87                     if(in_data[4*(i + w*j)+2]<bmin) bmin = in_data[4*(i + w*j)+2];
88                     if(in_data[4*(i + w*j)+3]<amin) amin = in_data[4*(i + w*j)+3];
89                 }
90             }
91             if (Operator==MORPHOLOGY_OPERATOR_DILATE){
92                 out_data[4*(x + w*y)]=rmax;
93                 out_data[4*(x + w*y)+1]=gmax;
94                 out_data[4*(x + w*y)+2]=bmax;
95                 out_data[4*(x + w*y)+3]=amax;
96             } else {
97                 out_data[4*(x + w*y)]=rmin;
98                 out_data[4*(x + w*y)+1]=gmin;
99                 out_data[4*(x + w*y)+2]=bmin;
100                 out_data[4*(x + w*y)+3]=amin;
101             }
102         }
103     }
105     if (free_in_on_exit) {
106         nr_pixblock_release(in);
107         delete in;
108     }
110     out->empty = FALSE;
111     slot.set(_output, out);
112     return 0;
115 void FilterMorphology::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
117     int const enlarge_x = (int)std::ceil(this->xradius * (std::fabs(trans[0]) + std::fabs(trans[1])));
118     int const enlarge_y = (int)std::ceil(this->yradius * (std::fabs(trans[2]) + std::fabs(trans[3])));
120     area.x0 -= enlarge_x;
121     area.x1 += enlarge_x;
122     area.y0 -= enlarge_y;
123     area.y1 += enlarge_y;
126 void FilterMorphology::set_operator(FilterMorphologyOperator &o){
127     Operator = o;
130 void FilterMorphology::set_xradius(double x){
131     xradius = x;
134 void FilterMorphology::set_yradius(double y){
135     yradius = y;
138 FilterTraits FilterMorphology::get_input_traits() {
139     return TRAIT_PARALLER;
142 } /* namespace Filters */
143 } /* namespace Inkscape */
145 /*
146   Local Variables:
147   mode:c++
148   c-file-style:"stroustrup"
149   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
150   indent-tabs-mode:nil
151   fill-column:99
152   End:
153 */
154 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :