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
- 929 discussions
[repo.or.cz] gfxprim.git branch generate updated: bf71ed549471116331486980f67e4f64b840640d
by metan 06 Oct '11
by metan 06 Oct '11
06 Oct '11
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, generate has been updated
via bf71ed549471116331486980f67e4f64b840640d (commit)
via 4d19114d20f531cd49c79158af4263ea4af98109 (commit)
from d291a122c53ce9d70a5777b380ae9ca82978987b (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/bf71ed549471116331486980f67e4f64b840…
commit bf71ed549471116331486980f67e4f64b840640d
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Oct 6 19:28:37 2011 +0200
Attempt to fix the aligned pixel access.
* The Get/PutPixel is now full of special cases
Beware that the code wasn't tested to work yet.
diff --git a/include/core/GP_Common.h b/include/core/GP_Common.h
index 23e5527..cae989e 100644
--- a/include/core/GP_Common.h
+++ b/include/core/GP_Common.h
@@ -140,51 +140,6 @@
a = tmp; } while (0)
-/*
- * Helper macros to read/write parts of words
- *
- * Return (shifted) count bits at offset of value
- * Note: operates with value types same as val
- */
-#define GP_GET_BITS(offset, count, val) - ( ( (val)>>(offset) ) & ( ((((typeof(val))1)<<(count)) - 1) ) )
-
-/*
- * Debugging version, evaluates args twice.
- */
-#define GP_GET_BITS_DBG(offset, count, val) - ( printf("GET_BITS(%d, %d, 0x%x)=%d", offset, count, val, - GP_GET_BITS(offset, count, val)), GP_GET_BITS(offset, count, val))
-
-/*
- * Set count bits of dest at ofset to val (shifted by offset)
- *
- * Does not check val for overflow
- * Operates on 8, 16, and 32 bit values, depending on the type of dest,
- * this should be unsigned
- *
- * GP_SET_BITS_OR anly sets (|=) the bits, assuming these are clear beforehand
- * GP_CLEAR_BITS sets the target bits to zero
- * GP_SET_BITS does both
- */
-#define GP_CLEAR_BITS(offset, count, dest) - ( (dest) &= ~(((((typeof(dest))1) << (count)) - 1) << (offset)) )
-
-#define GP_SET_BITS_OR(offset, dest, val) ( (dest) |= ((val)<<(offset)) )
-
-#define GP_SET_BITS(offset, count, dest, val) do { - GP_CLEAR_BITS(offset, count, dest); - GP_SET_BITS_OR(offset, dest, val); -} while (0)
-
-/*
- * Debugging version, evaluates args twice.
- */
-#define GP_SET_BITS_DBG(offset, count, dest, val) do { - GP_SET_BITS(offset, count, dest, val); - printf("SET_BITS(%d, %d, p, %d)n", offset, count, val); -} while (0)
-
/* Determines the sign of the integer value; it is +1 if value is positive,
* -1 if negative, and 0 if it is zero.
diff --git a/include/core/GP_Convert.gen.h.t b/include/core/GP_Convert.gen.h.t
index 56759ee..760eb74 100644
--- a/include/core/GP_Convert.gen.h.t
+++ b/include/core/GP_Convert.gen.h.t
@@ -45,7 +45,7 @@
%% block body
-#include "GP_Common.h"
+#include "GP_GetSetBits.h"
#include "GP_Context.h"
#include "GP_Pixel.h"
diff --git a/include/core/GP_GetPutPixel.gen.h.t b/include/core/GP_GetPutPixel.gen.h.t
index ee1ea90..2a8529b 100644
--- a/include/core/GP_GetPutPixel.gen.h.t
+++ b/include/core/GP_GetPutPixel.gen.h.t
@@ -7,7 +7,49 @@ Do not include directly, use GP_Pixel.h
%% block body
-#include "GP_Common.h"
+
+ /*
+
+ Note about byte aligment
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Unaligned acces happens when instruction that works with multiple byte value
+ gets an address that is not divideable by the size of the value. Eg. if 32
+ bit integer instruction gets an address that is not a multiple of 4. On
+ intel cpus this type of acces works and is supported however the C standard
+ defines this as undefined behavior. This fails to work ARM and most of the
+ non intel cpus. So some more trickery must be done in order to write
+ unaligned multibyte values. First of all we must compute offset and number of
+ bytes to be accessed (which is cruicial for speed as we are going to read the
+ pixel value byte by byte.
+
+ The offsets (starting with the first one eg. pixel_size mod 8) forms subgroup
+ in the mod 8 cyclic group. The maximal count of bits, from the start of the
+ byte, then will be max from this subgroup + pixel_size. If this number is
+ less or equal to 8 * N, we could write such pixel by writing N bytes.
+
+ For example the offsets of 16 BPP forms subgroup only with {0} so we only
+ need 2 bytes to write it. As a matter of fact the 16 and 32 BPP are special
+ cases that are always aligned and together with the 8 BPP (which is aligned
+ trivially). These three are coded as special cases which yields to faster
+ operations in case of 16 and 32 BPP. The 24 BPP is not aligned as there are
+ no instruction to operate 3 byte long numbers.
+
+ For second example take offsets of 20 BPP that forms subgroup {4, 0}
+ so the max + pixel_size = 24 and indeed we fit into 3 bytes.
+
+ If pixel_size is coprime to 8, the offsets generates whole group and so
+ the max + pixel_size = 7 + pixel_size. The 17 BPP fits into 24 bits and
+ so also 3 bytes are needed. The 19 BPP fits into 26 bits and because of
+ that 4 bytes are needed.
+
+ Once we figure maximal number of bytes and the offset all that is to be done
+ is to fetch first and last byte to combine it together with given pixel value
+ and write the result back to the bitmap.
+
+ */
+
+#include "GP_GetSetBits.h"
#include "GP_Context.h"
%% for ps in pixelsizes
@@ -44,12 +86,73 @@ Do not include directly, use GP_Pixel.h
*/
static inline GP_Pixel GP_GetPixel_Raw_{{ ps.suffix }}(const GP_Context *c, int x, int y)
{
-{# Special case to prevent some of the "overflow" warnings -#}
-%% if ps.size == config.pixel_size
- return *(GP_PIXEL_ADDR_{{ ps.suffix}}(c, x, y));
+%% if ps.size == 32
+ /*
+ * 32 BPP is expected to have aligned pixels
+ */
+ return *((uint32_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y));
+%% elif ps.size == 16
+ /*
+ * 16 BPP is expected to have aligned pixels
+ */
+ return *((uint16_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y));
+%% elif ps.size == 8
+ /*
+ * 8 BPP is byte aligned
+ */
+ return *((uint8_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y));
+%% elif ps.size == 1 or ps.size == 2 or ps.size == 4 or ps.size == 8
+ /*
+ * Whole pixel is stored only and only in one byte
+ *
+ * The full list = {1, 2, 4, 8}
+ */
+ return GP_GET_BITS1_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ *(GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)));
+%% elif ps.size <= 10 or ps.size == 12 or ps.size == 16
+ /*
+ * The pixel is stored in one or two bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 16
+ *
+ * The full list = {3, 5, 6, 7, 9, 10, 12, 16}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ return GP_GET_BITS2_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ *(GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)));
+%% elif ps.size <= 18 or ps.size == 20 or ps.size == 24
+ /*
+ * The pixel is stored in two or three bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 24
+ *
+ * The full list = {11, 13, 14, 15, 17, 18, 20, 24}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ return GP_GET_BITS3_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ *(GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)));
+%% elif ps.size <= 23 or ps.size == 25 or ps.size == 26 or ps.size == 28 or ps.size == 32
+ /*
+ * The pixel is stored in three or four bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 32
+ *
+ * The full list = {19, 21, 22, 23, 25, 26, 28, 32}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ return GP_GET_BITS4_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ *(GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)));
%% else
- return GP_GET_BITS(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
- *(GP_PIXEL_ADDR_{{ ps.suffix}}(c, x, y)));
+ #error not implemented
%% endif
}
@@ -58,12 +161,73 @@ static inline GP_Pixel GP_GetPixel_Raw_{{ ps.suffix }}(const GP_Context *c, int
*/
static inline void GP_PutPixel_Raw_{{ ps.suffix }}(GP_Context *c, int x, int y, GP_Pixel p)
{
-{# Special case to prevent some of the "overflow" warnings -#}
-%% if ps.size == config.pixel_size
- *(GP_PIXEL_ADDR_{{ ps.suffix}}(c, x, y)) = p;
+%% if ps.size == 32
+ /*
+ * 32 BPP is expected to have aligned pixels
+ */
+ *((uint32_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)) = p;
+%% elif ps.size == 16
+ /*
+ * 16 BPP is expected to have aligned pixels
+ */
+ *((uint16_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)) = p;
+%% elif ps.size == 8
+ /*
+ * 8 BPP is byte aligned
+ */
+ *((uint8_t*)GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y)) = p;
+%% elif ps.size == 1 or ps.size == 2 or ps.size == 4 or ps.size == 8
+ /*
+ * Whole pixel is stored only and only in one byte
+ *
+ * The full list = {1, 2, 4, 8}
+ */
+ GP_SET_BITS1_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y), p);
+%% elif ps.size <= 10 or ps.size == 12 or ps.size == 16
+ /*
+ * The pixel is stored in one or two bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 16
+ *
+ * The full list = {3, 5, 6, 7, 9, 10, 12, 16}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ GP_SET_BITS2_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y), p);
+%% elif ps.size <= 18 or ps.size == 20 or ps.size == 24
+ /*
+ * The pixel is stored in two or three bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 24
+ *
+ * The full list = {11, 13, 14, 15, 17, 18, 20, 24}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ GP_SET_BITS3_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y), p);
+%% elif ps.size <= 23 or ps.size == 25 or ps.size == 26 or ps.size == 28 or ps.size == 32
+ /*
+ * The pixel is stored in three or four bytes
+ *
+ * The max from subgroup (of mod 8 factor group) generated by
+ * pixel_size mod 8 + pixel_size <= 32
+ *
+ * The full list = {19, 21, 22, 23, 25, 26, 28, 32}
+ *
+ * Hint: If the pixel size is coprime to 8 the group is generated by
+ * pixel_size mod 8 and maximal size thus is pixel_size + 7
+ */
+ GP_SET_BITS4_ALIGNED(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
+ GP_PIXEL_ADDR_{{ ps.suffix }}(c, x, y), p);
%% else
- GP_SET_BITS(GP_PIXEL_ADDR_OFFSET_{{ ps.suffix }}(x), {{ ps.size }},
- *(GP_PIXEL_ADDR_{{ ps.suffix}}(c, x, y)), p);
+ #error not implemented
%% endif
}
diff --git a/include/core/GP_GetSetBits.h b/include/core/GP_GetSetBits.h
new file mode 100644
index 0000000..bd55fe2
--- /dev/null
+++ b/include/core/GP_GetSetBits.h
@@ -0,0 +1,148 @@
+/*****************************************************************************
+ * 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) 2011 Tomas Gavenciak <gavento(a)ucw.cz> *
+ * Copyright (C) 2011 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ The macros are taking generally three arguments
+
+ */
+
+#ifndef GP_GET_SET_BITS_H
+#define GP_GET_SET_BITS_H
+
+/*
+ * Helper macros to read/write parts of words
+ *
+ * Return (shifted) count bits at offset of value
+ * Note: operates with value types same as val
+ */
+#define GP_GET_BITS(offset, len, val) + ( ( (val)>>(offset) ) & ( ((((typeof(val))1)<<(len)) - 1) ) )
+
+/*
+ * Align-safe getbits
+ *
+ * TODO: Fix big endian
+ */
+#define GP_GET_BITS4_ALIGNED(offset, len, val) ({ + uint32_t v; + v = ((uint8_t *)&val)[0]; + v |= ((uint8_t *)&val)[1]<<8; + v |= ((uint8_t *)&val)[2]<<16; + v |= ((uint8_t *)&val)[3]<<24; + + GP_GET_BITS(offset, len, v); +})
+
+#define GP_GET_BITS3_ALIGNED(offset, len, val) ({ + uint32_t v; + v = ((uint8_t *)&val)[0]; + v |= ((uint8_t *)&val)[1]<<8; + v |= ((uint8_t *)&val)[2]<<16; + + GP_GET_BITS(offset, len, v); +})
+
+#define GP_GET_BITS2_ALIGNED(offset, len, val) ({ + uint16_t v; + v = ((uint8_t *)&val)[0]; + v |= ((uint8_t *)&val)[1]<<8; + + GP_GET_BITS(offset, len, v); +})
+
+#define GP_GET_BITS1_ALIGNED(offset, len, val) ({ + uint8_t v; + v = ((uint8_t *)&val)[0]; + + GP_GET_BITS(offset, len, v); +})
+
+/*
+ * Set count bits of dest at ofset to val (shifted by offset)
+ *
+ * Does not check val for overflow
+ * Operates on 8, 16, and 32 bit values, depending on the type of dest,
+ * this should be unsigned
+ *
+ * GP_SET_BITS_OR anly sets (|=) the bits, assuming these are clear beforehand
+ * GP_CLEAR_BITS sets the target bits to zero
+ * GP_SET_BITS does both
+ */
+#define GP_CLEAR_BITS(offset, len, dest) + ( (dest) &= ~(((((typeof(dest))1) << (len)) - 1) << (offset)) )
+
+#define GP_SET_BITS_OR(offset, dest, val) ( (dest) |= ((val)<<(offset)) )
+
+#define GP_SET_BITS(offset, len, dest, val) do { + GP_CLEAR_BITS(offset, len, dest); + GP_SET_BITS_OR(offset, dest, val); +} while (0)
+
+/*
+ * Align-safe setbits
+ */
+#define GP_SET_BITS1_ALIGNED(offset, len, dest, val) do { + uint8_t v = ((uint8_t *)dest)[0]; + GP_SET_BITS(offset, len, v, val); + ((uint8_t *)dest)[0] = v; +} while (0)
+
+#define GP_SET_BITS2_ALIGNED(offset, len, dest, val) do { + uint16_t v; + v = ((uint8_t *)dest)[0]; + v |= ((uint8_t *)dest)[1]<<8; + + GP_SET_BITS(offset, len, v, val); + + ((uint8_t *)dest)[0] = 0xff & v; + ((uint8_t *)dest)[1] = 0xff & (v >> 8); +} while (0)
+
+#define GP_SET_BITS3_ALIGNED(offset, len, dest, val) do { + uint32_t v; + v = ((uint8_t *)dest)[0]; + v |= ((uint8_t *)dest)[2]<<16; + + GP_SET_BITS(offset, len, v, val); + + ((uint8_t *)dest)[0] = 0xff & v; + ((uint8_t *)dest)[1] = 0xff & (v >> 8); + ((uint8_t *)dest)[2] = 0xff & (v >> 16); +} while (0)
+
+#define GP_SET_BITS4_ALIGNED(offset, len, dest, val) do { + uint32_t v; + v = ((uint8_t *)dest)[0]; + v |= ((uint8_t *)dest)[3]<<24; + + GP_SET_BITS(offset, len, v, val); + + ((uint8_t *)dest)[0] = 0xff & v; + ((uint8_t *)dest)[1] = 0xff & (v >> 8); + ((uint8_t *)dest)[2] = 0xff & (v >> 16); + ((uint8_t *)dest)[3] = 0xff & (v >> 24); +} while (0)
+
+
+#endif /* GP_GET_SET_BITS_H */
diff --git a/libs/core/GP_Pixel.gen.c.t b/libs/core/GP_Pixel.gen.c.t
index e0cf7c0..f41625b 100644
--- a/libs/core/GP_Pixel.gen.c.t
+++ b/libs/core/GP_Pixel.gen.c.t
@@ -8,6 +8,7 @@ Do not include directly, use GP_Pixel.h
%% block body
#include <stdio.h>
#include "GP_Pixel.h"
+#include "GP_GetSetBits.h"
/*
* Description of all known pixel types
@@ -29,6 +30,8 @@ const GP_PixelTypeDescription const GP_PixelTypes [] = {
%% endfor
};
+#warning FIXME: do generic get set bit for pixel printing
+
%% for pt in pixeltypes
%% if not pt.is_unknown()
/*
diff --git a/tests/SDL/shapetest.c b/tests/SDL/shapetest.c
index 57cca2d..3c61629 100644
--- a/tests/SDL/shapetest.c
+++ b/tests/SDL/shapetest.c
@@ -485,6 +485,8 @@ int main(int argc, char ** argv)
}
}
+ GP_SetDebugLevel(10);
+
/* Initialize SDL */
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
fprintf(stderr, "Could not initialize SDL: %sn", SDL_GetError());
http://repo.or.cz/w/gfxprim.git/commit/4d19114d20f531cd49c79158af4263ea4af9…
commit 4d19114d20f531cd49c79158af4263ea4af98109
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Oct 6 18:15:08 2011 +0200
Remove the compression from the 'make tar' target.
The compression of .git repository data is too slow
and takes several minutes, which is bad, when you are
about to leave the train, but the data needs to be
backed up.
diff --git a/Makefile b/Makefile
index 5c4d45f..acc8543 100644
--- a/Makefile
+++ b/Makefile
@@ -35,4 +35,4 @@ endif
tar:
$(MAKE) clean
- cd .. && tar cjf gfxprim-`date +%Y-%b-%d-%HH%MM`.tar.bz2 gfxprim
+ cd .. && tar cf gfxprim-`date +%Y-%b-%d-%HH%MM`.tar gfxprim
-----------------------------------------------------------------------
Summary of changes:
Makefile | 2 +-
include/core/GP_Common.h | 45 ---------
include/core/GP_Convert.gen.h.t | 2 +-
include/core/GP_GetPutPixel.gen.h.t | 186 ++++++++++++++++++++++++++++++++--
include/core/GP_GetSetBits.h | 148 ++++++++++++++++++++++++++++
libs/core/GP_Pixel.gen.c.t | 3 +
tests/SDL/shapetest.c | 2 +
7 files changed, 330 insertions(+), 58 deletions(-)
create mode 100644 include/core/GP_GetSetBits.h
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 generate updated: d291a122c53ce9d70a5777b380ae9ca82978987b
by metan 04 Oct '11
by metan 04 Oct '11
04 Oct '11
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, generate has been updated
via d291a122c53ce9d70a5777b380ae9ca82978987b (commit)
via 2754045bba9b30539121e3a860de208463511fe3 (commit)
via a26979d8c8abdbf13131422e59e055e4abf39918 (commit)
via 871fb9ebb0895f698f22e2ad4cbe983e78d5c194 (commit)
from b51b045c4d615a275513234d727bb99d90ecfa80 (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/d291a122c53ce9d70a5777b380ae9ca82978…
commit d291a122c53ce9d70a5777b380ae9ca82978987b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Oct 4 20:14:27 2011 +0200
Make grinder parameter parsing little more robust.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index a0e8f2c..26d6d0d 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -428,11 +428,11 @@ static const char *app_help = {
" n"
" <<<<<<<<<< Bitmap Grinder >>>>>>>>>>> n"
" n"
- " +-+-----+ n"
- " / | +-+| .11. n"
+ " +~+-----+ n"
+ " /| | +-+| .11. n"
" +-{ D| |010101011. n"
- " | \ | +-.0100101. n"
- " O=+ +-+-----+ .10110101. n"
+ " | \| | +-.0100101. n"
+ " O=+ +~+-----+ .10110101. n"
" .010101. n"
" .1. n"
" n"
@@ -481,7 +481,16 @@ int main(int argc, char *argv[])
return 0;
break;
case 'v':
- GP_SetDebugLevel(atoi(optarg));
+ i = atoi(optarg);
+
+ if (i == 0) {
+ fprintf(stderr, "ERROR: invalid debug level "
+ "'%s', expected number > 0n",
+ optarg);
+ return 1;
+ }
+
+ GP_SetDebugLevel(i);
break;
case 'f':
add_filter(optarg);
@@ -496,8 +505,7 @@ int main(int argc, char *argv[])
}
if (optind >= argc) {
- fprintf(stderr, "Expected bitmap filenamesn");
- print_help();
+ fprintf(stderr, "ERROR: Expected bitmap filenamesn");
return 1;
}
http://repo.or.cz/w/gfxprim.git/commit/2754045bba9b30539121e3a860de20846351…
commit 2754045bba9b30539121e3a860de208463511fe3
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Oct 4 20:09:24 2011 +0200
Fixed error value from GP_LoadImage.
Fixed error value from GP_LoadImage
in case file doesn't exist/user has
no permisssion to read it.
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loaders.c
index 72e2a31..63f1da5 100644
--- a/libs/loaders/GP_Loaders.c
+++ b/libs/loaders/GP_Loaders.c
@@ -27,6 +27,10 @@
*/
#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <GP_Debug.h>
#include "GP_Loaders.h"
@@ -35,6 +39,12 @@ GP_RetCode GP_LoadImage(const char *src_path, GP_Context **res)
int len = strlen(src_path);
GP_RetCode ret = GP_ENOIMPL;
+ if (access(src_path, R_OK)) {
+ GP_DEBUG(1, "Failed to access file '%s' : %s",
+ src_path, strerror(errno));
+ return GP_EBADFILE;
+ }
+
switch (src_path[len - 1]) {
/* PNG, JPG, JPEG */
case 'g':
http://repo.or.cz/w/gfxprim.git/commit/a26979d8c8abdbf13131422e59e055e4abf3…
commit a26979d8c8abdbf13131422e59e055e4abf39918
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Oct 4 19:48:39 2011 +0200
Added some more info to grinder README.
diff --git a/demos/grinder/README b/demos/grinder/README
index 749485f..ad2c2e7 100644
--- a/demos/grinder/README
+++ b/demos/grinder/README
@@ -10,3 +10,35 @@ grinder -f filter_name:filter_params... -f filter_name:filter_params... -f filte
Which will apply pipeline of filters to each image and store results to out_X.ppm
see grinder -h for list of filters and options
+
+
+COOL EFECTS
+~~~~~~~~~~~
+
+Pixelize yourself
+-----------------
+
+This filter creates pixelated image of the input (for example photograph of your head).
+
+grinder -p -f resize:ratio=0.2 -f blur:sigma=4 -f resize:ratio=0.1 -f resize:alg=nn:ratio=4 head.png
+
+And now, what it does:
+
+* The first resize just resizes down the image as the images that gets out a
+ digital camera are usually too big and too noisy. This only prepares the
+ image so it has reasonable size. Ideally there should be a low-pass filter
+ (eg. gaussian blur) before each downscaling but as we are scaling the image
+ further, we don't care now.
+
+* The blur does low-pass filter (cuts off all high frequencies). If you are not
+ familiar with digital signal processing, think of this just as smoothing the
+ image after the interpolation (which works only on a few neighbour pixels so
+ on downscaling some of the pixels may not be used for the interpolation at
+ all).
+
+* The second resize resizes the image to be really small (and the result is
+ quite good looking as we used low-pass filter beforhand).
+
+* The last resize scales the image up, but this time we used nearest neighbour
+ interpolation, which just picks up one pixel which is nearest to the
+ interpolated value. This actually creates the 'pixel' effect.
http://repo.or.cz/w/gfxprim.git/commit/871fb9ebb0895f698f22e2ad4cbe983e78d5…
commit 871fb9ebb0895f698f22e2ad4cbe983e78d5c194
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Oct 4 19:45:57 2011 +0200
Optimized convolution, made it non static.
* Optimized convolution for separable filters
- that leads to 10-30% faster gaussian blur
* Made the convolution declarations public
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h
index ae0debd..3194cb8 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Linear.h
@@ -36,7 +36,10 @@
*
* The sigma parameters defines the blur radii in horizontal and vertical
* direction.
- *
+ *
+ * Internaly this is implemented as separable linear filter (calls vertical and
+ * horizontal convolution with generated gaussian kernel).
+ *
* This variant could work in-place so it's perectly okay to call
*
* GP_FilterGaussianBlur_Raw(context, context, ...);
@@ -49,4 +52,41 @@ GP_Context *GP_FilterGaussianBlur(GP_Context *src,
GP_ProgressCallback *callback,
float sigma_x, float sigma_y);
+/*
+ * Linear convolution.
+ *
+ * The kernel is array of kw * kh floats and is indexed as two directional array.
+ *
+ * To define 3x3 average filter
+ *
+ * kernel[] = {
+ * 1, 1, 1,
+ * 1, 1, 1,
+ * 1, 1, 1,
+ * };
+ *
+ * kw = kh = 3
+ *
+ * This function works also in-place.
+ */
+void GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kw, uint32_t kh);
+
+/*
+ * Special cases for convolution only in horizontal/vertical direction.
+ *
+ * These are about 10-30% faster than the generic implementation (depending on
+ * the kernel size, bigger kernel == more savings).
+ *
+ * Both works also in-place.
+ */
+void GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kw);
+
+void GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kh);
+
#endif /* GP_LINEAR_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 48dc0ee..8f7c2a3 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -29,10 +29,6 @@
#include <GP_Linear.h>
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res,
- GP_ProgressCallback *callback,
- float kernel[], uint32_t kw, uint32_t kh);
-
static inline unsigned int gaussian_kernel_size(float sigma)
{
int center = 3 * sigma;
@@ -83,21 +79,25 @@ void GP_FilterGaussianBlur_Raw(GP_Context *src, GP_Context *res,
if (callback != NULL)
new_callback = &gaussian_callback;
- /* compute kernel and apply on horizontal direction */
+ /* compute kernel and apply in horizontal direction */
if (sigma_x > 0) {
float kernel_x[size_x];
gaussian_kernel_init(sigma_x, kernel_x);
- GP_FilterLinearConvolution(src, res, new_callback, kernel_x, size_x, 1);
+
+ GP_FilterHLinearConvolution_Raw(src, res, new_callback,
+ kernel_x, size_x);
}
if (new_callback != NULL)
new_callback->callback = gaussian_callback_2;
- /* compute kernel and apply on vertical direction */
+ /* compute kernel and apply in vertical direction */
if (sigma_y > 0) {
float kernel_y[size_y];
gaussian_kernel_init(sigma_y, kernel_y);
- GP_FilterLinearConvolution(res, res, new_callback, kernel_y, 1, size_y);
+
+ GP_FilterVLinearConvolution_Raw(res, res, new_callback,
+ kernel_y, size_y);
}
GP_ProgressCallbackDone(callback);
@@ -124,9 +124,220 @@ GP_Context *GP_FilterGaussianBlur(GP_Context *src,
return res;
}
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res,
- GP_ProgressCallback *callback,
- float kernel[], uint32_t kw, uint32_t kh)
+void GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kw)
+{
+ float kernel_sum = 0;
+ GP_Coord x, y;
+ uint32_t i;
+
+ 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 += kernel[i];
+
+ /* do linear convolution */
+ for (y = 0; y < (GP_Coord)res->h; y++) {
+ GP_Pixel pix;
+ uint32_t R[kw], G[kw], B[kw];
+
+ /* prefill the buffer on the start */
+ for (i = 0; i < kw - 1; i++) {
+ int cx = i - kw/2;
+
+ if (cx < 0)
+ cx = 0;
+
+ pix = GP_GetPixel_Raw_24BPP(src, cx, y);
+
+ R[i] = GP_Pixel_GET_R_RGB888(pix);
+ G[i] = GP_Pixel_GET_G_RGB888(pix);
+ B[i] = GP_Pixel_GET_B_RGB888(pix);
+ }
+
+ int idx = kw - 1;
+
+ for (x = 0; x < (GP_Coord)res->w; x++) {
+ float r = 0, g = 0, b = 0;
+
+ int cx = x + kw/2;
+
+ if (cx >= (int)src->w)
+ cx = src->w - 1;
+
+ pix = GP_GetPixel_Raw_24BPP(src, cx, y);
+
+ R[idx] = GP_Pixel_GET_R_RGB888(pix);
+ G[idx] = GP_Pixel_GET_G_RGB888(pix);
+ B[idx] = GP_Pixel_GET_B_RGB888(pix);
+
+ /* count the pixel value from neighbours weighted by kernel */
+ for (i = 0; i < kw; i++) {
+ int k;
+
+ if ((int)i < idx + 1)
+ k = kw - idx - 1 + i;
+ else
+ k = i - idx - 1;
+
+ r += R[i] * kernel[k];
+ g += G[i] * kernel[k];
+ b += B[i] * kernel[k];
+ }
+
+ /* normalize the result */
+ r /= kernel_sum;
+ g /= kernel_sum;
+ b /= kernel_sum;
+
+ /* and clamp just to be extra sure */
+ if (r > 255)
+ r = 255;
+ if (r < 0)
+ r = 0;
+ if (g > 255)
+ g = 255;
+ if (g < 0)
+ g = 0;
+ if (b > 255)
+ b = 255;
+ if (b < 0)
+ b = 0;
+
+ pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
+
+ GP_PutPixel_Raw_24BPP(res, x, y, pix);
+
+ idx++;
+
+ if (idx >= (int)kw)
+ idx = 0;
+ }
+
+ if (callback != NULL && y % 100 == 0)
+ GP_ProgressCallbackReport(callback, 100.00 * y/res->h);
+ }
+
+ GP_ProgressCallbackDone(callback);
+}
+
+/*
+ * Special case for vertical only kernel (10-30% faster).
+ *
+ * Can be used in-place.
+ */
+void GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kh)
+{
+ float kernel_sum = 0;
+ GP_Coord x, y;
+ uint32_t i;
+
+ 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 += kernel[i];
+
+ /* do linear convolution */
+ for (x = 0; x < (GP_Coord)res->w; x++) {
+ GP_Pixel pix;
+ uint32_t R[kh], G[kh], B[kh];
+
+ /* prefill the buffer on the start */
+ for (i = 0; i < kh - 1; i++) {
+ int cy = i - kh/2;
+
+ if (cy < 0)
+ cy = 0;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, cy);
+
+ R[i] = GP_Pixel_GET_R_RGB888(pix);
+ G[i] = GP_Pixel_GET_G_RGB888(pix);
+ B[i] = GP_Pixel_GET_B_RGB888(pix);
+ }
+
+ int idx = kh - 1;
+
+ for (y = 0; y < (GP_Coord)res->h; y++) {
+ float r = 0, g = 0, b = 0;
+
+ int cy = y + kh/2;
+
+ if (cy >= (int)src->h)
+ cy = src->h - 1;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, cy);
+
+ R[idx] = GP_Pixel_GET_R_RGB888(pix);
+ G[idx] = GP_Pixel_GET_G_RGB888(pix);
+ B[idx] = GP_Pixel_GET_B_RGB888(pix);
+
+ /* count the pixel value from neighbours weighted by kernel */
+ for (i = 0; i < kh; i++) {
+ int k;
+
+ if ((int)i < idx + 1)
+ k = kh - idx - 1 + i;
+ else
+ k = i - idx - 1;
+
+ r += R[i] * kernel[k];
+ g += G[i] * kernel[k];
+ b += B[i] * kernel[k];
+ }
+
+ /* normalize the result */
+ r /= kernel_sum;
+ g /= kernel_sum;
+ b /= kernel_sum;
+
+ /* and clamp just to be extra sure */
+ if (r > 255)
+ r = 255;
+ if (r < 0)
+ r = 0;
+ if (g > 255)
+ g = 255;
+ if (g < 0)
+ g = 0;
+ if (b > 255)
+ b = 255;
+ if (b < 0)
+ b = 0;
+
+ pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
+
+ GP_PutPixel_Raw_24BPP(res, x, y, pix);
+
+ idx++;
+
+ if (idx >= (int)kh)
+ idx = 0;
+ }
+
+ if (callback != NULL && x % 100 == 0)
+ GP_ProgressCallbackReport(callback, 100.00 * x/res->w);
+ }
+
+ GP_ProgressCallbackDone(callback);
+}
+
+
+/*
+ * Linear convolution.
+ *
+ * Can be used in-place.
+ */
+void GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float kernel[], uint32_t kw, uint32_t kh)
{
float kernel_sum = 0;
GP_Coord x, y;
@@ -216,10 +427,16 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res,
/* and clamp just to be extra sure */
if (r > 255)
r = 255;
+ if (r < 0)
+ r = 0;
if (g > 255)
g = 255;
+ if (g < 0)
+ g = 0;
if (b > 255)
b = 255;
+ if (b < 0)
+ b = 0;
pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/README | 32 ++++++
demos/grinder/grinder.c | 22 +++--
include/filters/GP_Linear.h | 42 ++++++++-
libs/filters/GP_Linear.c | 239 +++++++++++++++++++++++++++++++++++++++++--
libs/loaders/GP_Loaders.c | 10 ++
5 files changed, 326 insertions(+), 19 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 generate updated: b51b045c4d615a275513234d727bb99d90ecfa80
by bluebear 03 Oct '11
by bluebear 03 Oct '11
03 Oct '11
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, generate has been updated
via b51b045c4d615a275513234d727bb99d90ecfa80 (commit)
via e4cf0a42e6042ad9020da661c5beb10870c2dcfa (commit)
from b24c82a3c5df97a39f72ec848917e4eb56f34d8c (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/b51b045c4d615a275513234d727bb99d90ec…
commit b51b045c4d615a275513234d727bb99d90ecfa80
Merge: e4cf0a4 b24c82a
Author: BlueBear <jiri.bluebear.dluhos(a)gmail.com>
Date: Mon Oct 3 00:44:54 2011 +0200
Merge branch 'generate' of git://repo.or.cz/gfxprim into generate
http://repo.or.cz/w/gfxprim.git/commit/e4cf0a42e6042ad9020da661c5beb10870c2…
commit e4cf0a42e6042ad9020da661c5beb10870c2dcfa
Author: BlueBear <jiri.bluebear.dluhos(a)gmail.com>
Date: Mon Oct 3 00:44:30 2011 +0200
Fixed (hopefully) more +/-1 errors in Ring.
diff --git a/libs/gfx/algo/FillRing.algo.h b/libs/gfx/algo/FillRing.algo.h
index 96dfa79..9b3a002 100644
--- a/libs/gfx/algo/FillRing.algo.h
+++ b/libs/gfx/algo/FillRing.algo.h
@@ -54,17 +54,17 @@ void FN_NAME(CONTEXT_T context, int xcenter, int ycenter, } outer_error += -2*y + 1; - if (y <= (int) inner_r && y >= -((int) inner_r)) { + if (y < inner_r && y > -inner_r) { while (inner_error < 0) { inner_error += 2*inner_x + 1; inner_x++; } inner_error += -2*y + 1; - HLINE(context, xcenter - outer_x + 1, xcenter - inner_x + 1, ycenter - y, pixval); - HLINE(context, xcenter + inner_x - 1, xcenter + outer_x - 1, ycenter - y, pixval); - HLINE(context, xcenter - outer_x + 1, xcenter - inner_x + 1, ycenter + y, pixval); - HLINE(context, xcenter + inner_x - 1, xcenter + outer_x - 1, ycenter + y, pixval); + HLINE(context, xcenter - outer_x + 1, xcenter - inner_x, ycenter - y, pixval); + HLINE(context, xcenter + inner_x, xcenter + outer_x - 1, ycenter - y, pixval); + HLINE(context, xcenter - outer_x + 1, xcenter - inner_x, ycenter + y, pixval); + HLINE(context, xcenter + inner_x, xcenter + outer_x
- 1, ycenter + y, pixval); } else { HLINE(context, xcenter - outer_x + 1, xcenter + outer_x - 1, ycenter-y, pixval); HLINE(context, xcenter - outer_x + 1, xcenter + outer_x - 1, ycenter+y, pixval);
-----------------------------------------------------------------------
Summary of changes:
libs/gfx/algo/FillRing.algo.h | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
[repo.or.cz] gfxprim.git branch generate updated: b24c82a3c5df97a39f72ec848917e4eb56f34d8c
by metan 02 Oct '11
by metan 02 Oct '11
02 Oct '11
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, generate has been updated
via b24c82a3c5df97a39f72ec848917e4eb56f34d8c (commit)
via 50865b7cb15b959c035b59ad6cbfaffa23bf69e5 (commit)
via 448b2fe286974b47356304c85b66982b933f8ada (commit)
from bc1b6594de0de8e6f717e824e3ded14e95b95870 (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/b24c82a3c5df97a39f72ec848917e4eb56f3…
commit b24c82a3c5df97a39f72ec848917e4eb56f34d8c
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 18:19:43 2011 +0200
Add parameters for nonsymetric blur.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 3c0c075..a0e8f2c 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -314,8 +314,8 @@ static GP_RetCode blur(GP_Context **c, const char *params)
sigma_y = sigma;
}
- if (sigma_x <= 0 || sigma_y <= 0) {
- print_error("blur: sigma_x and sigma_y parameter must be >= 0");
+ if (sigma_x <= 0 && sigma_y <= 0) {
+ print_error("blur: at least one of sigma_x and sigma_y must be >= 0");
return GP_EINVAL;
}
http://repo.or.cz/w/gfxprim.git/commit/50865b7cb15b959c035b59ad6cbfaffa23bf…
commit 50865b7cb15b959c035b59ad6cbfaffa23bf69e5
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 18:19:18 2011 +0200
Fix gaussian blur only in one direction.
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 1538ee2..48dc0ee 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -84,22 +84,23 @@ void GP_FilterGaussianBlur_Raw(GP_Context *src, GP_Context *res,
new_callback = &gaussian_callback;
/* compute kernel and apply on horizontal direction */
- float kernel_x[size_x];
- gaussian_kernel_init(sigma_x, kernel_x);
- GP_FilterLinearConvolution(src, res, new_callback, kernel_x, size_x, 1);
-
+ if (sigma_x > 0) {
+ float kernel_x[size_x];
+ gaussian_kernel_init(sigma_x, kernel_x);
+ GP_FilterLinearConvolution(src, res, new_callback, kernel_x, size_x, 1);
+ }
+
if (new_callback != NULL)
new_callback->callback = gaussian_callback_2;
/* compute kernel and apply on vertical direction */
- float kernel_y[size_y];
- gaussian_kernel_init(sigma_y, kernel_y);
- GP_FilterLinearConvolution(res, res, new_callback, kernel_y, 1, size_y);
-
- if (callback != NULL) {
- callback->percentage = 100;
- callback->callback(callback);
+ if (sigma_y > 0) {
+ float kernel_y[size_y];
+ gaussian_kernel_init(sigma_y, kernel_y);
+ GP_FilterLinearConvolution(res, res, new_callback, kernel_y, 1, size_y);
}
+
+ GP_ProgressCallbackDone(callback);
}
GP_Context *GP_FilterGaussianBlur(GP_Context *src,
http://repo.or.cz/w/gfxprim.git/commit/448b2fe286974b47356304c85b66982b933f…
commit 448b2fe286974b47356304c85b66982b933f8ada
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 18:13:39 2011 +0200
grinder: gaussian blur: add params for two sigmas.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index a2f6d4d..3c0c075 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -149,8 +149,8 @@ static int scale_check_size(const struct param *self __attribute__((unused)),
static struct param scale_params[] = {
{"alg", PARAM_ENUM, "algorithm to be used", scale_algs, NULL},
- {"w", PARAM_INT, "new width", NULL, scale_check_size},
- {"h", PARAM_INT, "new height", NULL, scale_check_size},
+ {"w", PARAM_INT, "new width (only width may be passed)", NULL, scale_check_size},
+ {"h", PARAM_INT, "new height (only height may be passed)", NULL, scale_check_size},
{NULL, 0, NULL, NULL, NULL}
};
@@ -294,24 +294,32 @@ static GP_RetCode invert(GP_Context **c, const char *params)
}
static struct param blur_params[] = {
- {"sigma", PARAM_FLOAT, "sigma parameter (eg. radii of blur)", NULL, NULL},
+ {"sigma", PARAM_FLOAT, "sigma parameter, radii of blur (sets both)", NULL, NULL},
+ {"sigma_x", PARAM_FLOAT, "sigma parameter for horizontal direction", NULL, NULL},
+ {"sigma_y", PARAM_FLOAT, "sigma parameter for vertical direction", NULL, NULL},
{NULL, 0, NULL, NULL, NULL}
};
static GP_RetCode blur(GP_Context **c, const char *params)
{
float sigma = 0;
+ float sigma_x = 0;
+ float sigma_y = 0;
- if (param_parse(params, blur_params, "blur", param_err, &sigma))
+ if (param_parse(params, blur_params, "blur", param_err, &sigma, &sigma_x, &sigma_y))
return GP_EINVAL;
- if (sigma <= 0) {
- print_error("blur: sigma parameter must be >= 0");
+ if (sigma > 0) {
+ sigma_x = sigma;
+ sigma_y = sigma;
+ }
+
+ if (sigma_x <= 0 || sigma_y <= 0) {
+ print_error("blur: sigma_x and sigma_y parameter must be >= 0");
return GP_EINVAL;
}
-
- GP_FilterGaussianBlur_Raw(*c, *c, progress_callback, sigma, sigma);
+ GP_FilterGaussianBlur_Raw(*c, *c, progress_callback, sigma_x, sigma_y);
return GP_ESUCCESS;
}
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/grinder.c | 24 ++++++++++++++++--------
libs/filters/GP_Linear.c | 23 ++++++++++++-----------
2 files changed, 28 insertions(+), 19 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 generate updated: bc1b6594de0de8e6f717e824e3ded14e95b95870
by metan 02 Oct '11
by metan 02 Oct '11
02 Oct '11
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, generate has been updated
via bc1b6594de0de8e6f717e824e3ded14e95b95870 (commit)
from 108607fa657f1e25d17ee497bfc1b840f5e9ac0c (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/bc1b6594de0de8e6f717e824e3ded14e95b9…
commit bc1b6594de0de8e6f717e824e3ded14e95b95870
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 17:46:59 2011 +0200
Some small fixes for grinder.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 8da1833..a2f6d4d 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -164,11 +164,17 @@ static GP_RetCode scale(GP_Context **c, const char *params)
&alg, &w, &h))
return GP_EINVAL;
- if (w == -1 || h == -1) {
+ if (w == -1 && h == -1) {
print_error("scale: w and/or h missing");
return GP_EINVAL;
}
+ if (w == -1)
+ w = (*c)->w * (1.00 * h/(*c)->h) + 0.5;
+
+ if (h == -1)
+ h = (*c)->h * (1.00 * w/(*c)->w) + 0.5;
+
GP_Context *res = NULL;
res = GP_FilterResize(*c, progress_callback, alg, w, h);
@@ -304,15 +310,8 @@ static GP_RetCode blur(GP_Context **c, const char *params)
return GP_EINVAL;
}
- GP_Context *res = NULL;
+ GP_FilterGaussianBlur_Raw(*c, *c, progress_callback, sigma, sigma);
- res = GP_FilterGaussianBlur(*c, progress_callback, sigma, sigma);
-
- if (res == NULL)
- return GP_EINVAL;
-
- GP_ContextFree(*c);
- *c = res;
return GP_ESUCCESS;
}
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/grinder.c | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 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 generate updated: 108607fa657f1e25d17ee497bfc1b840f5e9ac0c
by metan 02 Oct '11
by metan 02 Oct '11
02 Oct '11
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, generate has been updated
via 108607fa657f1e25d17ee497bfc1b840f5e9ac0c (commit)
via 27108512e85e27b4f46c4be703126f2b2ee9fd68 (commit)
via af00d9dd985a5b6a6ef304281a94ddd245e05cc4 (commit)
via def6da387aaeaaef3071c0015ec053561da26780 (commit)
from 631e1ca332e1b3bfccd1ebc4d83fa407eba13d51 (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/108607fa657f1e25d17ee497bfc1b840f5e9…
commit 108607fa657f1e25d17ee497bfc1b840f5e9ac0c
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 17:08:41 2011 +0200
Way more work on the progress callback.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 4ea0543..8da1833 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -29,6 +29,16 @@
#include "params.h"
+static GP_ProgressCallback *progress_callback = NULL;
+
+static const char *progress_prefix = NULL;
+
+static void show_progress(GP_ProgressCallback *self)
+{
+ fprintf(stderr, "rFilter %s %3.2f%%",
+ progress_prefix, self->percentage);
+}
+
static int param_err(const struct param *self, const char *val, void *priv)
{
/* invalid parameter name */
@@ -107,7 +117,7 @@ static GP_RetCode resize(GP_Context **c, const char *params)
GP_Size h = ratio * (*c)->h;
GP_Context *res = NULL;
- res = GP_FilterResize(*c, NULL, alg, w, h);
+ res = GP_FilterResize(*c, progress_callback, alg, w, h);
if (res == NULL)
return GP_EINVAL;
@@ -161,7 +171,7 @@ static GP_RetCode scale(GP_Context **c, const char *params)
GP_Context *res = NULL;
- res = GP_FilterResize(*c, NULL, alg, w, h);
+ res = GP_FilterResize(*c, progress_callback, alg, w, h);
if (res == NULL)
return GP_EINVAL;
@@ -296,7 +306,7 @@ static GP_RetCode blur(GP_Context **c, const char *params)
GP_Context *res = NULL;
- res = GP_FilterGaussianBlur(*c, sigma);
+ res = GP_FilterGaussianBlur(*c, progress_callback, sigma, sigma);
if (res == NULL)
return GP_EINVAL;
@@ -393,11 +403,18 @@ static void apply_filters(GP_Context **src)
unsigned int i;
GP_RetCode ret;
- for (i = 0; i < filter_cnt; i++)
+ for (i = 0; i < filter_cnt; i++) {
+
+ progress_prefix = filters[i]->name;
+
if ((ret = filters[i]->apply(src, filter_params[i]))) {
fprintf(stderr, "Error: %sn", GP_RetCodeName(ret));
exit(1);
}
+
+ if (progress_callback != NULL)
+ fprintf(stderr, " donen");
+ }
}
static const char *app_help = {
@@ -416,6 +433,7 @@ static const char *app_help = {
" =============== n"
" n"
"-h - prints this help n"
+ "-p - show filter progress n"
"-v int - sets gfxprim verbosity level n"
"-f params - apply filter, multiple filters may be usedn"
" n"
@@ -445,7 +463,11 @@ int main(int argc, char *argv[])
GP_RetCode ret;
int opt, i;
- while ((opt = getopt(argc, argv, "f:hv:")) != -1) {
+ GP_ProgressCallback callback = {
+ .callback = show_progress,
+ };
+
+ while ((opt = getopt(argc, argv, "f:hpv:")) != -1) {
switch (opt) {
case 'h':
print_help();
@@ -457,6 +479,9 @@ int main(int argc, char *argv[])
case 'f':
add_filter(optarg);
break;
+ case 'p':
+ progress_callback = &callback;
+ break;
default:
print_help();
return 1;
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Filter.h
similarity index 71%
copy from include/filters/GP_Linear.h
copy to include/filters/GP_Filter.h
index 98e53f0..cc9918d 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Filter.h
@@ -22,15 +22,37 @@
/*
- Linear filters.
+ Common filters typedefs and includes.
*/
-#ifndef GP_LINEAR_H
-#define GP_LINEAR_H
+#ifndef GP_FILTER_H
+#define GP_FILTER_H
-#include <GP_Context.h>
+#include "core/GP_Context.h"
-GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma);
+/*
+ * Progress callback
+ */
+typedef struct GP_ProgressCallback {
+ float percentage;
+ void (*callback)(struct GP_ProgressCallback *self);
+ void *priv;
+} GP_ProgressCallback;
+
+static inline void GP_ProgressCallbackReport(GP_ProgressCallback *callback,
+ float percentage)
+{
+ if (callback == NULL)
+ return;
+
+ callback->percentage = percentage;
+ callback->callback(callback);
+}
+
+static inline void GP_ProgressCallbackDone(GP_ProgressCallback *callback)
+{
+ GP_ProgressCallbackReport(callback, 100);
+}
-#endif /* GP_LINEAR_H */
+#endif /* GP_FILTER_H */
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h
index 98e53f0..ae0debd 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Linear.h
@@ -29,8 +29,24 @@
#ifndef GP_LINEAR_H
#define GP_LINEAR_H
-#include <GP_Context.h>
+#include "GP_Filter.h"
-GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma);
+/*
+ * Gaussian blur
+ *
+ * The sigma parameters defines the blur radii in horizontal and vertical
+ * direction.
+ *
+ * This variant could work in-place so it's perectly okay to call
+ *
+ * GP_FilterGaussianBlur_Raw(context, context, ...);
+ */
+void GP_FilterGaussianBlur_Raw(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float sigma_x, float sigma_y);
+
+GP_Context *GP_FilterGaussianBlur(GP_Context *src,
+ GP_ProgressCallback *callback,
+ float sigma_x, float sigma_y);
#endif /* GP_LINEAR_H */
diff --git a/include/filters/GP_Resize.h b/include/filters/GP_Resize.h
index 884a8f7..54acaed 100644
--- a/include/filters/GP_Resize.h
+++ b/include/filters/GP_Resize.h
@@ -52,10 +52,10 @@ typedef enum GP_InterpolationType {
} GP_InterpolationType;
void GP_FilterResize_Raw(GP_Context *src, GP_Context *res,
- GP_ProgressCallback callback,
+ GP_ProgressCallback *callback,
GP_InterpolationType type);
-GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback callback,
+GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback *callback,
GP_InterpolationType type, GP_Size w, GP_Size h);
#endif /* GP_RESIZE_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 764d6b6..1538ee2 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -29,46 +29,102 @@
#include <GP_Linear.h>
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
+static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
float kernel[], uint32_t kw, uint32_t kh);
-GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma)
+static inline unsigned int gaussian_kernel_size(float sigma)
{
- GP_Context *dst;
-
- if (src->pixel_type != GP_PIXEL_RGB888)
- return NULL;
-
- dst = GP_ContextCopy(src, 0);
-
- if (dst == NULL)
- return NULL;
+ int center = 3 * sigma;
+ return 2 * center + 1;
+}
- /* compute kernel */
+static inline void gaussian_kernel_init(float sigma, float *kernel)
+{
int i, center = 3 * sigma;
int N = 2 * center + 1;
- float kernel[N];
-
+
double sigma2 = sigma * sigma;
-
+
for (i = 0; i < N; i++) {
double r = center - i;
-
kernel[i] = exp(-0.5 * (r * r) / sigma2);
}
+}
- GP_DEBUG(1, "Gaussian blur sigma=%2.3f kernel %ix%i image %ux%u",
- sigma, N, N, src->w, src->h);
+static void gaussian_callback_1(GP_ProgressCallback *self)
+{
+ GP_ProgressCallbackReport(self->priv, self->percentage/2);
+}
- /* apply in both directions */
- GP_FilterLinearConvolution(src, dst, kernel, N, 1);
- GP_FilterLinearConvolution(dst, dst, kernel, 1, N);
+static void gaussian_callback_2(GP_ProgressCallback *self)
+{
+ GP_ProgressCallbackReport(self->priv, self->percentage/2 + 50);
+}
+
+void GP_FilterGaussianBlur_Raw(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
+ float sigma_x, float sigma_y)
+{
+ unsigned int size_x = gaussian_kernel_size(sigma_x);
+ unsigned int size_y = gaussian_kernel_size(sigma_y);
+
+ GP_DEBUG(1, "Gaussian blur sigma_x=%2.3f sigma_y=%2.3f kernel %ix%i image %ux%u",
+ sigma_x, sigma_y, size_x, size_y, src->w, src->h);
+
+ GP_ProgressCallback *new_callback = NULL;
- return dst;
+ GP_ProgressCallback gaussian_callback = {
+ .callback = gaussian_callback_1,
+ .priv = callback
+ };
+
+ if (callback != NULL)
+ new_callback = &gaussian_callback;
+
+ /* compute kernel and apply on horizontal direction */
+ float kernel_x[size_x];
+ gaussian_kernel_init(sigma_x, kernel_x);
+ GP_FilterLinearConvolution(src, res, new_callback, kernel_x, size_x, 1);
+
+ if (new_callback != NULL)
+ new_callback->callback = gaussian_callback_2;
+
+ /* compute kernel and apply on vertical direction */
+ float kernel_y[size_y];
+ gaussian_kernel_init(sigma_y, kernel_y);
+ GP_FilterLinearConvolution(res, res, new_callback, kernel_y, 1, size_y);
+
+ if (callback != NULL) {
+ callback->percentage = 100;
+ callback->callback(callback);
+ }
}
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
+GP_Context *GP_FilterGaussianBlur(GP_Context *src,
+ GP_ProgressCallback *callback,
+ float sigma_x, float sigma_y)
+{
+ GP_Context *res;
+
+ if (src->pixel_type != GP_PIXEL_RGB888)
+ return NULL;
+
+ res = GP_ContextCopy(src, 0);
+
+ if (res == NULL) {
+ GP_DEBUG(1, "Malloc failed :(");
+ return NULL;
+ }
+
+ GP_FilterGaussianBlur_Raw(src, res, callback, sigma_x, sigma_y);
+
+ return res;
+}
+
+static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res,
+ GP_ProgressCallback *callback,
float kernel[], uint32_t kw, uint32_t kh)
{
float kernel_sum = 0;
@@ -83,7 +139,7 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
kernel_sum += kernel[i];
/* do linear convolution */
- for (y = 0; y < (GP_Coord)dst->h; y++) {
+ for (y = 0; y < (GP_Coord)res->h; y++) {
GP_Pixel pix;
uint32_t R[kw][kh], G[kw][kh], B[kw][kh];
@@ -112,7 +168,7 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
int idx = kw - 1;
- for (x = 0; x < (GP_Coord)dst->w; x++) {
+ for (x = 0; x < (GP_Coord)res->w; x++) {
float r = 0, g = 0, b = 0;
for (j = 0; j < kh; j++) {
@@ -166,13 +222,17 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
- GP_PutPixel_Raw_24BPP(dst, x, y, pix);
+ GP_PutPixel_Raw_24BPP(res, x, y, pix);
idx++;
if (idx >= (int)kw)
idx = 0;
}
+
+ if (callback != NULL && y % 100 == 0)
+ GP_ProgressCallbackReport(callback, 100.00 * y/res->h);
}
-}
+ GP_ProgressCallbackDone(callback);
+}
diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c
index 50041c2..6f944a6 100644
--- a/libs/filters/GP_Resize.c
+++ b/libs/filters/GP_Resize.c
@@ -28,7 +28,7 @@
#include <GP_Resize.h>
void GP_FilterInterpolate_NN(GP_Context *src, GP_Context *res,
- GP_ProgressCallback callback)
+ GP_ProgressCallback *callback)
{
GP_Coord x, y;
@@ -45,7 +45,12 @@ void GP_FilterInterpolate_NN(GP_Context *src, GP_Context *res,
GP_PutPixel_Raw_24BPP(res, x, y, pix);
}
+
+ if (callback != NULL && y % 100 == 0)
+ GP_ProgressCallbackReport(callback, 100.00 * y/res->h);
}
+
+ GP_ProgressCallbackDone(callback);
}
#define A 0.5
@@ -75,7 +80,7 @@ typedef union v4f {
#define SUM_V4SF(a) ((a).f[0] + (a).f[1] + (a).f[2] + (a).f[3])
void GP_FilterInterpolate_Cubic(GP_Context *src, GP_Context *res,
- GP_ProgressCallback callback)
+ GP_ProgressCallback *callback)
{
float col_r[src->h], col_g[src->h], col_b[src->h];
uint32_t i, j;
@@ -196,11 +201,16 @@ void GP_FilterInterpolate_Cubic(GP_Context *src, GP_Context *res,
GP_Pixel pix = GP_Pixel_CREATE_RGB888((uint8_t)r, (uint8_t)g, (uint8_t)b);
GP_PutPixel_Raw_24BPP(res, i, j, pix);
}
+
+ if (callback != NULL && i % 100 == 0)
+ GP_ProgressCallbackReport(callback, 100.00 * i/res->w);
}
+
+ GP_ProgressCallbackDone(callback);
}
void GP_FilterResize_Raw(GP_Context *src, GP_Context *res,
- GP_ProgressCallback callback,
+ GP_ProgressCallback *callback,
GP_InterpolationType type)
{
switch (type) {
@@ -213,7 +223,7 @@ void GP_FilterResize_Raw(GP_Context *src, GP_Context *res,
}
}
-GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback callback,
+GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback *callback,
GP_InterpolationType type, GP_Size w, GP_Size h)
{
GP_Context *res;
http://repo.or.cz/w/gfxprim.git/commit/27108512e85e27b4f46c4be703126f2b2ee9…
commit 27108512e85e27b4f46c4be703126f2b2ee9fd68
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 15:09:51 2011 +0200
The GP.h header shouldn't be used in library itself.
diff --git a/libs/core/GP_Blit.gen.c.t b/libs/core/GP_Blit.gen.c.t
index 2491b0b..2bc3f69 100644
--- a/libs/core/GP_Blit.gen.c.t
+++ b/libs/core/GP_Blit.gen.c.t
@@ -6,7 +6,7 @@
#include <stdio.h>
#include <string.h>
#include "GP_Pixel.h"
-#include "GP.h"
+#include "GP_GetPutPixel.h"
#include "GP_Context.h"
#include "GP_Blit.h"
http://repo.or.cz/w/gfxprim.git/commit/af00d9dd985a5b6a6ef304281a94ddd245e0…
commit af00d9dd985a5b6a6ef304281a94ddd245e05cc4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 12:33:02 2011 +0200
Cleaned up resize filters api, prepared for progress callback.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 82e7228..4ea0543 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -107,15 +107,8 @@ static GP_RetCode resize(GP_Context **c, const char *params)
GP_Size h = ratio * (*c)->h;
GP_Context *res = NULL;
- switch (alg) {
- case 0:
- res = GP_Scale_NN(*c, w, h);
- break;
- case 1:
- res = GP_Scale_BiCubic(*c, w, h);
- break;
- }
-
+ res = GP_FilterResize(*c, NULL, alg, w, h);
+
if (res == NULL)
return GP_EINVAL;
@@ -168,14 +161,7 @@ static GP_RetCode scale(GP_Context **c, const char *params)
GP_Context *res = NULL;
- switch (alg) {
- case 0:
- res = GP_Scale_NN(*c, w, h);
- break;
- case 1:
- res = GP_Scale_BiCubic(*c, w, h);
- break;
- }
+ res = GP_FilterResize(*c, NULL, alg, w, h);
if (res == NULL)
return GP_EINVAL;
diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Filters.h
index fc498b0..90f63b3 100644
--- a/include/filters/GP_Filters.h
+++ b/include/filters/GP_Filters.h
@@ -35,10 +35,13 @@
/* Image rotations (90 180 270 grads) and mirroring */
#include "filters/GP_Rotate.h"
+/* Point filters, brightness, contrast ... */
#include "filters/GP_Point.h"
+
+/* Linear convolution base filters (mostly blurs) */
#include "filters/GP_Linear.h"
-/* Image down and up scaling */
-#include "filters/GP_Scale.h"
+/* Image scaling */
+#include "filters/GP_Resize.h"
#endif /* GP_FILTERS_H */
diff --git a/include/filters/GP_Scale.h b/include/filters/GP_Resize.h
similarity index 63%
rename from include/filters/GP_Scale.h
rename to include/filters/GP_Resize.h
index 06414c2..884a8f7 100644
--- a/include/filters/GP_Scale.h
+++ b/include/filters/GP_Resize.h
@@ -22,31 +22,40 @@
/*
- GP_Context resize.
+ GP_Context interpolations.
- */
+ Nearest Neighbour
+ ~~~~~~~~~~~~~~~~~
-#ifndef GP_SCALE_H
-#define GP_SCALE_H
+ Fast, but produces pixelated images. Works however well for images with sharp
+ edges mostly consisting of big one color regions (eg doesn't blur the
+ result on upscaling).
-#include "core/GP_Context.h"
-/*
- * Nearest neighbour
- *
- * Faster than others, but produces pixelated images. Works however well for
- * images with sharp edges mostly consisting of big once color parts (eg
- * doesn't blurr the result on upscaling).
- */
-GP_Context *GP_Scale_NN(GP_Context *src, GP_Size w, GP_Size h);
+ Bicubic
+ ~~~~~~~
+
+ Works well for upscaling as is. To get decent result on downscaling,
+ low-pass filter (for example gaussian blur) must be used on original image
+ before scaling is done.
-/*
- * Bicubic Scaling
- *
- * Works well for upscaling. Not so good for downscaling big images to small
- * ones (looses too much information).
*/
-GP_Context *GP_Scale_BiCubic(GP_Context *src, GP_Size w, GP_Size h);
+#ifndef GP_RESIZE_H
+#define GP_RESIZE_H
+
+#include "GP_Filter.h"
+
+typedef enum GP_InterpolationType {
+ GP_INTER_NN, /* Nearest Neighbour */
+ GP_INTER_CUBIC, /* Bicubic */
+} GP_InterpolationType;
+
+void GP_FilterResize_Raw(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback callback,
+ GP_InterpolationType type);
+
+GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback callback,
+ GP_InterpolationType type, GP_Size w, GP_Size h);
-#endif /* GP_SCALE_H */
+#endif /* GP_RESIZE_H */
diff --git a/libs/filters/GP_Scale.c b/libs/filters/GP_Resize.c
similarity index 75%
rename from libs/filters/GP_Scale.c
rename to libs/filters/GP_Resize.c
index 88c14a9..50041c2 100644
--- a/libs/filters/GP_Scale.c
+++ b/libs/filters/GP_Resize.c
@@ -25,38 +25,27 @@
#include <GP_Debug.h>
-#include <GP_Scale.h>
+#include <GP_Resize.h>
-
-GP_Context *GP_Scale_NN(GP_Context *src, GP_Size w, GP_Size h)
+void GP_FilterInterpolate_NN(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback callback)
{
- GP_Context *dst;
-
- if (src->pixel_type != GP_PIXEL_RGB888)
- return NULL;
-
- dst = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
-
- if (dst == NULL)
- return NULL;
-
- GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
- src->w, src->h, w, h,
- 1.00 * w / src->w, 1.00 * h / src->h);
-
GP_Coord x, y;
+
+ GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
+ src->w, src->h, res->w, res->h,
+ 1.00 * res->w / src->w, 1.00 * res->h / src->h);
- for (y = 0; y < (int)h; y++)
- for (x = 0; x < (int)w; x++) {
- GP_Coord xi = (1.00 * x / w) * src->w;
- GP_Coord yi = (1.00 * y / h) * src->h;
+ for (y = 0; y < (GP_Coord)res->h; y++) {
+ for (x = 0; x < (GP_Coord)res->w; x++) {
+ GP_Coord xi = (1.00 * x / res->w) * src->w;
+ GP_Coord yi = (1.00 * y / res->h) * src->h;
GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, xi, yi);
- GP_PutPixel_Raw_24BPP(dst, x, y, pix);
+ GP_PutPixel_Raw_24BPP(res, x, y, pix);
}
-
- return dst;
+ }
}
#define A 0.5
@@ -85,26 +74,18 @@ typedef union v4f {
#define MUL_V4SF(a, b) ((union v4f)((a).v * (b).v))
#define SUM_V4SF(a) ((a).f[0] + (a).f[1] + (a).f[2] + (a).f[3])
-GP_Context *GP_Scale_BiCubic(GP_Context *src, GP_Size w, GP_Size h)
+void GP_FilterInterpolate_Cubic(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback callback)
{
- GP_Context *dst;
float col_r[src->h], col_g[src->h], col_b[src->h];
uint32_t i, j;
- if (src->pixel_type != GP_PIXEL_RGB888)
- return NULL;
-
- dst = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
-
- if (dst == NULL)
- return NULL;
-
GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f",
- src->w, src->h, w, h,
- 1.00 * w / src->w, 1.00 * h / src->h);
+ src->w, src->h, res->w, res->h,
+ 1.00 * res->w / src->w, 1.00 * res->h / src->h);
- for (i = 0; i < w; i++) {
- float x = (1.00 * i / w) * (src->w - 4.5) + 2.5;
+ for (i = 0; i < res->w; i++) {
+ float x = (1.00 * i / res->w) * (src->w - 4.5) + 2.5;
v4f cvx;
int xi = x - 1;
@@ -154,8 +135,8 @@ GP_Context *GP_Scale_BiCubic(GP_Context *src, GP_Size w, GP_Size h)
}
/* now interpolate column for new image */
- for (j = 0; j < h; j++) {
- float y = (1.00 * j / h) * (src->h - 4.5) + 2.5;
+ for (j = 0; j < res->h; j++) {
+ float y = (1.00 * j / res->h) * (src->h - 4.5) + 2.5;
v4f cvy, rv, gv, bv;
float r, g, b;
int yi = y - 1;
@@ -213,9 +194,41 @@ GP_Context *GP_Scale_BiCubic(GP_Context *src, GP_Size w, GP_Size h)
b = 0;
GP_Pixel pix = GP_Pixel_CREATE_RGB888((uint8_t)r, (uint8_t)g, (uint8_t)b);
- GP_PutPixel_Raw_24BPP(dst, i, j, pix);
+ GP_PutPixel_Raw_24BPP(res, i, j, pix);
}
}
+}
+
+void GP_FilterResize_Raw(GP_Context *src, GP_Context *res,
+ GP_ProgressCallback callback,
+ GP_InterpolationType type)
+{
+ switch (type) {
+ case GP_INTER_NN:
+ GP_FilterInterpolate_NN(src, res, callback);
+ break;
+ case GP_INTER_CUBIC:
+ GP_FilterInterpolate_Cubic(src, res, callback);
+ break;
+ }
+}
+
+GP_Context *GP_FilterResize(GP_Context *src, GP_ProgressCallback callback,
+ GP_InterpolationType type, GP_Size w, GP_Size h)
+{
+ GP_Context *res;
+
+ if (src->pixel_type != GP_PIXEL_RGB888)
+ return NULL;
+
+ res = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
+
+ if (res == NULL) {
+ GP_DEBUG(1, "Malloc failed :(");
+ return NULL;
+ }
+
+ GP_FilterResize_Raw(src, res, callback, type);
- return dst;
+ return res;
}
http://repo.or.cz/w/gfxprim.git/commit/def6da387aaeaaef3071c0015ec053561da2…
commit def6da387aaeaaef3071c0015ec053561da26780
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Oct 2 12:27:44 2011 +0200
Remove scale test as demos/grinder serves better.
diff --git a/tests/SDL/Makefile b/tests/SDL/Makefile
index 6d93313..8c02ba1 100644
--- a/tests/SDL/Makefile
+++ b/tests/SDL/Makefile
@@ -6,8 +6,7 @@ INCLUDE=core gfx SDL backends
LDLIBS+=-lGP -L$(TOPDIR)/build/ -lGP_SDL -lSDL -lpng
APPS=pixeltest fileview fonttest linetest randomshapetest shapetest sierpinsky- symbolstest textaligntest trianglefps input blittest subcontext scale_test- showimage
+ symbolstest textaligntest trianglefps input blittest subcontext showimage
include $(TOPDIR)/include.mk
include $(TOPDIR)/app.mk
diff --git a/tests/SDL/scale_test.c b/tests/SDL/scale_test.c
deleted file mode 100644
index aa026b9..0000000
--- a/tests/SDL/scale_test.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*****************************************************************************
- * 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-2011 Cyril Hrubis <metan(a)ucw.cz> *
- * *
- *****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "GP.h"
-
-int main(int argc, char *argv[])
-{
- GP_Context *bitmap;
- GP_SetDebugLevel(10);
- GP_RetCode ret;
- GP_Size w, h;
-
- if (argc < 4) {
- fprintf(stderr, "Usage: image w hn");
- return 1;
- }
-
- if ((ret = GP_LoadImage(argv[1], &bitmap))) {
- fprintf(stderr, "Failed to load bitmap: %sn", GP_RetCodeName(ret));
- return 1;
- }
-
- w = atoi(argv[2]);
- h = atoi(argv[3]);
-
- bitmap = GP_Scale_BiCubic(bitmap, w, h);
-
- if ((ret = GP_SavePPM("out.ppm", bitmap, "b"))) {
- fprintf(stderr, "Failed to load bitmap: %sn", GP_RetCodeName(ret));
- return 1;
- }
-
- return 0;
-}
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/grinder.c | 51 +++++++-----
include/filters/{GP_Scale.h => GP_Filter.h} | 46 ++++++-----
include/filters/GP_Filters.h | 7 +-
include/filters/GP_Linear.h | 20 ++++-
include/filters/{GP_Point.h => GP_Resize.h} | 48 ++++++-----
libs/core/GP_Blit.gen.c.t | 2 +-
libs/filters/GP_Linear.c | 114 ++++++++++++++++++++------
libs/filters/{GP_Scale.c => GP_Resize.c} | 105 +++++++++++++++----------
tests/SDL/Makefile | 3 +-
tests/SDL/scale_test.c | 56 -------------
10 files changed, 259 insertions(+), 193 deletions(-)
rename include/filters/{GP_Scale.h => GP_Filter.h} (72%)
copy include/filters/{GP_Point.h => GP_Resize.h} (63%)
rename libs/filters/{GP_Scale.c => GP_Resize.c} (72%)
delete mode 100644 tests/SDL/scale_test.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 generate updated: 631e1ca332e1b3bfccd1ebc4d83fa407eba13d51
by metan 01 Oct '11
by metan 01 Oct '11
01 Oct '11
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, generate has been updated
via 631e1ca332e1b3bfccd1ebc4d83fa407eba13d51 (commit)
from 4c68110cd82c373fe1d0c19ca01362edb452a0ad (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/631e1ca332e1b3bfccd1ebc4d83fa407eba1…
commit 631e1ca332e1b3bfccd1ebc4d83fa407eba13d51
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 1 22:11:44 2011 +0200
Cleaned up the point pixel template.
diff --git a/libs/filters/GP_Brightness.gen.c.t b/libs/filters/GP_Brightness.gen.c.t
index 8262dc1..1ba6fb9 100644
--- a/libs/filters/GP_Brightness.gen.c.t
+++ b/libs/filters/GP_Brightness.gen.c.t
@@ -5,9 +5,8 @@ Brightness filters -- Increments all color channels by a fixed value.
%% endblock
%% block body
-#include <GP_Context.h>
-#include <GP_Pixel.h>
-#include <GP_GetPutPixel.h>
+
+{{ filter_include() }}
%% call(ps) filter_per_pixel_size('Brightness', 'int32_t inc')
pix = pix + inc;
@@ -19,6 +18,6 @@ pix = pix + inc;
{{ filter_clamp_val(chan[0], chan[2]) }}
%% endcall
-{{ filter_functions('Brightness', 'int32_t inc', 'inc') }}
+{{ filter_functions('Brightness', 'int32_t inc', 'inc', "inc=%i") }}
%% endblock body
diff --git a/libs/filters/GP_Contrast.gen.c.t b/libs/filters/GP_Contrast.gen.c.t
index 5a78363..3398d1a 100644
--- a/libs/filters/GP_Contrast.gen.c.t
+++ b/libs/filters/GP_Contrast.gen.c.t
@@ -5,9 +5,8 @@ Contrast filters -- Multiply all color channels by a fixed value.
%% endblock
%% block body
-#include <GP_Context.h>
-#include <GP_Pixel.h>
-#include <GP_GetPutPixel.h>
+
+{{ filter_include() }}
%% call(ps) filter_per_pixel_size('Contrast', 'float mul')
pix = 1.00 * pix * mul;
@@ -19,6 +18,6 @@ pix = 1.00 * pix * mul;
{{ filter_clamp_val(chan[0], chan[2]) }}
%% endcall
-{{ filter_functions('Contrast', 'float mul', 'mul') }}
+{{ filter_functions('Contrast', 'float mul', 'mul', "mul=%2.3f") }}
%% endblock body
diff --git a/libs/filters/GP_Invert.gen.c.t b/libs/filters/GP_Invert.gen.c.t
index f641fcf..1c11b30 100644
--- a/libs/filters/GP_Invert.gen.c.t
+++ b/libs/filters/GP_Invert.gen.c.t
@@ -5,9 +5,8 @@ Invert filters -- Invert image
%% endblock
%% block body
-#include <GP_Context.h>
-#include <GP_Pixel.h>
-#include <GP_GetPutPixel.h>
+
+{{ filter_include() }}
%% call(ps) filter_per_pixel_size('Invert')
pix = {{ 2 ** ps.size - 1 }} - pix;
diff --git a/pylib/templates/filter.point.c.t b/pylib/templates/filter.point.c.t
index 93461d9..271418c 100644
--- a/pylib/templates/filter.point.c.t
+++ b/pylib/templates/filter.point.c.t
@@ -1,9 +1,12 @@
%% extends "base.c.t"
-%% macro maybe_opts(opts)
-%% if opts
-,{{ opts }}
-%% endif
+{% macro maybe_opts(opts) %}{% if opts %}, {{ opts }}{% endif %}{% endmacro %}
+
+%% macro filter_include()
+#include <GP_Context.h>
+#include <GP_Pixel.h>
+#include <GP_GetPutPixel.h>
+#include <GP_Debug.h>
%% endmacro
/*
@@ -54,6 +57,7 @@ void GP_Filter{{ name }}_{{ pt.name }}(const GP_Context *src, GP_Context *res{{
GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(res, x, y, pix);
}
}
+
%% endif
%% endfor
%% endmacro
@@ -72,9 +76,11 @@ void GP_Filter{{ name }}_{{ pt.name }}(const GP_Context *src, GP_Context *res{{
/*
* Switch per pixel sizes or pixel types.
*/
-%% macro filter_functions(name, opts="", params="")
+%% macro filter_functions(name, opts="", params="", fmt="")
void GP_Filter{{ name }}_Raw(const GP_Context *src, GP_Context *res{{ maybe_opts(opts) }})
{
+ GP_DEBUG(1, "Running filter {{ name }} {{ fmt }}"{{ maybe_opts(params) }});
+
switch (src->pixel_type) {
%% for pt in pixeltypes
case GP_PIXEL_{{ pt.name }}:
-----------------------------------------------------------------------
Summary of changes:
libs/filters/GP_Brightness.gen.c.t | 7 +++----
libs/filters/GP_Contrast.gen.c.t | 7 +++----
libs/filters/GP_Invert.gen.c.t | 5 ++---
pylib/templates/filter.point.c.t | 16 +++++++++++-----
4 files changed, 19 insertions(+), 16 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 generate updated: 4c68110cd82c373fe1d0c19ca01362edb452a0ad
by metan 01 Oct '11
by metan 01 Oct '11
01 Oct '11
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, generate has been updated
via 4c68110cd82c373fe1d0c19ca01362edb452a0ad (commit)
from 96956ac4fbd2c35d57c122ecd44a88c352153a5e (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/4c68110cd82c373fe1d0c19ca01362edb452…
commit 4c68110cd82c373fe1d0c19ca01362edb452a0ad
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 1 15:48:36 2011 +0200
Fix linear convolution corner cases at the corners.
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index bf41660..764d6b6 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -101,7 +101,7 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
if (cy >= (int)src->h)
cy = src->h - 1;
-
+
pix = GP_GetPixel_Raw_24BPP(src, cx, cy);
R[i][j] = GP_Pixel_GET_R_RGB888(pix);
@@ -117,14 +117,18 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
for (j = 0; j < kh; j++) {
int cy = y + j - kh/2;
-
+ int cx = x + kw/2;
+
if (cy < 0)
cy = 0;
-
+
if (cy >= (int)src->h)
cy = src->h - 1;
- pix = GP_GetPixel_Raw_24BPP(src, x, cy);
+ if (cx >= (int)src->w)
+ cx = src->w - 1;
+
+ pix = GP_GetPixel_Raw_24BPP(src, cx, cy);
R[idx][j] = GP_Pixel_GET_R_RGB888(pix);
G[idx][j] = GP_Pixel_GET_G_RGB888(pix);
@@ -133,10 +137,12 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
/* count the pixel value from neighbours weighted by kernel */
for (i = 0; i < kw; i++) {
- int k = i - idx;
-
- if (k < 0)
- k += kw;
+ int k;
+
+ if ((int)i < idx + 1)
+ k = kw - idx - 1 + i;
+ else
+ k = i - idx - 1;
for (j = 0; j < kh; j++) {
r += R[i][j] * kernel[k + j * kw];
-----------------------------------------------------------------------
Summary of changes:
libs/filters/GP_Linear.c | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 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 generate updated: 96956ac4fbd2c35d57c122ecd44a88c352153a5e
by metan 01 Oct '11
by metan 01 Oct '11
01 Oct '11
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, generate has been updated
via 96956ac4fbd2c35d57c122ecd44a88c352153a5e (commit)
from 8de6ee02d1d25d761c590a1bdaeb142fd04191e3 (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/96956ac4fbd2c35d57c122ecd44a88c35215…
commit 96956ac4fbd2c35d57c122ecd44a88c352153a5e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 1 13:58:00 2011 +0200
Implemented linear convolution and gaussian blur.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 803570d..82e7228 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -292,17 +292,25 @@ static GP_RetCode invert(GP_Context **c, const char *params)
}
static struct param blur_params[] = {
+ {"sigma", PARAM_FLOAT, "sigma parameter (eg. radii of blur)", NULL, NULL},
{NULL, 0, NULL, NULL, NULL}
};
static GP_RetCode blur(GP_Context **c, const char *params)
{
- if (param_parse(params, blur_params, "blur", param_err))
+ float sigma = 0;
+
+ if (param_parse(params, blur_params, "blur", param_err, &sigma))
return GP_EINVAL;
+ if (sigma <= 0) {
+ print_error("blur: sigma parameter must be >= 0");
+ return GP_EINVAL;
+ }
+
GP_Context *res = NULL;
- res = GP_FilterBlur(*c);
+ res = GP_FilterGaussianBlur(*c, sigma);
if (res == NULL)
return GP_EINVAL;
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h
index 2ef5a0e..98e53f0 100644
--- a/include/filters/GP_Linear.h
+++ b/include/filters/GP_Linear.h
@@ -31,6 +31,6 @@
#include <GP_Context.h>
-GP_Context *GP_FilterBlur(GP_Context *src);
+GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma);
#endif /* GP_LINEAR_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
index 66c0db6..bf41660 100644
--- a/libs/filters/GP_Linear.c
+++ b/libs/filters/GP_Linear.c
@@ -20,6 +20,8 @@
* *
*****************************************************************************/
+#include <math.h>
+
#include <GP_Context.h>
#include <GP_GetPutPixel.h>
@@ -27,13 +29,13 @@
#include <GP_Linear.h>
-static float HX[] = {0.17, 0.66, 0.17};
-static float HY[] = {0.17, 0.66, 0.17};
+static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
+ float kernel[], uint32_t kw, uint32_t kh);
-GP_Context *GP_FilterBlur(GP_Context *src)
+GP_Context *GP_FilterGaussianBlur(GP_Context *src, float sigma)
{
GP_Context *dst;
-
+
if (src->pixel_type != GP_PIXEL_RGB888)
return NULL;
@@ -42,89 +44,113 @@ GP_Context *GP_FilterBlur(GP_Context *src)
if (dst == NULL)
return NULL;
- GP_DEBUG(1, "Linear blur filter (3x3 kernel) %ux%u", src->w, src->h);
- GP_Coord x, y;
+ /* compute kernel */
+ int i, center = 3 * sigma;
+ int N = 2 * center + 1;
+ float kernel[N];
- for (y = 0; y < (GP_Coord)dst->h; y++) {
- GP_Pixel pix;
- uint32_t R1, R2, R3;
- uint32_t G1, G2, G3;
- uint32_t B1, B2, B3;
-
- pix = GP_GetPixel_Raw_24BPP(src, 0, y);
-
- R1 = GP_Pixel_GET_R_RGB888(pix);
- G1 = GP_Pixel_GET_G_RGB888(pix);
- B1 = GP_Pixel_GET_B_RGB888(pix);
-
- R2 = R1;
- G2 = G1;
- B2 = B1;
+ double sigma2 = sigma * sigma;
- for (x = 0; x < (GP_Coord)dst->w; x++) {
- float r, g, b;
+ for (i = 0; i < N; i++) {
+ double r = center - i;
+
+ kernel[i] = exp(-0.5 * (r * r) / sigma2);
+ }
- pix = GP_GetPixel_Raw_24BPP(src, x, y);
-
- R3 = GP_Pixel_GET_R_RGB888(pix);
- G3 = GP_Pixel_GET_G_RGB888(pix);
- B3 = GP_Pixel_GET_B_RGB888(pix);
+ GP_DEBUG(1, "Gaussian blur sigma=%2.3f kernel %ix%i image %ux%u",
+ sigma, N, N, src->w, src->h);
- r = R1 * HX[0] + R2 * HX[1] + R3 * HX[2];
- g = G1 * HX[0] + G2 * HX[1] + G3 * HX[2];
- b = B1 * HX[0] + B2 * HX[1] + B3 * HX[2];
+ /* apply in both directions */
+ GP_FilterLinearConvolution(src, dst, kernel, N, 1);
+ GP_FilterLinearConvolution(dst, dst, kernel, 1, N);
- if (r > 255)
- r = 255;
- if (g > 255)
- g = 255;
- if (b > 255)
- b = 255;
+ return dst;
+}
- pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
+static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *dst,
+ float kernel[], uint32_t kw, uint32_t kh)
+{
+ float kernel_sum = 0;
+ GP_Coord x, y;
+ uint32_t i, j;
- GP_PutPixel_Raw_24BPP(dst, x, y, pix);
-
- R1 = R2;
- G1 = G2;
- B1 = B2;
-
- R2 = R3;
- G2 = G3;
- B2 = B3;
- }
- }
-
- for (x = 0; x < (GP_Coord)dst->w; x++) {
- GP_Pixel pix;
- uint32_t R1, R2, R3;
- uint32_t G1, G2, G3;
- uint32_t B1, B2, B3;
-
- pix = GP_GetPixel_Raw_24BPP(src, x, 0);
+ GP_DEBUG(1, "Linear convolution kernel %ix%i image %ux%u",
+ kw, kh, src->w, src->h);
- R1 = GP_Pixel_GET_R_RGB888(pix);
- G1 = GP_Pixel_GET_G_RGB888(pix);
- B1 = GP_Pixel_GET_B_RGB888(pix);
-
- R2 = R1;
- G2 = G1;
- B2 = B1;
+ /* count kernel sum for normalization */
+ for (i = 0; i < kw * kh; i++)
+ kernel_sum += kernel[i];
- for (y = 0; y < (GP_Coord)dst->h; y++) {
- float r, g, b;
+ /* do linear convolution */
+ for (y = 0; y < (GP_Coord)dst->h; y++) {
+ GP_Pixel pix;
+ uint32_t R[kw][kh], G[kw][kh], B[kw][kh];
+
+ /* prefill the buffer on the start */
+ for (j = 0; j < kh; j++) {
+ for (i = 0; i < kw - 1; i++) {
+ int cx = i - kw/2;
+ int cy = y + j - kh/2;
+
+ if (cx < 0)
+ cx = 0;
+
+ if (cy < 0)
+ cy = 0;
+
+ if (cy >= (int)src->h)
+ cy = src->h - 1;
+
+ pix = GP_GetPixel_Raw_24BPP(src, cx, cy);
+
+ R[i][j] = GP_Pixel_GET_R_RGB888(pix);
+ G[i][j] = GP_Pixel_GET_G_RGB888(pix);
+ B[i][j] = GP_Pixel_GET_B_RGB888(pix);
+ }
+ }
- pix = GP_GetPixel_Raw_24BPP(src, x, y);
-
- R3 = GP_Pixel_GET_R_RGB888(pix);
- G3 = GP_Pixel_GET_G_RGB888(pix);
- B3 = GP_Pixel_GET_B_RGB888(pix);
+ int idx = kw - 1;
- r = R1 * HY[0] + R2 * HY[1] + R3 * HY[2];
- g = G1 * HY[0] + G2 * HY[1] + G3 * HY[2];
- b = B1 * HY[0] + B2 * HY[1] + B3 * HY[2];
+ for (x = 0; x < (GP_Coord)dst->w; x++) {
+ float r = 0, g = 0, b = 0;
+
+ for (j = 0; j < kh; j++) {
+ int cy = y + j - kh/2;
+
+ if (cy < 0)
+ cy = 0;
+
+ if (cy >= (int)src->h)
+ cy = src->h - 1;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, cy);
+
+ R[idx][j] = GP_Pixel_GET_R_RGB888(pix);
+ G[idx][j] = GP_Pixel_GET_G_RGB888(pix);
+ B[idx][j] = GP_Pixel_GET_B_RGB888(pix);
+ }
+ /* count the pixel value from neighbours weighted by kernel */
+ for (i = 0; i < kw; i++) {
+ int k = i - idx;
+
+ if (k < 0)
+ k += kw;
+
+ for (j = 0; j < kh; j++) {
+ r += R[i][j] * kernel[k + j * kw];
+ g += G[i][j] * kernel[k + j * kw];
+ b += B[i][j] * kernel[k + j * kw];
+ }
+ }
+
+ /* normalize the result */
+ r /= kernel_sum;
+ g /= kernel_sum;
+ b /= kernel_sum;
+
+ /* and clamp just to be extra sure */
if (r > 255)
r = 255;
if (g > 255)
@@ -136,15 +162,11 @@ GP_Context *GP_FilterBlur(GP_Context *src)
GP_PutPixel_Raw_24BPP(dst, x, y, pix);
- R1 = R2;
- G1 = G2;
- B1 = B2;
-
- R2 = R3;
- G2 = G3;
- B2 = B3;
+ idx++;
+
+ if (idx >= (int)kw)
+ idx = 0;
}
}
-
- return dst;
}
+
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/grinder.c | 12 +++-
include/filters/GP_Linear.h | 2 +-
libs/filters/GP_Linear.c | 188 ++++++++++++++++++++++++-------------------
3 files changed, 116 insertions(+), 86 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 generate updated: 8de6ee02d1d25d761c590a1bdaeb142fd04191e3
by metan 01 Oct '11
by metan 01 Oct '11
01 Oct '11
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, generate has been updated
via 8de6ee02d1d25d761c590a1bdaeb142fd04191e3 (commit)
from 7765fb749d234f875480769baba4b8c3c4919a0d (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/8de6ee02d1d25d761c590a1bdaeb142fd041…
commit 8de6ee02d1d25d761c590a1bdaeb142fd04191e3
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 1 02:06:24 2011 +0200
First simple linear blur.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c
index 78d33d7..803570d 100644
--- a/demos/grinder/grinder.c
+++ b/demos/grinder/grinder.c
@@ -291,6 +291,28 @@ static GP_RetCode invert(GP_Context **c, const char *params)
return GP_ESUCCESS;
}
+static struct param blur_params[] = {
+ {NULL, 0, NULL, NULL, NULL}
+};
+
+static GP_RetCode blur(GP_Context **c, const char *params)
+{
+ if (param_parse(params, blur_params, "blur", param_err))
+ return GP_EINVAL;
+
+ GP_Context *res = NULL;
+
+ res = GP_FilterBlur(*c);
+
+ if (res == NULL)
+ return GP_EINVAL;
+
+ GP_ContextFree(*c);
+ *c = res;
+
+ return GP_ESUCCESS;
+}
+
/* filters */
struct filter {
@@ -307,6 +329,7 @@ static struct filter filter_table[] = {
{"bright", "alter image brightness", bright_params, bright},
{"contrast", "alter image contrast", contrast_params, contrast},
{"invert", "inverts image", invert_params, invert},
+ {"blur", "gaussian blur", blur_params, blur},
{NULL, NULL, NULL, NULL}
};
diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Filters.h
index 4c1304d..fc498b0 100644
--- a/include/filters/GP_Filters.h
+++ b/include/filters/GP_Filters.h
@@ -36,6 +36,7 @@
#include "filters/GP_Rotate.h"
#include "filters/GP_Point.h"
+#include "filters/GP_Linear.h"
/* Image down and up scaling */
#include "filters/GP_Scale.h"
diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Linear.h
similarity index 76%
copy from include/filters/GP_Filters.h
copy to include/filters/GP_Linear.h
index 4c1304d..2ef5a0e 100644
--- a/include/filters/GP_Filters.h
+++ b/include/filters/GP_Linear.h
@@ -16,28 +16,21 @@
* 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> *
* *
*****************************************************************************/
/*
- GP_Context filters.
+ Linear filters.
*/
-#ifndef GP_FILTERS_H
-#define GP_FILTERS_H
-
-/* Image rotations (90 180 270 grads) and mirroring */
-#include "filters/GP_Rotate.h"
+#ifndef GP_LINEAR_H
+#define GP_LINEAR_H
-#include "filters/GP_Point.h"
+#include <GP_Context.h>
-/* Image down and up scaling */
-#include "filters/GP_Scale.h"
+GP_Context *GP_FilterBlur(GP_Context *src);
-#endif /* GP_FILTERS_H */
+#endif /* GP_LINEAR_H */
diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c
new file mode 100644
index 0000000..66c0db6
--- /dev/null
+++ b/libs/filters/GP_Linear.c
@@ -0,0 +1,150 @@
+/*****************************************************************************
+ * 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-2011 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+#include <GP_Context.h>
+#include <GP_GetPutPixel.h>
+
+#include <GP_Debug.h>
+
+#include <GP_Linear.h>
+
+static float HX[] = {0.17, 0.66, 0.17};
+static float HY[] = {0.17, 0.66, 0.17};
+
+GP_Context *GP_FilterBlur(GP_Context *src)
+{
+ GP_Context *dst;
+
+ if (src->pixel_type != GP_PIXEL_RGB888)
+ return NULL;
+
+ dst = GP_ContextCopy(src, 0);
+
+ if (dst == NULL)
+ return NULL;
+
+ GP_DEBUG(1, "Linear blur filter (3x3 kernel) %ux%u", src->w, src->h);
+
+ GP_Coord x, y;
+
+ for (y = 0; y < (GP_Coord)dst->h; y++) {
+ GP_Pixel pix;
+ uint32_t R1, R2, R3;
+ uint32_t G1, G2, G3;
+ uint32_t B1, B2, B3;
+
+ pix = GP_GetPixel_Raw_24BPP(src, 0, y);
+
+ R1 = GP_Pixel_GET_R_RGB888(pix);
+ G1 = GP_Pixel_GET_G_RGB888(pix);
+ B1 = GP_Pixel_GET_B_RGB888(pix);
+
+ R2 = R1;
+ G2 = G1;
+ B2 = B1;
+
+ for (x = 0; x < (GP_Coord)dst->w; x++) {
+ float r, g, b;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, y);
+
+ R3 = GP_Pixel_GET_R_RGB888(pix);
+ G3 = GP_Pixel_GET_G_RGB888(pix);
+ B3 = GP_Pixel_GET_B_RGB888(pix);
+
+ r = R1 * HX[0] + R2 * HX[1] + R3 * HX[2];
+ g = G1 * HX[0] + G2 * HX[1] + G3 * HX[2];
+ b = B1 * HX[0] + B2 * HX[1] + B3 * HX[2];
+
+ if (r > 255)
+ r = 255;
+ if (g > 255)
+ g = 255;
+ if (b > 255)
+ b = 255;
+
+ pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
+
+ GP_PutPixel_Raw_24BPP(dst, x, y, pix);
+
+ R1 = R2;
+ G1 = G2;
+ B1 = B2;
+
+ R2 = R3;
+ G2 = G3;
+ B2 = B3;
+ }
+ }
+
+ for (x = 0; x < (GP_Coord)dst->w; x++) {
+ GP_Pixel pix;
+ uint32_t R1, R2, R3;
+ uint32_t G1, G2, G3;
+ uint32_t B1, B2, B3;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, 0);
+
+ R1 = GP_Pixel_GET_R_RGB888(pix);
+ G1 = GP_Pixel_GET_G_RGB888(pix);
+ B1 = GP_Pixel_GET_B_RGB888(pix);
+
+ R2 = R1;
+ G2 = G1;
+ B2 = B1;
+
+ for (y = 0; y < (GP_Coord)dst->h; y++) {
+ float r, g, b;
+
+ pix = GP_GetPixel_Raw_24BPP(src, x, y);
+
+ R3 = GP_Pixel_GET_R_RGB888(pix);
+ G3 = GP_Pixel_GET_G_RGB888(pix);
+ B3 = GP_Pixel_GET_B_RGB888(pix);
+
+ r = R1 * HY[0] + R2 * HY[1] + R3 * HY[2];
+ g = G1 * HY[0] + G2 * HY[1] + G3 * HY[2];
+ b = B1 * HY[0] + B2 * HY[1] + B3 * HY[2];
+
+ if (r > 255)
+ r = 255;
+ if (g > 255)
+ g = 255;
+ if (b > 255)
+ b = 255;
+
+ pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
+
+ GP_PutPixel_Raw_24BPP(dst, x, y, pix);
+
+ R1 = R2;
+ G1 = G2;
+ B1 = B2;
+
+ R2 = R3;
+ G2 = G3;
+ B2 = B3;
+ }
+ }
+
+ return dst;
+}
-----------------------------------------------------------------------
Summary of changes:
demos/grinder/grinder.c | 23 +++
include/filters/GP_Filters.h | 1 +
.../core/GP_Debug.c => include/filters/GP_Linear.h | 21 ++--
libs/filters/GP_Linear.c | 150 ++++++++++++++++++++
4 files changed, 185 insertions(+), 10 deletions(-)
copy libs/core/GP_Debug.c => include/filters/GP_Linear.h (88%)
create mode 100644 libs/filters/GP_Linear.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