summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-07-21 16:37:38 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-07-21 16:37:38 +0000
commitdd78fe909d51f28f7d2e42dcc17ffcb45eb39b23 (patch)
tree2c331954debb4c2bc08181f16b0c6b0eb88690e3 /src/display
parentFix type mismatch of std::min args in ColorMatrixMatrix constructor (diff)
downloadinkscape-dd78fe909d51f28f7d2e42dcc17ffcb45eb39b23.tar.gz
inkscape-dd78fe909d51f28f7d2e42dcc17ffcb45eb39b23.zip
Add unpremul_alpha utility function. Some preparations
(bzr r9508.1.26)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/cairo-templates.h104
-rw-r--r--src/display/cairo-utils.h9
-rw-r--r--src/display/nr-filter-colormatrix.cpp12
-rw-r--r--src/display/nr-filter-convolve-matrix.cpp7
4 files changed, 125 insertions, 7 deletions
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h
index efbd9c094..871d5c867 100644
--- a/src/display/cairo-templates.h
+++ b/src/display/cairo-templates.h
@@ -268,6 +268,110 @@ void ink_cairo_surface_filter(cairo_surface_t *in, cairo_surface_t *out, Filter
cairo_surface_mark_dirty(out);
}
+template <typename Synth>
+void ink_cairo_surface_synthesize(cairo_surface_t *out, Synth synth)
+{
+ // ASSUMPTIONS
+ // 1. Cairo ARGB32 surface strides are always divisible by 4
+ // 2. We can only receive CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_A8 surfaces
+
+ int w = cairo_image_surface_get_width(out);
+ int h = cairo_image_surface_get_height(out);
+ int strideout = cairo_image_surface_get_stride(out);
+ int bppout = cairo_image_surface_get_format(out) == CAIRO_FORMAT_A8 ? 1 : 4;
+ int limit = w * h;
+ // NOTE: fast path is not used, because we would need 2 divisions to get pixel indices
+
+ guint32 *const out_data = (guint32*) cairo_image_surface_get_data(out);
+
+ #if HAVE_OPENMP
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int num_threads = prefs->getIntLimited("/options/threading/numthreads", omp_get_num_procs(), 1, 256);
+ #endif
+
+ if (bppout == 4) {
+ #if HAVE_OPENMP
+ #pragma omp parallel for num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint32 *out_p = out_data + i * strideout/4;
+ for (int j = 0; j < w; ++j) {
+ *out_p = synth(j, i);
+ ++out_p;
+ }
+ }
+ } else {
+ // bppout == 1
+ #if HAVE_OPENMP
+ #pragma omp parallel for num_threads(num_threads)
+ #endif
+ for (int i = 0; i < h; ++i) {
+ guint8 *out_p = reinterpret_cast<guint8*>(out_data) + i * strideout;
+ for (int j = 0; j < w; ++j) {
+ guint32 out_px = synth(j, i);
+ *out_p = out_px >> 24;
+ ++out_p;
+ }
+ }
+ }
+ cairo_surface_mark_dirty(out);
+}
+
+// simple pixel accessor for image surface that handles different edge wrapping modes
+class PixelAccessor {
+public:
+ typedef PixelAccessor self;
+ enum EdgeMode {
+ EDGE_PAD,
+ EDGE_WRAP,
+ EDGE_ZERO
+ };
+
+ PixelAccessor(cairo_surface_t *s, EdgeMode e)
+ : _surface(s)
+ , _px(cairo_image_surface_get_data(s))
+ , _x(0), _y(0)
+ , _w(cairo_image_surface_get_width(s))
+ , _h(cairo_image_surface_get_height(s))
+ , _stride(cairo_image_surface_get_stride(s))
+ , _edge_mode(e)
+ , _alpha(cairo_image_surface_get_format(s) == CAIRO_FORMAT_A8)
+ {}
+
+ guint32 pixelAt(int x, int y) {
+ // This is a lot of ifs for a single pixel access. However, branch prediction
+ // should help us a lot, as the result of ifs is always the same for a single image.
+ int real_x = x, real_y = y;
+ switch (_edge_mode) {
+ case EDGE_PAD:
+ real_x = CLAMP(x, 0, _w-1);
+ real_y = CLAMP(y, 0, _h-1);
+ break;
+ case EDGE_WRAP:
+ real_x %= _w;
+ real_y %= _h;
+ break;
+ case EDGE_ZERO:
+ default:
+ if (x < 0 || x >= _w || y < 0 || y >= _h)
+ return 0;
+ break;
+ }
+ if (_alpha) {
+ return *(_px + real_y*_stride + real_x) << 24;
+ } else {
+ guint32 *px = reinterpret_cast<guint32*>(_px +real_y*_stride + real_x*4);
+ return *px;
+ }
+ }
+private:
+ cairo_surface_t *_surface;
+ guint8 *_px;
+ int _x, _y, _w, _h, _stride;
+ EdgeMode _edge_mode;
+ bool _alpha;
+};
+
// Some helpers for pixel manipulation
G_GNUC_CONST inline gint32
diff --git a/src/display/cairo-utils.h b/src/display/cairo-utils.h
index 02bfe0f73..12fcd8b3d 100644
--- a/src/display/cairo-utils.h
+++ b/src/display/cairo-utils.h
@@ -98,11 +98,18 @@ void convert_pixels_argb32_to_pixbuf(guchar *data, int w, int h, int rs);
void convert_pixbuf_normal_to_argb32(GdkPixbuf *);
void convert_pixbuf_argb32_to_normal(GdkPixbuf *);
-inline guint32 premul_alpha(guint32 color, guint32 alpha)
+G_GNUC_CONST inline guint32
+premul_alpha(guint32 color, guint32 alpha)
{
guint32 temp = alpha * color + 128;
return (temp + (temp >> 8)) >> 8;
}
+G_GNUC_CONST inline guint32
+unpremul_alpha(guint32 color, guint32 alpha)
+{
+ // NOTE: you must check for alpha != 0 yourself.
+ return (255 * color + alpha/2) / alpha;
+}
// TODO: move those to 2Geom
void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width);
diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp
index 8b7956833..7ab606182 100644
--- a/src/display/nr-filter-colormatrix.cpp
+++ b/src/display/nr-filter-colormatrix.cpp
@@ -51,9 +51,9 @@ struct ColorMatrixMatrix {
// we need to un-premultiply alpha values for this type of matrix
// TODO: unpremul can be ignored if there is an identity mapping on the alpha channel
if (a != 0) {
- r = (r * 255 + a/2) / a;
- b = (b * 255 + a/2) / a;
- g = (g * 255 + a/2) / a;
+ r = unpremul_alpha(r, a);
+ g = unpremul_alpha(g, a);
+ b = unpremul_alpha(b, a);
}
gint32 ro = r*_v[0] + g*_v[1] + b*_v[2] + a*_v[3] + _v[4];
@@ -141,9 +141,9 @@ struct ColorMatrixLuminanceToAlpha {
EXTRACT_ARGB32(in, a, r, g, b)
// unpremultiply color values
if (a != 0) {
- r = (r * 255 + a/2) / a;
- b = (b * 255 + a/2) / a;
- g = (g * 255 + a/2) / a;
+ r = unpremul_alpha(r, a);
+ g = unpremul_alpha(g, a);
+ b = unpremul_alpha(b, a);
}
guint32 ao = r*54 + g*182 + b*18;
return ((ao + 127) / 255) << 24;
diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp
index fc88102d8..0119736cf 100644
--- a/src/display/nr-filter-convolve-matrix.cpp
+++ b/src/display/nr-filter-convolve-matrix.cpp
@@ -140,6 +140,13 @@ static void convolve2D(unsigned char *const out_data, unsigned char const *const
}
}
+/*
+void FilterConvolveMatrix::render_cairo(FilterSlot &slot)
+{
+ cairo_surface_t *input = slot.getcairo(_input);
+ cairo_surface_t *out = ink_cairo_surface_create_identical(input);
+}*/
+
int FilterConvolveMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) {
NRPixBlock *in = slot.get(_input);
if (!in) {