This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via b7b1aa5e558261c0787fad6e924969625cd465ce (commit)
from 0f6d751635c094c8857706c11538637cda8dfc6f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/b7b1aa5e558261c0787fad6e924969625cd4…
commit b7b1aa5e558261c0787fad6e924969625cd465ce
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jul 6 14:50:23 2012 +0200
doc: Add grabbers docs + spellcheck in API.
diff --git a/doc/Makefile b/doc/Makefile
index 3fdfaad..7eb952d 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,7 +1,8 @@
all: api.html examples.html
api.html: general.txt api.txt context.txt loaders.txt filters.txt - basic_types.txt drawing_api.txt backends.txt gamma.txt
+ basic_types.txt drawing_api.txt backends.txt gamma.txt + grabbers.txt
asciidoc -a toc api.txt
examples.html: examples.txt ../demos/c_simple/*.c ../demos/py_simple/*.py
diff --git a/doc/api.txt b/doc/api.txt
index 402c6dd..37979b4 100644
--- a/doc/api.txt
+++ b/doc/api.txt
@@ -10,3 +10,4 @@ include::drawing_api.txt[]
include::filters.txt[]
include::loaders.txt[]
include::backends.txt[]
+include::grabbers.txt[]
diff --git a/doc/backends.txt b/doc/backends.txt
index ecd3468..66728f7 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -245,3 +245,4 @@ returned. If backend size already matches w and h, nothing is done.
Note that backend->context pointer may change upon calling this function and
at least backend->context->pixels pointer will change.
+
diff --git a/doc/grabbers.txt b/doc/grabbers.txt
new file mode 100644
index 0000000..571cc06
--- /dev/null
+++ b/doc/grabbers.txt
@@ -0,0 +1,126 @@
+Grabbers
+--------
+
+Grabber is an abstraction for a device whose output is a stream of images.
+
+There is currently V4L2 driver that implements a grabber.
+
+To link against grabbers use +-lGP_grabbers+ or better
++`gfxprim-config --libs-grabbers`+ in your linker flags.
+
+Grabber API
+~~~~~~~~~~~
+
+The grabber API consist of structure with callbacks. Every grabber
+initialization yields pointer to this structure. Although is possible to call
+these pointers directly it's not recommended and everybody should rather use
+the inline functions instead.
+
+The grabber API consist GP_Grabber structure and of several functions:
+
+[source,c]
+-------------------------------------------------------------------------------
+typdef struct GP_Grabber {
+ /*
+ * Currently loaded frame frame.
+ */
+ GP_Context *frame;
+
+ /*
+ * Connection fd usable for select() or poll().
+ *
+ * Set to -1 if not available.
+ */
+ int fd;
+
+ /* ... */
+};
+-------------------------------------------------------------------------------
+
+The frame is a pointer to currently loaded frame. Its content is undefined
+until you start the grabber with 'GP_GrabberStart()'.
+
+The 'fd' is a file descriptor suitable for select() or poll(). It's set to -1
+if there is none.
+
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <grabbers/GP_Grabber.h>
+/* or */
+#include <GP.h>
+
+void GP_GrabberExit(GP_Grabber *backend);
+-------------------------------------------------------------------------------
+
+Exits the grabber, frees memory, unmaps memory mappings, closes file
+descriptors etc...
+
+Returns zero on success and non-zero on failure.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <grabbers/GP_Grabber.h>
+/* or */
+#include <GP.h>
+
+int GP_GrabberStart(struct GP_Grabber *self);
+-------------------------------------------------------------------------------
+
+Starts a grabber. After calling this calling you can start retrieving frames
+with 'GP_GrabberPoll()'.
+
+Returns zero on success and non-zero on failure.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <grabbers/GP_Grabber.h>
+/* or */
+#include <GP.h>
+
+int GP_GrabberStop(struct GP_Grabber *self);
+-------------------------------------------------------------------------------
+
+Stops a grabber. Call this when you doesn't need to receive frames but still
+plan to use the grabber later.
+
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <grabbers/GP_Grabber.h>
+/* or */
+#include <GP.h>
+
+int GP_GrabberPoll(struct GP_Grabber *self);
+-------------------------------------------------------------------------------
+
+Once grabber is created you can call this function to receive a frame. If
+grabber 'fd' is not -1 it's preferable to call it when select() or poll()
+returns that data are available on the 'fd'.
+
+This function returns non-zero if new frame was received and stored into the
+'frame' context. Otherwise zero is returned.
+
+Grabber Initializations
+~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <grabbers/GP_V4L2.h>
+/* or */
+#include <GP.h>
+
+struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
+ unsigned int preferred_width,
+ unsigned int preferred_height);
+-------------------------------------------------------------------------------
+
+Opens and initializes V4L2 device. The device is a path in +/dev+ filesystem
+the first V4L2 device in your system should be +/dev/video0+.
+
+The height and width are preferred values, you will most likely get frame by
+that width and height, but the driver may return different values if chosen
+width and height are not supported.
+
+Returns either pointer to the initialized grabber or, in case of failure, NULL
+and errno is filled.
diff --git a/include/grabbers/GP_V4L2.h b/include/grabbers/GP_V4L2.h
index aa6bf08..9b7b043 100644
--- a/include/grabbers/GP_V4L2.h
+++ b/include/grabbers/GP_V4L2.h
@@ -32,7 +32,7 @@ struct GP_Grabber;
* fixed image size.
*/
struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
- unsigned int prefered_width,
- unsigned int prefered_height);
+ unsigned int preferred_width,
+ unsigned int preferred_height);
#endif /* GP_GRABBERS_V4L2_H */
diff --git a/libs/grabbers/GP_V4L2.c b/libs/grabbers/GP_V4L2.c
index fa8a795..4a00e51 100644
--- a/libs/grabbers/GP_V4L2.c
+++ b/libs/grabbers/GP_V4L2.c
@@ -233,8 +233,8 @@ static int v4l2_stop(struct GP_Grabber *self)
}
struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
- unsigned int prefered_width,
- unsigned int prefered_height)
+ unsigned int preferred_width,
+ unsigned int preferred_height)
{
int fd, i, err;
int mode = 0;
@@ -308,8 +308,8 @@ struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = prefered_width;
- fmt.fmt.pix.height = prefered_height;
+ fmt.fmt.pix.width = preferred_width;
+ fmt.fmt.pix.height = preferred_height;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
@@ -422,8 +422,8 @@ err:
#else
struct GP_Grabber *GP_GrabberV4L2Init(const char GP_UNUSED(*device),
- unsigned int GP_UNUSED(prefered_width),
- unsigned int GP_UNUSED(prefered_height))
+ unsigned int GP_UNUSED(preferred_width),
+ unsigned int GP_UNUSED(preferred_height))
{
GP_WARN("V4L2 support not compiled in.");
-----------------------------------------------------------------------
Summary of changes:
doc/Makefile | 3 +-
doc/api.txt | 1 +
doc/backends.txt | 1 +
doc/grabbers.txt | 126 ++++++++++++++++++++++++++++++++++++++++++++
include/grabbers/GP_V4L2.h | 4 +-
libs/grabbers/GP_V4L2.c | 12 ++--
6 files changed, 138 insertions(+), 9 deletions(-)
create mode 100644 doc/grabbers.txt
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
discards 9f9b4467ff22f7341d61b9820098769f33d9f17e (commit)
via 0f6d751635c094c8857706c11538637cda8dfc6f (commit)
via e19bfecb48d67a5903328380fe26a5601c69878e (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (9f9b4467ff22f7341d61b9820098769f33d9f17e)
N -- N -- N (0f6d751635c094c8857706c11538637cda8dfc6f)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/0f6d751635c094c8857706c11538637cda8d…
commit 0f6d751635c094c8857706c11538637cda8dfc6f
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Jul 3 13:41:07 2012 +0200
doc: Update backend docs.
diff --git a/doc/backends.txt b/doc/backends.txt
index 9ce83d7..ecd3468 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -138,15 +138,34 @@ typdef struct GP_Backend {
};
-------------------------------------------------------------------------------
+The file descriptor 'fd' is either set to -1 (in case of SDL that shadows it)
+or to a backend connection file descriptor usable for 'select()' or 'poll()'.
+
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
void GP_BackendExit(GP_Backend *backend);
-------------------------------------------------------------------------------
-Calls an backend exit callback.
+Calls an backend exit callback. Resets the display, keyboard, etc. state back.
+
+WARNING: It's very important to call this functions on application exit. If you
+ doesn't do so, the state of the display, resolution etc. may not be
+ reset back to its original state. This includes program crashes and
+ iterruptions. Also this function may not be signal-async-safe, it's
+ better to set signal hanlers that calls it as this usually works and
+ not doing so may leave non-working system with black display or
+ non-responding keyboard.
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
GP_BackendFlip(GP_Backend *backend);
-------------------------------------------------------------------------------
@@ -154,6 +173,10 @@ Flips a screen. Updates rectangle for a buffered backends.
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
void GP_BackendUpdateRect(GP_Backend *backend,
GP_Coord x0, GP_Coord y0,
GP_Coord x1, GP_Coord y1);
@@ -163,6 +186,10 @@ Updates particular rectangle for a buffered backends.
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
void GP_BackendPoll(GP_Backend *backend);
-------------------------------------------------------------------------------
@@ -170,8 +197,33 @@ Polls for backend events. For backends that do not expose file descriptor
(namely SDL) this should be called repeatedly. For other backend it may be
called either repeatedly or when data are ready on file-descriptor.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
+void GP_BackendWait(GP_Backend *backend);
+-------------------------------------------------------------------------------
+
+Blocks until backend event arrives.
+
+NOTE: Events recieved by backend are not necessarily translated into the input
+ events.
+
+WARNING: Using GP_BackendWait() in multithreaded program will most likely
+ cause deadlocks. As the backend data structures and connection is
+ guarded by a lock any other backend function (called from different
+ thread while GP_BackendWait() is blocking) will lock until
+ GP_BackendWait() returns (i.e. event was recieved).
+
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
int GP_BackendSetCaption(GP_Backend *backend, const char *caption)
-------------------------------------------------------------------------------
@@ -180,6 +232,10 @@ support caption, operation failed) non zero is returned.
[source,c]
-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
int GP_BackendResize(GP_Backend *backend, uint32_t w, uint32_t h);
-------------------------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/e19bfecb48d67a5903328380fe26a5601c69…
commit e19bfecb48d67a5903328380fe26a5601c69878e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Jul 3 12:42:31 2012 +0200
filters: Add initial version of multithreaded linear convolution.
diff --git a/include/filters/GP_LinearThreads.h b/include/filters/GP_LinearThreads.h
new file mode 100644
index 0000000..76c46db
--- /dev/null
+++ b/include/filters/GP_LinearThreads.h
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * This file is part of gfxprim library. *
+ * *
+ * Gfxprim is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2.1 of the License, or (at your option) any later version. *
+ * *
+ * Gfxprim is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with gfxprim; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301 USA *
+ * *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+#ifndef FILTERS_GP_LINEAR_THREADS_H
+#define FILTERS_GP_LINEAR_THREADS_H
+
+#include "GP_Filter.h"
+
+int GP_FilterLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, uint32_t kh,
+ float kern_div, GP_ProgressCallback *callback);
+
+int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, float kern_div,
+ GP_ProgressCallback *callback);
+
+int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kh, float kern_div,
+ GP_ProgressCallback *callback);
+
+#endif /* FILTERS_GP_LINEAR_THREADS_H */
diff --git a/libs/filters/GP_LinearThreads.c b/libs/filters/GP_LinearThreads.c
new file mode 100644
index 0000000..5ccdebc
--- /dev/null
+++ b/libs/filters/GP_LinearThreads.c
@@ -0,0 +1,300 @@
+/*****************************************************************************
+ * This file is part of gfxprim library. *
+ * *
+ * Gfxprim is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2.1 of the License, or (at your option) any later version. *
+ * *
+ * Gfxprim is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with gfxprim; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301 USA *
+ * *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "core/GP_Common.h"
+#include "core/GP_Debug.h"
+
+#include "GP_Linear.h"
+#include "GP_LinearThreads.h"
+
+static int nr_threads(GP_Size w, GP_Size h)
+{
+ int count = sysconf(_SC_NPROCESSORS_ONLN);
+ int threads = GP_MIN(count, (int)(w * h / 1024) + 1);
+
+ if (count < -1)
+ threads = 1;
+
+ GP_DEBUG(1, "Found %u CPUs size %ux%u runnig %u threads",
+ count, w, h, threads);
+
+ return threads;
+}
+
+/*
+ * Multithreaded callback wrapper.
+ */
+struct callback_priv {
+ float max;
+ int abort;
+ unsigned int nr_threads;
+ pthread_mutex_t mutex;
+ GP_ProgressCallback *orig_callback;
+};
+
+static int progress_callback_mp(GP_ProgressCallback *self)
+{
+ struct callback_priv *priv = self->priv;
+
+ /* If any thread got non-zero return value from a callback, abort all */
+ if (priv->abort)
+ return 1;
+
+ if (pthread_mutex_trylock(&priv->mutex)) {
+ GP_DEBUG(1, "Mutex locked, skipping calllback.");
+ return 0;
+ }
+
+ /* Compute max value for the percentage */
+ priv->orig_callback->percentage = GP_MAX(self->percentage, priv->max);
+ priv->max = priv->orig_callback->percentage;
+
+ /* Call the original callback */
+ int ret = priv->orig_callback->callback(priv->orig_callback);
+
+ /* Turn on abort flag if callback returned nonzero */
+ if (ret)
+ priv->abort = 1;
+
+ pthread_mutex_unlock(&priv->mutex);
+
+ return ret;
+}
+
+static void callback_priv_init(struct callback_priv *priv, int nr_threads,
+ GP_ProgressCallback *orig_callback)
+{
+ priv->nr_threads = nr_threads;
+ priv->orig_callback = orig_callback;
+ priv->max = 0;
+ priv->abort = 0;
+ pthread_mutex_init(&priv->mutex, NULL);
+}
+
+static void callback_priv_exit(struct callback_priv *priv)
+{
+ pthread_mutex_destroy(&priv->mutex);
+}
+
+/*
+ * This code just packs and unpacks convolution parameters.
+ */
+struct convolution {
+ const GP_Context *src;
+ GP_Coord x_src;
+ GP_Coord y_src;
+ GP_Size w_src;
+ GP_Size h_src;
+
+ GP_Context *dst;
+ GP_Coord x_dst;
+ GP_Coord y_dst;
+
+ float *kernel;
+ unsigned int ks;
+ float kern_div;
+
+ GP_ProgressCallback *callback;
+};
+
+static void convolution_init(struct convolution *conv, const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst, GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], unsigned int ks, float kern_div,
+ GP_ProgressCallback *callback)
+{
+ conv->src = src;
+ conv->x_src = x_src;
+ conv->y_src = y_src;
+ conv->w_src = w_src;
+ conv->h_src = h_src;
+ conv->dst = dst;
+ conv->x_dst = x_dst;
+ conv->y_dst = y_dst;
+ conv->kernel = kernel;
+ conv->ks = ks;
+ conv->kern_div = kern_div;
+ conv->callback = callback;
+}
+
+static void *h_linear_convolution(void *arg)
+{
+ struct convolution *conv = arg;
+
+ long ret;
+
+ ret = GP_FilterHLinearConvolution_Raw(conv->src, conv->x_src, conv->y_src,
+ conv->w_src, conv->h_src, conv->dst,
+ conv->x_dst, conv->y_dst, conv->kernel,
+ conv->ks, conv->kern_div, conv->callback);
+ return (void*)ret;
+}
+
+static void *v_linear_convolution(void *arg)
+{
+ struct convolution *conv = arg;
+
+ long ret;
+
+ ret = GP_FilterVLinearConvolution_Raw(conv->src, conv->x_src, conv->y_src,
+ conv->w_src, conv->h_src, conv->dst,
+ conv->x_dst, conv->y_dst, conv->kernel,
+ conv->ks, conv->kern_div, conv->callback);
+ return (void*)ret;
+}
+
+
+int GP_FilterHLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, float kern_div,
+ GP_ProgressCallback *callback)
+{
+ int t = nr_threads(w_src, h_src);
+
+ if (t == 1) {
+ return GP_FilterHLinearConvolution_Raw(src, x_src, y_src,
+ w_src, h_src,
+ dst, x_dst, y_dst,
+ kernel, kw, kern_div,
+ callback);
+ }
+
+ /* Create multithreaded safe callback on the stack */
+ struct callback_priv priv;
+ callback_priv_init(&priv, t, callback);
+ GP_ProgressCallback callback_mp = {0, progress_callback_mp, &priv};
+
+ /* Run t threads */
+ int i;
+ pthread_t threads[t];
+ struct convolution convs[t];
+ GP_Size h = h_src/t;
+
+ for (i = 0; i < t; i++) {
+ GP_Coord y_src_2 = y_src + i * h;
+ GP_Coord y_dst_2 = y_dst + i * h;
+ GP_Size h_src_2 = h;
+
+ if (i == t - 1)
+ h_src_2 = h_src - i * h;
+
+ /* Pack convolution parameters into the structure */
+ convolution_init(&convs[i], src, x_src, y_src_2, w_src, h_src_2,
+ dst, x_dst, y_dst_2, kernel, kw, kern_div,
+ callback ? &callback_mp : NULL);
+
+ pthread_create(&threads[i], NULL, h_linear_convolution, &convs[i]);
+ }
+
+ int ret = 0;
+
+ for (i = 0; i < t; i++) {
+ long r;
+
+ pthread_join(threads[i], (void*)&r);
+
+ ret |= (int)r;
+ }
+
+ callback_priv_exit(&priv);
+
+ return ret;
+}
+
+
+int GP_FilterVLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kh, float kern_div,
+ GP_ProgressCallback *callback)
+{
+ int t = nr_threads(w_src, h_src);
+
+ if (t == 1) {
+ return GP_FilterVLinearConvolution_Raw(src, x_src, y_src,
+ w_src, h_src,
+ dst, x_dst, y_dst,
+ kernel, kh, kern_div,
+ callback);
+ }
+
+ /* Create multithreaded safe callback on the stack */
+ struct callback_priv priv;
+ callback_priv_init(&priv, t, callback);
+ GP_ProgressCallback callback_mp = {0, progress_callback_mp, &priv};
+
+ int i;
+ pthread_t threads[t];
+ struct convolution convs[t];
+ GP_Size h = h_src/t;
+
+ for (i = 0; i < t; i++) {
+ GP_Coord y_src_2 = y_src + i * h;
+ GP_Coord y_dst_2 = y_dst + i * h;
+ GP_Size h_src_2 = h;
+
+ if (i == t - 1)
+ h_src_2 = h_src - i * h;
+
+ /* Pack convolution parameters into the structure */
+ convolution_init(&convs[i], src, x_src, y_src_2, w_src, h_src_2,
+ dst, x_dst, y_dst_2, kernel, kh, kern_div,
+ callback ? &callback_mp : NULL);
+
+ pthread_create(&threads[i], NULL, v_linear_convolution, &convs[i]);
+ }
+
+ int ret = 0;
+
+ for (i = 0; i < t; i++) {
+ long r;
+ pthread_join(threads[i], (void*)&r);
+
+ ret |= (int)r;
+ }
+
+ callback_priv_exit(&priv);
+
+ return ret;
+}
+
+/*
+int GP_FilterLinearConvolutionMP_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, uint32_t kh,
+ float kern_div, GP_ProgressCallback *callback)
+{
+}
+*/
-----------------------------------------------------------------------
Summary of changes:
doc/backends.txt | 58 ++++++++++++++++++++++++++++++++++++++-
libs/filters/GP_LinearThreads.c | 3 +-
2 files changed, 58 insertions(+), 3 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via 090ff9d7d97bdde4cb8daac440294a7460319f2d (commit)
from 079d90a0e58cde797f3816a793a7cdb05d18d2bc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/090ff9d7d97bdde4cb8daac440294a746031…
commit 090ff9d7d97bdde4cb8daac440294a7460319f2d
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Jul 1 21:59:03 2012 +0200
filters: GP_Linear.c: Further speedups.
Don't use uint8_t temporary array which fairly slows down
the computation, use array of int values instead.
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index b6e5983..ca5c38a 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -53,7 +53,7 @@ int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
/* Do horizontal linear convolution */
for (y = 0; y < (GP_Coord)h_src; y++) {
- uint8_t R[size], G[size], B[size];
+ int R[size], G[size], B[size];
int yi = GP_MIN(y_src + y, (int)src->h - 1);
/* Fetch the whole row */
@@ -107,7 +107,11 @@ int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
r /= ikern_div;
g /= ikern_div;
b /= ikern_div;
-
+
+ R[x] = r;
+ G[x] = g;
+ B[x] = b;
+
/* and clamp just to be extra sure */
r = GP_CLAMP(r, 0, 255);
g = GP_CLAMP(g, 0, 255);
@@ -116,7 +120,7 @@ int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
GP_PutPixel_Raw_24BPP(dst, x_dst + x, y_dst + y,
GP_Pixel_CREATE_RGB888(r, g, b));
}
-
+
if (GP_ProgressCallbackReport(callback, y, dst->h, dst->w))
return 1;
}
@@ -148,7 +152,7 @@ int GP_FilterVLinearConvolution_Raw(const GP_Context *src,
/* Do vertical linear convolution */
for (x = 0; x < (GP_Coord)w_src; x++) {
- uint8_t R[size], G[size], B[size];
+ int R[size], G[size], B[size];
int xi = GP_MIN(x_src + x, (int)src->w - 1);
/* Fetch the whole row */
-----------------------------------------------------------------------
Summary of changes:
libs/filters/GP_Linear.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via 079d90a0e58cde797f3816a793a7cdb05d18d2bc (commit)
from 43f5f45fcff837cf1f091fb9933d454e36800f3e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/079d90a0e58cde797f3816a793a7cdb05d18…
commit 079d90a0e58cde797f3816a793a7cdb05d18d2bc
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Jul 1 21:38:57 2012 +0200
doc: Update resapling docs.
diff --git a/doc/filters.txt b/doc/filters.txt
index 9d4228e..074e7d4 100644
--- a/doc/filters.txt
+++ b/doc/filters.txt
@@ -693,8 +693,8 @@ int GP_FilterConvolution(const GP_Context *src, GP_Context *dst,
GP_ProgressCallback *callback);
GP_Context *GP_FilterConvolutionAlloc(const GP_Context *src,
- const GP_FilterKernel2D *kernel,
- GP_ProgressCallback *callback);
+ const GP_FilterKernel2D *kernel,
+ GP_ProgressCallback *callback);
void GP_FilterKernel2DPrint(const GP_FilterKernel2D *kernel);
-------------------------------------------------------------------------------
@@ -854,8 +854,12 @@ Interpolation filters
#include <GP_Filters.h>
typedef enum GP_InterpolationType {
- GP_INTERP_NN, /* Nearest Neighbour */
- GP_INTERP_CUBIC, /* Bicubic */
+ GP_INTERP_NN, /* Nearest Neighbour */
+ GP_INTERP_LINEAR_INT, /* Bilinear - fixed point arithmetics */
+ GP_INTERP_LINEAR_LF_INT, /* Bilinear + low pass filter on downscaling */
+ GP_INTERP_CUBIC, /* Bicubic */
+ GP_INTERP_CUBIC_INT, /* Bicubic - fixed point arithmetics */
+ GP_INTERP_MAX = GP_INTERP_CUBIC_INT,
} GP_InterpolationType;
GP_Context *GP_FilterResize(const GP_Context *src, GP_Context *dst,
@@ -882,6 +886,14 @@ Fast, but produces "pixelated" images. May however work better for images with
sharp edges mostly consisting of big one color regions (it doesn't blur the
result on upscaling).
+Also is commonly used to show preview before you resample the image correctly.
+
+Bilinear Interpolation
+^^^^^^^^^^^^^^^^^^^^^^
+
+Bilinear is faster than bicubic interpolation and produces quite good results
+expecially the low pass variant doesn't need additional filter on downsampling.
+
Bicubic Interpolation
^^^^^^^^^^^^^^^^^^^^^
-----------------------------------------------------------------------
Summary of changes:
doc/filters.txt | 20 ++++++++++++++++----
1 files changed, 16 insertions(+), 4 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via c42e0dadc0536639298fe8d898726f565c7b2168 (commit)
from 61f49dcc7034e8eeeccf9a950d1c2731f5c9969d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/c42e0dadc0536639298fe8d898726f565c7b…
commit c42e0dadc0536639298fe8d898726f565c7b2168
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Jul 1 18:13:55 2012 +0200
doc: Update filters.txt doc.
diff --git a/doc/filters.txt b/doc/filters.txt
index eac6bff..9d4228e 100644
--- a/doc/filters.txt
+++ b/doc/filters.txt
@@ -487,23 +487,262 @@ It's defined as:
[latex, discrete_linear_convolution.png, 140]
-------------------------------------------------------------------------------
[
-O(x,y)=sum_{i=-infty}^{infty}sum_{j=-infty}^{infty}I(x-i,y-j) cdot K(i,j)
+O(x,y)=sum_{i=-infty}^{infty}sum_{j=-infty}^{infty}I(x+i,y+j) cdot K(i,j)
]
-------------------------------------------------------------------------------
The K denotes convolution kernel and in practice, due to computational
complexity, the i and j are bounded in relatively small intervals. For example
-if i and j are in (-1,1) the kernel size is 3x3.
+i and j are in (-1,1) and the kernel size is 3x3.
-Note that pixel values around the image corners are undefined. The linear
-convolution in GFXprim simply uses the corner pixel values for all pixels
-outside the image.
+Note that pixel values outside the image are undefined. The linear convolution
+in GFXprim simply uses the closest border pixel values for all pixels outside
+the image.
Particular convolution kernel is called separable if it could be decomposed
into two one dimensional kernels (these when combined yields back the original
kernel). Such convolution then could be applied as two one dimensional
convolutions which is faster operation (especially for big kernels).
+Generic Linear Convolution
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Following paragraph describes linear convolution implementation as well as a
+little of the math background skip it if you just need to use one of the
+ready-to-use filters.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <filters/GP_Linear.h>
+/* or */
+#include <GP.h>
+
+int GP_FilterLinearConvolution_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, uint32_t kh,
+ float kern_div, GP_ProgressCallback *callback);
+-------------------------------------------------------------------------------
+
+Internal generic convolution filter, this is a base for all linear convolution
+filters with non-separable kernel.
+
+The src coordinate and sizes denotes rectangle in the source context that the
+filter operates on.
+
+The dst coordinates defines offset into the dst context.
+
+The kernel is two-dimensional array of a size kw * kh indexed as
+kernel[x + y*kw].
+
+The kern_div is a coeficient that is used to divide the resuting values often
+used to normalize the result.
+
+This filter works 'in-place'.
+
+The pixel value is computed as:
+[latex, discrete_linear_convolution_alg1.png, 140]
+-------------------------------------------------------------------------------
+[
+O(x,y)={1 over kern_div} cdot sum_{i=0}^{kw - 1}sum_{j=0}^{kh - 1}
+ I(x + i - lfloor kw/2 rfloor, y + j - lfloor kh/2 rfloor)
+ cdot kernel(i,j)
+]
+-------------------------------------------------------------------------------
+
+Which is the same as:
+
+[latex, discrete_linear_convolution_alg2.png, 140]
+-------------------------------------------------------------------------------
+[
+O(x,y)={1 over kern_div} cdot
+ sum_{i=-lfloor kw/2 rfloor}^{lfloor kw/2 rfloor}
+ sum_{j=-lfloor kh/2 rfloor}^{lfloor kh/2 rfloor}
+ I(x + i, y + j)
+ cdot kernel(i + lfloor kw/2 rfloor, j + lfloor kh/2 rfloor)
+]
+-------------------------------------------------------------------------------
+
+NOTE: The number of kernel rows and columns is expected to be odd number.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <filters/GP_Linear.h>
+/* or */
+#include <GP.h>
+
+int GP_FilterHLinearConvolution_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kw, float kern_div,
+ GP_ProgressCallback *callback);
+
+int GP_FilterVLinearConvolution_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float kernel[], uint32_t kh, float kern_div,
+ GP_ProgressCallback *callback);
+
+int GP_FilterVHLinearConvolution_Raw(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ float hkernel[], uint32_t kw, float hkern_div,
+ float vkernel[], uint32_t kh, float vkern_div,
+ GP_ProgressCallback *callback);
+
+void GP_FilterKernelPrint_Raw(float kernel[], int kw, int kh, float kern_div);
+-------------------------------------------------------------------------------
+
+Internal special functions for one dimensional vertical and horizontal
+convolution these two functions are base for all separable convolution filters.
+
+The src coordinate and sizes denotes rectangle in the source context that the
+filter operates on.
+
+The dst coordinates are offset into the dst.
+
+The kernel is one-dimensional array of floats of size kw or kh.
+
+The kern_div is a coeficient that is used to divide the resuting values.
+
+The last function does both vertical and horizontal convolution and takes care
+of correct progress callback.
+
+These filters work 'in-place'.
+
+The pixel value is computed as:
+[latex, discrete_linear_1D_convolution_alg1.png, 140]
+-------------------------------------------------------------------------------
+[
+O(x,y)={1 over kern_div} cdot sum_{i=0}^{kw - 1}
+ I(x + i - lfloor kw/2 rfloor, y)
+ cdot kernel(i)
+]
+
+[
+O(x,y)={1 over kern_div} cdot sum_{j=0}^{kw - 1}
+ I(x, y + j - lfloor kh/2 rfloor)
+ cdot kernel(j)
+]
+-------------------------------------------------------------------------------
+
+Which is the same as:
+
+[latex, discrete_linear_1D_convolution_alg2.png, 140]
+-------------------------------------------------------------------------------
+[
+O(x,y)={1 over kern_div} cdot
+ sum_{i=-lfloor kw/2 rfloor}^{lfloor kw/2 rfloor}
+ I(x + i, y)
+ cdot kernel(i + lfloor kw/2 rfloor)
+]
+
+[
+O(x,y)={1 over kern_div} cdot
+ sum_{j=-lfloor kh/2 rfloor}^{lfloor kh/2 rfloor}
+ I(x, y + j)
+ cdot kernel(i, j + lfloor kh/2 rfloor)
+]
+-------------------------------------------------------------------------------
+
+NOTE: The number of kernel rows and columns is expected to be odd number.
+
+NOTE: The linear convolutions are internally implemented using integer
+ arithmetics, which works fine, but you need to take a care not to
+ overflow 32bit signed integer. If the pixel channel size is 8bit
+ long and 10bits are used for the fixed point part of the number
+ the rest must fit into about 10 bits to be safe.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <filters/GP_Convolution.h>
+/* or */
+#include <GP.h>
+
+typedef struct GP_FilterKernel2D {
+ unsigned int w;
+ unsigned int h;
+ float div;
+ float *kernel;
+} GP_FilterKernel2D;
+
+int GP_FilterConvolutionEx(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Coord h_src,
+ GP_Context *dst,
+ GP_Coord x_dst, GP_Coord y_dst,
+ const GP_FilterKernel2D *kernel,
+ GP_ProgressCallback *callback);
+
+GP_Context *GP_FilterConvolutionExAlloc(const GP_Context *src,
+ GP_Coord x_src, GP_Coord y_src,
+ GP_Size w_src, GP_Size h_src,
+ const GP_FilterKernel2D *kernel,
+ GP_ProgressCallback *callback);
+
+int GP_FilterConvolution(const GP_Context *src, GP_Context *dst,
+ const GP_FilterKernel2D *kernel,
+ GP_ProgressCallback *callback);
+
+GP_Context *GP_FilterConvolutionAlloc(const GP_Context *src,
+ const GP_FilterKernel2D *kernel,
+ GP_ProgressCallback *callback);
+
+void GP_FilterKernel2DPrint(const GP_FilterKernel2D *kernel);
+-------------------------------------------------------------------------------
+
+Linear convolution filters, you should prefferably use this API over the _Raw
+variants.
+
+The Ex variants takes a rectangle on which the filter should operate as well
+as offset into the destination. The destination must be large enough so that
+starting with offset there is at least w_dst and h_dst pixels.
+
+The kernel is a pointer to a structure initalized with the kernel size, divider
+and array of kernel values.
+
+The last function prints convolution kernel in human-readable format into the
+stdout.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <GP.h>
+
+/*
+ * Example box smoothing filter.
+ */
+static void box_smoothing(GP_Context *img)
+{
+ float box_filter[] = {
+ 1, 1, 1,
+ 1, 1, 1,
+ 1, 1, 1,
+ };
+
+ GP_FilterKernel2D box_kernel = {
+ .w = 3,
+ .h = 3,
+ .div = 9,
+ .kernel = box_filter,
+ };
+
+ GP_FilterConvolution(img, img, &box_kernel, NULL);
+}
+-------------------------------------------------------------------------------
+
+Example function that implements simple 'in-place' smoothing filter.
+
+Laplace Filter
+^^^^^^^^^^^^^^
+
[source,c]
-------------------------------------------------------------------------------
#include <GP_Filters.h>
@@ -548,6 +787,9 @@ The convolution kernel is defined as:
NOTE: This filter is not separable but could be written as a sum of two one
dimensional filters as the kernel definition suggests.
+Laplacian Edge Sharpening
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
[source,c]
-------------------------------------------------------------------------------
#include <GP_Filters.h>
@@ -585,6 +827,9 @@ image:images/edge_sharpening/lenna_small_w_0_5.png[
"Edge Sharpening w=0.5",
link="images/edge_sharpening/lenna_w_0_5.png"]
+Gaussian Blur
+^^^^^^^^^^^^^
+
[source,c]
-------------------------------------------------------------------------------
#include <GP_Filters.h>
-----------------------------------------------------------------------
Summary of changes:
doc/filters.txt | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 250 insertions(+), 5 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")