Gfxprim
Threads by month
- ----- 2026 -----
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
June 2012
- 2 participants
- 35 discussions
[repo.or.cz] gfxprim.git branch master updated: 04f9434ac9e4649dba4c394b00187a7f1004b0a4
by metan 29 Jun '12
by metan 29 Jun '12
29 Jun '12
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 04f9434ac9e4649dba4c394b00187a7f1004b0a4 (commit)
via dad06bc1a3ee9080149efdce008821be2ce64754 (commit)
via b348a1d81f3a985f258b57a467827fafbc2923d9 (commit)
from fc824cf87cc0e855dbbc14082dbd9cfd1d41045d (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/04f9434ac9e4649dba4c394b00187a7f1004…
commit 04f9434ac9e4649dba4c394b00187a7f1004b0a4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 29 22:57:13 2012 +0200
doc: Add Laplace based filter docs.
diff --git a/doc/README b/doc/README
index 8298f04..87e78a6 100644
--- a/doc/README
+++ b/doc/README
@@ -2,7 +2,7 @@ This directory contains asciidoc documentation.
The html pages are generated by typing 'make'.
-In order to do that asciidoc and source-highlight must be installed.
+In order to do that asciidoc and source-highlight, latex and dvipng must be installed.
The pdf documentation could be generated by typing 'make api.pdf' for that fop
diff --git a/doc/filters.txt b/doc/filters.txt
index 1abf977..9f6c012 100644
--- a/doc/filters.txt
+++ b/doc/filters.txt
@@ -476,6 +476,112 @@ Catch all function for symmetry filters.
Linear filters
~~~~~~~~~~~~~~
+Linear filters family consists of filters based on discrete linear
+convolution, that means that computed pixel value depends on linear
+combination of the image pixels.
+
+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)
+]
+-------------------------------------------------------------------------------
+
+The K denotes convolution kernel and in practice, due to computional
+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.
+
+Note that pixel values around the image cornes are undefined. The linear
+convolution in GFXprim simply uses the corner 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).
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <GP_Filters.h>
+/* or */
+#include <GP.h>
+
+int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback);
+
+GP_Context *GP_FilterLaplaceAlloc(const GP_Context *src,
+ GP_ProgressCallback *callback);
+-------------------------------------------------------------------------------
+
+Discrete laplace filter that produces a second derivative of the original
+image.
+
+The convolution kernel is defined as:
+
+[latex, laplacian_kernel.png, 130]
+-------------------------------------------------------------------------------
+[
+begin{bmatrix}
+0 & 1 & 0 \
+0 & -2 & 0 \
+0 & 1 & 0
+end{bmatrix}
++
+begin{bmatrix}
+0 & 0 & 0 \
+1 & -2 & 1 \
+0 & 0 & 0
+end{bmatrix}
+=
+begin{bmatrix}
+0 & 1 & 0 \
+1 & -4 & 1 \
+0 & 1 & 0
+end{bmatrix}
+]
+-------------------------------------------------------------------------------
+
+NOTE: This filter is not separable but could be written as a sum of two one
+ dimensional filters as the kernel definition suggests.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <GP_Filters.h>
+/* or */
+#include <GP.h>
+
+int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
+ float w, GP_ProgressCallback *callback);
+
+GP_Context *GP_FilterEdgeSharpeningAlloc(const GP_Context *src, float w,
+ GP_ProgressCallback *callback);
+-------------------------------------------------------------------------------
+
+Laplace based edge sharpening filter, substracts weighted second derivative
+from the original image.
+
+[latex, laplacian_edge_sharpening.png, 140]
+-------------------------------------------------------------------------------
+[
+O(x,y) = I(x,y) - w * I''(x,y)
+]
+-------------------------------------------------------------------------------
+
+.Original Image; Edge Sharpening w=0.1, w=0.3, w=0.5
+image:images/dither/lenna_small.png[
+ "Original Image",
+ link="images/dither/lenna.png"]
+image:images/edge_sharpening/lenna_small_w_0_1.png[
+ "Edge Sharpening w=0.1",
+ link="images/edge_sharpening/lenna_w_0_1.png"]
+image:images/edge_sharpening/lenna_small_w_0_3.png[
+ "Edge Sharpening w=0.5",
+ link="images/edge_sharpening/lenna_w_0_3.png"]
+image:images/edge_sharpening/lenna_small_w_0_5.png[
+ "Edge Sharpening w=0.5",
+ link="images/edge_sharpening/lenna_w_0_5.png"]
+
[source,c]
-------------------------------------------------------------------------------
#include <GP_Filters.h>
diff --git a/doc/images/edge_sharpening/lenna_small_w_0_1.png b/doc/images/edge_sharpening/lenna_small_w_0_1.png
new file mode 100644
index 0000000..848ccea
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_small_w_0_1.png differ
diff --git a/doc/images/edge_sharpening/lenna_small_w_0_3.png b/doc/images/edge_sharpening/lenna_small_w_0_3.png
new file mode 100644
index 0000000..a311e36
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_small_w_0_3.png differ
diff --git a/doc/images/edge_sharpening/lenna_small_w_0_5.png b/doc/images/edge_sharpening/lenna_small_w_0_5.png
new file mode 100644
index 0000000..46891b2
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_small_w_0_5.png differ
diff --git a/doc/images/edge_sharpening/lenna_w_0_1.png b/doc/images/edge_sharpening/lenna_w_0_1.png
new file mode 100644
index 0000000..405291f
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_w_0_1.png differ
diff --git a/doc/images/edge_sharpening/lenna_w_0_3.png b/doc/images/edge_sharpening/lenna_w_0_3.png
new file mode 100644
index 0000000..4417327
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_w_0_3.png differ
diff --git a/doc/images/edge_sharpening/lenna_w_0_5.png b/doc/images/edge_sharpening/lenna_w_0_5.png
new file mode 100644
index 0000000..0a9e7c9
Binary files /dev/null and b/doc/images/edge_sharpening/lenna_w_0_5.png differ
http://repo.or.cz/w/gfxprim.git/commit/dad06bc1a3ee9080149efdce008821be2ce6…
commit dad06bc1a3ee9080149efdce008821be2ce64754
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 29 22:54:26 2012 +0200
filters: Fix the laplace filter (it's not separable, gah)
diff --git a/include/filters/GP_Laplace.h b/include/filters/GP_Laplace.h
index e250cd6..ead7e6e 100644
--- a/include/filters/GP_Laplace.h
+++ b/include/filters/GP_Laplace.h
@@ -32,17 +32,30 @@
#include "GP_Filter.h"
/*
- * Laplace, second-derivative filter.
+ * Discrete Laplace, second-derivative filter.
+ *
+ * Implemented by separable linear convolution with kernels
+ *
+ * [1 -2 1] and [ 1 ]
+ * [-2 ]
+ * [ 1 ]
*/
int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
GP_ProgressCallback *callback);
+GP_Context *GP_FilterLaplaceAlloc(const GP_Context *src,
+ GP_ProgressCallback *callback);
+
/*
* Laplace based filter sharpening.
*
- * The w is direct weight used to multiply the result.
+ * This filter substract result of Laplace filter weigted by w from the
+ * original image which amplifies edges.
*/
int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
float w, GP_ProgressCallback *callback);
+GP_Context *GP_FilterEdgeSharpeningAlloc(const GP_Context *src, float w,
+ GP_ProgressCallback *callback);
+
#endif /* FILTERS_GP_LAPLACE_H */
diff --git a/libs/filters/GP_Laplace.c b/libs/filters/GP_Laplace.c
index 3de0a97..b6a91a1 100644
--- a/libs/filters/GP_Laplace.c
+++ b/libs/filters/GP_Laplace.c
@@ -32,30 +32,71 @@ int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
{
GP_DEBUG(1, "Laplace filter %ux%u", src->w, src->h);
- float kern[3] = {1, -2, 1};
+ float kern[9] = {0, 1, 0,
+ 1, -4, 1,
+ 0, 1, 0};
- if (GP_FilterVHLinearConvolution_Raw(src, dst, kern, 3, 1,
- kern, 3, 1, callback))
+ if (GP_FilterLinearConvolution_Raw(src, dst, kern, 3, 3, 1, callback))
return 1;
return 0;
}
+GP_Context *GP_FilterLaplaceAlloc(const GP_Context *src,
+ GP_ProgressCallback *callback)
+{
+ GP_Context *ret = GP_ContextCopy(src, 0);
+
+ if (ret == NULL)
+ return NULL;
+
+ if (GP_FilterLaplace(src, ret, callback)) {
+ GP_ContextFree(ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+
int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
float w, GP_ProgressCallback *callback)
{
- float kern[3] = {0, 1, 0};
-
+ /* Identity kernel */
+ float kern[9] = {0, 0, 0,
+ 0, 1, 0,
+ 0, 0, 0};
+
GP_DEBUG(1, "Laplace Edge Sharpening filter %ux%u w=%f",
src->w, src->h, w);
- kern[0] -= 1.00 * w;
- kern[1] -= -2.00 * w;
- kern[2] -= 1.00 * w;
+ /* Create combined kernel */
+ kern[1] -= 1.00 * w;
+ kern[3] -= 1.00 * w;
+ kern[4] -= -4.00 * w;
+ kern[5] -= 1.00 * w;
+ kern[7] -= 1.00 * w;
- if (GP_FilterVHLinearConvolution_Raw(src, dst, kern, 3, 1,
- kern, 3, 1, callback))
+ GP_FilterKernelPrint(kern, 3, 3, 1);
+
+ if (GP_FilterLinearConvolution_Raw(src, dst, kern, 3, 3, 1, callback))
return 1;
return 0;
}
+
+GP_Context *GP_FilterEdgeSharpeningAlloc(const GP_Context *src, float w,
+ GP_ProgressCallback *callback)
+{
+ GP_Context *ret = GP_ContextCopy(src, 0);
+
+ if (ret == NULL)
+ return NULL;
+
+ if (GP_FilterEdgeSharpening(src, ret, w, callback)) {
+ GP_ContextFree(ret);
+ return NULL;
+ }
+
+ return ret;
+}
http://repo.or.cz/w/gfxprim.git/commit/b348a1d81f3a985f258b57a467827fafbc29…
commit b348a1d81f3a985f258b57a467827fafbc2923d9
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 29 22:43:19 2012 +0200
filters: Added GP_FilterKernelPrint() function.
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h
index 56be135..ba286ec 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Linear.h
@@ -112,4 +112,9 @@ int GP_FilterVHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
float vkernel[], uint32_t kh, float vkern_div,
GP_ProgressCallback *callback);
+/*
+ * Prints a kernel into the stdout.
+ */
+void GP_FilterKernelPrint(float kernel[], int kw, int kh, float kern_div);
+
#endif /* FILTERS_GP_LINEAR_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 6f906b8..c84b17b 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -464,3 +464,21 @@ int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
GP_ProgressCallbackDone(callback);
return 0;
}
+
+void GP_FilterKernelPrint(float kernel[], int kw, int kh, float kern_div)
+{
+ int i, j;
+
+ for (i = 0; i < kw; i++) {
+
+ if (i == kw/2)
+ printf("% 8.2f * | ", 1/kern_div);
+ else
+ printf(" | ");
+
+ for (j = 0; j < kh; j++)
+ printf("% 8.2f ", kernel[j + i * kw]);
+
+ printf("|n");
+ }
+}
-----------------------------------------------------------------------
Summary of changes:
doc/README | 2 +-
doc/filters.txt | 106 ++++++++++++++++++++++
doc/images/edge_sharpening/lenna_small_w_0_1.png | Bin 0 -> 127188 bytes
doc/images/edge_sharpening/lenna_small_w_0_3.png | Bin 0 -> 143643 bytes
doc/images/edge_sharpening/lenna_small_w_0_5.png | Bin 0 -> 156274 bytes
doc/images/edge_sharpening/lenna_w_0_1.png | Bin 0 -> 429215 bytes
doc/images/edge_sharpening/lenna_w_0_3.png | Bin 0 -> 476119 bytes
doc/images/edge_sharpening/lenna_w_0_5.png | Bin 0 -> 514664 bytes
include/filters/GP_Laplace.h | 17 +++-
include/filters/GP_Linear.h | 5 +
libs/filters/GP_Laplace.c | 61 +++++++++++--
libs/filters/GP_Linear.c | 18 ++++
12 files changed, 196 insertions(+), 13 deletions(-)
create mode 100644 doc/images/edge_sharpening/lenna_small_w_0_1.png
create mode 100644 doc/images/edge_sharpening/lenna_small_w_0_3.png
create mode 100644 doc/images/edge_sharpening/lenna_small_w_0_5.png
create mode 100644 doc/images/edge_sharpening/lenna_w_0_1.png
create mode 100644 doc/images/edge_sharpening/lenna_w_0_3.png
create mode 100644 doc/images/edge_sharpening/lenna_w_0_5.png
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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: fc824cf87cc0e855dbbc14082dbd9cfd1d41045d
by metan 25 Jun '12
by metan 25 Jun '12
25 Jun '12
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 fc824cf87cc0e855dbbc14082dbd9cfd1d41045d (commit)
via 4f69149259b86bbd5087a7cbdd193af75950117b (commit)
from a45f634d8d10e20dae3f726ade452674f0bed6e8 (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/fc824cf87cc0e855dbbc14082dbd9cfd1d41…
commit fc824cf87cc0e855dbbc14082dbd9cfd1d41045d
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 25 11:32:37 2012 +0200
grabbers: V4L2 fix typo in YUV to RGB conversion.
diff --git a/libs/grabbers/GP_V4L2.c b/libs/grabbers/GP_V4L2.c
index 418839f..fa8a795 100644
--- a/libs/grabbers/GP_V4L2.c
+++ b/libs/grabbers/GP_V4L2.c
@@ -118,7 +118,7 @@ static void v4l2_yuv422_fillframe(struct GP_Grabber *self, void *buf)
*tmp++ = R;
*tmp++ = G;
- *tmp++ = G;
+ *tmp++ = B;
py += 2;
http://repo.or.cz/w/gfxprim.git/commit/4f69149259b86bbd5087a7cbdd193af75950…
commit 4f69149259b86bbd5087a7cbdd193af75950117b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 25 11:25:19 2012 +0200
build: Add -D_FORTIFY_SOURCE=2 into default CFLAGS.
diff --git a/configure b/configure
index 4a59e25..9721a42 100755
--- a/configure
+++ b/configure
@@ -228,7 +228,7 @@ if __name__ == '__main__':
# Dictionary for default configuration parameters
#
cfg = {'CC' : ['gcc', 'Path/name of the C compiler'],
- 'CFLAGS' : ['-W -Wall -Wextra -fPIC -O2 -ggdb', 'C compiler flags'],
+ 'CFLAGS' : ['-W -Wall -Wextra -fPIC -O2 -ggdb -D_FORTIFY_SOURCE=2', 'C compiler flags'],
'PYTHON_BIN' : ['python', 'Path/name of python interpreter'],
'SWIG' : ['swig', 'Simplified Wrapper and Interface Generator'],
'include_path': ['/usr/include', 'Path to the system headers']}
-----------------------------------------------------------------------
Summary of changes:
configure | 2 +-
libs/grabbers/GP_V4L2.c | 2 +-
2 files changed, 2 insertions(+), 2 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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: a45f634d8d10e20dae3f726ade452674f0bed6e8
by metan 22 Jun '12
by metan 22 Jun '12
22 Jun '12
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 a45f634d8d10e20dae3f726ade452674f0bed6e8 (commit)
from f874ce61275191ecdd5aae7938b0d56e368820ec (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/a45f634d8d10e20dae3f726ade452674f0be…
commit a45f634d8d10e20dae3f726ade452674f0bed6e8
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 22 00:16:13 2012 +0200
core: Fix context include.
diff --git a/libs/core/GP_Context.c b/libs/core/GP_Context.c
index 85530d1..8b66a3b 100644
--- a/libs/core/GP_Context.c
+++ b/libs/core/GP_Context.c
@@ -30,7 +30,7 @@
#include "GP_Transform.h"
#include "GP_Pixel.h"
#include "GP_GetPutPixel.h"
-#include "GP_GammaCorrection.h"
+#include "GP_Gamma.h"
#include "GP_Context.h"
#include "GP_Blit.h"
-----------------------------------------------------------------------
Summary of changes:
libs/core/GP_Context.c | 2 +-
1 files changed, 1 insertions(+), 1 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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: f874ce61275191ecdd5aae7938b0d56e368820ec
by metan 19 Jun '12
by metan 19 Jun '12
19 Jun '12
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 f874ce61275191ecdd5aae7938b0d56e368820ec (commit)
via 800afa4e6dcb7ae2bd05b5847a99824755fae03a (commit)
from 69da631cdcad26baa4ba500942f0c6d74cebff44 (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/f874ce61275191ecdd5aae7938b0d56e3688…
commit f874ce61275191ecdd5aae7938b0d56e368820ec
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Jun 19 20:58:21 2012 +0200
grabbers: Introduce grabbers library and V4L2 grabber.
diff --git a/configure b/configure
index bd08e4b..4a59e25 100755
--- a/configure
+++ b/configure
@@ -188,7 +188,7 @@ def write_config_mk(cfg, libs):
# Generate app compilation helper
#
def write_gfxprim_config(cfg, libs):
- modules = ['loaders', 'backends']
+ modules = ['loaders', 'backends', 'grabbers']
f = open('gfxprim-config', 'w')
f.write('#!/bin/shn'
@@ -212,6 +212,8 @@ def write_gfxprim_config(cfg, libs):
ldflags = ''
if i == 'backends':
ldflags += '-lGP_backends '
+ if i == 'grabbers':
+ ldflags += '-lGP_grabbers '
ldflags += libs.get_linker_flags(i)
f.write('t--libs-%s) echo -n "%s ";;n' % (i, ldflags))
@@ -253,7 +255,10 @@ if __name__ == '__main__':
[header_exists, "X11/Xlib.h"], "", "-lX11", ["backends"]],
["freetype",
"A high-quality and portable font engine",
- [header_exists, "ft2build.h"], "", "`freetype-config --libs`", ["core"]]], cfg)
+ [header_exists, "ft2build.h"], "", "`freetype-config --libs`", ["core"]],
+ ["V4L2",
+ "Video for linux 2",
+ [header_exists, "linux/videodev2.h"], "", "", ["grabbers"]]], cfg)
parser = OptionParser();
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile
index 6e3b7d7..2107993 100644
--- a/demos/c_simple/Makefile
+++ b/demos/c_simple/Makefile
@@ -6,7 +6,11 @@ INCLUDE=
LDLIBS+=-lGP -lGP_backends -lSDL -L$(TOPDIR)/build/
APPS=backend_example loaders_example loaders filters_symmetry gfx_koch- virtual_backend_example meta_data meta_data_dump tmp_file showimage
+ virtual_backend_example meta_data meta_data_dump tmp_file showimage+ v4l2_show v4l2_grab
+
+v4l2_show: LDLIBS+=-lGP_grabbers
+v4l2_grab: LDLIBS+=-lGP_grabbers
include $(TOPDIR)/pre.mk
include $(TOPDIR)/app.mk
diff --git a/demos/c_simple/v4l2_grab.c b/demos/c_simple/v4l2_grab.c
new file mode 100644
index 0000000..7aa8469
--- /dev/null
+++ b/demos/c_simple/v4l2_grab.c
@@ -0,0 +1,141 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ Gets an image from v4l2 device.
+
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include <GP.h>
+
+static int get_image(const char *filename, GP_Grabber *grabber)
+{
+ /* turn on grabber */
+ if (GP_GrabberStart(grabber)) {
+ fprintf(stderr, "Failed to start grabbern");
+ return 1;
+ }
+
+ /* throw away first frame, it's usually wrong */
+ while (!GP_GrabberPoll(grabber))
+ usleep(100000);
+
+ while (!GP_GrabberPoll(grabber))
+ usleep(100000);
+
+ /* save image */
+ if (GP_SaveJPG(grabber->frame, filename, NULL)) {
+ fprintf(stderr, "Failed to save image '%s': %s",
+ filename, strerror(errno));
+ return 1;
+ }
+
+ /* turn off grabber */
+ if (GP_GrabberStop(grabber)) {
+ fprintf(stderr, "Failed to start grabbern");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ const char *v4l2_device = "/dev/video0";
+ const char *image_filename = "frame.jpg";
+ unsigned int w = 640, h = 480;
+ int secs = 0;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "d:hH:o:W:l:s:")) != -1) {
+ switch (opt) {
+ case 'o':
+ image_filename = optarg;
+ break;
+ case 'd':
+ v4l2_device = optarg;
+ break;
+ case 'W':
+ w = atoi(optarg);
+ break;
+ case 'H':
+ h = atoi(optarg);
+ break;
+ case 's':
+ secs = atoi(optarg);
+ break;
+ case 'l':
+ GP_SetDebugLevel(atoi(optarg));
+ break;
+ case 'h':
+ printf("Usage; %s optsn", argv[0]);
+ printf("-o output image file, default is 'frame.jpg'n"
+ "-d v4l2 device name (default is '/dev/video0'n"
+ "-W output image width, default is 640n"
+ "-H output image height, default is 480n"
+ "-l sets GFXprim debug level (default is 0)n"
+ "-s take image every s seconds (the images are stored as frameX.jpg)n"
+ "-h prints this helpn");
+ return 0;
+ break;
+ default:
+ fprintf(stderr, "Invalid paramter '%c'n", opt);
+ return 1;
+ }
+ }
+
+ GP_Grabber *grabber = GP_GrabberV4L2Init(v4l2_device, w, h);
+
+ if (grabber == NULL) {
+ fprintf(stderr, "Failed to initalize grabber '%s': %sn",
+ v4l2_device, strerror(errno));
+ return 1;
+ }
+
+ if (secs == 0) {
+ get_image(image_filename, grabber);
+ GP_GrabberExit(grabber);
+ return 0;
+ }
+
+ int i = 0;
+
+ for (;;) {
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "frame%03i.jpg", i++);
+
+ if (get_image(buf, grabber)) {
+ fprintf(stderr, "Failed to get image, exitting...n");
+ return 1;
+ }
+
+ sleep(secs);
+ }
+
+
+ return 0;
+}
diff --git a/demos/c_simple/v4l2_show.c b/demos/c_simple/v4l2_show.c
new file mode 100644
index 0000000..077ba7b
--- /dev/null
+++ b/demos/c_simple/v4l2_show.c
@@ -0,0 +1,162 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ Simple V4L2 grabber interactive example.
+
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include <GP.h>
+#include <backends/GP_X11.h>
+
+int main(int argc, char *argv[])
+{
+ GP_Backend *backend;
+ GP_Grabber *grabber;
+ const char *v4l2_device = "/dev/video0";
+ unsigned int w = 320, h = 240;
+ int mode = 0;
+ int opt;
+
+ /* Turn on debug messages */
+ //GP_SetDebugLevel(10);
+
+ while ((opt = getopt(argc, argv, "d:hH:W:l:")) != -1) {
+ switch (opt) {
+ case 'd':
+ v4l2_device = optarg;
+ break;
+ case 'W':
+ w = atoi(optarg);
+ break;
+ case 'H':
+ h = atoi(optarg);
+ break;
+ case 'l':
+ GP_SetDebugLevel(atoi(optarg));
+ break;
+ case 'h':
+ printf("Usage; %s optsn", argv[0]);
+ printf("-d v4l2 device name (default is '/dev/video0'n"
+ "-W output image width, default is 640n"
+ "-H output image height, default is 480n"
+ "-l sets GFXprim debug level (default is 0)n"
+ "-h prints this helpn");
+ return 0;
+ break;
+ default:
+ fprintf(stderr, "Invalid paramter '%c'n", opt);
+ return 1;
+ }
+ }
+
+ grabber = GP_GrabberV4L2Init(v4l2_device, w, h);
+
+ if (grabber == NULL) {
+ fprintf(stderr, "Failed to initalize grabber '%s': %sn",
+ v4l2_device, strerror(errno));
+ return 1;
+ }
+
+ backend = GP_BackendX11Init(NULL, 0, 0, grabber->frame->w,
+ grabber->frame->h, "V4L2", 0);
+
+ if (backend == NULL) {
+ GP_GrabberExit(grabber);
+ return 1;
+ }
+
+ if (GP_GrabberStart(grabber)) {
+ fprintf(stderr, "Failed to start grabbern");
+ GP_BackendExit(backend);
+ GP_GrabberExit(grabber);
+ return 1;
+ }
+
+ printf("Press SPACE to change mode and Q to exit.n");
+
+ for (;;) {
+ if (GP_GrabberPoll(grabber) > 0) {
+ GP_Context *res, *img = grabber->frame;
+
+ switch (mode) {
+ case 0:
+ res = img;
+ break;
+ case 1:
+ GP_FilterEdgePrewitt(img, &res, NULL, NULL);
+ break;
+ case 2:
+ GP_FilterGaussianBlur(img, img, 1, 1, NULL);
+ res = GP_FilterFloydSteinberg_RGB888_Alloc(img, GP_PIXEL_G2, NULL);
+ break;
+ }
+
+ GP_Blit_Clipped(res, 0, 0, res->w, res->h, backend->context, 0, 0);
+ GP_BackendFlip(backend);
+
+ if (mode)
+ GP_ContextFree(res);
+ }
+
+ usleep(1000);
+
+ GP_BackendPoll(backend);
+
+ /* Read and parse events */
+ GP_Event ev;
+
+ while (GP_EventGet(&ev)) {
+ switch (ev.type) {
+ case GP_EV_KEY:
+
+ /* ignore key up events */
+ if (!ev.code)
+ continue;
+
+ switch (ev.val.key.key) {
+ case GP_KEY_ESC:
+ case GP_KEY_Q:
+ GP_BackendExit(backend);
+ GP_GrabberExit(grabber);
+ return 0;
+ break;
+ case GP_KEY_SPACE:
+
+ mode++;
+
+ if (mode > 2)
+ mode = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ GP_BackendExit(backend);
+
+ return 0;
+}
diff --git a/include/GP.h b/include/GP.h
index b01e512..4b622e6 100644
--- a/include/GP.h
+++ b/include/GP.h
@@ -47,4 +47,7 @@
/* bitmap filters */
#include "filters/GP_Filters.h"
+/* grabbers */
+#include "grabbers/GP_Grabbers.h"
+
#endif /* GP_H */
diff --git a/include/GP.h b/include/grabbers/GP_Grabber.h
similarity index 58%
copy from include/GP.h
copy to include/grabbers/GP_Grabber.h
index b01e512..5591297 100644
--- a/include/GP.h
+++ b/include/grabbers/GP_Grabber.h
@@ -16,35 +16,75 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos *
- * <jiri.bluebear.dluhos(a)gmail.com> *
- * *
* Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
-#ifndef GP_H
-#define GP_H
+#ifndef GP_GRABBERS_GRABBER_H
+#define GP_GRABBERS_GRABBER_H
+
+struct GP_Context;
+
+typedef struct GP_Grabber {
+ /*
+ * Context with current frame.
+ */
+ struct GP_Context *frame;
+
+ /*
+ * Returns 0 if there are no images in queue and 1 otherwise.
+ */
+ int (*Poll)(struct GP_Grabber *self);
+
+ /*
+ * Grabber fd, may be set -1 if grabber doesn't have one.
+ */
+ int fd;
+
+ /*
+ * Starts the actuall grabbing. May be NULL if not needed.
+ */
+ int (*Start)(struct GP_Grabber *self);
+
+ /*
+ * Stops the grabbing. May be NULL if not needed.
+ */
+ int (*Stop)(struct GP_Grabber *self);
-/* library core */
-#include "core/GP_Core.h"
+ /*
+ * Exit functions. Closes fd, frees memory.
+ */
+ void (*Exit)(struct GP_Grabber *self);
-/* public drawing API */
-#include "gfx/GP_Gfx.h"
+ char priv[];
+} GP_Grabber;
-/* fonts and text drawing */
-#include "text/GP_Text.h"
+#define GP_GRABBER_PRIV(grabber) ((void*)(grabber)->priv)
-/* backends */
-#include "backends/GP_Backend.h"
+static inline void GP_GrabberExit(struct GP_Grabber *self)
+{
+ self->Exit(self);
+}
-/* input and events */
-#include "input/GP_Input.h"
+static inline int GP_GrabberPoll(struct GP_Grabber *self)
+{
+ return self->Poll(self);
+}
-/* bitmap loaders */
-#include "loaders/GP_Loaders.h"
+static inline int GP_GrabberStart(struct GP_Grabber *self)
+{
+ if (self->Start)
+ return self->Start(self);
+
+ return 0;
+}
-/* bitmap filters */
-#include "filters/GP_Filters.h"
+static inline int GP_GrabberStop(struct GP_Grabber *self)
+{
+ if (self->Stop)
+ return self->Stop(self);
+
+ return 0;
+}
-#endif /* GP_H */
+#endif /* GP_GRABBERS_GRABBER_H */
diff --git a/include/GP.h b/include/grabbers/GP_Grabbers.h
similarity index 72%
copy from include/GP.h
copy to include/grabbers/GP_Grabbers.h
index b01e512..d305edf 100644
--- a/include/GP.h
+++ b/include/grabbers/GP_Grabbers.h
@@ -16,35 +16,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos *
- * <jiri.bluebear.dluhos(a)gmail.com> *
- * *
* Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
-#ifndef GP_H
-#define GP_H
-
-/* library core */
-#include "core/GP_Core.h"
-
-/* public drawing API */
-#include "gfx/GP_Gfx.h"
-
-/* fonts and text drawing */
-#include "text/GP_Text.h"
-
-/* backends */
-#include "backends/GP_Backend.h"
-
-/* input and events */
-#include "input/GP_Input.h"
-
-/* bitmap loaders */
-#include "loaders/GP_Loaders.h"
+#ifndef GP_GRABBERS_GRABBERS_H
+#define GP_GRABBERS_GRABBERS_H
-/* bitmap filters */
-#include "filters/GP_Filters.h"
+#include "grabbers/GP_Grabber.h"
+#include "grabbers/GP_V4L2.h"
-#endif /* GP_H */
+#endif /* GP_GRABBERS_GRABBERS_H */
diff --git a/include/GP.h b/include/grabbers/GP_V4L2.h
similarity index 72%
copy from include/GP.h
copy to include/grabbers/GP_V4L2.h
index b01e512..aa6bf08 100644
--- a/include/GP.h
+++ b/include/grabbers/GP_V4L2.h
@@ -16,35 +16,23 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos *
- * <jiri.bluebear.dluhos(a)gmail.com> *
- * *
* Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
-#ifndef GP_H
-#define GP_H
-
-/* library core */
-#include "core/GP_Core.h"
-
-/* public drawing API */
-#include "gfx/GP_Gfx.h"
-
-/* fonts and text drawing */
-#include "text/GP_Text.h"
-
-/* backends */
-#include "backends/GP_Backend.h"
-
-/* input and events */
-#include "input/GP_Input.h"
+#ifndef GP_GRABBERS_V4L2_H
+#define GP_GRABBERS_V4L2_H
-/* bitmap loaders */
-#include "loaders/GP_Loaders.h"
+struct GP_Grabber;
-/* bitmap filters */
-#include "filters/GP_Filters.h"
+/*
+ * Create V4L2 grabber.
+ *
+ * The prefered_width and height may not be used if driver does support only
+ * fixed image size.
+ */
+struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
+ unsigned int prefered_width,
+ unsigned int prefered_height);
-#endif /* GP_H */
+#endif /* GP_GRABBERS_V4L2_H */
diff --git a/libs/Makefile b/libs/Makefile
index 01fbd7a..5fe3d19 100644
--- a/libs/Makefile
+++ b/libs/Makefile
@@ -1,3 +1,3 @@
TOPDIR=..
-SUBDIRS=core gfx text loaders filters input backends SDL
+SUBDIRS=core gfx text loaders filters input backends grabbers SDL
include $(TOPDIR)/post.mk
diff --git a/libs/grabbers/GP_V4L2.c b/libs/grabbers/GP_V4L2.c
new file mode 100644
index 0000000..418839f
--- /dev/null
+++ b/libs/grabbers/GP_V4L2.c
@@ -0,0 +1,434 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ Based on V4L2 example code.
+
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <stdint.h>
+
+#include "core/GP_Context.h"
+
+#include "core/GP_Debug.h"
+
+#include "../../config.h"
+
+#ifdef HAVE_V4L2
+
+#include <linux/videodev2.h>
+
+#include "GP_Grabber.h"
+#include "GP_V4L2.h"
+
+struct v4l2_priv {
+ int mode;
+
+ /* pointer to page aligned user buffer */
+ void *bufptr[4];
+ size_t buf_len[4];
+
+ char device[];
+};
+
+static int v4l2_stop(struct GP_Grabber *self);
+
+static void v4l2_exit(struct GP_Grabber *self)
+{
+ struct v4l2_priv *priv = GP_GRABBER_PRIV(self);
+ int i;
+
+ GP_DEBUG(1, "Grabber '%s' exitting", priv->device);
+
+ v4l2_stop(self);
+
+ if (priv->mode == 2) {
+ for (i = 0; i < 4; i++)
+ munmap(priv->bufptr[i], priv->buf_len[i]);
+ }
+
+ close(self->fd);
+ GP_ContextFree(self->frame);
+ free(self);
+}
+
+#define CLAMP(x, max) + if (x > max) + x = max; + if (x < 0) + x = 0; +
+#define MUL 1024
+
+static void v4l2_yuv422_fillframe(struct GP_Grabber *self, void *buf)
+{
+ unsigned int i, j;
+ unsigned char *py, *pu, *pv;
+ unsigned char *tmp = self->frame->pixels;
+
+ py = buf;
+ pu = buf + 1;
+ pv = buf + 3;
+
+ for (i = 0; i < self->frame->h; i++) {
+ for (j = 0; j < self->frame->w; j++) {
+ int32_t PU = ((int32_t)*pu) - 128;
+ int32_t PV = ((int32_t)*pv) - 128;
+
+ int32_t R = MUL * (*py) + ((int32_t)(MUL * 1.772)) * PU;
+ int32_t G = MUL * (*py) - ((int32_t)(MUL * 0.344)) * PU
+ - ((int32_t)(MUL * 0.714)) * PV;
+ int32_t B = MUL * (*py) + ((int32_t)(MUL * 1.402)) * PV;
+
+ R = (R + MUL/2)/MUL;
+ G = (G + MUL/2)/MUL;
+ B = (B + MUL/2)/MUL;
+
+ CLAMP(R, 255);
+ CLAMP(G, 255);
+ CLAMP(B, 255);
+
+ *tmp++ = R;
+ *tmp++ = G;
+ *tmp++ = G;
+
+ py += 2;
+
+ if ((j & 1) == 1) {
+ pu += 4;
+ pv += 4;
+ }
+ }
+ }
+}
+
+static int v4l2_poll(struct GP_Grabber *self)
+{
+ struct v4l2_priv *priv = GP_GRABBER_PRIV(self);
+
+ GP_DEBUG(3, "Grabber '%s' poll", priv->device);
+
+ /* read/write interface */
+ if (priv->mode == 1) {
+ GP_WARN("Read/write I/O not implemented.");
+ return 0;
+ }
+
+ /* mmaped interface */
+ struct v4l2_buffer buf;
+
+ memset(&buf, 0, sizeof(buf));
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+
+ if (ioctl(self->fd, VIDIOC_DQBUF, &buf)) {
+ switch (errno) {
+ case EAGAIN:
+ return 0;
+ default:
+ GP_WARN("Failed to ioctl VIDIOC_DQBUF on '%s' : %s",
+ priv->device, strerror(errno));
+ return 0;
+ }
+ }
+
+ if (buf.index >= 4) {
+ GP_WARN("Got invalid buffer index on '%s'", priv->device);
+ return 0;
+ }
+
+ v4l2_yuv422_fillframe(self, priv->bufptr[buf.index]);
+
+ if (ioctl(self->fd, VIDIOC_QBUF, &buf)) {
+ GP_WARN("Failed to ioctl VIDIOC_QBUF on '%s' : %s",
+ priv->device, strerror(errno));
+ }
+
+ return 1;
+}
+
+static int v4l2_start(struct GP_Grabber *self)
+{
+ struct v4l2_priv *priv = GP_GRABBER_PRIV(self);
+
+ /* read/write interface */
+ if (priv->mode == 1)
+ return 0;
+
+ /* mmap interface */
+ int i;
+ struct v4l2_buffer buf;
+ memset(&buf, 0, sizeof(buf));
+
+ for (i = 0; i < 4; i++) {
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+
+ if (ioctl(self->fd, VIDIOC_QBUF, &buf)) {
+ GP_WARN("Failed to ioclt VIDIOC_QBUF on '%s': %s",
+ priv->device, strerror(errno));
+ return 1;
+ }
+ }
+
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (ioctl(self->fd, VIDIOC_STREAMON, &type)) {
+ GP_WARN("Failed to ioclt VIDIOC_STREAMON on '%s': %s",
+ priv->device, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+static int v4l2_stop(struct GP_Grabber *self)
+{
+ struct v4l2_priv *priv = GP_GRABBER_PRIV(self);
+
+ /* read/write interface */
+ if (priv->mode == 1)
+ return 0;
+
+ /* mmap interface */
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (ioctl(self->fd, VIDIOC_STREAMOFF, &type)) {
+ GP_WARN("Failed to ioclt VIDIOC_STREAMON on '%s': %s",
+ priv->device, strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
+
+struct GP_Grabber *GP_GrabberV4L2Init(const char *device,
+ unsigned int prefered_width,
+ unsigned int prefered_height)
+{
+ int fd, i, err;
+ int mode = 0;
+
+ GP_DEBUG(1, "Opening V4L2 grabber '%s'", device);
+
+ fd = open(device, O_RDWR | O_NONBLOCK);
+
+ if (fd < 0) {
+ err = errno;
+ GP_WARN("Failed to open V4L2 grabber '%s'", device);
+ goto err;
+ }
+
+ struct v4l2_capability cap;
+
+ if (ioctl(fd, VIDIOC_QUERYCAP, &cap)) {
+ err = errno;
+ GP_WARN("ioctl VIDIOC_QUERYCAP failed, '%s' not V4L2 device?",
+ device);
+ goto err0;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ err = ENOSYS;
+ GP_WARN("Device '%s' has no capture capability", device);
+ goto err0;
+ }
+
+
+ if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
+ GP_DEBUG(1, "Device '%s' doesn't support read write I/O", device);
+ } else {
+ mode = 1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ GP_DEBUG(1, "Device '%s' doesn't support streaming I/O", device);
+ } else {
+ mode = 2;
+ }
+
+ if (mode == 0) {
+ err = ENOSYS;
+ GP_WARN("No suitable mode found for '%s'", device);
+ goto err0;
+ }
+
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+
+ memset(&cropcap, 0, sizeof(cropcap));
+
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (ioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0) {
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ /* reset to default */
+ crop.c = cropcap.defrect;
+
+ if (ioctl(fd, VIDIOC_S_CROP, &crop)) {
+ /* error/cropping not supported */
+ }
+
+ } else {
+ /* errors ignored? */
+ }
+
+ struct v4l2_format fmt;
+
+ 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.pixelformat = V4L2_PIX_FMT_YUYV;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ if (ioctl(fd, VIDIOC_S_FMT, &fmt)) {
+ err = errno;
+ GP_WARN("Failed to set video format for device '%s'", device);
+ goto err0;
+ }
+
+ GP_Grabber *new = malloc(sizeof(GP_Grabber) + sizeof(struct v4l2_priv) + strlen(device) + 1);
+
+ if (new == NULL) {
+ err = ENOMEM;
+ GP_WARN("Malloc failed :(");
+ goto err0;
+ }
+
+ new->frame = GP_ContextAlloc(fmt.fmt.pix.width, fmt.fmt.pix.height, GP_PIXEL_RGB888);
+
+ if (new->frame == NULL) {
+ err = ENOMEM;
+ goto err1;
+ }
+
+ struct v4l2_priv *priv = GP_GRABBER_PRIV(new);
+
+ strcpy(priv->device, device);
+ priv->mode = mode;
+
+ switch (mode) {
+ case 1:
+ break;
+ case 2: {
+ /* setup mmap interface */
+ struct v4l2_requestbuffers req;
+
+ memset(&req, 0, sizeof(req));
+
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ if (ioctl(fd, VIDIOC_REQBUFS, &req)) {
+ err = errno;
+ GP_WARN("Failed to ioctl VIDIOC_REQBUFS on '%s' : %s",
+ device, strerror(errno));
+ goto err2;
+ }
+
+ if (req.count != 4) {
+ err = ENOSYS;
+ GP_WARN("Unexpected number of buffers on '%s'", device);
+ goto err2;
+ }
+
+ struct v4l2_buffer buf;
+ memset(&buf, 0, sizeof(buf));
+
+ priv->bufptr[0] = NULL;
+ priv->bufptr[1] = NULL;
+ priv->bufptr[2] = NULL;
+ priv->bufptr[3] = NULL;
+
+ for (i = 0; i < 4; i++) {
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = i;
+
+ if (ioctl(fd, VIDIOC_QUERYBUF, &buf)) {
+ err = errno;
+ GP_WARN("Failed to ioclt VIDIOC_QUERYBUF on '%s': %s",
+ device, strerror(errno));
+ goto err2;
+ }
+
+ priv->bufptr[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
+ priv->buf_len[i] = buf.length;
+
+ if (priv->bufptr[i] == MAP_FAILED) {
+ err = errno;
+ GP_WARN("mmap failed on '%s': %s", device, strerror(errno));
+ goto err3;
+ }
+ }
+ } break;
+ }
+
+ new->fd = fd;
+ new->Exit = v4l2_exit;
+ new->Poll = v4l2_poll;
+ new->Start = v4l2_start;
+ new->Stop = v4l2_stop;
+
+ return new;
+err3:
+ for (i = 0; i < 4; i++)
+ if (priv->bufptr[i] != NULL)
+ munmap(priv->bufptr[i], priv->buf_len[i]);
+err2:
+ GP_ContextFree(new->frame);
+err1:
+ free(new);
+err0:
+ close(fd);
+err:
+ errno = err;
+ return NULL;
+}
+
+#else
+
+struct GP_Grabber *GP_GrabberV4L2Init(const char GP_UNUSED(*device),
+ unsigned int GP_UNUSED(prefered_width),
+ unsigned int GP_UNUSED(prefered_height))
+{
+ GP_WARN("V4L2 support not compiled in.");
+
+ errno = ENOSYS;
+ return NULL;
+}
+
+#endif /* HAVE_V4L2 */
diff --git a/libs/grabbers/Makefile b/libs/grabbers/Makefile
new file mode 100644
index 0000000..4df5769
--- /dev/null
+++ b/libs/grabbers/Makefile
@@ -0,0 +1,8 @@
+TOPDIR=../..
+CSOURCES=$(shell ls *.c)
+LIBNAME=grabbers
+BUILDLIB=yes
+
+include $(TOPDIR)/pre.mk
+include $(TOPDIR)/lib.mk
+include $(TOPDIR)/post.mk
http://repo.or.cz/w/gfxprim.git/commit/800afa4e6dcb7ae2bd05b5847a99824755fa…
commit 800afa4e6dcb7ae2bd05b5847a99824755fae03a
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Jun 19 18:36:07 2012 +0200
pywrap: filters: Fix warning.
diff --git a/pylib/gfxprim/filters/filters.i b/pylib/gfxprim/filters/filters.i
index abcb96d..e321b1a 100644
--- a/pylib/gfxprim/filters/filters.i
+++ b/pylib/gfxprim/filters/filters.i
@@ -3,6 +3,7 @@
%{
#include "filters/GP_Filters.h"
+#include "core/GP_Debug.h"
%}
%import ../core/core.i
-----------------------------------------------------------------------
Summary of changes:
configure | 9 +-
demos/c_simple/Makefile | 6 +-
demos/c_simple/v4l2_grab.c | 141 +++++++
.../particle_demo.c => c_simple/v4l2_show.c} | 161 ++++----
include/GP.h | 3 +
.../loaders.c => include/grabbers/GP_Grabber.h | 105 +++---
.../{input/GP_Input.h => grabbers/GP_Grabbers.h} | 12 +-
.../GP_InputDriverKBD.h => grabbers/GP_V4L2.h} | 20 +-
libs/Makefile | 2 +-
libs/grabbers/GP_V4L2.c | 434 ++++++++++++++++++++
libs/{backends => grabbers}/Makefile | 2 +-
pylib/gfxprim/filters/filters.i | 1 +
12 files changed, 749 insertions(+), 147 deletions(-)
create mode 100644 demos/c_simple/v4l2_grab.c
copy demos/{particle/particle_demo.c => c_simple/v4l2_show.c} (53%)
copy demos/c_simple/loaders.c => include/grabbers/GP_Grabber.h (59%)
copy include/{input/GP_Input.h => grabbers/GP_Grabbers.h} (91%)
copy include/{input/GP_InputDriverKBD.h => grabbers/GP_V4L2.h} (80%)
create mode 100644 libs/grabbers/GP_V4L2.c
copy libs/{backends => grabbers}/Makefile (88%)
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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: 69da631cdcad26baa4ba500942f0c6d74cebff44
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 69da631cdcad26baa4ba500942f0c6d74cebff44 (commit)
from ed37eafd478e7e915aaa44fb1ab0d5e412fd86d4 (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/69da631cdcad26baa4ba500942f0c6d74ceb…
commit 69da631cdcad26baa4ba500942f0c6d74cebff44
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 19:58:22 2012 +0200
filters: Add Laplace filter and Laplace based Edge Sharpening.
diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Filters.h
index d00a852..92ce03a 100644
--- a/include/filters/GP_Filters.h
+++ b/include/filters/GP_Filters.h
@@ -56,4 +56,7 @@
/* Bitmap dithering */
#include "filters/GP_Dither.h"
+/* Laplace based filters */
+#include "filters/GP_Laplace.h"
+
#endif /* GP_FILTERS_H */
diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Laplace.h
similarity index 62%
copy from include/filters/GP_Filters.h
copy to include/filters/GP_Laplace.h
index d00a852..e250cd6 100644
--- a/include/filters/GP_Filters.h
+++ b/include/filters/GP_Laplace.h
@@ -16,44 +16,33 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
- * <jiri.bluebear.dluhos(a)gmail.com> *
- * *
- * Copyright (C) 2009-2011 Cyril Hrubis <metan(a)ucw.cz> *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
/*
- GP_Context filters.
+ Laplace filter and Laplace-based filters.
*/
-#ifndef GP_FILTERS_H
-#define GP_FILTERS_H
-
-/* Filter per channel parameter passing interface */
-#include "filters/GP_FilterParam.h"
-
-/* Point filters, brightness, contrast ... */
-#include "filters/GP_Point.h"
-
-/* Addition, difference, min, max ... */
-#include "filters/GP_Arithmetic.h"
-
-/* Histograms, ... */
-#include "filters/GP_Stats.h"
+#ifndef FILTERS_GP_LAPLACE_H
+#define FILTERS_GP_LAPLACE_H
-/* Image rotations (90 180 270 grads) and mirroring */
-#include "filters/GP_Rotate.h"
+#include "GP_Filter.h"
-/* Linear convolution based filters (mostly blurs) */
-#include "filters/GP_Linear.h"
-
-/* Image scaling (resampling) */
-#include "filters/GP_Resize.h"
+/*
+ * Laplace, second-derivative filter.
+ */
+int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback);
-/* Bitmap dithering */
-#include "filters/GP_Dither.h"
+/*
+ * Laplace based filter sharpening.
+ *
+ * The w is direct weight used to multiply the result.
+ */
+int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
+ float w, GP_ProgressCallback *callback);
-#endif /* GP_FILTERS_H */
+#endif /* FILTERS_GP_LAPLACE_H */
diff --git a/include/filters/GP_Filters.h b/libs/filters/GP_Laplace.c
similarity index 62%
copy from include/filters/GP_Filters.h
copy to libs/filters/GP_Laplace.c
index d00a852..3de0a97 100644
--- a/include/filters/GP_Filters.h
+++ b/libs/filters/GP_Laplace.c
@@ -16,44 +16,46 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
- * <jiri.bluebear.dluhos(a)gmail.com> *
- * *
- * Copyright (C) 2009-2011 Cyril Hrubis <metan(a)ucw.cz> *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
-/*
-
- GP_Context filters.
+#include "core/GP_Debug.h"
+#include "core/GP_GetPutPixel.h"
- */
+#include "GP_Linear.h"
-#ifndef GP_FILTERS_H
-#define GP_FILTERS_H
+#include "GP_Laplace.h"
-/* Filter per channel parameter passing interface */
-#include "filters/GP_FilterParam.h"
+int GP_FilterLaplace(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback)
+{
+ GP_DEBUG(1, "Laplace filter %ux%u", src->w, src->h);
-/* Point filters, brightness, contrast ... */
-#include "filters/GP_Point.h"
+ float kern[3] = {1, -2, 1};
-/* Addition, difference, min, max ... */
-#include "filters/GP_Arithmetic.h"
+ if (GP_FilterVHLinearConvolution_Raw(src, dst, kern, 3, 1,
+ kern, 3, 1, callback))
+ return 1;
-/* Histograms, ... */
-#include "filters/GP_Stats.h"
+ return 0;
+}
-/* Image rotations (90 180 270 grads) and mirroring */
-#include "filters/GP_Rotate.h"
+int GP_FilterEdgeSharpening(const GP_Context *src, GP_Context *dst,
+ float w, GP_ProgressCallback *callback)
+{
+ float kern[3] = {0, 1, 0};
-/* Linear convolution based filters (mostly blurs) */
-#include "filters/GP_Linear.h"
+ GP_DEBUG(1, "Laplace Edge Sharpening filter %ux%u w=%f",
+ src->w, src->h, w);
-/* Image scaling (resampling) */
-#include "filters/GP_Resize.h"
+ kern[0] -= 1.00 * w;
+ kern[1] -= -2.00 * w;
+ kern[2] -= 1.00 * w;
-/* Bitmap dithering */
-#include "filters/GP_Dither.h"
+ if (GP_FilterVHLinearConvolution_Raw(src, dst, kern, 3, 1,
+ kern, 3, 1, callback))
+ return 1;
-#endif /* GP_FILTERS_H */
+ return 0;
+}
-----------------------------------------------------------------------
Summary of changes:
include/filters/GP_Filters.h | 3 +
.../GP_Backends.h => filters/GP_Laplace.h} | 28 ++++-----
libs/{text/GP_Font.c => filters/GP_Laplace.c} | 61 +++++++++-----------
3 files changed, 43 insertions(+), 49 deletions(-)
copy include/{backends/GP_Backends.h => filters/GP_Laplace.h} (75%)
copy libs/{text/GP_Font.c => filters/GP_Laplace.c} (66%)
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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: ed37eafd478e7e915aaa44fb1ab0d5e412fd86d4
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 ed37eafd478e7e915aaa44fb1ab0d5e412fd86d4 (commit)
via d9fe7ce7722c160fdcd2978e893bd9889a292163 (commit)
from ee9f5789995fbcd567bc45c4cbf615956e58ce90 (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/ed37eafd478e7e915aaa44fb1ab0d5e412fd…
commit ed37eafd478e7e915aaa44fb1ab0d5e412fd86d4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 18:31:08 2012 +0200
filters: Experimental Edge detection code.
diff --git a/libs/filters/GP_Edge.c b/libs/filters/GP_Edge.c
new file mode 100644
index 0000000..4f73c52
--- /dev/null
+++ b/libs/filters/GP_Edge.c
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * 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 <math.h>
+
+#include "core/GP_Debug.h"
+#include "core/GP_GetPutPixel.h"
+
+#include "GP_Linear.h"
+
+/*
+ * Apply prewitt operator.
+ */
+static int prewitt(const GP_Context *src, GP_Context *dx, GP_Context *dy,
+ GP_ProgressCallback *callback)
+{
+ float smooth_kern[3] = {1, 1, 1,};
+ float grad_kern[3] = {-1, 0, 1};
+
+ if (GP_FilterVHLinearConvolution_Raw(src, dx, smooth_kern, 3, 1,
+ grad_kern, 3, 1, callback))
+ return 1;
+
+ if (GP_FilterVHLinearConvolution_Raw(src, dy, grad_kern, 3, 1,
+ smooth_kern, 3, 1, callback))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Apply sobel operator.
+ */
+static int sobel(const GP_Context *src, GP_Context *dx, GP_Context *dy,
+ GP_ProgressCallback *callback)
+{
+ float x_kern[] = {
+ -1, 0, 1,
+ -2, 0, 2,
+ -1, 0, 1,
+ };
+
+ if (GP_FilterLinearConvolution_Raw(src, dx, x_kern, 3, 3, 32, callback))
+ return 1;
+
+ float y_kern[] = {
+ -1, -2, -1,
+ 0, 0, 0,
+ 1, 2, 1,
+ };
+
+ if (GP_FilterLinearConvolution_Raw(src, dy, y_kern, 3, 3, 32, callback))
+ return 1;
+
+ return 0;
+}
+
+static int edge_detect(const GP_Context *src,
+ GP_Context **E, GP_Context **Phi, int type,
+ GP_ProgressCallback *callback)
+{
+ //TODO
+ GP_ASSERT(src->pixel_type == GP_PIXEL_RGB888);
+
+ GP_Context *dx, *dy;
+
+ dx = GP_ContextCopy(src, 0);
+ dy = GP_ContextCopy(src, 0);
+
+ if (dx == NULL || dy == NULL)
+ goto err0;
+
+ switch (type) {
+ case 0:
+ if (sobel(src, dx, dy, callback))
+ goto err0;
+ break;
+ case 1:
+ if (prewitt(src, dx, dy, callback))
+ goto err0;
+ break;
+ default:
+ goto err0;
+ }
+
+ uint32_t i, j;
+
+ for (i = 0; i < src->w; i++) {
+ for (j = 0; j < src->h; j++) {
+ GP_Pixel pix_x = GP_GetPixel_Raw_24BPP(dx, i, j);
+ GP_Pixel pix_y = GP_GetPixel_Raw_24BPP(dy, i, j);
+ int Rx, Gx, Bx;
+ int Ry, Gy, By;
+ int RE, GE, BE;
+ int RPhi, GPhi, BPhi;
+
+ Rx = GP_Pixel_GET_R_RGB888(pix_x);
+ Gx = GP_Pixel_GET_G_RGB888(pix_x);
+ Bx = GP_Pixel_GET_B_RGB888(pix_x);
+
+ Ry = GP_Pixel_GET_R_RGB888(pix_y);
+ Gy = GP_Pixel_GET_G_RGB888(pix_y);
+ By = GP_Pixel_GET_B_RGB888(pix_y);
+
+ RE = sqrt(Rx*Rx + Ry*Ry) + 0.5;
+ GE = sqrt(Gx*Gx + Gy*Gy) + 0.5;
+ BE = sqrt(Bx*Bx + By*By) + 0.5;
+
+ GP_PutPixel_Raw_24BPP(dx, i, j,
+ GP_Pixel_CREATE_RGB888(RE, GE, BE));
+
+ if (Rx != 0 && Ry != 0)
+ RPhi = ((atan2(Rx, Ry) + M_PI) * 255)/(2*M_PI);
+ else
+ RPhi = 0;
+
+ if (Gx != 0 && Gy != 0)
+ GPhi = ((atan2(Gx, Gy) + M_PI) * 255)/(2*M_PI);
+ else
+ GPhi = 0;
+
+ if (Bx != 0 && By != 0)
+ BPhi = ((atan2(Bx, By) + M_PI) * 255)/(2*M_PI);
+ else
+ BPhi = 0;
+
+ GP_PutPixel_Raw_24BPP(dy, i, j,
+ GP_Pixel_CREATE_RGB888(RPhi, GPhi, BPhi));
+ }
+ }
+
+ if (Phi != NULL)
+ *Phi = dy;
+ else
+ GP_ContextFree(dy);
+
+ if (E != NULL)
+ *E = dx;
+ else
+ GP_ContextFree(dx);
+
+ return 0;
+err0:
+ GP_ContextFree(dx);
+ GP_ContextFree(dy);
+ return 1;
+}
+
+int GP_FilterEdgeSobel(const GP_Context *src,
+ GP_Context **E, GP_Context **Phi,
+ GP_ProgressCallback *callback)
+{
+ GP_DEBUG(1, "Sobel edge detection image %ux%u", src->w, src->h);
+
+ return edge_detect(src, E, Phi, 1, callback);
+}
+
+int GP_FilterEdgePrewitt(const GP_Context *src,
+ GP_Context **E, GP_Context **Phi,
+ GP_ProgressCallback *callback)
+{
+ GP_DEBUG(1, "Prewitt edge detection image %ux%u", src->w, src->h);
+
+ return edge_detect(src, E, Phi, 1, callback);
+}
http://repo.or.cz/w/gfxprim.git/commit/d9fe7ce7722c160fdcd2978e893bd9889a29…
commit d9fe7ce7722c160fdcd2978e893bd9889a292163
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 17:54:24 2012 +0200
filters: Fix typo in VH Convolution.
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 3fb7dbb..6f906b8 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -337,7 +337,7 @@ int GP_FilterVHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
conv_callback.callback = v_callback;
- if (GP_FilterHLinearConvolution_Raw(src, dst, vkernel, kh, vkern_div, new_callback))
+ if (GP_FilterHLinearConvolution_Raw(dst, dst, vkernel, kh, vkern_div, new_callback))
return 1;
GP_ProgressCallbackDone(callback);
-----------------------------------------------------------------------
Summary of changes:
libs/filters/GP_Edge.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++
libs/filters/GP_Linear.c | 2 +-
2 files changed, 185 insertions(+), 1 deletions(-)
create mode 100644 libs/filters/GP_Edge.c
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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: ee9f5789995fbcd567bc45c4cbf615956e58ce90
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 ee9f5789995fbcd567bc45c4cbf615956e58ce90 (commit)
from c0d173dc45cf696113927b923decf2d1e140cace (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/ee9f5789995fbcd567bc45c4cbf615956e58…
commit ee9f5789995fbcd567bc45c4cbf615956e58ce90
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 17:44:42 2012 +0200
filters: Make the linear covolutions general.
The convolutions were automatically normalizing
the results (by the sum of the convolution
matrix), which is not usable for general case.
Fixed that by adding divide parameter.
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h
index 21c627b..56be135 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Linear.h
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, *
* Boston, MA 02110-1301 USA *
* *
- * Copyright (C) 2009-2011 Cyril Hrubis <metan(a)ucw.cz> *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
@@ -75,12 +75,14 @@ GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst,
* };
*
* kw = kh = 3
+ *
+ * kern_div = 9
*
* This function works also in-place.
*/
int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
float kernel[], uint32_t kw, uint32_t kh,
- GP_ProgressCallback *callback);
+ float kern_div, GP_ProgressCallback *callback);
/*
* Special cases for convolution only in horizontal/vertical direction.
@@ -93,11 +95,21 @@ int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
* Both works also in-place.
*/
int GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
- float kernel[], uint32_t kw,
+ float kernel[], uint32_t kw, float kern_div,
GP_ProgressCallback *callback);
int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
- float kernel[], uint32_t kh,
+ float kernel[], uint32_t kh, float kern_div,
GP_ProgressCallback *callback);
+/*
+ * Applies both horizontal and vertical convolution and takes care of the
+ * correct progress callback (both horizontal and vertical kernels are expected
+ * to be similar in size).
+ */
+int GP_FilterVHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
+ float hkernel[], uint32_t kw, float hkern_div,
+ float vkernel[], uint32_t kh, float vkern_div,
+ GP_ProgressCallback *callback);
+
#endif /* FILTERS_GP_LINEAR_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index a55d1fe..3fb7dbb 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -22,12 +22,12 @@
#include <math.h>
-#include <core/GP_Context.h>
-#include <core/GP_GetPutPixel.h>
+#include "core/GP_Context.h"
+#include "core/GP_GetPutPixel.h"
-#include <core/GP_Debug.h>
+#include "core/GP_Debug.h"
-#include <GP_Linear.h>
+#include "GP_Linear.h"
static inline unsigned int gaussian_kernel_size(float sigma)
{
@@ -36,17 +36,21 @@ static inline unsigned int gaussian_kernel_size(float sigma)
return 2 * center + 1;
}
-static inline void gaussian_kernel_init(float sigma, float *kernel)
+static inline float gaussian_kernel_init(float sigma, float *kernel)
{
int i, center = 3 * sigma;
int N = 2 * center + 1;
-
+ float ret = 0;
+
double sigma2 = sigma * sigma;
for (i = 0; i < N; i++) {
double r = center - i;
kernel[i] = exp(-0.5 * (r * r) / sigma2);
+ ret += kernel[i];
}
+
+ return ret;
}
static int gaussian_callback_horiz(GP_ProgressCallback *self)
@@ -88,10 +92,10 @@ int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst,
/* compute kernel and apply in horizontal direction */
if (sigma_x > 0) {
float kernel_x[size_x];
- gaussian_kernel_init(sigma_x, kernel_x);
-
+ float sum = gaussian_kernel_init(sigma_x, kernel_x);
+
if (GP_FilterHLinearConvolution_Raw(src, dst, kernel_x, size_x,
- new_callback))
+ sum, new_callback))
return 1;
}
@@ -101,10 +105,10 @@ int GP_FilterGaussianBlur_Raw(const GP_Context *src, GP_Context *dst,
/* compute kernel and apply in vertical direction */
if (sigma_y > 0) {
float kernel_y[size_y];
- gaussian_kernel_init(sigma_y, kernel_y);
+ float sum = gaussian_kernel_init(sigma_y, kernel_y);
if (GP_FilterVLinearConvolution_Raw(dst, dst, kernel_y, size_y,
- new_callback))
+ sum, new_callback))
return 1;
}
@@ -147,24 +151,21 @@ GP_Context *GP_FilterGaussianBlur(const GP_Context *src, GP_Context *dst,
} while (0)
int GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
- float kernel[], uint32_t kw,
+ float kernel[], uint32_t kw, float kern_div,
GP_ProgressCallback *callback)
{
- int32_t kernel_sum = 0;
GP_Coord x, y;
uint32_t i;
- int32_t ikernel[kw];
+ int32_t ikernel[kw], ikern_div;
uint32_t size = dst->w + kw - 1;
-
- for (i = 0; i < kw; i++)
- ikernel[i] = kernel[i] * MUL + 0.5;
-
+
GP_DEBUG(1, "Horizontal linear convolution kernel width %i image %ux%u",
kw, src->w, src->h);
- /* count kernel sum for normalization */
for (i = 0; i < kw; i++)
- kernel_sum += ikernel[i];
+ ikernel[i] = kernel[i] * MUL + 0.5;
+
+ ikern_div = kern_div * MUL + 0.5;
/* do linear convolution */
for (y = 0; y < (GP_Coord)dst->h; y++) {
@@ -203,10 +204,10 @@ int GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
b += B[i + x] * ikernel[i];
}
- /* normalize the result */
- r /= kernel_sum;
- g /= kernel_sum;
- b /= kernel_sum;
+ /* divide the result */
+ r /= ikern_div;
+ g /= ikern_div;
+ b /= ikern_div;
/* and clamp just to be extra sure */
CLAMP(r);
@@ -226,13 +227,12 @@ int GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
}
int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
- float kernel[], uint32_t kh,
+ float kernel[], uint32_t kh, float kern_div,
GP_ProgressCallback *callback)
{
- int32_t kernel_sum = 0;
GP_Coord x, y;
uint32_t i;
- int32_t ikernel[kh];
+ int32_t ikernel[kh], ikern_div;
uint32_t size = dst->h + kh - 1;
for (i = 0; i < kh; i++)
@@ -241,9 +241,7 @@ int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
GP_DEBUG(1, "Vertical linear convolution kernel width %i image %ux%u",
kh, src->w, src->h);
- /* count kernel sum for normalization */
- for (i = 0; i < kh; i++)
- kernel_sum += ikernel[i];
+ ikern_div = kern_div * MUL + 0.5;
/* do linear convolution */
for (x = 0; x < (GP_Coord)dst->w; x++) {
@@ -282,10 +280,10 @@ int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
b += B[y + i] * ikernel[i];
}
- /* normalize the result */
- r /= kernel_sum;
- g /= kernel_sum;
- b /= kernel_sum;
+ /* divide the result */
+ r /= ikern_div;
+ g /= ikern_div;
+ b /= ikern_div;
/* and clamp just to be extra sure */
CLAMP(r);
@@ -304,6 +302,47 @@ int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
return 0;
}
+static int h_callback(GP_ProgressCallback *self)
+{
+ GP_ProgressCallback *callback = self->priv;
+
+ callback->percentage = self->percentage / 2;
+ return callback->callback(callback);
+}
+
+static int v_callback(GP_ProgressCallback *self)
+{
+ GP_ProgressCallback *callback = self->priv;
+
+ callback->percentage = self->percentage / 2 + 50;
+ return callback->callback(callback);
+}
+
+int GP_FilterVHLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
+ float hkernel[], uint32_t kw, float hkern_div,
+ float vkernel[], uint32_t kh, float vkern_div,
+ GP_ProgressCallback *callback)
+{
+ GP_ProgressCallback *new_callback;
+
+ GP_ProgressCallback conv_callback = {
+ .callback = h_callback,
+ .priv = callback,
+ };
+
+ new_callback = callback ? &conv_callback : NULL;
+
+ if (GP_FilterVLinearConvolution_Raw(src, dst, hkernel, kw, hkern_div, new_callback))
+ return 1;
+
+ conv_callback.callback = v_callback;
+
+ if (GP_FilterHLinearConvolution_Raw(src, dst, vkernel, kh, vkern_div, new_callback))
+ return 1;
+
+ GP_ProgressCallbackDone(callback);
+ return 0;
+}
/*
* Linear convolution.
@@ -312,19 +351,14 @@ int GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
*/
int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
float kernel[], uint32_t kw, uint32_t kh,
- GP_ProgressCallback *callback)
+ float kern_div, GP_ProgressCallback *callback)
{
- float kernel_sum = 0;
GP_Coord x, y;
uint32_t i, j;
GP_DEBUG(1, "Linear convolution kernel %ix%i image %ux%u",
kw, kh, src->w, src->h);
- /* count kernel sum for normalization */
- for (i = 0; i < kw * kh; i++)
- kernel_sum += kernel[i];
-
/* do linear convolution */
for (y = 0; y < (GP_Coord)dst->h; y++) {
GP_Pixel pix;
@@ -394,10 +428,10 @@ int GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *dst,
}
}
- /* normalize the result */
- r /= kernel_sum;
- g /= kernel_sum;
- b /= kernel_sum;
+ /* divide the result */
+ r /= kern_div;
+ g /= kern_div;
+ b /= kern_div;
/* and clamp just to be extra sure */
if (r > 255)
-----------------------------------------------------------------------
Summary of changes:
include/filters/GP_Linear.h | 20 ++++++--
libs/filters/GP_Linear.c | 122 +++++++++++++++++++++++++++---------------
2 files changed, 94 insertions(+), 48 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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: c0d173dc45cf696113927b923decf2d1e140cace
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 c0d173dc45cf696113927b923decf2d1e140cace (commit)
from ce9e4793af70584532932e14d4adec6c38eefc4d (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/c0d173dc45cf696113927b923decf2d1e140…
commit c0d173dc45cf696113927b923decf2d1e140cace
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 14:27:37 2012 +0200
examples: Add simple showimage example.
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile
index 44926f8..6e3b7d7 100644
--- a/demos/c_simple/Makefile
+++ b/demos/c_simple/Makefile
@@ -6,7 +6,7 @@ INCLUDE=
LDLIBS+=-lGP -lGP_backends -lSDL -L$(TOPDIR)/build/
APPS=backend_example loaders_example loaders filters_symmetry gfx_koch- virtual_backend_example meta_data meta_data_dump tmp_file
+ virtual_backend_example meta_data meta_data_dump tmp_file showimage
include $(TOPDIR)/pre.mk
include $(TOPDIR)/app.mk
diff --git a/demos/c_simple/showimage.c b/demos/c_simple/showimage.c
new file mode 100644
index 0000000..9abbb6d
--- /dev/null
+++ b/demos/c_simple/showimage.c
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+/*
+
+ Simple example that shows X11 window with image.
+
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "GP.h"
+#include "backends/GP_X11.h"
+
+int main(int argc, char *argv[])
+{
+ GP_Backend *backend;
+ GP_Context *image;
+
+ GP_SetDebugLevel(10);
+
+ if (argc != 2) {
+ fprintf(stderr, "Takes image as an argumentn");
+ return 1;
+ }
+
+ /* Load image */
+ image = GP_LoadImage(argv[1], NULL);
+
+ if (image == NULL) {
+ fprintf(stderr, "Failed to load bitmap: %sn", strerror(errno));
+ return 1;
+ }
+
+ /* Initalize backend */
+ backend = GP_BackendX11Init(NULL, 0, 0, image->w, image->h, argv[1], 0);
+
+ if (backend == NULL) {
+ fprintf(stderr, "Failed to initalize backendn");
+ return 1;
+ }
+
+ /* Blit image into the window and show it */
+ GP_Blit(image, 0, 0, image->w, image->h, backend->context, 0, 0);
+ GP_BackendFlip(backend);
+
+ /* Wait for events */
+ for (;;) {
+ GP_BackendWait(backend);
+
+ GP_Event ev;
+
+ while (GP_EventGet(&ev)) {
+ if (ev.type == GP_EV_KEY && ev.val.val == GP_KEY_Q) {
+ GP_BackendExit(backend);
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/doc/examples.txt b/doc/examples.txt
index ec356e2..cbd4cf5 100644
--- a/doc/examples.txt
+++ b/doc/examples.txt
@@ -94,6 +94,11 @@ Example in C
include::../demos/c_simple/backend_example.c[]
------------------------------------------------------------------
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/showimage.c[]
+------------------------------------------------------------------
+
GFXprim + PyGTK
---------------
-----------------------------------------------------------------------
Summary of changes:
demos/c_simple/Makefile | 2 +-
demos/c_simple/{loaders_example.c => showimage.c} | 56 ++++++++++++++------
doc/examples.txt | 5 ++
3 files changed, 45 insertions(+), 18 deletions(-)
copy demos/c_simple/{loaders_example.c => showimage.c} (67%)
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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: ce9e4793af70584532932e14d4adec6c38eefc4d
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 ce9e4793af70584532932e14d4adec6c38eefc4d (commit)
from e4962e78d7114be162c9c83e6068f03e9455fb01 (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/ce9e4793af70584532932e14d4adec6c38ee…
commit ce9e4793af70584532932e14d4adec6c38eefc4d
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 14:04:58 2012 +0200
doc: Add gamma docs + spellchecks.
diff --git a/doc/Makefile b/doc/Makefile
index 8d4ffbf..3fdfaad 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,7 +1,7 @@
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
+ basic_types.txt drawing_api.txt backends.txt gamma.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 c2fca5c..402c6dd 100644
--- a/doc/api.txt
+++ b/doc/api.txt
@@ -5,6 +5,7 @@ Cyril Hrubis <metan(a)ucw.cz>
include::general.txt[]
include::basic_types.txt[]
include::context.txt[]
+include::gamma.txt[]
include::drawing_api.txt[]
include::filters.txt[]
include::loaders.txt[]
diff --git a/doc/context.txt b/doc/context.txt
index f92473c..13d5270 100644
--- a/doc/context.txt
+++ b/doc/context.txt
@@ -24,6 +24,11 @@ typedef struct GP_Context {
enum GP_PixelType pixel_type; /* pixel format */
+ /*
+ * Pointer to optional Gamma correction tables.
+ */
+ struct GP_Gamma *gamma;
+
uint8_t axes_swap:1; /* swap axes */
uint8_t x_swap:1; /* mirror x */
uint8_t y_swap:1; /* mirror y */
@@ -195,8 +200,11 @@ The 'free_pixels' flag for the resulting context is set.
void GP_ContextFree(GP_Context *context);
-------------------------------------------------------------------------------
-Frees the context memory. If 'free_pixels' flag is set, the pixels buffer is
-freed too.
+Frees the context memory.
+
+If 'free_pixels' flag is set, the pixels buffer is freed too.
+
+If gamma pointer is not 'NULL' the 'GP_GammaRelease()' is called.
Subcontext
~~~~~~~~~~
@@ -274,3 +282,4 @@ void GP_ContextPrintInfo(const GP_Context *self);
This function prints the content of 'GP_Context' structure, in a readable
format, into the stdout.
+
diff --git a/doc/gamma.txt b/doc/gamma.txt
new file mode 100644
index 0000000..f15f072
--- /dev/null
+++ b/doc/gamma.txt
@@ -0,0 +1,137 @@
+Gamma Correction
+----------------
+
+What is gamma and what is it doing in my computer?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+First of all gamma is a function, or better there is a gamma function and
+it's inverse function. Both gamma function and it's inverse are defined on
+interval [0,1] and are defined as out = in^(gamma)^ and it's inverse as
+out = in^(1/gamma)^.
+
+The purpose of this function is to compensate nonlinearity of human eye
+perception. The human eye is more sensitive to dark tones than the light ones
+so without gamma correction storage and manipulation with image data would
+either be less efficient in space (in case you decided to use more bits and
+encode the image linearly) or quantization in darker tones would be more
+visible resulting in "pixelated" images (aliasing).
+
+So there is a gamma, the Internet seems to suggest that usual values for
+gamma are 2.5 for old CRT monitors and about 2.2 for LCD ones, ideally you
+should have color profile for your device (you need special hardware to
+measure it). So if you are trying to draw linear gradient on the screen
+you need to generate sequence of numbers accordingly to gamma function
+(the 50% intensity is around 186 for gamma = 2.2 and 8bit grayscale pixel).
+
+Moreover image formats tend to save data in nonlinear fashion (some formats
+include gamma value used to for the image) so before you apply filter that
+manipulates with pixel values, you need to convert it to linear space (adding
+some more bits to compensate for rounding errors).
+
+Also it's important to take gamma, into an account, when drawing anti aliased
+shapes, you can't get right results otherwise.
+
+NOTE: The gamma support in GFXprim is quite new and at a time of writing this
+docs, only one filter does support gamma correction. (The anti-aliased drawing
+and text still use legacy gamma support.)
+
+Implementation
+~~~~~~~~~~~~~~
+
+The 'GP_Gamma' structure defines per context, per channel, gamma tables.
+
+The tables for particular gamma are reference counted. There is only one table
+for particular gamma value and bit depth in memory at a time.
+
+Also the table output, for linear values, has two more bits than original in
+order not to loose precision.
+
+The pointers to gamma tables are storied in 'GP_Gamma' structure and are
+organized in the same order as channels. First N tables for each channel and
+gamma value gamma, then N tables for inverse 1/gamma function.
+
+So when we have RGB888 pixel and gamma 2.2 there are two tables in the memory,
+one for gamma 2.2 input 8bit output 10bit and it's inverse input 10bit output
+8bit. The 'GP_Gamma' contains six pointers. First three points to the gamma
+table for gamma 2.2 with 8bit input (256 array members) and the output format
+is 10bits so each array member is 'uint16_t'. The other three are for inverse
+gamma function (gamma = 0.454545...) with 10bit input (1024 array members) and
+8bit output so each member is 'uint8_t'.
+
+The whole interface is designed for speed, so that conversion to linear space
+or from linear space is just a matter of indexing arrays. Imagine you need to
+get gamma-corrected pixel value. First you take individual pixel channels then
+use the GP_Gamma structure as follows:
+
+[source,c]
+-------------------------------------------------------------------------------
+
+/* To convert channel gamma value to linear value: */
+gamma->tables[chan_number].u16[chan_val]
+
+/* ... or when result has no more than 8bits ... */
+
+gamma->tables[chan_number].u8[chan_val]
+
+/* The inverse transformation is done as: */
+
+gamma->tables[chan_count + chan_number].u8[chan_val]
+
+/* ... or when original pixel channel had more than 8bits ... */
+
+gamma->tables[chan_count + chan_number].u16[chan_val]
+
+/*
+ * When doing more than one conversion it's better to save pointers to
+ * individual table (example for RGB888):
+ */
+
+uint16_t *R_2_LIN = gamma->tables[0].u16;
+/* ... */
+uint8_t *R_2_GAMMA = gamma->tables[3].u8;
+/* ... */
+
+-------------------------------------------------------------------------------
+
+Gamma low level API
+~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_Gamma.h>
+/* or */
+#include <GP.h>
+
+GP_Gamma *GP_GammaAcquire(GP_PixelType pixel_type, float gamma);
+-------------------------------------------------------------------------------
+
+Returns pointer to gamma table for particular pixel_type and gamma value.
+
+The same gamma is used for all channels.
+
+May fail and return 'NULL' if 'malloc()' has failed.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_Gamma.h>
+/* or */
+#include <GP.h>
+
+GP_Gamma *GP_GammaCopy(GP_Gamma *gamma);
+-------------------------------------------------------------------------------
+
+Copies a Gamma table (actually only increases ref_count).
+
+Can't fail.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_Gamma.h>
+/* or */
+#include <GP.h>
+
+void GP_GammaRelease(GP_Gamma *self);
+-------------------------------------------------------------------------------
+
+Releases Gama table (if ref_count has fallen to zero, frees memory).
+
diff --git a/include/core/GP_Gamma.h b/include/core/GP_Gamma.h
index a4112a7..9a93587 100644
--- a/include/core/GP_Gamma.h
+++ b/include/core/GP_Gamma.h
@@ -36,22 +36,22 @@
perception. The human eye is more sensitive to dark tones than the light ones
so without gamma correction storage and manipulation with image data would
either be less efficient in space (in case you decided to use more bits and
- encode the image lineary) or quantization in darker tones would be more
+ encode the image linearly) or quantization in darker tones would be more
visible resulting in "pixelated" images (aliasing).
- So there is a gamma, the internet seems to suggest that usual values for
+ So there is a gamma, the Internet seems to suggest that usual values for
gamma are 2.5 for old CRT monitors and about 2.2 for LCD ones, ideally you
should have color profile for your device (you need special hardware to
measure it). So if you are trying to draw linear gradient on the screen
- you need to generate sequence of numbers accordinly to gamma function
+ you need to generate sequence of numbers accordingly to gamma function
(the 50% intensity is around 186 for gamma = 2.2 and 8bit grayscale pixel).
Moreover image formats tend to save data in nonlinear fashion (some formats
- include gama value used to for the image) so before you apply filter that
+ include gamma value used to for the image) so before you apply filter that
manipulates with pixel values, you need to convert it to linear space (adding
some more bits to compensate for rounding errors).
- Also it's important to take gamma, into an accound, when drawing anti aliased
+ Also it's important to take gamma, into an account, when drawing anti-aliased
shapes, you can't get right results otherwise.
*/
@@ -62,21 +62,21 @@
channel, gamma tables.
The tables for particular gamma are reference counted. There is only one
- table for particulal gamma value and bit depth in memory at a time.
+ table for particular gamma value and bit depth in memory at a time.
Also the table output, for linear values, has two more bits than original in
order not to loose precision.
- The pointers to gamma tables are storied in GP_Gamma structure the pointers
- are organized in the same order as channes. First N tables for each channel
- and gamma value gamma, then N tables for inverse 1/gamma function.
+ The pointers to gamma tables are storied in GP_Gamma structure and are
+ organized in the same order as channels. First N tables for each channel and
+ gamma value gamma, then N tables for inverse 1/gamma function.
So when we have RGB888 pixel and gamma 2.2 there are two tables in the
memory, one for gamma 2.2 input 8bit output 10bit and it's inverse input
10bit output 8bit. The GP_Gamma contains six pointers. First three points to
- the gamma table for gamma 2.2 whith 8bit input (256 array members) and the
+ the gamma table for gamma 2.2 with 8bit input (256 array members) and the
output format is 10bits so each array member is uint16_t. The other three
- are for inverse gamma funcion (gamma = 0.454545...) with 10bit input (1024
+ are for inverse gamma function (gamma = 0.454545...) with 10bit input (1024
array members) and 8bit output so each member is uint8_t.
The whole interface is designed for speed, so that conversion to linear
@@ -94,16 +94,16 @@
gamma->tables[chan_count + chan_number].u8[chan_val]
- of when original pixel channel had more than 8bits
+ or when original pixel channel had more than 8bits
gamma->tables[chan_count + chan_number].u16[chan_val]
When doing more than one conversion it's better to save pointers to
individual table (example for RGB888):
- uint16_t *R2Lin = gamma->tables[0].u16;
+ uint16_t *R_2_LIN = gamma->tables[0].u16;
...
- uint8_t *R2Gamma = gamma->tables[3].u8;
+ uint8_t *R_2_GAMMA = gamma->tables[3].u8;
...
*/
@@ -139,9 +139,9 @@ typedef struct GP_GammaTable {
* Gamma structure for general pixel type.
*
* The GP_Gamma structure contains pointers to tables for each pixel
- * channel and for gamma and it's inverse transfomation.
+ * channel and for gamma and it's inverse transformation.
*
- * The interface is specialy designed so that getting Gamma corrected value is
+ * The interface is specially designed so that getting Gamma corrected value is
* a matter of indexing two arrays.
*/
typedef struct GP_Gamma {
diff --git a/libs/filters/GP_Cubic.h b/libs/filters/GP_Cubic.h
index 213031a..5d3c0e6 100644
--- a/libs/filters/GP_Cubic.h
+++ b/libs/filters/GP_Cubic.h
@@ -53,7 +53,7 @@ extern int16_t GP_CubicTable[];
/*
* Fixed point version of above.
*
- * Both input and output value are multiplied by MUL.
+ * The input and output are expected in 24.8 fixed point format
*/
static inline int cubic_int(int x)
{
diff --git a/libs/filters/GP_ResizeCubic.gen.c.t b/libs/filters/GP_ResizeCubic.gen.c.t
index f782b39..901e253 100644
--- a/libs/filters/GP_ResizeCubic.gen.c.t
+++ b/libs/filters/GP_ResizeCubic.gen.c.t
@@ -1,6 +1,6 @@
%% extends "filter.c.t"
-{% block descr %}Nearest Neighbour resampling{% endblock %}
+{% block descr %}Cubic resampling{% endblock %}
%% block body
-----------------------------------------------------------------------
Summary of changes:
doc/Makefile | 2 +-
doc/api.txt | 1 +
doc/context.txt | 13 +++-
doc/gamma.txt | 137 +++++++++++++++++++++++++++++++++++
include/core/GP_Gamma.h | 32 ++++----
libs/filters/GP_Cubic.h | 2 +-
libs/filters/GP_ResizeCubic.gen.c.t | 2 +-
7 files changed, 168 insertions(+), 21 deletions(-)
create mode 100644 doc/gamma.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.")
1
0
[repo.or.cz] gfxprim.git branch master updated: e4962e78d7114be162c9c83e6068f03e9455fb01
by metan 18 Jun '12
by metan 18 Jun '12
18 Jun '12
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 e4962e78d7114be162c9c83e6068f03e9455fb01 (commit)
via 3e363191fedfbf7391ffe5fafc3fa8a3fb3fc78f (commit)
from f4da6fbfe83e00302e52a89265b2f2e84283df4c (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/e4962e78d7114be162c9c83e6068f03e9455…
commit e4962e78d7114be162c9c83e6068f03e9455fb01
Merge: 3e36319 f4da6fb
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 13:19:37 2012 +0200
Merge ssh://repo.or.cz/srv/git/gfxprim
http://repo.or.cz/w/gfxprim.git/commit/3e363191fedfbf7391ffe5fafc3fa8a3fb3f…
commit 3e363191fedfbf7391ffe5fafc3fa8a3fb3fc78f
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Mon Jun 18 13:17:51 2012 +0200
filters: Add generated cubic resampling (with gamma) yay!
diff --git a/libs/filters/GP_Cubic.h b/libs/filters/GP_Cubic.h
index 3e7dbef..213031a 100644
--- a/libs/filters/GP_Cubic.h
+++ b/libs/filters/GP_Cubic.h
@@ -29,7 +29,7 @@
#ifndef FILTERS_GP_CUBIC_H
#define FILTERS_GP_CUBIC_H
-#define A 0.5
+#define Ap 0.5
static inline float cubic_float(float x)
{
@@ -37,10 +37,10 @@ static inline float cubic_float(float x)
x = -x;
if (x < 1)
- return (2 - A)*x*x*x + (A - 3)*x*x + 1;
+ return (2 - Ap)*x*x*x + (Ap - 3)*x*x + 1;
if (x < 2)
- return -A*x*x*x + 5*A*x*x - 8*A*x + 4*A;
+ return -Ap*x*x*x + 5*Ap*x*x - 8*Ap*x + 4*Ap;
return 0;
}
diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c
index 79362ef..022ba99 100644
--- a/libs/filters/GP_Resize.c
+++ b/libs/filters/GP_Resize.c
@@ -30,6 +30,7 @@
#include "GP_Resize.h"
+/* See GP_ResizeNN.gen.c */
int GP_FilterResizeNN_Raw(const GP_Context *src, GP_Context *dst,
GP_ProgressCallback *callback);
@@ -58,6 +59,35 @@ GP_Context *GP_FilterResizeNNAlloc(const GP_Context *src,
return res;
}
+/* See GP_ResizeCubic.gen.c */
+int GP_FilterResizeCubicInt_Raw(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback);
+
+int GP_FilterResizeCubicInt(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback)
+{
+ GP_ASSERT(src->pixel_type == dst->pixel_type);
+
+ return GP_FilterResizeCubicInt_Raw(src, dst, callback);
+}
+
+GP_Context *GP_FilterResizeCubicIntAlloc(const GP_Context *src,
+ GP_Size w, GP_Size h,
+ GP_ProgressCallback *callback)
+{
+ GP_Context *res = GP_ContextAlloc(w, h, src->pixel_type);
+
+ if (res == NULL)
+ return NULL;
+
+ if (GP_FilterResizeCubicInt_Raw(src, res, callback)) {
+ GP_ContextFree(res);
+ return NULL;
+ }
+
+ return res;
+}
+
static const char *interp_types[] = {
"Nearest Neighbour",
"Linear (Int)",
@@ -252,213 +282,6 @@ int GP_FilterInterpolate_Cubic(const GP_Context *src, GP_Context *dst,
return 0;
}
-#include "GP_Cubic.h"
-
-#define MUL 1024
-
-#define MUL_I(a, b) ({ - a[0] *= b[0]; - a[1] *= b[1]; - a[2] *= b[2]; - a[3] *= b[3]; -})
-
-#define SUM_I(a) - ((a)[0] + (a)[1] + (a)[2] + (a)[3])
-
-#include "core/GP_GammaCorrection.h"
-
-int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst,
- GP_ProgressCallback *callback)
-{
- int32_t col_r[src->w], col_g[src->w], col_b[src->w];
- uint32_t i, j;
-
- GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
- src->w, src->h, dst->w, dst->h,
- 1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
-
- uint16_t *R_2_LIN = NULL;
- uint16_t *G_2_LIN = NULL;
- uint16_t *B_2_LIN = NULL;
-
- uint8_t *R_2_GAMMA = NULL;
- uint8_t *G_2_GAMMA = NULL;
- uint8_t *B_2_GAMMA = NULL;
-
- if (src->gamma) {
- R_2_LIN = src->gamma->tables[0]->u16;
- G_2_LIN = src->gamma->tables[1]->u16;
- B_2_LIN = src->gamma->tables[2]->u16;
-
- R_2_GAMMA = src->gamma->tables[3]->u8;
- G_2_GAMMA = src->gamma->tables[4]->u8;
- B_2_GAMMA = src->gamma->tables[5]->u8;
- }
-
- /* pre-generate x mapping and constants */
- int32_t xmap[dst->w][4];
- int32_t xmap_c[dst->w][4];
-
- for (i = 0; i < dst->w; i++) {
- float x = (1.00 * i / (dst->w - 1)) * (src->w - 1);
-
- xmap[i][0] = floor(x - 1);
- xmap[i][1] = x;
- xmap[i][2] = x + 1;
- xmap[i][3] = x + 2;
-
-
- xmap_c[i][0] = cubic_int((xmap[i][0] - x) * MUL + 0.5);
- xmap_c[i][1] = cubic_int((xmap[i][1] - x) * MUL + 0.5);
- xmap_c[i][2] = cubic_int((xmap[i][2] - x) * MUL + 0.5);
- xmap_c[i][3] = cubic_int((xmap[i][3] - x) * MUL + 0.5);
-
- if (xmap[i][0] < 0)
- xmap[i][0] = 0;
-
- if (xmap[i][3] >= (int32_t)src->w)
- xmap[i][3] = src->w - 1;
- }
-
- /* cubic resampling */
- for (i = 0; i < dst->h; i++) {
- float y = (1.00 * i / (dst->h - 1)) * (src->h - 1);
- int32_t cvy[4];
- int yi[4];
-
- yi[0] = floor(y - 1);
- yi[1] = y;
- yi[2] = y + 1;
- yi[3] = y + 2;
-
- cvy[0] = cubic_int((yi[0] - y) * MUL + 0.5);
- cvy[1] = cubic_int((yi[1] - y) * MUL + 0.5);
- cvy[2] = cubic_int((yi[2] - y) * MUL + 0.5);
- cvy[3] = cubic_int((yi[3] - y) * MUL + 0.5);
-
- if (yi[0] < 0)
- yi[0] = 0;
-
- if (yi[3] >= (int)src->h)
- yi[3] = src->h - 1;
-
- /* Generate interpolated row */
- for (j = 0; j < src->w; j++) {
- int32_t rv[4], gv[4], bv[4];
- GP_Pixel pix[4];
-
- pix[0] = GP_GetPixel_Raw_24BPP(src, j, yi[0]);
- pix[1] = GP_GetPixel_Raw_24BPP(src, j, yi[1]);
- pix[2] = GP_GetPixel_Raw_24BPP(src, j, yi[2]);
- pix[3] = GP_GetPixel_Raw_24BPP(src, j, yi[3]);
-
- rv[0] = GP_Pixel_GET_R_RGB888(pix[0]);
- rv[1] = GP_Pixel_GET_R_RGB888(pix[1]);
- rv[2] = GP_Pixel_GET_R_RGB888(pix[2]);
- rv[3] = GP_Pixel_GET_R_RGB888(pix[3]);
-
- gv[0] = GP_Pixel_GET_G_RGB888(pix[0]);
- gv[1] = GP_Pixel_GET_G_RGB888(pix[1]);
- gv[2] = GP_Pixel_GET_G_RGB888(pix[2]);
- gv[3] = GP_Pixel_GET_G_RGB888(pix[3]);
-
- bv[0] = GP_Pixel_GET_B_RGB888(pix[0]);
- bv[1] = GP_Pixel_GET_B_RGB888(pix[1]);
- bv[2] = GP_Pixel_GET_B_RGB888(pix[2]);
- bv[3] = GP_Pixel_GET_B_RGB888(pix[3]);
-
-
- if (src->gamma) {
- rv[0] = R_2_LIN[rv[0]];
- rv[1] = R_2_LIN[rv[1]];
- rv[2] = R_2_LIN[rv[2]];
- rv[3] = R_2_LIN[rv[3]];
-
- gv[0] = G_2_LIN[gv[0]];
- gv[1] = G_2_LIN[gv[1]];
- gv[2] = G_2_LIN[gv[2]];
- gv[3] = G_2_LIN[gv[3]];
-
- bv[0] = G_2_LIN[bv[0]];
- bv[1] = G_2_LIN[bv[1]];
- bv[2] = G_2_LIN[bv[2]];
- bv[3] = G_2_LIN[bv[3]];
- }
-
- MUL_I(rv, cvy);
- MUL_I(gv, cvy);
- MUL_I(bv, cvy);
-
- col_r[j] = SUM_I(rv);
- col_g[j] = SUM_I(gv);
- col_b[j] = SUM_I(bv);
- }
-
- /* now interpolate column for new image */
- for (j = 0; j < dst->w; j++) {
- int32_t rv[4], gv[4], bv[4];
- int32_t r, g, b;
-
- rv[0] = col_r[xmap[j][0]];
- rv[1] = col_r[xmap[j][1]];
- rv[2] = col_r[xmap[j][2]];
- rv[3] = col_r[xmap[j][3]];
-
- gv[0] = col_g[xmap[j][0]];
- gv[1] = col_g[xmap[j][1]];
- gv[2] = col_g[xmap[j][2]];
- gv[3] = col_g[xmap[j][3]];
-
- bv[0] = col_b[xmap[j][0]];
- bv[1] = col_b[xmap[j][1]];
- bv[2] = col_b[xmap[j][2]];
- bv[3] = col_b[xmap[j][3]];
-
- MUL_I(rv, xmap_c[j]);
- MUL_I(gv, xmap_c[j]);
- MUL_I(bv, xmap_c[j]);
-
- r = (SUM_I(rv) + MUL*MUL/2) / MUL / MUL;
- g = (SUM_I(gv) + MUL*MUL/2) / MUL / MUL;
- b = (SUM_I(bv) + MUL*MUL/2) / MUL / MUL;
-
- if (src->gamma) {
- if (r > 1023)
- r = 1023;
- if (g > 1023)
- g = 1023;
- if (b > 1023)
- b = 1023;
-
- if (r < 0)
- r = 0;
- if (g < 0)
- g = 0;
- if (b < 0)
- b = 0;
-
- r = R_2_GAMMA[r];
- g = G_2_GAMMA[g];
- b = B_2_GAMMA[b];
- } else {
- CLAMP(r);
- CLAMP(g);
- CLAMP(b);
- }
-
- GP_Pixel pix = GP_Pixel_CREATE_RGB888((uint8_t)r, (uint8_t)g, (uint8_t)b);
- GP_PutPixel_Raw_24BPP(dst, j, i, pix);
- }
-
- if (GP_ProgressCallbackReport(callback, i, dst->h, dst->w))
- return 1;
- }
-
- GP_ProgressCallbackDone(callback);
- return 0;
-}
-
/*
* Sample row.
*
@@ -742,7 +565,7 @@ int GP_FilterResize_Raw(const GP_Context *src, GP_Context *dst,
case GP_INTERP_CUBIC:
return GP_FilterInterpolate_Cubic(src, dst, callback);
case GP_INTERP_CUBIC_INT:
- return GP_FilterInterpolate_CubicInt(src, dst, callback);
+ return GP_FilterResizeCubicInt_Raw(src, dst, callback);
}
return 1;
diff --git a/libs/filters/GP_ResizeCubic.gen.c.t b/libs/filters/GP_ResizeCubic.gen.c.t
new file mode 100644
index 0000000..f782b39
--- /dev/null
+++ b/libs/filters/GP_ResizeCubic.gen.c.t
@@ -0,0 +1,210 @@
+%% extends "filter.c.t"
+
+{% block descr %}Nearest Neighbour resampling{% endblock %}
+
+%% block body
+
+#include <math.h>
+
+#include "core/GP_Context.h"
+#include "core/GP_GetPutPixel.h"
+#include "core/GP_Gamma.h"
+#include "core/GP_Debug.h"
+
+#include "GP_Cubic.h"
+
+#include "GP_Resize.h"
+
+#define MUL 1024
+
+#define MUL_I(a, b) ({ + a[0] *= b[0]; + a[1] *= b[1]; + a[2] *= b[2]; + a[3] *= b[3]; +})
+
+#define SUM_I(a) + ((a)[0] + (a)[1] + (a)[2] + (a)[3])
+
+#define CLAMP(val, max) do { + if (val < 0) + val = 0; + if (val > max) + val = max; +} while (0)
+
+%% for pt in pixeltypes
+%% if not pt.is_unknown() and not pt.is_palette()
+
+static int GP_FilterResizeCubicInt_{{ pt.name }}_Raw(const GP_Context *src,
+ GP_Context *dst, GP_ProgressCallback *callback)
+{
+ %% for c in pt.chanslist
+ int32_t col_{{ c[0] }}[src->w];
+ %% endfor
+
+ uint32_t i, j;
+
+ GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
+ src->w, src->h, dst->w, dst->h,
+ 1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
+
+{{ fetch_gamma_tables(pt, "src") }}
+
+ /* pre-generate x mapping and constants */
+ int32_t xmap[dst->w][4];
+ int32_t xmap_c[dst->w][4];
+
+ for (i = 0; i < dst->w; i++) {
+ float x = (1.00 * i / (dst->w - 1)) * (src->w - 1);
+
+ xmap[i][0] = floor(x - 1);
+ xmap[i][1] = x;
+ xmap[i][2] = x + 1;
+ xmap[i][3] = x + 2;
+
+ xmap_c[i][0] = cubic_int((xmap[i][0] - x) * MUL + 0.5);
+ xmap_c[i][1] = cubic_int((xmap[i][1] - x) * MUL + 0.5);
+ xmap_c[i][2] = cubic_int((xmap[i][2] - x) * MUL + 0.5);
+ xmap_c[i][3] = cubic_int((xmap[i][3] - x) * MUL + 0.5);
+
+ if (xmap[i][0] < 0)
+ xmap[i][0] = 0;
+
+ if (xmap[i][2] >= (int32_t)src->w)
+ xmap[i][2] = src->w - 1;
+
+ if (xmap[i][3] >= (int32_t)src->w)
+ xmap[i][3] = src->w - 1;
+ }
+
+ /* cubic resampling */
+ for (i = 0; i < dst->h; i++) {
+ float y = (1.00 * i / (dst->h - 1)) * (src->h - 1);
+ int32_t cvy[4];
+ int yi[4];
+
+ yi[0] = floor(y - 1);
+ yi[1] = y;
+ yi[2] = y + 1;
+ yi[3] = y + 2;
+
+ cvy[0] = cubic_int((yi[0] - y) * MUL + 0.5);
+ cvy[1] = cubic_int((yi[1] - y) * MUL + 0.5);
+ cvy[2] = cubic_int((yi[2] - y) * MUL + 0.5);
+ cvy[3] = cubic_int((yi[3] - y) * MUL + 0.5);
+
+ if (yi[0] < 0)
+ yi[0] = 0;
+
+ if (yi[2] >= (int)src->h)
+ yi[2] = src->h - 1;
+
+ if (yi[3] >= (int)src->h)
+ yi[3] = src->h - 1;
+
+ /* Generate interpolated row */
+ for (j = 0; j < src->w; j++) {
+ %% for c in pt.chanslist
+ int32_t {{ c[0] }}v[4];
+ %% endfor
+ GP_Pixel pix[4];
+
+ pix[0] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[0]);
+ pix[1] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[1]);
+ pix[2] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[2]);
+ pix[3] = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, j, yi[3]);
+
+ %% for c in pt.chanslist
+ {{ c[0] }}v[0] = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix[0]);
+ {{ c[0] }}v[1] = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix[1]);
+ {{ c[0] }}v[2] = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix[2]);
+ {{ c[0] }}v[3] = GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix[3]);
+ %% endfor
+
+ if (src->gamma) {
+ %% for c in pt.chanslist
+ {{ c[0] }}v[0] = {{ c[0] }}_2_LIN[{{ c[0] }}v[0]];
+ {{ c[0] }}v[1] = {{ c[0] }}_2_LIN[{{ c[0] }}v[1]];
+ {{ c[0] }}v[2] = {{ c[0] }}_2_LIN[{{ c[0] }}v[2]];
+ {{ c[0] }}v[3] = {{ c[0] }}_2_LIN[{{ c[0] }}v[3]];
+ %% endfor
+ }
+
+ %% for c in pt.chanslist
+ MUL_I({{ c[0] }}v, cvy);
+ %% endfor
+
+ %% for c in pt.chanslist
+ col_{{ c[0] }}[j] = SUM_I({{ c[0] }}v);
+ %% endfor
+ }
+
+ /* now interpolate column for new image */
+ for (j = 0; j < dst->w; j++) {
+ %% for c in pt.chanslist
+ int32_t {{ c[0] }}v[4];
+ int32_t {{ c[0] }};
+ %% endfor
+
+ %% for c in pt.chanslist
+ {{ c[0] }}v[0] = col_{{ c[0] }}[xmap[j][0]];
+ {{ c[0] }}v[1] = col_{{ c[0] }}[xmap[j][1]];
+ {{ c[0] }}v[2] = col_{{ c[0] }}[xmap[j][2]];
+ {{ c[0] }}v[3] = col_{{ c[0] }}[xmap[j][3]];
+ %% endfor
+
+ %% for c in pt.chanslist
+ MUL_I({{ c[0] }}v, xmap_c[j]);
+ %% endfor
+
+ %% for c in pt.chanslist
+ {{ c[0] }} = (SUM_I({{ c[0] }}v) + MUL*MUL/2) / MUL / MUL;
+ %% endfor
+
+ if (src->gamma) {
+ %% for c in pt.chanslist
+ CLAMP({{ c[0] }}, {{ 2 ** (c[2] + 2) - 1 }});
+ %% endfor
+ %% for c in pt.chanslist
+ {{ c[0] }} = {{ c[0] }}_2_GAMMA[{{ c[0] }}];
+ %% endfor
+ } else {
+ %% for c in pt.chanslist
+ CLAMP({{ c[0] }}, {{ 2 ** c[2] - 1 }});
+ %% endfor
+ }
+
+ GP_Pixel pix = GP_Pixel_CREATE_{{ pt.name }}({{ expand_chanslist(pt, "(uint8_t)") }});
+ GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, j, i, pix);
+ }
+
+ if (GP_ProgressCallbackReport(callback, i, dst->h, dst->w))
+ return 1;
+ }
+
+ GP_ProgressCallbackDone(callback);
+ return 0;
+}
+
+%% endif
+%% endfor
+
+int GP_FilterResizeCubicInt_Raw(const GP_Context *src, GP_Context *dst,
+ GP_ProgressCallback *callback)
+{
+ switch (src->pixel_type) {
+ %% for pt in pixeltypes
+ %% if not pt.is_unknown() and not pt.is_palette()
+ case GP_PIXEL_{{ pt.name }}:
+ return GP_FilterResizeCubicInt_{{ pt.name }}_Raw(src, dst, callback);
+ break;
+ %% endif
+ %% endfor
+ default:
+ return -1;
+ }
+}
+
+%% endblock body
diff --git a/libs/filters/Makefile b/libs/filters/Makefile
index e07d92a..c9661e6 100644
--- a/libs/filters/Makefile
+++ b/libs/filters/Makefile
@@ -8,7 +8,7 @@ POINT_FILTERS=GP_Contrast.gen.c GP_Brightness.gen.c GP_Invert.gen.c ARITHMETIC_FILTERS=GP_Difference.gen.c GP_Addition.gen.c GP_Min.gen.c GP_Max.gen.c GP_Multiply.gen.c
-RESAMPLING_FILTERS=GP_ResizeNN.gen.c GP_Cubic.gen.c
+RESAMPLING_FILTERS=GP_ResizeNN.gen.c GP_Cubic.gen.c GP_ResizeCubic.gen.c
GENSOURCES=GP_MirrorV.gen.c GP_Rotate.gen.c GP_FloydSteinberg.gen.c GP_HilbertPeano.gen.c $(POINT_FILTERS) $(ARITHMETIC_FILTERS) $(STATS_FILTERS) $(RESAMPLING_FILTERS)
diff --git a/pylib/templates/common.c.t b/pylib/templates/common.c.t
index 785174d..30f3814 100644
--- a/pylib/templates/common.c.t
+++ b/pylib/templates/common.c.t
@@ -13,11 +13,42 @@
/*
* Converts channels to params
*/
-{% macro expand_chanslist(chlist) %} {{ chlist[0][0] }}{% for i in chlist %}, {{ i[0] }}{% endfor %}{% endmacro %}
-
+{% macro expand_chanslist(pt, pref="", suff="") %}{{ pref+pt.chanslist[0][0]+suff }}{% for c in pt.chanslist[1:] %}, {{ pref+c[0]+suff }}{% endfor %}{% endmacro %}
/*
* Clamps n-bits value
*/
%%macro clamp_val(val, bits)
if ({{ val }} > {{ 2 ** bits - 1 }}) {{ val }} = {{ 2 ** bits - 1}};
%% endmacro
+
+{% macro gamma_in_bits(size) %}{% if size + 2 > 8 %}16{% else %}8{% endif %}{% endmacro %}
+{% macro gamma_out_bits(size) %}{% if size > 8 %}16{% else %}8{% endif %}{% endmacro %}
+
+/*
+ * Prepares pointers to Gamma tables.
+ */
+%% macro fetch_gamma_tables(pt, ctx, pref="", suff="")
+ /* prepare Gamma tables */
+ %% for c in pt.chanslist
+ uint{{ gamma_in_bits(c[2]) }}_t *{{ pref+c[0] }}_2_LIN{{ suff }} = NULL;
+ %% endfor
+
+ %% for c in pt.chanslist
+ uint{{ gamma_out_bits(c[2]) }}_t *{{ pref+c[0] }}_2_GAMMA{{ suff }} = NULL;
+ %% endfor
+
+ %% set i = 0
+ if ({{ ctx }}->gamma) {
+ %% for c in pt.chanslist
+ {{ pref+c[0] }}_2_LIN{{ suff }} = {{ ctx }}->gamma->tables[{{ i }}]->u{{ gamma_in_bits(c[2]) }};
+ %% set i = i + 1
+ %% endfor
+
+ %% set i = len(pt.chanslist)
+ %% for c in pt.chanslist
+ {{ pref+c[0] }}_2_GAMMA{{ suff }} = {{ ctx }}->gamma->tables[{{ i }}]->u{{ gamma_out_bits(c[2]) }};
+ %% set i = i + 1
+ %% endfor
+ }
+%% endmacro
+
-----------------------------------------------------------------------
Summary of changes:
libs/filters/GP_Cubic.h | 6 +-
libs/filters/GP_Resize.c | 239 +++++------------------------------
libs/filters/GP_ResizeCubic.gen.c.t | 210 ++++++++++++++++++++++++++++++
libs/filters/Makefile | 2 +-
pylib/templates/common.c.t | 35 +++++-
5 files changed, 278 insertions(+), 214 deletions(-)
create mode 100644 libs/filters/GP_ResizeCubic.gen.c.t
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.")
1
0