46template <
typename Comparison, Geom::Dim2 axis,
int BPP>
51 int w = cairo_image_surface_get_width(out);
52 int h = cairo_image_surface_get_height(out);
55 int stridein = cairo_image_surface_get_stride(input);
56 int strideout = cairo_image_surface_get_stride(out);
58 unsigned char *in_data = cairo_image_surface_get_data(input);
59 unsigned char *out_data = cairo_image_surface_get_data(out);
61 int ri = round(radius);
68 std::deque<std::pair<int, unsigned char>> vals[BPP];
71 for (
int p = 0; p < BPP; ++p) {
72 vals[p].emplace_back(-1, 0);
76 unsigned char *in_p = in_data + i * (axis ==
Geom::X ? stridein : BPP);
77 unsigned char *out_p = out_data + i * (axis ==
Geom::X ? strideout : BPP);
100 for (
int j = 0; j < std::min(ri,
w); ++j) {
101 for(
int p = 0; p < BPP; ++p) {
103 if (!vals[p].empty() && vals[p].front().first <= j) vals[p].pop_front();
104 while(!vals[p].empty() && !comp(vals[p].back().second, *in_p)) vals[p].pop_back();
105 vals[p].emplace_back(j + wi, *in_p);
108 if (axis ==
Geom::Y) in_p += stridein - BPP;
112 for (
int j = ri; j <
w; ++j) {
113 for(
int p = 0; p < BPP; ++p) {
115 if (!vals[p].empty() && vals[p].front().first <= j) vals[p].pop_front();
116 while(!vals[p].empty() && !comp(vals[p].back().second, *in_p)) vals[p].pop_back();
117 vals[p].emplace_back(j + wi, *in_p);
120 *out_p = vals[p].front().second;
124 in_p += stridein - BPP;
125 out_p += strideout - BPP;
130 for(
int p = 0; p < BPP; ++p) {
131 while(!vals[p].empty() && !comp(vals[p].back().second, 0)) vals[p].pop_back();
132 vals[p].emplace_back(
w + wi, 0);
135 for (
int j = std::max(
w,ri); j <
w+ri; ++j) {
136 for(
int p = 0; p < BPP; ++p) {
138 if (!vals[p].empty() && vals[p].front().first <= j) vals[p].pop_front();
140 *out_p = vals[p].front().second;
143 if (axis ==
Geom::Y) out_p += strideout - BPP;
147 cairo_surface_mark_dirty(out);
161 cairo_surface_destroy(out);
169 int bpp = cairo_image_surface_get_format(input) == CAIRO_FORMAT_A8 ? 1 : 4;
175 morphologicalFilter1D< std::greater<unsigned char>,
Geom::X, 1 >(input, interm, xr);
177 morphologicalFilter1D< std::greater<unsigned char>,
Geom::X, 4 >(input, interm, xr);
181 morphologicalFilter1D< std::less<unsigned char>,
Geom::X, 1 >(input, interm, xr);
183 morphologicalFilter1D< std::less<unsigned char>,
Geom::X, 4 >(input, interm, xr);
194 morphologicalFilter1D< std::greater<unsigned char>,
Geom::Y, 1 >(interm, out, yr);
196 morphologicalFilter1D< std::greater<unsigned char>,
Geom::Y, 4 >(interm, out, yr);
200 morphologicalFilter1D< std::less<unsigned char>,
Geom::Y, 1 >(interm, out, yr);
202 morphologicalFilter1D< std::less<unsigned char>,
Geom::Y, 4 >(interm, out, yr);
206 cairo_surface_destroy(interm);
209 cairo_surface_destroy(out);
217 area.
expandBy(enlarge_x, enlarge_y);
224 return enlarge_x * enlarge_y;
Cairo software blending templates.
static const int POOL_THRESHOLD
void copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out)
cairo_surface_t * ink_cairo_surface_create_identical(cairo_surface_t *s)
Create a surface that differs only in pixel content.
Cairo integration helpers.
3x3 matrix representing an affine transformation.
Coord expansionX() const
Calculates the amount of x-scaling imparted by the Affine.
Coord expansionY() const
Calculates the amount of y-scaling imparted by the Affine.
Axis aligned, non-empty, generic rectangle.
void expandBy(C amount)
Expand the rectangle in both directions by the specified amount.
~FilterMorphology() override
void set_operator(FilterMorphologyOperator o)
double complexity(Geom::Affine const &ctm) const override
void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans) const override
void set_xradius(double x)
void render_cairo(FilterSlot &slot) const override
void set_yradius(double y)
cairo_surface_t * getcairo(int slot)
Returns the pixblock in specified slot.
void set(int slot, cairo_surface_t *s)
Sets or re-sets the pixblock associated with given slot.
int get_device_scale() const
Gets the device scale; for high DPI monitors.
FilterUnits const & get_units() const
Geom::Affine get_matrix_primitiveunits2pb() const
Gets the primitiveUnits to pixblock coordinates transformation matrix.
struct _cairo_surface cairo_surface_t
@ MORPHOLOGY_OPERATOR_DILATE
Helper class to stream background task notifications as a series of messages.
std::shared_ptr< dispatch_pool > get_global_dispatch_pool()