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 master updated: e90eda658220809b70c37e954d2624e3cfdcd5ea
by metan 10 Nov '12
by metan 10 Nov '12
10 Nov '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 e90eda658220809b70c37e954d2624e3cfdcd5ea (commit)
from aaa7f50197c97d3b9b7f5d30cbe1f91c51f52384 (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/e90eda658220809b70c37e954d2624e3cfdc…
commit e90eda658220809b70c37e954d2624e3cfdcd5ea
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 17:27:32 2012 +0100
doc: Move ProgressCallback to core, add example.
diff --git a/doc/basic_types.txt b/doc/basic_types.txt
index f02688a..1542083 100644
--- a/doc/basic_types.txt
+++ b/doc/basic_types.txt
@@ -88,33 +88,3 @@ void GP_ColorLoadContextPixels(GP_Pixel pixels[], GP_Context *context);
Loads array of 'GP_Pixel' of size 'GP_COL_MAX', the array is then used with
the GP_Color enum as 'pixels[GP_COL_BLACK]'.
-Progress Callback
-~~~~~~~~~~~~~~~~~
-
-The 'GP_ProgressCallback' is a structure that stores user-defined callback
-function and user-defined pointer and percentage.
-
-It is passed as last parameter to functions that would take some time to
-complete and adds capability to track the operation progress as well as to
-abort the operation.
-
-Currently it's used for filters and loaders.
-
-[source,c]
--------------------------------------------------------------------------------
-typdedef struct GP_ProgressCallback {
- float percentage;
- int (*callback)(struct GP_ProgressCallback *self);
- void *priv;
-} GP_ProgressCallback;
--------------------------------------------------------------------------------
-
-If non 'NULL' progress callback structure is passed to a function, the
-callback function is periodically called and the percentage is updated.
-
-The return value from callback could abort the function execution. If non zero
-value is returned operation is aborted, all memory freed etc. and in case of
-bitmap loaders 'errno' is set to 'ECANCELED'.
-
-The callback, if supported, is the last parameter of a function.
-
diff --git a/doc/core.txt b/doc/core.txt
index fdb8056..3e20ee2 100644
--- a/doc/core.txt
+++ b/doc/core.txt
@@ -56,6 +56,39 @@ Value clamping macros.
NOTE: this header is not included by including the 'GP.h' header.
+Progress Callback
+~~~~~~~~~~~~~~~~~
+
+The 'GP_ProgressCallback' is a structure that stores user-defined callback
+function and user-defined pointer and percentage.
+
+It is passed as last parameter to functions that would take some time to
+complete and adds capability to track the operation progress as well as to
+abort the operation.
+
+Currently it's used for filters and loaders.
+
+[source,c]
+-------------------------------------------------------------------------------
+typdedef struct GP_ProgressCallback {
+ float percentage;
+ int (*callback)(struct GP_ProgressCallback *self);
+ void *priv;
+} GP_ProgressCallback;
+-------------------------------------------------------------------------------
+
+If non 'NULL' progress callback structure is passed to a function, the
+callback function is periodically called and the percentage is updated.
+
+The return value from callback could abort the function execution. If non zero
+value is returned operation is aborted, all memory freed etc. and in case of
+bitmap loaders 'errno' is set to 'ECANCELED'.
+
+The callback, if supported, is the last parameter of a function.
+
+For example usage see progress callback
+link:example_loaders_progress_callback.html[example].
+
Temporary Buffer Allocator
~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/example_loaders_progress_callback.txt b/doc/example_loaders_progress_callback.txt
new file mode 100644
index 0000000..7da5160
--- /dev/null
+++ b/doc/example_loaders_progress_callback.txt
@@ -0,0 +1,7 @@
+Graphics Backend Example
+------------------------
+
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/loaders.c[]
+------------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
doc/basic_types.txt | 30 ------------------
doc/core.txt | 33 ++++++++++++++++++++
...d.txt => example_loaders_progress_callback.txt} | 2 +-
3 files changed, 34 insertions(+), 31 deletions(-)
copy doc/{example_backend.txt => example_loaders_progress_callback.txt} (80%)
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: aaa7f50197c97d3b9b7f5d30cbe1f91c51f52384
by metan 10 Nov '12
by metan 10 Nov '12
10 Nov '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 aaa7f50197c97d3b9b7f5d30cbe1f91c51f52384 (commit)
via 5c61bb13e751a867d68d1443e20b80a992ae1e11 (commit)
from fd437dffad5c449ae3dff083562b0db30ea1eb8e (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/aaa7f50197c97d3b9b7f5d30cbe1f91c51f5…
commit aaa7f50197c97d3b9b7f5d30cbe1f91c51f52384
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 17:07:02 2012 +0100
doc: Add more examples and links.
diff --git a/doc/backends.txt b/doc/backends.txt
index 66728f7..a471652 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -10,6 +10,8 @@ controlling the drawing.
So far there are three backends implemented, Linux mmaped frame-buffer, libSDL
and X11 backend.
+For example usage see backend link:example_backend.html[example].
+
Initialization functions
~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/example_backend.txt b/doc/example_backend.txt
new file mode 100644
index 0000000..ed13dea
--- /dev/null
+++ b/doc/example_backend.txt
@@ -0,0 +1,7 @@
+Graphics Backend Example
+------------------------
+
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/backend_example.c[]
+------------------------------------------------------------------
diff --git a/doc/example_v4l2.txt b/doc/example_v4l2.txt
new file mode 100644
index 0000000..2f1e389
--- /dev/null
+++ b/doc/example_v4l2.txt
@@ -0,0 +1,17 @@
+Graphics Backend Example
+------------------------
+
+Simple grabber that saves images taken from v4l2 device.
+
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/v4l2_grab.c[]
+------------------------------------------------------------------
+
+More sophisticated example utilizing v4l2 device and
+link:backends.html[backends].
+
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/v4l2_show.c[]
+------------------------------------------------------------------
diff --git a/doc/grabbers.txt b/doc/grabbers.txt
index 93af01b..a794847 100644
--- a/doc/grabbers.txt
+++ b/doc/grabbers.txt
@@ -8,6 +8,8 @@ There is currently V4L2 driver that implements a grabber.
To link against grabbers use +-lGP_grabbers+ or better
+`gfxprim-config --libs-grabbers`+ in your linker flags.
+For example usage see grabber link:example_v4l2.html[examples].
+
Grabber API
~~~~~~~~~~~
http://repo.or.cz/w/gfxprim.git/commit/5c61bb13e751a867d68d1443e20b80a992ae…
commit 5c61bb13e751a867d68d1443e20b80a992ae1e11
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 16:55:08 2012 +0100
doc: Remove the all-in-one page API docs.
diff --git a/doc/Makefile b/doc/Makefile
index 19b89d2..4160ae0 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,6 +1,6 @@
SOURCES=general.txt context.txt loaders.txt filters.txt basic_types.txt drawing_api.txt backends.txt gamma.txt grabbers.txt - environment_variables.txt debug.txt core.txt
+ environment_variables.txt debug.txt core.txt api.txt
EXAMPLE_SOURCES=$(wildcard example_*.txt)
@@ -14,13 +14,7 @@ GENIMAGES=discrete_linear_1D_convolution_alg1 discrete_linear_1D_convolution_alg
PAGES=$(subst .txt,.html,$(SOURCES))
PAGES+=$(subst .txt,.html,$(EXAMPLE_SOURCES))
-all: api.html examples.html $(PAGES) api_links.html
-
-#
-# Create all in one API page
-#
-api.html: $(SOURCES) api.txt
- asciidoc -a toc api.txt
+all: examples.html $(PAGES) api.html
#
# Create page for each part of API description
@@ -28,17 +22,9 @@ api.html: $(SOURCES) api.txt
$(PAGES): %.html: %.txt
asciidoc $<
-api_links.html: api_links.txt
- asciidoc $<
-
examples.html: examples.txt ../demos/c_simple/*.c ../demos/py_simple/*.py
asciidoc -a toc examples.txt
-api.pdf: api.txt
- asciidoc -b docbook api.txt
- xsltproc /usr/share/sgml/docbook/xsl-stylesheets/fo/docbook.xsl api.xml > api.fo
- fop api.fo -pdf api.pdf
-
#
# Clean up generated images
#
diff --git a/doc/README b/doc/README
index 87e78a6..ae93336 100644
--- a/doc/README
+++ b/doc/README
@@ -3,7 +3,3 @@ This directory contains asciidoc documentation.
The html pages are generated by typing 'make'.
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
-and xsltproc must be installed.
diff --git a/doc/api.txt b/doc/api.txt
index 899df1c..aff68ea 100644
--- a/doc/api.txt
+++ b/doc/api.txt
@@ -2,17 +2,56 @@ GFXprim API
===========
Cyril Hrubis <metan(a)ucw.cz>
-This documentation is also available link:api_links.html[divided into several
-pages].
-
-include::general.txt[]
-include::basic_types.txt[]
-include::environment_variables.txt[]
-include::debug.txt[]
-include::context.txt[]
-include::gamma.txt[]
-include::drawing_api.txt[]
-include::filters.txt[]
-include::loaders.txt[]
-include::backends.txt[]
-include::grabbers.txt[]
+. link:basic_types.html[Basic library types]
+ +
+ Describes how colors and pixels are handled also describes progress callback
+ in great detail.
+ +
+. link:core.html[Library Core overview]
+ +
+ Describes functions and macros in library core.
+ +
+. link:debug.html[Debug Messages]
+ +
+ Interface to debug layer.
+ +
+. link:context.html[Context]
+ +
+ The Context is description of in-memory bitmap including some meta-data
+ (size, pixel format, etc...).
+ +
+. link:environment_variables.html[Environment Variables]
+ +
+ Description of environment variables that affects GFXprim behavior.
+ +
+. link:gamma.html[Gamma correction]
+ +
+ The gama correction description and handling in GFXprim.
+ +
+. link:drawing_api.html[Drawing primitives]
+ +
+ Drawing API for primitives such as lines, polygons and circles as well as
+ text drawing.
+ +
+. link:filters.html[Context filters]
+ +
+ Context filters, basically all algorithms that takes an Context as an input
+ and returns Context as output.
+ +
+ Includes resampling, convolutions, low pass (blur) filters, dithering and
+ more.
+ +
+. link:loaders.html[Context loaders]
+ +
+ Handles loading and saving images in standard formats.
+ +
+. link:backends.html[Backends]
+ +
+ Backends API for drawing on the screen or into a window.
+ +
+. link:grabbers.html[Grabbers]
+ +
+ Video grabbers interface such as V4L2.
+ +
+
+There is also a nice page with code link:examples.html[examples].
diff --git a/doc/api_links.txt b/doc/api_links.txt
deleted file mode 100644
index 3aff6f9..0000000
--- a/doc/api_links.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-GFXprim API
-===========
-Cyril Hrubis <metan(a)ucw.cz>
-
-Also available in link:api.html[all in one page form].
-
-
-. link:basic_types.html[Basic library types]
- +
- Describes how colors and pixels are handled also describes progress callback
- in great detail.
- +
-. link:core.html[Library Core overview]
- +
- Describes functions and macros in library core.
- +
-. link:debug.html[Debug Messages]
- +
- Interface to debug layer.
- +
-. link:context.html[Context]
- +
- The Context is description of in-memory bitmap including some meta-data
- (size, pixel format, etc...).
- +
-. link:environment_variables.html[Environment Variables]
- +
- Description of environment variables that affects GFXprim behavior.
- +
-. link:gamma.html[Gamma correction]
- +
- The gama correction description and handling in GFXprim.
- +
-. link:drawing_api.html[Drawing primitives]
- +
- Drawing API for primitives such as lines, polygons and circles as well as
- text drawing.
- +
-. link:filters.html[Context filters]
- +
- Context filters, basically all algorithms that takes an Context as an input
- and returns Context as output.
- +
- Includes resampling, convolutions, low pass (blur) filters, dithering and
- more.
- +
-. link:loaders.html[Context loaders]
- +
- Handles loading and saving images in standard formats.
- +
-. link:backends.html[Backends]
- +
- Backends API for drawing on the screen or into a window.
- +
-. link:grabbers.html[Grabbers]
- +
- Video grabbers interface such as V4L2.
- +
-
-There is also a nice page with code link:examples.html[examples].
-----------------------------------------------------------------------
Summary of changes:
doc/Makefile | 18 +-----
doc/README | 4 -
doc/api.txt | 67 +++++++++++++++----
doc/api_links.txt | 60 -----------------
doc/backends.txt | 2 +
...loader_registration.txt => example_backend.txt} | 6 +-
doc/example_v4l2.txt | 17 +++++
doc/grabbers.txt | 2 +
8 files changed, 79 insertions(+), 97 deletions(-)
delete mode 100644 doc/api_links.txt
copy doc/{example_loader_registration.txt => example_backend.txt} (55%)
create mode 100644 doc/example_v4l2.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: fd437dffad5c449ae3dff083562b0db30ea1eb8e
by metan 10 Nov '12
by metan 10 Nov '12
10 Nov '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 fd437dffad5c449ae3dff083562b0db30ea1eb8e (commit)
via b455c46c4d84d1ac66113db48722d9247cb2fc34 (commit)
via 03e092e8d75543e3446afe498e359bb1e4be6856 (commit)
via 03b001ae92a7ad29e60bcaa3ca1bb93e46963048 (commit)
from 80d1a231acdf63c758e84a257c20aaffca6550e3 (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/fd437dffad5c449ae3dff083562b0db30ea1…
commit fd437dffad5c449ae3dff083562b0db30ea1eb8e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 16:49:36 2012 +0100
doc: Library core functions and macros docs.
diff --git a/doc/Makefile b/doc/Makefile
index acdade4..19b89d2 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,6 +1,6 @@
SOURCES=general.txt context.txt loaders.txt filters.txt basic_types.txt drawing_api.txt backends.txt gamma.txt grabbers.txt - environment_variables.txt debug.txt
+ environment_variables.txt debug.txt core.txt
EXAMPLE_SOURCES=$(wildcard example_*.txt)
diff --git a/doc/api_links.txt b/doc/api_links.txt
index 2e41996..3aff6f9 100644
--- a/doc/api_links.txt
+++ b/doc/api_links.txt
@@ -10,6 +10,10 @@ Also available in link:api.html[all in one page form].
Describes how colors and pixels are handled also describes progress callback
in great detail.
+
+. link:core.html[Library Core overview]
+ +
+ Describes functions and macros in library core.
+ +
. link:debug.html[Debug Messages]
+
Interface to debug layer.
diff --git a/doc/core.txt b/doc/core.txt
new file mode 100644
index 0000000..fdb8056
--- /dev/null
+++ b/doc/core.txt
@@ -0,0 +1,140 @@
+Library Core
+------------
+
+The core of the library contains the 'GP_Context' structure which describes
+in-memory bitmap (see context) as well as the most basic functionality (i.e.
+reading/writing pixels, gamma handling, blits, progress callback, debug
+printing...). More complex parts of the core library are discussed in separate
+pages.
+
+Some of the interfaces described here (most notably the allocator) are
+semi-internal interfaces and as such the API may change in the future.
+
+Common Macros and Inline Functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_Common.h>
+/* or */
+#include <GP.h>
+
+GP_MIN(a, b);
+
+GP_MAX(a, b);
+
+GP_ABS(a);
+
+GP_SWAP(a, b);
+
+GP_SIGN(a);
+
+-------------------------------------------------------------------------------
+
+These common macros implements basic functions such as minimum, maximum,
+absolute value, swap and sign.
+
+All macros use 'typeof()' in order to evaluate their arguments exactly once.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_Clamp.h>
+
+/*
+ * Clamps integer value to 8 bit unsigned value.
+ */
+GP_CLAMP_INT_0_255(val);
+
+/*
+ * Clamps integer value.
+ */
+GP_CLAMP(val, min, max);
+
+-------------------------------------------------------------------------------
+
+Value clamping macros.
+
+NOTE: this header is not included by including the 'GP.h' header.
+
+Temporary Buffer Allocator
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Temporary buffer allocator is used to allocate temporary buffer needed for
+certain operations (mostly used in image filters).
+
+The intended usage of temporary buffers is:
+
+* Count sum of the size needed for all buffers
+* Allocate temporary buffer of this size
+* Partition the buffer into smaller blocks
+* Use the blocks as needed
+* Once operation is done, free the buffer
+
+The allocator code greatly simplifies these steps. Moreover it avoids memory
+fragmentation by creating small buffers on the process stack (current theshold
+is set to 2kB) and by grouping the temporary buffers into one continuous
+region.
+
+NOTE: The allocator itself does not align the resulting blocks. It's your
+ responsibility to allocate the buffers in a way that the result is
+ adequately aligned (hint: the start of the block is aligned, so
+ get blocks that needs to be aligned first).
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_TempAlloc.h>
+
+/*
+ * A macro that creates block allocator.
+ *
+ * The name must be unique among variable and functions names.
+ *
+ * The bsize is actual size of the block allocated.
+ */
+GP_TempAllocCreate(name, bsize);
+
+/*
+ * A macro that returns pointer to the start of a block of a bsize
+ * partioned from the block allocator passed as self argument.
+ */
+GP_TempAllocGet(self, bsize);
+
+/*
+ * Free the allocator memory.
+ */
+GP_TempAllocFree(self);
+-------------------------------------------------------------------------------
+
+Example usage of the allocator:
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <core/GP_TempAlloc.h>
+
+int foo(...)
+{
+ GP_TempAllocCreate(tmp, 3 * img->width);
+
+ uint8_t *R = GP_TempAllocGet(tmp, img->width);
+ uint8_t *G = GP_TempAllocGet(tmp, img->width);
+ uint8_t *B = GP_TempAllocGet(tmp, img->width);
+
+ /* start of the code that uses the buffers */
+
+ ...
+
+ if (error) {
+ GP_TempAllocFree(self);
+ return -1;
+ }
+
+ ...
+
+ /* end of the code that uses the buffers */
+
+ GP_TempAllocFree(self);
+
+ return 0;
+}
+-------------------------------------------------------------------------------
+
http://repo.or.cz/w/gfxprim.git/commit/b455c46c4d84d1ac66113db48722d9247cb2…
commit b455c46c4d84d1ac66113db48722d9247cb2fc34
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 16:32:43 2012 +0100
doc: Update loaders documentation.
diff --git a/doc/Makefile b/doc/Makefile
index bda6964..acdade4 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -2,6 +2,8 @@ SOURCES=general.txt context.txt loaders.txt filters.txt basic_types.txt drawing_api.txt backends.txt gamma.txt grabbers.txt environment_variables.txt debug.txt
+EXAMPLE_SOURCES=$(wildcard example_*.txt)
+
#
# Names of generated images for cleanup
#
@@ -10,7 +12,7 @@ GENIMAGES=discrete_linear_1D_convolution_alg1 discrete_linear_1D_convolution_alg
discrete_linear_convolution_alg2 laplacian_edge_sharpening laplacian_kernel
PAGES=$(subst .txt,.html,$(SOURCES))
-
+PAGES+=$(subst .txt,.html,$(EXAMPLE_SOURCES))
all: api.html examples.html $(PAGES) api_links.html
diff --git a/doc/example_loader_registration.txt b/doc/example_loader_registration.txt
new file mode 100644
index 0000000..b287560
--- /dev/null
+++ b/doc/example_loader_registration.txt
@@ -0,0 +1,7 @@
+Image Loader Registration Example
+---------------------------------
+
+[source,c]
+------------------------------------------------------------------
+include::../demos/c_simple/loaders_register.c[]
+------------------------------------------------------------------
diff --git a/doc/loaders.txt b/doc/loaders.txt
index 99ed35d..e12c6f8 100644
--- a/doc/loaders.txt
+++ b/doc/loaders.txt
@@ -3,14 +3,25 @@ Context loaders
This part of GFXprim library aims to create API to load and save images
from/to common image file formats.
+Currently we support JPEG, PNG and some PNM images for loading and saving and
+BMP, GIF and PSP for loading.
+
+Loaders API
+~~~~~~~~~~~
+
All loading functions returns a pointer to allocated and loaded image or upon
-a failure 'NULL' and 'errno' is set.
+a failure 'NULL'.
+
+All saving functions returns zero on success and non-zero on failure. If
+image saving is aborted by a callback, the opened file is closed and removed
+from a filesystem before the call returns.
+
+In case of a failure 'errno' is set.
-All saving functions returns zero on success and non-zero on failure and
-'errno' is set. If image saving is aborted by a callback, the opened file is
-closed and removed from a filesystem before the call returns.
+The signature matching functions takes a 32 bytes long buffer and looks for a
+valid image signature. If signature is found 1 is returned.
-The possible 'errno' values (for both loading and saving) are:
+The possible 'errno' values are:
* anything returned by +open()+, +close()+, +lseek()+, +read()+, +write()+, ...
- 'ENOENT' if file doesn't exist
@@ -22,8 +33,11 @@ The possible 'errno' values (for both loading and saving) are:
* 'EIO' invalid image data (wrong signature, header or image data)
* 'ECANCELED' action canceled by returning non-zero from within a callback
-Common Loader
-~~~~~~~~~~~~~
+You can get more information about the error condition by turning on GFXprim
+debug messages.
+
+Image Loader
+~~~~~~~~~~~~
[source,c]
-------------------------------------------------------------------------------
@@ -34,9 +48,21 @@ Common Loader
GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback);
-------------------------------------------------------------------------------
-Loads image from a file. The format is now matched by an image file extension.
-Fallback to file signature if file content doesn't match it's extension is on
-the TODO.
+Loads image from a file.
+
+The image format is first guessed by the file extension. If loader for the
+file extension is found it's called and if it succedes the image data is
+returned.
+
+If extension based guess fails either because the extension wasn't matched or
+if the loader for the extension failed; the signature based method is used.
+The loader loads several bytes (currently 32) from the file and calls
+signature matching functions for each format that implements signature
+matching. If image signature is found particular image loader it is called
+and the result is returned.
+
+If file extension disagrees with file signature a warning is printed into the
+stdout.
[source,c]
-------------------------------------------------------------------------------
@@ -48,16 +74,115 @@ int GP_SaveImage(GP_Context *src, const char *dst_path,
GP_ProgressCallback *callback);
-------------------------------------------------------------------------------
-Saves a context into a file. The file format is matched accordingly to the
-file extension, if extension is invalid or if support for requested image
-format wasn't compiled in, non-zero is returned and 'errno' is set to
-'ENOSYS'.
+Saves a context into a file.
+
+The file format is matched accordingly to the file extension. If extension is
+not found non-zero is returned and 'errno' is set to 'EINVAL'. If extension
+was found but support for saving the image format is not implemented 'errno'
+is set to 'ENOSYS'.
+
+
+Advanced usage
+^^^^^^^^^^^^^^
+
+[source,c]
+-------------------------------------------------------------------------------
+typedef struct GP_Loader {
+ /*
+ * Loads an image.
+ *
+ * Returns allocated and initialized bitmap on success, NULL on failure
+ * and errno must be set.
+ */
+ GP_Context *(*Load)(const char *src_path, GP_ProgressCallback *callback);
+
+ /*
+ * Save an image.
+ *
+ * Returns zero on succes, non-zero on failure and errno must be set.
+ */
+ int (*Save)(const GP_Context *src, const char *dst_path,
+ GP_ProgressCallback *callback);
+
+ /*
+ * The buffer is filled with 32 bytes from an image start, returns 1 if
+ * image signature was found zero otherwise.
+ */
+ int (*Match)(const void *buf);
+
+ /*
+ * Short format name.
+ */
+ const char *fmt_name;
+
+ /* don't touch */
+ struct GP_Loader *next;
+
+ /*
+ * NULL terminated array of file extensions.
+ */
+ const char *extensions[];
+} GP_Loader;
+
+/*
+ * List loaders into the stdout.
+ */
+void GP_ListLoaders(void);
+
+/*
+ * Register a loader.
+ */
+void GP_LoaderRegister(GP_Loader *self);
+
+/*
+ * Unregister loader.
+ */
+void GP_LoaderUnregister(GP_Loader *self);
+-------------------------------------------------------------------------------
+
+The 'GP_Loader' structure describes an image loader.
+
+The 'Load', 'Save' and 'Match' functions could be 'NULL' if the particular
+functionality is not implemented.
+
+The 'fmt_name' is a short string that describes the format. For example:
+'Netbpm portable pixmap'.
+
+The extensions is 'NULL'-terminated array of strings that holds all possible
+extensions that are commonly used for this image format.
+
+All internal loaders are all described in list of this structures which is
+used to implement functions such as 'GP_LoadImage()'.
+
+You can print currently active loaders via the 'GP_ListLoaders()' register and
+unregister your own loaders by 'GP_LoaderRegister()' and
+'GP_LoaderUnregister()'. Once image loader is registered the generic loading
+functions could use it to load and save images.
+
+For example usage see image loader registration
+link:example_loader_registration.html[example].
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_Loaders.h>
+/* or */
+#include <GP.h>
+
+const GP_Loader *GP_MatchSignature(const void *buf)
+-------------------------------------------------------------------------------
+
+Returns pointer to image loader accordingly to image signature or 'NULL' if no
+suitable loader was found. The buf pointer must point to a buffer at least 32
+bytes long.
+
+WARNING: If you attempt to modify the content of the strucutre the behavior is
+ undefined. Most likely the program will crash.
-PNG
-~~~
+PNG Loader
+~~~~~~~~~~
The 'PNG' image support is implemented by the libpng library.
-WARNING: PNG images with alpha channel are not supported yet.
+NOTE: PNG images with alpha channel are not supported yet.
[source,c]
-------------------------------------------------------------------------------
@@ -114,8 +239,19 @@ Currently only 'RGB888' format is supported, you should convert the
'GP_Context' to 'RGB888' before calling this function otherwise non-zero is
returned and 'errno' is set to 'ENOSYS'.
-JPEG
-~~~~
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_PNG.h>
+/* or */
+#include <GP.h>
+
+int GP_MatchPNG(const void *buf);
+-------------------------------------------------------------------------------
+
+Matches a PNG signature.
+
+JPEG Loader
+~~~~~~~~~~~
The 'JPEG' image support is implemented by the jpeg library.
[source,c]
@@ -180,8 +316,19 @@ is closed and removed before the call returns non-zero and 'errno' is set to
The 'JPG' format could store either 'G8' or 'RGB888' pixeltypes and you must
convert the context into one of them before this functions is called.
-GIF
-~~~
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_JPG.h>
+/* or */
+#include <GP.h>
+
+int GP_MatchJPG(const void *buf);
+-------------------------------------------------------------------------------
+
+Matches a JPG signature.
+
+GIF Loader
+~~~~~~~~~~
The 'GIF' image support is implemented by the giflib library.
@@ -229,8 +376,19 @@ GP_Context *GP_LoadGIF(const char *src_path, GP_ProgressCallback *callback);
Same as above but takes path to the file as a parameter and check for the
signature. Basically this combines both of the calls above.
-BMP
-~~~
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_GIF.h>
+/* or */
+#include <GP.h>
+
+int GP_MatchGIF(const void *buf);
+-------------------------------------------------------------------------------
+
+Matches a GIF signature.
+
+BMP Loader
+~~~~~~~~~~
The 'BMP' loading support is nearly complete the only missing features should
be fancy RGB compressions and RLE support.
@@ -280,9 +438,72 @@ GP_Context *GP_LoadBMP(const char *src_path, GP_ProgressCallback *callback);
Same as above but takes path to the file as a parameter and check for the
signature. Basically this combines both of the calls above.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_BMP.h>
+/* or */
+#include <GP.h>
+
+int GP_MatchBMP(const void *buf);
+-------------------------------------------------------------------------------
+
+Matches a BMP signature.
+
+PSP Loader
+~~~~~~~~~~
+
+The 'PSP' loader can load a composite image from a Paint Shop Pro Image Files.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_PSP.h>
+/* or */
+#include <GP.h>
+
+int GP_OpenPSP(const char *src_path, FILE **f);
+-------------------------------------------------------------------------------
+
+Opens file and checks for 'PSP' signature. Upon successful return (file could
+be opened, signature matches) zero is returned. Upon failure non-zero is
+returned and 'errno' is set.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_PSP.h>
+/* or */
+#include <GP.h>
+
+GP_Context *GP_ReadPSP(FILE *f, GP_ProgressCallback *callback);
+-------------------------------------------------------------------------------
+
+Reads 'PSP' image into a context.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_PSP.h>
+/* or */
+#include <GP.h>
+
+GP_Context *GP_LoadPSP(const char *src_path, GP_ProgressCallback *callback);
+-------------------------------------------------------------------------------
+
+Same as above but takes path to the file as a parameter and check for the
+signature. Basically this combines both of the calls above.
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <loaders/GP_PSP.h>
+/* or */
+#include <GP.h>
+
+int GP_MatchPSP(const void *buf);
+-------------------------------------------------------------------------------
+
+Matches a PSP signature.
+
PBM, PGM, PPM
~~~~~~~~~~~~~
There is a code do load and write 'PBM', 'PGM' and 'PPM' images too. However
it's not finished and its API is outdated. Use at your own risk.
-
http://repo.or.cz/w/gfxprim.git/commit/03e092e8d75543e3446afe498e359bb1e4be…
commit 03e092e8d75543e3446afe498e359bb1e4be6856
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 15:07:30 2012 +0100
loaders: Add GP_MatchImage().
diff --git a/include/loaders/GP_Loader.h b/include/loaders/GP_Loader.h
index ef7add1..6730613 100644
--- a/include/loaders/GP_Loader.h
+++ b/include/loaders/GP_Loader.h
@@ -102,6 +102,12 @@ typedef struct GP_Loader {
const char *extensions[];
} GP_Loader;
+/*
+ * Takes pointer to buffer at least 32 bytes long and returns a pointer to
+ * matched loader or NULL.
+ */
+const GP_Loader *GP_MatchSignature(const void *buf);
+
void GP_LoaderRegister(GP_Loader *self);
void GP_LoaderUnregister(GP_Loader *self);
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index b1769be..3d626a6 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -199,13 +199,13 @@ static struct GP_Loader *loader_by_filename(const char *path)
return loader_by_extension(ext);
}
-static struct GP_Loader *loader_by_signature(const char *path)
+static const GP_Loader *loader_by_signature(const char *path)
{
uint8_t buf[32];
FILE *f;
int err;
- GP_DEBUG(1, "Trying to match file signature");
+ GP_DEBUG(1, "Trying to load a file by signature");
f = fopen(path, "rb");
@@ -224,16 +224,7 @@ static struct GP_Loader *loader_by_signature(const char *path)
fclose(f);
- struct GP_Loader *i;
-
- for (i = loaders; i != NULL; i = i->next) {
- if (i->Match && i->Match(buf)) {
- GP_DEBUG(1, "Found loader '%s'", i->fmt_name);
- return i;
- }
- }
-
- return NULL;
+ return GP_MatchSignature(buf);
}
GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
@@ -253,7 +244,7 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
}
GP_Context *img;
- struct GP_Loader *ext_load = NULL, *sig_load;
+ const GP_Loader *ext_load = NULL, *sig_load;
ext_load = loader_by_filename(src_path);
@@ -431,3 +422,19 @@ int GP_SaveImage(const GP_Context *src, const char *dst_path,
errno = ENOSYS;
return 1;
}
+
+const GP_Loader *GP_MatchSignature(const void *buf)
+{
+ struct GP_Loader *i;
+
+ for (i = loaders; i != NULL; i = i->next) {
+ if (i->Match && i->Match(buf) == 1) {
+ GP_DEBUG(1, "Found loader '%s'", i->fmt_name);
+ return i;
+ }
+ }
+
+ GP_DEBUG(1, "Loader not found");
+
+ return NULL;
+}
http://repo.or.cz/w/gfxprim.git/commit/03b001ae92a7ad29e60bcaa3ca1bb93e4696…
commit 03b001ae92a7ad29e60bcaa3ca1bb93e46963048
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 14:39:44 2012 +0100
loaders: Now we aren't fooled by wrong filename extension.
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index 0ef1024..b1769be 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -236,6 +236,48 @@ static struct GP_Loader *loader_by_signature(const char *path)
return NULL;
}
+GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
+{
+ int saved_errno;
+
+ if (access(src_path, R_OK)) {
+
+ saved_errno = errno;
+
+ GP_DEBUG(1, "Failed to access file '%s' : %s",
+ src_path, strerror(errno));
+
+ errno = saved_errno;
+
+ return NULL;
+ }
+
+ GP_Context *img;
+ struct GP_Loader *ext_load = NULL, *sig_load;
+
+ ext_load = loader_by_filename(src_path);
+
+ if (ext_load != NULL) {
+ img = ext_load->Load(src_path, callback);
+
+ if (img)
+ return img;
+ }
+
+ sig_load = loader_by_signature(src_path);
+
+ if (ext_load && sig_load) {
+ GP_WARN("File '%s': Extension says %s but signature %s",
+ src_path, ext_load->fmt_name, sig_load->fmt_name);
+ }
+
+ if (sig_load)
+ return sig_load->Load(src_path, callback);
+
+ errno = ENOSYS;
+ return NULL;
+}
+
enum GP_ImageFmt {
GP_FMT_UNKNOWN,
GP_FMT_PNG,
@@ -341,61 +383,6 @@ enum GP_ImageFmt filename_to_fmt(const char *path)
return GP_FMT_UNKNOWN;
}
-GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
-{
- int saved_errno;
-
- if (access(src_path, R_OK)) {
-
- saved_errno = errno;
-
- GP_DEBUG(1, "Failed to access file '%s' : %s",
- src_path, strerror(errno));
-
- errno = saved_errno;
-
- return NULL;
- }
-
- enum GP_ImageFmt fmt = filename_to_fmt(src_path);
-
- switch (fmt) {
- case GP_FMT_JPG:
- return GP_LoadJPG(src_path, callback);
- case GP_FMT_PNG:
- return GP_LoadPNG(src_path, callback);
- case GP_FMT_GIF:
- return GP_LoadGIF(src_path, callback);
- case GP_FMT_PSP:
- return GP_LoadPSP(src_path, callback);
- case GP_FMT_BMP:
- return GP_LoadBMP(src_path, callback);
- case GP_FMT_PBM:
- return GP_LoadPBM(src_path, callback);
- case GP_FMT_PGM:
- return GP_LoadPGM(src_path, callback);
- case GP_FMT_PPM:
- return GP_LoadPPM(src_path, callback);
- case GP_FMT_UNKNOWN:
- break;
- }
-
- struct GP_Loader *l;
-
- l = loader_by_filename(src_path);
-
- if (l != NULL)
- return l->Load(src_path, callback);
-
- l = loader_by_signature(src_path);
-
- if (l != NULL)
- return l->Load(src_path, callback);
-
- errno = ENOSYS;
- return NULL;
-}
-
int GP_LoadMetaData(const char *src_path, GP_MetaData *data)
{
int saved_errno;
-----------------------------------------------------------------------
Summary of changes:
doc/Makefile | 6 +-
doc/api_links.txt | 4 +
doc/core.txt | 140 ++++++++++++++++++
doc/example_loader_registration.txt | 7 +
doc/loaders.txt | 269 +++++++++++++++++++++++++++++++---
include/loaders/GP_Loader.h | 6 +
libs/loaders/GP_Loader.c | 120 ++++++++--------
7 files changed, 463 insertions(+), 89 deletions(-)
create mode 100644 doc/core.txt
create mode 100644 doc/example_loader_registration.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: 80d1a231acdf63c758e84a257c20aaffca6550e3
by metan 10 Nov '12
by metan 10 Nov '12
10 Nov '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 80d1a231acdf63c758e84a257c20aaffca6550e3 (commit)
via 21bb72c7f2b7a1dc55c551a9cafe65fab22fb899 (commit)
via 697c44509ec28ec94d453c84be6d9292affd83f4 (commit)
via 5afca4870b21f2204799a5a113637968cb98090e (commit)
via a5f1f49a610ffd5f59cc3404d14efd03edd8be32 (commit)
from 6793b01905a9072059080e70fa79c685e43a945c (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/80d1a231acdf63c758e84a257c20aaffca65…
commit 80d1a231acdf63c758e84a257c20aaffca6550e3
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 14:01:00 2012 +0100
examples: Add loader registration example.
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile
index 8cc06a0..03c91c5 100644
--- a/demos/c_simple/Makefile
+++ b/demos/c_simple/Makefile
@@ -9,7 +9,7 @@ LDLIBS+=-lrt `$(TOPDIR)/gfxprim-config --libs --libs-backends`
APPS=backend_example loaders_example loaders filters_symmetry gfx_koch virtual_backend_example meta_data meta_data_dump tmp_file showimage v4l2_show v4l2_grab convolution weighted_median shapetest koch input- fileview linetest randomshapetest fonttest
+ fileview linetest randomshapetest fonttest loaders_register
v4l2_show: LDLIBS+=-lGP_grabbers
v4l2_grab: LDLIBS+=-lGP_grabbers
diff --git a/demos/c_simple/loaders_register.c b/demos/c_simple/loaders_register.c
new file mode 100644
index 0000000..2140af5
--- /dev/null
+++ b/demos/c_simple/loaders_register.c
@@ -0,0 +1,139 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ Shows how to register custom image loader/saver.
+
+ Feed it with small image (cca 60x60 pixels) to produce ascii art version.
+
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <GP.h>
+
+/*
+ * Saves 2 bpp grayscale image as ASCII Art
+ */
+static int save(const GP_Context *img, const char *dst_path,
+ GP_ProgressCallback *callback)
+{
+ if (img->pixel_type != GP_PIXEL_G2) {
+ errno = ENOSYS;
+ return 1;
+ }
+
+ FILE *f = fopen(dst_path, "w");
+
+ if (f == NULL)
+ return 1;
+
+ unsigned int i, j;
+
+ for (j = 0; j < img->h; j++) {
+ for (i = 0; i < img->w; i++) {
+ GP_Pixel p = GP_GetPixel_Raw(img, i, j);
+
+ switch (p) {
+ case 0:
+ fprintf(f, " ");
+ break;
+ case 1:
+ fprintf(f, "..");
+ break;
+ case 2:
+ fprintf(f, "()");
+ break;
+ case 3:
+ fprintf(f, "OO");
+ break;
+ }
+ }
+
+ fprintf(f, "n");
+
+ if (GP_ProgressCallbackReport(callback, img->h, j, img->w)) {
+ fclose(f);
+ unlink(dst_path);
+ errno = ECANCELED;
+ return 1;
+ }
+ }
+
+ if (fclose(f))
+ return 1;
+
+ GP_ProgressCallbackDone(callback);
+
+ return 0;
+}
+
+GP_Loader loader = {
+ .Load = NULL,
+ .Save = save,
+ .Match = NULL,
+ .fmt_name = "ASCII Art",
+ .extensions = {"txt", NULL},
+};
+
+int main(int argc, char *argv[])
+{
+ GP_Context *c, *gc;
+
+ GP_LoaderRegister(&loader);
+
+ /* List all loaders */
+ GP_ListLoaders();
+ printf("nn");
+
+ if (argc != 2) {
+ fprintf(stderr, "ERROR: Takes image as an argumentn");
+ return 1;
+ }
+
+ /* Now load image and save it using our loader */
+ c = GP_LoadImage(argv[1], NULL);
+
+ if (c == NULL) {
+ fprintf(stderr, "Failed to load image: %sn", strerror(errno));
+ return 1;
+ }
+
+ gc = GP_FilterFloydSteinberg_RGB888_Alloc(c, GP_PIXEL_G2, NULL);
+
+ if (gc == NULL) {
+ fprintf(stderr, "FloydSteinberg: %sn", strerror(errno));
+ return 1;
+ }
+
+ printf("Saving to test.txtn");
+
+ if (GP_SaveImage(gc, "test.txt", NULL)) {
+ fprintf(stderr, "Failed to save image: %sn", strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
http://repo.or.cz/w/gfxprim.git/commit/21bb72c7f2b7a1dc55c551a9cafe65fab22f…
commit 21bb72c7f2b7a1dc55c551a9cafe65fab22fb899
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 13:58:12 2012 +0100
loaders: Add the rest of loaders to GP_Loader list
diff --git a/include/loaders/GP_Loader.h b/include/loaders/GP_Loader.h
index a5ef06b..ef7add1 100644
--- a/include/loaders/GP_Loader.h
+++ b/include/loaders/GP_Loader.h
@@ -106,4 +106,9 @@ void GP_LoaderRegister(GP_Loader *self);
void GP_LoaderUnregister(GP_Loader *self);
+/*
+ * List loaders into the stdout
+ */
+void GP_ListLoaders(void);
+
#endif /* LOADERS_GP_LOADER_H */
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index 597cfe9..0ef1024 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -45,12 +45,39 @@ static GP_Loader psp_loader = {
.extensions = {"psp", "pspimage", NULL},
};
+static GP_Loader pbm_loader = {
+ .Load = GP_LoadPBM,
+ .Save = GP_SavePBM,
+ .Match = NULL,
+ .fmt_name = "Netpbm portable bitmap",
+ .next = &psp_loader,
+ .extensions = {"pbm", NULL},
+};
+
+static GP_Loader pgm_loader = {
+ .Load = GP_LoadPGM,
+ .Save = GP_SavePGM,
+ .Match = NULL,
+ .fmt_name = "Netpbm portable graymap",
+ .next = &pbm_loader,
+ .extensions = {"pgm", NULL},
+};
+
+static GP_Loader ppm_loader = {
+ .Load = GP_LoadPPM,
+ .Save = NULL,
+ .Match = NULL,
+ .fmt_name = "Netpbm portable pixmap",
+ .next = &pgm_loader,
+ .extensions = {"ppm", NULL},
+};
+
static GP_Loader bmp_loader = {
.Load = GP_LoadBMP,
.Save = NULL,
.Match = GP_MatchBMP,
.fmt_name = "BMP",
- .next = &psp_loader,
+ .next = &ppm_loader,
.extensions = {"bmp", "dib", NULL},
};
@@ -115,6 +142,26 @@ void GP_LoaderUnregister(GP_Loader *self)
i->next = self->next;
}
+void GP_ListLoaders(void)
+{
+ struct GP_Loader *i;
+ int j;
+
+ for (i = loaders; i != NULL; i = i->next) {
+ printf("Format: %sn", i->fmt_name);
+ printf("Load:t%sn", i->Load ? "Yes" : "No");
+ printf("Save:t%sn", i->Save ? "Yes" : "No");
+ printf("Match:t%sn", i->Match ? "Yes" : "No");
+ printf("Extensions: ");
+ for (j = 0; i->extensions[j] != NULL; j++)
+ printf("%s ", i->extensions[j]);
+ printf("n");
+
+ if (i->next != NULL)
+ printf("n");
+ }
+}
+
static struct GP_Loader *loader_by_extension(const char *ext)
{
struct GP_Loader *i;
http://repo.or.cz/w/gfxprim.git/commit/697c44509ec28ec94d453c84be6d9292affd…
commit 697c44509ec28ec94d453c84be6d9292affd83f4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 12:55:56 2012 +0100
doc: Fix Makefile, update .gitignore
diff --git a/doc/.gitignore b/doc/.gitignore
index 2d19fc7..4b4703c 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -1 +1,11 @@
*.html
+*.md5
+
+discrete_linear_1D_convolution_alg1.png
+discrete_linear_1D_convolution_alg2.png
+discrete_linear_convolution.png
+discrete_linear_convolution_alg1.png
+discrete_linear_convolution_alg2.png
+laplacian_edge_sharpening.png
+laplacian_kernel.png
+
diff --git a/doc/Makefile b/doc/Makefile
index 2b6df43..bda6964 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -2,6 +2,13 @@ SOURCES=general.txt context.txt loaders.txt filters.txt basic_types.txt drawing_api.txt backends.txt gamma.txt grabbers.txt environment_variables.txt debug.txt
+#
+# Names of generated images for cleanup
+#
+GENIMAGES=discrete_linear_1D_convolution_alg1 discrete_linear_1D_convolution_alg2 + discrete_linear_convolution discrete_linear_convolution_alg1 + discrete_linear_convolution_alg2 laplacian_edge_sharpening laplacian_kernel
+
PAGES=$(subst .txt,.html,$(SOURCES))
@@ -30,6 +37,18 @@ api.pdf: api.txt
xsltproc /usr/share/sgml/docbook/xsl-stylesheets/fo/docbook.xsl api.xml > api.fo
fop api.fo -pdf api.pdf
+#
+# Clean up generated images
+#
+CLEAN+=$(patsubst %,%.md5,$(GENIMAGES))
+CLEAN+=$(patsubst %,%.png,$(GENIMAGES))
+
+#
+# Clean up generated pages
+#
+CLEAN+=$(PAGES)
+
clean:
- rm -f api.html examples.html
+ rm -f $(CLEAN)
+ rm -f api_links.html api.html examples.html
rm -f api.xml api.fo api.pdf
http://repo.or.cz/w/gfxprim.git/commit/5afca4870b21f2204799a5a113637968cb98…
commit 5afca4870b21f2204799a5a113637968cb98090e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 12:42:31 2012 +0100
loaders: Fix PBM and PGM loading API.
diff --git a/include/loaders/GP_PBM.h b/include/loaders/GP_PBM.h
index 82cd45b..1603aff 100644
--- a/include/loaders/GP_PBM.h
+++ b/include/loaders/GP_PBM.h
@@ -43,7 +43,7 @@ GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback);
* EINVAL - context pixel type was not 1 bit grayscale.
*
*/
-int GP_SavePBM(const char *res_path, GP_Context *src,
+int GP_SavePBM(const GP_Context *src, const char *res_path,
GP_ProgressCallback *callback);
#endif /* LOADERS_GP_PBM_H */
diff --git a/include/loaders/GP_PGM.h b/include/loaders/GP_PGM.h
index f949cde..7b930cd 100644
--- a/include/loaders/GP_PGM.h
+++ b/include/loaders/GP_PGM.h
@@ -31,7 +31,7 @@
GP_Context *GP_LoadPGM(const char *src_path,
GP_ProgressCallback *callback);
-int GP_SavePGM(const char *res_path, GP_Context *src,
+int GP_SavePGM(const GP_Context *src, const char *res_path,
GP_ProgressCallback *callback);
#endif /* LOADERS_GP_PGM_H */
diff --git a/libs/loaders/GP_PBM.c b/libs/loaders/GP_PBM.c
index 2c11138..e481684 100644
--- a/libs/loaders/GP_PBM.c
+++ b/libs/loaders/GP_PBM.c
@@ -93,7 +93,7 @@ err1:
return NULL;
}
-int GP_SavePBM(const char *res_path, GP_Context *src,
+int GP_SavePBM(const GP_Context *src, const char *res_path,
GP_ProgressCallback *callback)
{
FILE *f;
diff --git a/libs/loaders/GP_PGM.c b/libs/loaders/GP_PGM.c
index 055df97..4a2321d 100644
--- a/libs/loaders/GP_PGM.c
+++ b/libs/loaders/GP_PGM.c
@@ -186,7 +186,7 @@ err0:
return NULL;
}
-int GP_SavePGM(const char *res_path, GP_Context *src,
+int GP_SavePGM(const GP_Context *src, const char *res_path,
GP_ProgressCallback *callback)
{
FILE *f;
diff --git a/libs/loaders/GP_PXMCommon.c b/libs/loaders/GP_PXMCommon.c
index 48bc361..e2738ab 100644
--- a/libs/loaders/GP_PXMCommon.c
+++ b/libs/loaders/GP_PXMCommon.c
@@ -238,7 +238,7 @@ int GP_PXMLoad8bpp(FILE *f, GP_Context *context)
#define BITMASK(byte, bit) (!!((byte)&(0x80>>(bit))))
-static int write_line_1bpp(FILE *f, const uint8_t *data, GP_Context *src)
+static int write_line_1bpp(FILE *f, const uint8_t *data, const GP_Context *src)
{
uint32_t x, max = src->bytes_per_row;
int ret;
@@ -278,7 +278,7 @@ static int write_line_1bpp(FILE *f, const uint8_t *data, GP_Context *src)
return 0;
}
-int GP_PXMSave1bpp(FILE *f, GP_Context *context)
+int GP_PXMSave1bpp(FILE *f, const GP_Context *context)
{
uint32_t y;
int ret;
@@ -296,7 +296,7 @@ int GP_PXMSave1bpp(FILE *f, GP_Context *context)
#define MASK_2BPP(byte, pix) (0x03 & (byte>>((3 - pix)<<1)))
-static int write_line_2bpp(FILE *f, const uint8_t *data, GP_Context *src)
+static int write_line_2bpp(FILE *f, const uint8_t *data, const GP_Context *src)
{
uint32_t x, max = src->bytes_per_row;
int ret;
@@ -332,7 +332,7 @@ static int write_line_2bpp(FILE *f, const uint8_t *data, GP_Context *src)
return EIO;
}
-int GP_PXMSave2bpp(FILE *f, GP_Context *context)
+int GP_PXMSave2bpp(FILE *f, const GP_Context *context)
{
uint32_t y;
int ret;
@@ -348,7 +348,7 @@ int GP_PXMSave2bpp(FILE *f, GP_Context *context)
return EIO;
}
-static int write_line_8bpp(FILE *f, const uint8_t *data, GP_Context *src)
+static int write_line_8bpp(FILE *f, const uint8_t *data, const GP_Context *src)
{
uint32_t x;
int ret;
@@ -371,7 +371,7 @@ static int write_line_8bpp(FILE *f, const uint8_t *data, GP_Context *src)
return 0;
}
-int GP_PXMSave8bpp(FILE *f, GP_Context *context)
+int GP_PXMSave8bpp(FILE *f, const GP_Context *context)
{
uint32_t y;
int ret;
diff --git a/libs/loaders/GP_PXMCommon.h b/libs/loaders/GP_PXMCommon.h
index 7ed531e..1780eec 100644
--- a/libs/loaders/GP_PXMCommon.h
+++ b/libs/loaders/GP_PXMCommon.h
@@ -40,10 +40,10 @@
*
* The pixel type is not checked here as these are internal funcitons.
*/
-int GP_PXMSave1bpp(FILE *f, GP_Context *context);
-int GP_PXMSave2bpp(FILE *f, GP_Context *context);
-int GP_PXMSave4bpp(FILE *f, GP_Context *context);
-int GP_PXMSave8bpp(FILE *f, GP_Context *context);
+int GP_PXMSave1bpp(FILE *f, const GP_Context *context);
+int GP_PXMSave2bpp(FILE *f, const GP_Context *context);
+int GP_PXMSave4bpp(FILE *f, const GP_Context *context);
+int GP_PXMSave8bpp(FILE *f, const GP_Context *context);
/*
* Load context from ascii file.
http://repo.or.cz/w/gfxprim.git/commit/a5f1f49a610ffd5f59cc3404d14efd03edd8…
commit a5f1f49a610ffd5f59cc3404d14efd03edd8be32
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 10 00:37:31 2012 +0100
loaders: More work on loaders, BMP signature.
diff --git a/include/loaders/GP_BMP.h b/include/loaders/GP_BMP.h
index e44d787..63473ea 100644
--- a/include/loaders/GP_BMP.h
+++ b/include/loaders/GP_BMP.h
@@ -62,4 +62,9 @@ GP_Context *GP_ReadBMP(FILE *f, GP_ProgressCallback *callback);
*/
GP_Context *GP_LoadBMP(const char *src_path, GP_ProgressCallback *callback);
+/*
+ * Match BMP signature.
+ */
+int GP_MatchBMP(const void *buf);
+
#endif /* LOADERS_GP_BMP_H */
diff --git a/libs/loaders/GP_BMP.c b/libs/loaders/GP_BMP.c
index 0b1f7f5..3ed5161 100644
--- a/libs/loaders/GP_BMP.c
+++ b/libs/loaders/GP_BMP.c
@@ -514,6 +514,11 @@ static int read_bitmap_pixels(FILE *f, struct bitmap_info_header *header,
return ENOSYS;
}
+int GP_MatchBMP(const void *buf)
+{
+ return !memcmp(buf, "BM", 2);
+}
+
int GP_OpenBMP(const char *src_path, FILE **f,
GP_Size *w, GP_Size *h, GP_PixelType *pixel_type)
{
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index 226d388..597cfe9 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -48,7 +48,7 @@ static GP_Loader psp_loader = {
static GP_Loader bmp_loader = {
.Load = GP_LoadBMP,
.Save = NULL,
- .Match = NULL,
+ .Match = GP_MatchBMP,
.fmt_name = "BMP",
.next = &psp_loader,
.extensions = {"bmp", "dib", NULL},
@@ -142,6 +142,9 @@ static struct GP_Loader *loader_by_filename(const char *path)
if (path[i] == '.')
break;
+ if (path[i] != '.')
+ return NULL;
+
ext = path + i + 1;
GP_DEBUG(1, "Loading file by filename extension '%s'", ext);
@@ -342,7 +345,6 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
if (l != NULL)
return l->Load(src_path, callback);
- //TODO file signature based check
errno = ENOSYS;
return NULL;
}
@@ -382,17 +384,15 @@ int GP_LoadMetaData(const char *src_path, GP_MetaData *data)
int GP_SaveImage(const GP_Context *src, const char *dst_path,
GP_ProgressCallback *callback)
{
- enum GP_ImageFmt fmt = filename_to_fmt(dst_path);
-
- switch (fmt) {
- case GP_FMT_JPG:
- return GP_SaveJPG(src, dst_path, callback);
- case GP_FMT_PNG:
- return GP_SavePNG(src, dst_path, callback);
+ struct GP_Loader *l = loader_by_filename(dst_path);
- default:
- break;
+ if (l == NULL) {
+ errno = EINVAL;
+ return 1;
}
+
+ if (l->Save)
+ return l->Save(src, dst_path, callback);
errno = ENOSYS;
return 1;
-----------------------------------------------------------------------
Summary of changes:
demos/c_simple/Makefile | 2 +-
demos/c_simple/{tmp_file.c => loaders_register.c} | 129 +++++++++++++--------
doc/.gitignore | 10 ++
doc/Makefile | 21 +++-
include/loaders/GP_BMP.h | 5 +
include/loaders/GP_Loader.h | 5 +
include/loaders/GP_PBM.h | 2 +-
include/loaders/GP_PGM.h | 2 +-
libs/loaders/GP_BMP.c | 5 +
libs/loaders/GP_Loader.c | 71 ++++++++++--
libs/loaders/GP_PBM.c | 2 +-
libs/loaders/GP_PGM.c | 2 +-
libs/loaders/GP_PXMCommon.c | 12 +-
libs/loaders/GP_PXMCommon.h | 8 +-
14 files changed, 198 insertions(+), 78 deletions(-)
copy demos/c_simple/{tmp_file.c => loaders_register.c} (53%)
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: 6793b01905a9072059080e70fa79c685e43a945c
by metan 06 Nov '12
by metan 06 Nov '12
06 Nov '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 6793b01905a9072059080e70fa79c685e43a945c (commit)
from 156709b6343ea54485a3d662ddc66448e3337c76 (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/6793b01905a9072059080e70fa79c685e43a…
commit 6793b01905a9072059080e70fa79c685e43a945c
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Tue Nov 6 19:54:09 2012 +0100
loaders: Add forgotten header, ouch.
I will not forgot to add the headers.
I will not forgot to add the headers.
I will not forgot to add the headers.
I will not forgot to add the headers.
diff --git a/include/loaders/GP_Loader.h b/include/loaders/GP_Loader.h
new file mode 100644
index 0000000..a5ef06b
--- /dev/null
+++ b/include/loaders/GP_Loader.h
@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+ /*
+
+ Core include file for loaders API.
+
+ */
+
+#ifndef LOADERS_GP_LOADER_H
+#define LOADERS_GP_LOADER_H
+
+#include "core/GP_Context.h"
+#include "core/GP_ProgressCallback.h"
+
+#include "GP_MetaData.h"
+
+/*
+ * Tries to load image accordingly to the file extension.
+ *
+ * If operation fails NULL is returned and errno is filled.
+ */
+GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback);
+
+/*
+ * Loads image Meta Data (if possible).
+ */
+int GP_LoadMetaData(const char *src_path, GP_MetaData *data);
+
+/*
+ * Simple saving function, the image format is matched by file extension.
+ *
+ * Retruns zero on succes.
+ *
+ * On failure non-zero is returned.
+ *
+ * When file type wasn't recognized by extension or if support for requested
+ * image format wasn't compiled in non-zero is returned and errno is set to
+ * ENOSYS.
+ *
+ * The resulting errno may also be set to any possible error from fopen(3), open(3),
+ * write(3), fwrite(3), seek(3), etc..
+ */
+int GP_SaveImage(const GP_Context *src, const char *dst_path,
+ GP_ProgressCallback *callback);
+
+/*
+ * You can register your own loader here.
+ */
+typedef struct GP_Loader {
+ /*
+ * Loads an image.
+ *
+ * Returns allocated and initialized bitmap on success, NULL on failure
+ * and errno must be set.
+ */
+ GP_Context *(*Load)(const char *src_path, GP_ProgressCallback *callback);
+
+ /*
+ * Save an image.
+ *
+ * Returns zero on succes, non-zero on failure and errno must be set.
+ */
+ int (*Save)(const GP_Context *src, const char *dst_path, GP_ProgressCallback *callback);
+
+ /*
+ * The buffer is filled with 32 bytes from an image start, returns 1 if
+ * image signature was found zero otherwise.
+ */
+ int (*Match)(const void *buf);
+
+ /*
+ * Short format name.
+ */
+ const char *fmt_name;
+
+ /* don't touch */
+ struct GP_Loader *next;
+
+ /*
+ * NULL terminated array of file extensions.
+ */
+ const char *extensions[];
+} GP_Loader;
+
+void GP_LoaderRegister(GP_Loader *self);
+
+void GP_LoaderUnregister(GP_Loader *self);
+
+#endif /* LOADERS_GP_LOADER_H */
-----------------------------------------------------------------------
Summary of changes:
include/loaders/GP_Loader.h | 109 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 109 insertions(+), 0 deletions(-)
create mode 100644 include/loaders/GP_Loader.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 master updated: 156709b6343ea54485a3d662ddc66448e3337c76
by metan 04 Nov '12
by metan 04 Nov '12
04 Nov '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 156709b6343ea54485a3d662ddc66448e3337c76 (commit)
from a960a02a7e253fcdd2ec0cfa64f7d2f513719961 (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/156709b6343ea54485a3d662ddc66448e333…
commit 156709b6343ea54485a3d662ddc66448e3337c76
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Nov 4 22:39:30 2012 +0100
loaders: More signature matching, yay!
diff --git a/include/loaders/GP_GIF.h b/include/loaders/GP_GIF.h
index 1eb87ff..62284d0 100644
--- a/include/loaders/GP_GIF.h
+++ b/include/loaders/GP_GIF.h
@@ -58,4 +58,9 @@ GP_Context *GP_ReadGIF(void *f, GP_ProgressCallback *callback);
*/
GP_Context *GP_LoadGIF(const char *src_path, GP_ProgressCallback *callback);
+/*
+ * Match GIF signature.
+ */
+int GP_MatchGIF(const void *buf);
+
#endif /* LOADERS_GP_GIF_H */
diff --git a/include/loaders/GP_JPG.h b/include/loaders/GP_JPG.h
index 73113c4..5906b11 100644
--- a/include/loaders/GP_JPG.h
+++ b/include/loaders/GP_JPG.h
@@ -62,4 +62,9 @@ int GP_LoadJPGMetaData(const char *src_path, GP_MetaData *data);
int GP_SaveJPG(const GP_Context *src, const char *dst_path,
GP_ProgressCallback *callback);
+/*
+ * Match JPG signature.
+ */
+int GP_MatchJPG(const void *buf);
+
#endif /* LOADERS_GP_JPG_H */
diff --git a/include/loaders/GP_PNG.h b/include/loaders/GP_PNG.h
index 3a8f2f8..4b6e3bb 100644
--- a/include/loaders/GP_PNG.h
+++ b/include/loaders/GP_PNG.h
@@ -79,4 +79,9 @@ int GP_LoadPNGMetaData(const char *src_path, GP_MetaData *data);
int GP_SavePNG(const GP_Context *src, const char *dst_path,
GP_ProgressCallback *callback);
+/*
+ * Match PNG signature.
+ */
+int GP_MatchPNG(const void *buf);
+
#endif /* LOADERS_GP_PNG_H */
diff --git a/libs/loaders/GP_GIF.c b/libs/loaders/GP_GIF.c
index 262e5d9..c4e2d2e 100644
--- a/libs/loaders/GP_GIF.c
+++ b/libs/loaders/GP_GIF.c
@@ -44,6 +44,23 @@
#include <gif_lib.h>
+#define GIF_SIGNATURE1 "GIF87a"
+#define GIF_SIGNATURE1_LEN 6
+
+#define GIF_SIGNATURE2 "GIF89a"
+#define GIF_SIGNATURE2_LEN 6
+
+int GP_MatchGIF(const void *buf)
+{
+ if (!memcmp(buf, GIF_SIGNATURE1, GIF_SIGNATURE1_LEN))
+ return 1;
+
+ if (!memcmp(buf, GIF_SIGNATURE2, GIF_SIGNATURE2_LEN))
+ return 1;
+
+ return 0;
+}
+
int GP_OpenGIF(const char *src_path, void **f)
{
GifFileType *gf;
diff --git a/libs/loaders/GP_JPG.c b/libs/loaders/GP_JPG.c
index bece7d5..bc47c4b 100644
--- a/libs/loaders/GP_JPG.c
+++ b/libs/loaders/GP_JPG.c
@@ -43,6 +43,18 @@
#include <jpeglib.h>
+/*
+ * 0xff 0xd8 - start of image
+ * 0xff 0xe0 - APP0 JFIF meta data
+ */
+#define JPEG_SIGNATURE "xffxd8xffxe0"
+#define JPEG_SIGNATURE_LEN 4
+
+int GP_MatchJPG(const void *buf)
+{
+ return !memcmp(buf, JPEG_SIGNATURE, JPEG_SIGNATURE_LEN);
+}
+
int GP_OpenJPG(const char *src_path, FILE **f)
{
int err;
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index ab374c4..226d388 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -36,7 +36,7 @@
#include "GP_Loader.h"
-static GP_Loader psp_image = {
+static GP_Loader psp_loader = {
.Load = GP_LoadPSP,
.Save = NULL,
.Match = GP_MatchPSP,
@@ -45,8 +45,44 @@ static GP_Loader psp_image = {
.extensions = {"psp", "pspimage", NULL},
};
-static GP_Loader *loaders = &psp_image;
-static GP_Loader *loaders_last = &psp_image;
+static GP_Loader bmp_loader = {
+ .Load = GP_LoadBMP,
+ .Save = NULL,
+ .Match = NULL,
+ .fmt_name = "BMP",
+ .next = &psp_loader,
+ .extensions = {"bmp", "dib", NULL},
+};
+
+static GP_Loader gif_loader = {
+ .Load = GP_LoadGIF,
+ .Save = NULL,
+ .Match = GP_MatchGIF,
+ .fmt_name = "Graphics Interchange Format",
+ .next = &bmp_loader,
+ .extensions = {"gif", NULL},
+};
+
+static GP_Loader png_loader = {
+ .Load = GP_LoadPNG,
+ .Save = GP_SavePNG,
+ .Match = GP_MatchPNG,
+ .fmt_name = "Portable Network Graphics",
+ .next = &gif_loader,
+ .extensions = {"png", NULL},
+};
+
+static GP_Loader jpeg_loader = {
+ .Load = GP_LoadJPG,
+ .Save = GP_SaveJPG,
+ .Match = GP_MatchJPG,
+ .fmt_name = "JPEG",
+ .next = &png_loader,
+ .extensions = {"jpg", "jpeg", NULL},
+};
+
+static GP_Loader *loaders = &jpeg_loader;
+static GP_Loader *loaders_last = &psp_loader;
void GP_LoaderRegister(GP_Loader *self)
{
diff --git a/libs/loaders/GP_PNG.c b/libs/loaders/GP_PNG.c
index 7cf7441..275d4be 100644
--- a/libs/loaders/GP_PNG.c
+++ b/libs/loaders/GP_PNG.c
@@ -43,6 +43,11 @@
#include "core/GP_BitSwap.h"
+int GP_MatchPNG(const void *buf)
+{
+ return !png_sig_cmp(buf, 0, 8);
+}
+
int GP_OpenPNG(const char *src_path, FILE **f)
{
uint8_t sig[8];
-----------------------------------------------------------------------
Summary of changes:
include/loaders/GP_GIF.h | 5 +++++
include/loaders/GP_JPG.h | 5 +++++
include/loaders/GP_PNG.h | 5 +++++
libs/loaders/GP_GIF.c | 17 +++++++++++++++++
libs/loaders/GP_JPG.c | 12 ++++++++++++
libs/loaders/GP_Loader.c | 42 +++++++++++++++++++++++++++++++++++++++---
libs/loaders/GP_PNG.c | 5 +++++
7 files changed, 88 insertions(+), 3 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
[repo.or.cz] gfxprim.git branch master updated: a960a02a7e253fcdd2ec0cfa64f7d2f513719961
by metan 04 Nov '12
by metan 04 Nov '12
04 Nov '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 a960a02a7e253fcdd2ec0cfa64f7d2f513719961 (commit)
via 581ccfd2c21886816a54a99edf7e43a443506e5e (commit)
from 9f7de83d6395614ad22b2492340900a09f930db8 (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/a960a02a7e253fcdd2ec0cfa64f7d2f51371…
commit a960a02a7e253fcdd2ec0cfa64f7d2f513719961
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Nov 4 01:14:52 2012 +0100
loaders: Add PSP signature matching.
diff --git a/include/loaders/GP_PSP.h b/include/loaders/GP_PSP.h
index 4827a98..a44ae9b 100644
--- a/include/loaders/GP_PSP.h
+++ b/include/loaders/GP_PSP.h
@@ -58,4 +58,9 @@ GP_Context *GP_ReadPSP(FILE *f, GP_ProgressCallback *callback);
*/
GP_Context *GP_LoadPSP(const char *src_path, GP_ProgressCallback *callback);
+/*
+ * Match PSP signature.
+ */
+int GP_MatchPSP(const void *buf);
+
#endif /* LOADERS_GP_PSP_H */
diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c
index 057322c..ab374c4 100644
--- a/libs/loaders/GP_Loader.c
+++ b/libs/loaders/GP_Loader.c
@@ -39,7 +39,7 @@
static GP_Loader psp_image = {
.Load = GP_LoadPSP,
.Save = NULL,
- .Match = NULL,
+ .Match = GP_MatchPSP,
.fmt_name = "Paint Shop Pro Image",
.next = NULL,
.extensions = {"psp", "pspimage", NULL},
diff --git a/libs/loaders/GP_PSP.c b/libs/loaders/GP_PSP.c
index 7ab8835..d77ee29 100644
--- a/libs/loaders/GP_PSP.c
+++ b/libs/loaders/GP_PSP.c
@@ -61,6 +61,11 @@ struct psp_version {
uint16_t minor;
};
+int GP_MatchPSP(const void *buf)
+{
+ return !memcmp(buf, PSP_SIGNATURE, PSP_SIGNATURE_LEN);
+}
+
int GP_OpenPSP(const char *src_path, FILE **f)
{
int err;
http://repo.or.cz/w/gfxprim.git/commit/581ccfd2c21886816a54a99edf7e43a44350…
commit 581ccfd2c21886816a54a99edf7e43a443506e5e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sun Nov 4 00:56:48 2012 +0100
loaders: Add initial support for loader registration.
diff --git a/include/loaders/GP_Loaders.h b/include/loaders/GP_Loaders.h
index 5292608..d523494 100644
--- a/include/loaders/GP_Loaders.h
+++ b/include/loaders/GP_Loaders.h
@@ -49,33 +49,6 @@
#include "GP_MetaData.h"
-/*
- * Tries to load image accordingly to the file extension.
- *
- * If operation fails NULL is returned and errno is filled.
- */
-GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback);
-
-/*
- * Loads image Meta Data (if possible).
- */
-int GP_LoadMetaData(const char *src_path, GP_MetaData *data);
-
-/*
- * Simple saving function, the image format is matched by file extension.
- *
- * Retruns zero on succes.
- *
- * On failure non-zero is returned.
- *
- * When file type wasn't recognized by extension or if support for requested
- * image format wasn't compiled in non-zero is returned and errno is set to
- * ENOSYS.
- *
- * The resulting errno may also be set to any possible error from fopen(3), open(3),
- * write(3), fwrite(3), seek(3), etc..
- */
-int GP_SaveImage(const GP_Context *src, const char *dst_path,
- GP_ProgressCallback *callback);
+#include "GP_Loader.h"
#endif /* LOADERS_GP_LOADERS_H */
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loader.c
similarity index 70%
rename from libs/loaders/GP_Loaders.c
rename to libs/loaders/GP_Loader.c
index cef1821..057322c 100644
--- a/libs/loaders/GP_Loaders.c
+++ b/libs/loaders/GP_Loader.c
@@ -34,6 +34,122 @@
#include "GP_Loaders.h"
+#include "GP_Loader.h"
+
+static GP_Loader psp_image = {
+ .Load = GP_LoadPSP,
+ .Save = NULL,
+ .Match = NULL,
+ .fmt_name = "Paint Shop Pro Image",
+ .next = NULL,
+ .extensions = {"psp", "pspimage", NULL},
+};
+
+static GP_Loader *loaders = &psp_image;
+static GP_Loader *loaders_last = &psp_image;
+
+void GP_LoaderRegister(GP_Loader *self)
+{
+ GP_DEBUG(1, "Registering loader for '%s'", self->fmt_name);
+
+ self->next = NULL;
+ loaders_last->next = self;
+}
+
+void GP_LoaderUnregister(GP_Loader *self)
+{
+ struct GP_Loader *i;
+
+ if (self == NULL)
+ return;
+
+ GP_DEBUG(1, "Unregistering loader for '%s'", self->fmt_name);
+
+ for (i = loaders; i != NULL; i = i->next) {
+ if (i->next == self)
+ break;
+ }
+
+ if (i == NULL) {
+ GP_WARN("Loader '%s' (%p) wasn't registered",
+ self->fmt_name, self);
+ return;
+ }
+
+ i->next = self->next;
+}
+
+static struct GP_Loader *loader_by_extension(const char *ext)
+{
+ struct GP_Loader *i;
+ int j;
+
+ for (i = loaders; i != NULL; i = i->next) {
+ for (j = 0; i->extensions[j] != NULL; j++) {
+ if (!strcasecmp(ext, i->extensions[j])) {
+ GP_DEBUG(1, "Found loader '%s'", i->fmt_name);
+ return i;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static struct GP_Loader *loader_by_filename(const char *path)
+{
+ size_t len = strlen(path);
+ const char *ext;
+ int i;
+
+ for (i = len - 1; i >= 0; i--)
+ if (path[i] == '.')
+ break;
+
+ ext = path + i + 1;
+
+ GP_DEBUG(1, "Loading file by filename extension '%s'", ext);
+
+ return loader_by_extension(ext);
+}
+
+static struct GP_Loader *loader_by_signature(const char *path)
+{
+ uint8_t buf[32];
+ FILE *f;
+ int err;
+
+ GP_DEBUG(1, "Trying to match file signature");
+
+ f = fopen(path, "rb");
+
+ if (f == NULL) {
+ err = errno;
+ GP_DEBUG(1, "Failed to open file '%s'", path);
+ errno = err;
+ return NULL;
+ }
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read start of the file '%s'", path);
+ errno = EIO;
+ return NULL;
+ }
+
+ fclose(f);
+
+ struct GP_Loader *i;
+
+ for (i = loaders; i != NULL; i = i->next) {
+ if (i->Match && i->Match(buf)) {
+ GP_DEBUG(1, "Found loader '%s'", i->fmt_name);
+ return i;
+ }
+ }
+
+ return NULL;
+}
+
enum GP_ImageFmt {
GP_FMT_UNKNOWN,
GP_FMT_PNG,
@@ -178,6 +294,18 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
break;
}
+ struct GP_Loader *l;
+
+ l = loader_by_filename(src_path);
+
+ if (l != NULL)
+ return l->Load(src_path, callback);
+
+ l = loader_by_signature(src_path);
+
+ if (l != NULL)
+ return l->Load(src_path, callback);
+
//TODO file signature based check
errno = ENOSYS;
return NULL;
-----------------------------------------------------------------------
Summary of changes:
include/loaders/GP_Loaders.h | 29 +------
include/loaders/GP_PSP.h | 5 +
libs/loaders/{GP_Loaders.c => GP_Loader.c} | 128 ++++++++++++++++++++++++++++
libs/loaders/GP_PSP.c | 5 +
4 files changed, 139 insertions(+), 28 deletions(-)
rename libs/loaders/{GP_Loaders.c => GP_Loader.c} (70%)
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: 9f7de83d6395614ad22b2492340900a09f930db8
by metan 03 Nov '12
by metan 03 Nov '12
03 Nov '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 9f7de83d6395614ad22b2492340900a09f930db8 (commit)
via 36dac7fab1a5a700d756545b06b95c5352dd1615 (commit)
from 1a4cfc00663ccc76f058a87cc00c031ec57dd982 (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/9f7de83d6395614ad22b2492340900a09f93…
commit 9f7de83d6395614ad22b2492340900a09f930db8
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 3 23:19:55 2012 +0100
tests: Add forgotten filters target to Makefile.
diff --git a/tests/Makefile b/tests/Makefile
index 6181430..7a0ad0d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,10 +1,11 @@
TOPDIR=..
include $(TOPDIR)/pre.mk
-SUBDIRS=core SDL drivers framework loaders gfx
+SUBDIRS=core SDL drivers framework loaders gfx filters
loaders: framework
gfx: framework
core: framework
+filters: framework
include $(TOPDIR)/post.mk
http://repo.or.cz/w/gfxprim.git/commit/36dac7fab1a5a700d756545b06b95c5352dd…
commit 36dac7fab1a5a700d756545b06b95c5352dd1615
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Nov 3 23:18:26 2012 +0100
loaders: Add PSP Image loader.
The loader could extract composite image
from Paint Shop Pro Image format.
diff --git a/include/loaders/GP_Loaders.h b/include/loaders/GP_Loaders.h
index ab0f4ef..5292608 100644
--- a/include/loaders/GP_Loaders.h
+++ b/include/loaders/GP_Loaders.h
@@ -43,6 +43,7 @@
#include "GP_PNG.h"
#include "GP_JPG.h"
#include "GP_GIF.h"
+#include "GP_PSP.h"
#include "GP_TmpFile.h"
diff --git a/include/loaders/GP_Loaders.h b/include/loaders/GP_PSP.h
similarity index 55%
copy from include/loaders/GP_Loaders.h
copy to include/loaders/GP_PSP.h
index ab0f4ef..4827a98 100644
--- a/include/loaders/GP_Loaders.h
+++ b/include/loaders/GP_PSP.h
@@ -16,65 +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-2012 Cyril Hrubis <metan(a)ucw.cz> *
* *
*****************************************************************************/
/*
-
- Core include file for loaders API.
+
+ Experimental Paint Shop Pro image loader.
*/
-#ifndef LOADERS_GP_LOADERS_H
-#define LOADERS_GP_LOADERS_H
+#ifndef LOADERS_GP_PSP_H
+#define LOADERS_GP_PSP_H
-#include "core/GP_Context.h"
#include "core/GP_ProgressCallback.h"
-
-#include "GP_PBM.h"
-#include "GP_PGM.h"
-#include "GP_PPM.h"
-
-#include "GP_BMP.h"
-#include "GP_PNG.h"
-#include "GP_JPG.h"
-#include "GP_GIF.h"
-
-#include "GP_TmpFile.h"
-
-#include "GP_MetaData.h"
+#include "core/GP_Context.h"
/*
- * Tries to load image accordingly to the file extension.
+ * The possible errno values:
*
- * If operation fails NULL is returned and errno is filled.
+ * - EIO for read/write failure
+ * - ENOSYS for not implemented bitmap format
+ * - ENOMEM from malloc()
+ * - EILSEQ for wrong image signature/data
+ * - ECANCELED when call was aborted from callback
*/
-GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback);
/*
- * Loads image Meta Data (if possible).
+ * Opens up the PSP image and checks signature.
+ * Returns zero on success.
*/
-int GP_LoadMetaData(const char *src_path, GP_MetaData *data);
+int GP_OpenPSP(const char *src_path, FILE **f);
/*
- * Simple saving function, the image format is matched by file extension.
- *
- * Retruns zero on succes.
- *
- * On failure non-zero is returned.
- *
- * When file type wasn't recognized by extension or if support for requested
- * image format wasn't compiled in non-zero is returned and errno is set to
- * ENOSYS.
- *
- * The resulting errno may also be set to any possible error from fopen(3), open(3),
- * write(3), fwrite(3), seek(3), etc..
+ * Reads image from PSP format.
+ */
+GP_Context *GP_ReadPSP(FILE *f, GP_ProgressCallback *callback);
+
+/*
+ * Does both GP_OpenPSP and GP_ReadPSP at once.
*/
-int GP_SaveImage(const GP_Context *src, const char *dst_path,
- GP_ProgressCallback *callback);
+GP_Context *GP_LoadPSP(const char *src_path, GP_ProgressCallback *callback);
-#endif /* LOADERS_GP_LOADERS_H */
+#endif /* LOADERS_GP_PSP_H */
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loaders.c
index b142e93..cef1821 100644
--- a/libs/loaders/GP_Loaders.c
+++ b/libs/loaders/GP_Loaders.c
@@ -40,6 +40,7 @@ enum GP_ImageFmt {
GP_FMT_JPG,
GP_FMT_BMP,
GP_FMT_GIF,
+ GP_FMT_PSP,
GP_FMT_PBM,
GP_FMT_PGM,
GP_FMT_PPM,
@@ -103,7 +104,7 @@ enum GP_ImageFmt filename_to_fmt(const char *path)
break;
}
break;
- /* BMP */
+ /* BMP, PSP */
case 'P':
case 'p':
switch (path[len - 2]) {
@@ -113,6 +114,12 @@ enum GP_ImageFmt filename_to_fmt(const char *path)
path[len - 3] == 'b')
return GP_FMT_BMP;
break;
+ case 'S':
+ case 's':
+ if (path[len - 3] == 'P' ||
+ path[len - 3] == 'p')
+ return GP_FMT_PSP;
+ break;
}
break;
/* GIF */
@@ -157,6 +164,8 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
return GP_LoadPNG(src_path, callback);
case GP_FMT_GIF:
return GP_LoadGIF(src_path, callback);
+ case GP_FMT_PSP:
+ return GP_LoadPSP(src_path, callback);
case GP_FMT_BMP:
return GP_LoadBMP(src_path, callback);
case GP_FMT_PBM:
@@ -165,7 +174,6 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
return GP_LoadPGM(src_path, callback);
case GP_FMT_PPM:
return GP_LoadPPM(src_path, callback);
-
case GP_FMT_UNKNOWN:
break;
}
diff --git a/libs/loaders/GP_PSP.c b/libs/loaders/GP_PSP.c
new file mode 100644
index 0000000..7ab8835
--- /dev/null
+++ b/libs/loaders/GP_PSP.c
@@ -0,0 +1,522 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+/*
+
+ Paint Shop Pro Image loader.
+
+ Written using documentation available freely on the internet.
+
+ */
+
+#include <stdint.h>
+#include <inttypes.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "core/GP_Debug.h"
+#include "core/GP_Pixel.h"
+#include "core/GP_GetPutPixel.h"
+#include "GP_JPG.h"
+#include "GP_PSP.h"
+
+#define BUF_TO_8(buf, off) + (buf[off] + (buf[off+1]<<8) + (buf[off+2]<<16) + (buf[off+3]<<24) + + ((uint64_t)buf[off+4]<<32) + ((uint64_t)buf[off+5]<<40) + + ((uint64_t)buf[off+6]<<48) + ((uint64_t)buf[off+7]<<56))
+
+#define BUF_TO_4(buf, off) + (buf[off] + (buf[off+1]<<8) + (buf[off+2]<<16) + (buf[off+3]<<24))
+
+#define BUF_TO_2(buf, off) + (buf[off] + (buf[off+1]<<8))
+
+#define PSP_SIGNATURE "Paint Shop Pro Image Filenx1a00000000"
+#define PSP_SIGNATURE_LEN 32
+
+struct psp_version {
+ uint16_t major;
+ uint16_t minor;
+};
+
+int GP_OpenPSP(const char *src_path, FILE **f)
+{
+ int err;
+
+ *f = fopen(src_path, "rb");
+
+ if (*f == NULL) {
+ err = errno;
+ GP_DEBUG(1, "Failed to open '%s' : %s",
+ src_path, strerror(errno));
+ goto err2;
+ }
+
+ char buf[36];
+
+ if (fread(buf, sizeof(buf), 1, *f) < 1) {
+ GP_DEBUG(1, "Failed to read file header");
+ err = EIO;
+ goto err1;
+ }
+
+ if (memcmp(buf, PSP_SIGNATURE, PSP_SIGNATURE_LEN)) {
+ GP_DEBUG(1, "Invalid signature, not a PSP image?");
+ err = EINVAL;
+ goto err1;
+ }
+
+ struct psp_version version;
+
+ version.major = BUF_TO_2(buf, 32);
+ version.minor = BUF_TO_2(buf, 34);
+
+ GP_DEBUG(1, "Have PSP image version %u.%u",
+ version.major, version.minor);
+
+ return 0;
+err1:
+ fclose(*f);
+err2:
+ errno = err;
+ return 1;
+}
+
+enum psp_block_id {
+ PSP_IMAGE_BLOCK,
+ PSP_CREATOR_BLOCK,
+ PSP_COLOR_BLOCK,
+ PSP_LAYER_START_BLOCK,
+ PSP_LAYER_BLOCK,
+ PSP_CHANNEL_BLOCK,
+ PSP_SELECTION_BLOCK,
+ PSP_ALPHA_BANK_BLOCK,
+ PSP_ALPHA_CHANNEL_BLOCK,
+ PSP_COMPOSITE_IMAGE_BLOCK,
+ PSP_EXTENDED_DATA_BLOCK,
+ PSP_TUBE_BLOCK,
+ PSP_ADJUSTMENT_EXTENSION_BLOCK,
+ PSP_VECTOR_EXTENSION_BLOCK,
+ PSP_SHAPE_BLOCK,
+ PSP_PAINTSTYLE_BLOCK,
+ PSP_COMPOSITE_IMAGE_BANK_BLOCK,
+ PSP_COMPOSITE_ATTRIBUTES_BLOCK,
+ PSP_JPEG_BLOCK,
+};
+
+static const char *psp_block_id_name(enum psp_block_id id)
+{
+ switch (id) {
+ case PSP_IMAGE_BLOCK:
+ return "Image";
+ case PSP_CREATOR_BLOCK:
+ return "Creator";
+ case PSP_COLOR_BLOCK:
+ return "Color";
+ case PSP_LAYER_START_BLOCK:
+ return "Layer Start";
+ case PSP_LAYER_BLOCK:
+ return "Layer";
+ case PSP_CHANNEL_BLOCK:
+ return "Channel";
+ case PSP_SELECTION_BLOCK:
+ return "Selection";
+ case PSP_ALPHA_BANK_BLOCK:
+ return "Alpha Bank";
+ case PSP_ALPHA_CHANNEL_BLOCK:
+ return "Alpha Channel";
+ case PSP_COMPOSITE_IMAGE_BLOCK:
+ return "Composite image";
+ case PSP_EXTENDED_DATA_BLOCK:
+ return "Extended Data";
+ case PSP_TUBE_BLOCK:
+ return "Tube";
+ case PSP_ADJUSTMENT_EXTENSION_BLOCK:
+ return "Adjustment Extension";
+ case PSP_VECTOR_EXTENSION_BLOCK:
+ return "Vector Extension";
+ case PSP_SHAPE_BLOCK:
+ return "Shape";
+ case PSP_PAINTSTYLE_BLOCK:
+ return "Paintstyle";
+ case PSP_COMPOSITE_IMAGE_BANK_BLOCK:
+ return "Composite Image Bank";
+ case PSP_COMPOSITE_ATTRIBUTES_BLOCK:
+ return "Composite Attributes";
+ case PSP_JPEG_BLOCK:
+ return "JPEG";
+ default:
+ return "Unknown";
+ }
+}
+
+enum psp_comp_type {
+ PSP_COMP_NONE,
+ PSP_COMP_RLE,
+ PSP_COMP_LZ77,
+ PSP_COMP_JPEG,
+};
+
+static const char *psp_comp_type_name(enum psp_comp_type type)
+{
+ switch (type) {
+ case PSP_COMP_NONE:
+ return "None";
+ case PSP_COMP_RLE:
+ return "RLE";
+ case PSP_COMP_LZ77:
+ return "LZ77";
+ case PSP_COMP_JPEG:
+ return "JPEG";
+ default:
+ return "Unknown";
+ }
+}
+
+struct psp_img_attrs {
+ int32_t w;
+ int32_t h;
+ /* resolution */
+ double res;
+ uint8_t res_metric;
+ /* compression, enum psp_comp_type */
+ uint16_t comp_type;
+ /* bit depth must be 1, 4, 8 or 24 */
+ uint16_t bit_depth;
+ /* plane count, must be 1 */
+ uint16_t plane_count;
+ /* color count = 2 ^ bit_depth */
+ uint16_t color_count;
+ /* grayscale flag, 0 -> not grayscale, 1 -> grayscale */
+ uint8_t grayscale_flag;
+ /* sum of the sizes of all layer color bitmaps */
+ uint32_t total_img_size;
+ /* active layer at the time of saving */
+ uint32_t active_layer;
+ uint16_t layer_count;
+
+ /* internal loader flags */
+ int is_loaded:1;
+ uint8_t subblock;
+ void *priv;
+ GP_Context *img;
+};
+
+static int psp_read_general_img_attr_chunk(FILE *f,
+ struct psp_img_attrs *attrs)
+{
+ uint8_t buf[38];
+
+ if (attrs->is_loaded) {
+ GP_WARN("Found Second Image Block");
+ return EINVAL;
+ }
+
+ //TODO SHIFT!!!
+ if (fread(buf, 4, 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read Image block header");
+ return EIO;
+ }
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read Image chunk data");
+ return EIO;
+ }
+
+ attrs->w = BUF_TO_4(buf, 0);
+ attrs->h = BUF_TO_4(buf, 4);
+ attrs->res = BUF_TO_8(buf, 8);
+ attrs->res_metric = buf[16];
+ attrs->comp_type = BUF_TO_2(buf, 17);
+ attrs->bit_depth = BUF_TO_2(buf, 19);
+ attrs->plane_count = BUF_TO_2(buf, 21);
+ attrs->color_count = BUF_TO_2(buf, 23);
+ attrs->grayscale_flag = buf[25];
+ attrs->total_img_size = BUF_TO_4(buf, 26);
+ attrs->active_layer = BUF_TO_4(buf, 32);
+ attrs->layer_count = BUF_TO_2(buf, 36);
+
+ GP_DEBUG(3, "Image w=%u h=%u, compress=%s, bit_depth=%u, grayscale=%u",
+ attrs->w, attrs->h, psp_comp_type_name(attrs->comp_type),
+ attrs->bit_depth, attrs->grayscale_flag);
+
+ GP_DEBUG(3, "Image colors=%u, layer_count=%u, active_layer=%u",
+ attrs->color_count, attrs->layer_count, attrs->active_layer);
+
+ attrs->is_loaded = 1;
+
+ return 0;
+}
+
+static int psp_next_block(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback);
+
+static int psp_read_layer_start_block(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback)
+{
+ int i;
+
+ /* we are allready in subblock -> error */
+ if (attrs->subblock) {
+ GP_WARN("Layer Start block inside of Subblock");
+ return EINVAL;
+ }
+
+ attrs->subblock++;
+
+ for (i = 0; i < attrs->layer_count; i++)
+ psp_next_block(f, attrs, callback);
+
+ attrs->subblock--;
+
+ return 0;
+}
+
+static int psp_read_composite_image_block(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback)
+{
+ uint8_t buf[8];
+ uint32_t chunk_size;
+ uint32_t i, composite_image_count;
+
+ /* we are allready in subblock -> error */
+ if (attrs->subblock) {
+ GP_WARN("Composite Image Bank block inside of a Subblock");
+ return EINVAL;
+ }
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read Composite Image Bank Info Chunk");
+ return EIO;
+ }
+
+ chunk_size = BUF_TO_4(buf, 0);
+ composite_image_count = BUF_TO_4(buf, 4);
+
+ //TODO: utilize chunk_size
+
+ GP_DEBUG(3, "Composite image count=%u", composite_image_count);
+
+ attrs->subblock++;
+
+ for (i = 0; i < composite_image_count; i++)
+ psp_next_block(f, attrs, callback);
+
+ attrs->subblock--;
+
+ return 0;
+}
+
+enum psp_comp_img_type {
+ PSP_IMAGE_COMPOSITE,
+ PSP_IMAGE_THUMBNAIL,
+};
+
+static const char *psp_comp_img_type_name(enum psp_comp_img_type type)
+{
+ switch (type) {
+ case PSP_IMAGE_COMPOSITE:
+ return "Composite";
+ case PSP_IMAGE_THUMBNAIL:
+ return "Thumbnail";
+ default:
+ return "Unknown";
+ }
+}
+
+struct psp_comp_img_attr_info {
+ uint32_t w;
+ uint32_t h;
+ uint16_t bit_depth;
+ uint16_t comp_type;
+ uint16_t plane_count;
+ uint32_t color_count;
+ uint16_t comp_img_type;
+};
+
+static int psp_read_composite_attributes_block(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback)
+{
+ uint8_t buf[24];
+ struct psp_comp_img_attr_info info;
+ uint32_t chunk_size;
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read Composite Image Bank Info Chunk");
+ return EIO;
+ }
+
+ chunk_size = BUF_TO_4(buf, 0);
+
+ info.w = BUF_TO_4(buf, 4);
+ info.h = BUF_TO_4(buf, 8);
+ info.bit_depth = BUF_TO_2(buf, 12);
+ info.comp_type = BUF_TO_2(buf, 14);
+ info.plane_count = BUF_TO_2(buf, 16);
+ info.color_count = BUF_TO_4(buf, 18);
+ info.comp_img_type = BUF_TO_2(buf, 22);
+
+ GP_DEBUG(4, "Composite Image w=%u h=%u, bit_depth=%u, comp_type=%s, "
+ "comp_img_type=%s",
+ info.w, info.h, info.bit_depth, psp_comp_type_name(info.comp_type),
+ psp_comp_img_type_name(info.comp_img_type));
+
+ attrs->priv = &info;
+ attrs->subblock++;
+
+ if (info.comp_img_type == PSP_IMAGE_COMPOSITE)
+ psp_next_block(f, attrs, callback);
+
+ attrs->subblock--;
+ attrs->priv = NULL;
+
+ return 0;
+}
+
+static int psp_read_jpeg(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback)
+{
+ uint8_t buf[14];
+ uint32_t chunk_size;
+ int err;
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read JPEG Information Chunk");
+ return EIO;
+ }
+
+ chunk_size = BUF_TO_4(buf, 0);
+
+ //TODO: utilize chunk_size
+
+ GP_DEBUG(5, "JPEG Chunk");
+
+ attrs->img = GP_ReadJPG(f, callback);
+
+ if (attrs->img == NULL) {
+ err = errno;
+ GP_WARN("Failed to load JPEG Data Chunk %s", strerror(err));
+ return err;
+ }
+
+ return 0;
+}
+
+#define GEN_IMG_HEADER_ID "~BK"
+#define GEN_IMG_HEADER_ID_LEN 4
+
+static int psp_next_block(FILE *f, struct psp_img_attrs *attrs,
+ GP_ProgressCallback *callback)
+{
+ uint8_t buf[10];
+ uint16_t block_id;
+ uint32_t block_size;
+ long offset;
+ int err = 0;
+
+ if (fread(buf, sizeof(buf), 1, f) < 1) {
+ GP_DEBUG(1, "Failed to read block header");
+ return EIO;
+ }
+
+ if (memcmp(buf, GEN_IMG_HEADER_ID, GEN_IMG_HEADER_ID_LEN)) {
+ GP_DEBUG(1, "Invalid block header identifier");
+ return EINVAL;
+ }
+
+ block_id = BUF_TO_2(buf, 4);
+ block_size = BUF_TO_4(buf, 6);
+
+ GP_DEBUG(2 + attrs->subblock, "%s Block size %u",
+ psp_block_id_name(block_id), block_size);
+
+ offset = ftell(f) + block_size;
+
+ switch (block_id) {
+ case PSP_IMAGE_BLOCK:
+ err = psp_read_general_img_attr_chunk(f, attrs);
+ break;
+ case PSP_LAYER_START_BLOCK:
+ err = psp_read_layer_start_block(f, attrs, callback);
+ break;
+ case PSP_COMPOSITE_IMAGE_BANK_BLOCK:
+ err = psp_read_composite_image_block(f, attrs, callback);
+ break;
+ case PSP_COMPOSITE_ATTRIBUTES_BLOCK:
+ err = psp_read_composite_attributes_block(f, attrs, callback);
+ break;
+ case PSP_JPEG_BLOCK:
+ err = psp_read_jpeg(f, attrs, callback);
+ break;
+ }
+
+ if (err)
+ return err;
+
+ if (fseek(f, offset, SEEK_SET) == -1) {
+ err = errno;
+ GP_DEBUG(1, "Failed to seek to next block");
+ return errno;
+ }
+
+ return 0;
+}
+
+GP_Context *GP_ReadPSP(FILE *f, GP_ProgressCallback *callback)
+{
+ int err = 0;
+ struct psp_img_attrs attrs = {.is_loaded = 0, .subblock = 0,
+ .priv = NULL, .img = NULL};
+
+ while (!err) {
+ err = psp_next_block(f, &attrs, callback);
+
+ if (err)
+ goto err1;
+
+ if (attrs.img != NULL) {
+ fclose(f);
+ return attrs.img;
+ }
+ }
+
+ fclose(f);
+ errno = ENOSYS;
+ return NULL;
+err1:
+ fclose(f);
+ errno = err;
+ return NULL;
+}
+
+GP_Context *GP_LoadPSP(const char *src_path, GP_ProgressCallback *callback)
+{
+ FILE *f;
+
+ if (GP_OpenPSP(src_path, &f))
+ return NULL;
+
+ return GP_ReadPSP(f, callback);
+}
-----------------------------------------------------------------------
Summary of changes:
include/loaders/GP_Loaders.h | 1 +
include/loaders/{GP_GIF.h => GP_PSP.h} | 20 +-
libs/loaders/GP_Loaders.c | 12 +-
libs/loaders/GP_PSP.c | 522 ++++++++++++++++++++++++++++++++
tests/Makefile | 3 +-
5 files changed, 545 insertions(+), 13 deletions(-)
copy include/loaders/{GP_GIF.h => GP_PSP.h} (82%)
create mode 100644 libs/loaders/GP_PSP.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: 1a4cfc00663ccc76f058a87cc00c031ec57dd982
by metan 02 Nov '12
by metan 02 Nov '12
02 Nov '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 1a4cfc00663ccc76f058a87cc00c031ec57dd982 (commit)
from f7e6f933c737b7904e59d85438747f27785a89ac (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/1a4cfc00663ccc76f058a87cc00c031ec57d…
commit 1a4cfc00663ccc76f058a87cc00c031ec57dd982
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Nov 2 16:33:03 2012 +0100
tests: framework: Make output silent by default.
- shuffle some code to cleanup the sources
- add verbose switch and set it off by default
- add global runtest script to execute all testsuites
diff --git a/tests/framework/Makefile b/tests/framework/Makefile
index f3e22a1..a688952 100644
--- a/tests/framework/Makefile
+++ b/tests/framework/Makefile
@@ -17,7 +17,7 @@ ALL+=libtst_preload.so libtst.a
libtst_preload.so: tst_preload.o tst_alloc_barriers.o tst_preload_FILE.o
gcc -Wl,-soname -Wl,tst_preload.so --shared -ldl -fPIC $^ -o $@
-libtst.a: tst_test.o tst_job.o tst_msg.o tst_log.o tst_main.o tst_timespec.o
+libtst.a: tst_suite.o tst_job.o tst_msg.o tst_log.o tst_main.o tst_timespec.o
ar rcs $@ $^
CLEAN+=libtst_preload.so libtst.a log.html log.json
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index ce39d41..e60736b 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -33,7 +33,6 @@
#include <stdarg.h>
#include <math.h>
-#include "tst_preload.h"
#include "tst_test.h"
#include "tst_job.h"
#include "tst_timespec.h"
@@ -48,100 +47,6 @@ static int in_child(void)
return my_job != NULL;
}
-static void start_test(struct tst_job *job)
-{
- (void)job;
-// fprintf(stderr, "Starting test e[1;37m%se[0mn", job->test->name);
-}
-
-void tst_diff_timespec(int *sec, int *nsec, struct timespec *start,
- struct timespec *stop)
-{
- if (stop->tv_nsec < start->tv_nsec) {
- *sec = stop->tv_sec - start->tv_sec - 1;
- *nsec = stop->tv_nsec + 1000000000 - start->tv_nsec;
- } else {
- *sec = stop->tv_sec - start->tv_sec;
- *nsec = stop->tv_nsec - start->tv_nsec;
- }
-}
-
-#define NAME_PADD 35
-
-static void stop_test(struct tst_job *job)
-{
- const char *name = job->test->name;
- int sec, nsec;
- const char *result = "";
-
- tst_diff_timespec(&sec, &nsec, &job->start_time, &job->stop_time);
-
- switch (job->result) {
- case TST_SUCCESS:
- result = "[ e[1;32mSUCCESSe[0m ]";
- break;
- case TST_SKIPPED:
- result = "[ e[1;30mSKIPPEDe[0m ]";
- break;
- case TST_UNTESTED:
- result = "[ e[1;34mUNTESTEDe[0m ]";
- break;
- case TST_INTERR:
- result = "[ e[1;31mINTERNAL ERRORe[0m ]";
- break;
- case TST_SIGSEGV:
- result = "[ e[1;31mSEGFAULTe[0m ]";
- break;
- case TST_TIMEOUT:
- result = "[ e[1;35mTIMEOUTe[0m ]";
- break;
- case TST_ABORTED:
- result = "[ e[1;31mABORTEDe[0m ]";
- break;
- case TST_FPE:
- result = "[ e[1;31mFP EXCEPTIONe[0m ]";
- break;
- case TST_MEMLEAK:
- result = "[ e[1;33mMEMLEAKe[0m ]";
- break;
- case TST_FAILED:
- result = "[ e[1;31mFAILUREe[0m ]";
- break;
- case TST_MAX:
- break;
- }
-
- fprintf(stderr, "e[1;37m%se[0m", name);
-
- int i;
-
- for (i = strlen(name); i < NAME_PADD; i++)
- fprintf(stderr, " ");
-
- fprintf(stderr, " finished (Time %3i.%03is) %sn",
- sec, nsec/1000000, result);
-
- if (job->bench_iter) {
- for (i = 0; i < NAME_PADD; i++)
- fprintf(stderr, " ");
-
- fprintf(stderr, " bench CPU time %i.%06is +/- %i.%06isn",
- (int)job->bench_mean.tv_sec,
- (int)job->bench_mean.tv_nsec/1000,
- (int)job->bench_var.tv_sec,
- (int)job->bench_var.tv_nsec/1000);
- }
-
- if (job->result == TST_MEMLEAK)
- tst_malloc_print(&job->malloc_stats);
-
- /* Now print test message store */
- tst_msg_print(&job->store);
-
- fprintf(stderr, "------------------------------------------------------"
- "------------------------- n");
-}
-
/*
* Removes recursively temporary directory.
*/
@@ -438,9 +343,6 @@ void tst_job_run(struct tst_job *job)
/* Prepare the test message store */
tst_msg_init(&job->store);
- /* marks test as started */
- start_test(job);
-
/* copy benchmark interation */
job->bench_iter = job->test->bench_iter;
@@ -667,8 +569,6 @@ void tst_job_collect(struct tst_job *job)
/* Write down stop time */
clock_gettime(CLOCK_MONOTONIC, &job->stop_time);
-
- stop_test(job);
}
void tst_job_wait(struct tst_job *job)
diff --git a/tests/framework/tst_job.h b/tests/framework/tst_job.h
index 76984e5..171c0f0 100644
--- a/tests/framework/tst_job.h
+++ b/tests/framework/tst_job.h
@@ -90,7 +90,4 @@ void tst_job_run(struct tst_job *job);
*/
void tst_job_wait(struct tst_job *job);
-void tst_diff_timespec(int *sec, int *nsec, struct timespec *start,
- struct timespec *stop);
-
#endif /* TST_JOB_H */
diff --git a/tests/framework/tst_log.c b/tests/framework/tst_log.c
index a70f8c0..9daec17 100644
--- a/tests/framework/tst_log.c
+++ b/tests/framework/tst_log.c
@@ -27,6 +27,7 @@
#include "tst_job.h"
#include "tst_msg.h"
#include "tst_preload.h"
+#include "tst_timespec.h"
#include "tst_log.h"
static const char *ret_to_bg_color(enum tst_ret ret)
@@ -249,7 +250,7 @@ static int append_html(struct tst_job *job, FILE *f)
static int hack_counter = 0;
const char *bgcol;
- tst_diff_timespec(&sec, &nsec, &job->start_time, &job->stop_time);
+ timespec_diff(&sec, &nsec, &job->start_time, &job->stop_time);
if (hack_counter)
bgcol = "#ccccee";
@@ -375,7 +376,7 @@ static int append_json(struct tst_job *job, FILE *f)
/* Time statistics */
int sec, nsec;
- tst_diff_timespec(&sec, &nsec, &job->start_time, &job->stop_time);
+ timespec_diff(&sec, &nsec, &job->start_time, &job->stop_time);
fprintf(f, "ttt"CPU Time": %i.%09i,n",
(int)job->cpu_time.tv_sec, (int)job->cpu_time.tv_nsec);
diff --git a/tests/framework/tst_main.c b/tests/framework/tst_main.c
index 28020a0..d1c6474 100644
--- a/tests/framework/tst_main.c
+++ b/tests/framework/tst_main.c
@@ -28,12 +28,16 @@
extern const struct tst_suite tst_suite;
+/* defined in tst_suite.c */
+extern int tst_suite_verbose;
+
void print_help(void)
{
fprintf(stderr, "Test suite '%s' Usage:nn", tst_suite.suite_name);
fprintf(stderr, "-h prints this helpn");
fprintf(stderr, "-l list all testsn");
fprintf(stderr, "-t name runs single test by namen");
+ fprintf(stderr, "-v turns on verbose moden");
fprintf(stderr, "without any option, all tests are executedn");
}
@@ -41,7 +45,7 @@ int main(int argc, char *argv[])
{
int opt;
- while ((opt = getopt(argc, argv, "hlt:")) != -1) {
+ while ((opt = getopt(argc, argv, "hlt:v")) != -1) {
switch (opt) {
case 'l':
tst_list_suite(&tst_suite);
@@ -55,6 +59,9 @@ int main(int argc, char *argv[])
print_help();
return 0;
break;
+ case 'v':
+ tst_suite_verbose = 1;
+ break;
default:
print_help();
return 1;
diff --git a/tests/framework/tst_msg.c b/tests/framework/tst_msg.c
index 852fb81..8deafd1 100644
--- a/tests/framework/tst_msg.c
+++ b/tests/framework/tst_msg.c
@@ -85,7 +85,7 @@ static char type_to_char(enum tst_report_type type)
}
}
-void tst_msg_print(struct tst_msg_store *self)
+void tst_msg_print(const struct tst_msg_store *self)
{
struct tst_msg *msg;
diff --git a/tests/framework/tst_msg.h b/tests/framework/tst_msg.h
index a6a290a..f144851 100644
--- a/tests/framework/tst_msg.h
+++ b/tests/framework/tst_msg.h
@@ -62,6 +62,6 @@ int tst_msg_append(struct tst_msg_store *self, int type, const char *msg);
/*
* Prints messages in the store.
*/
-void tst_msg_print(struct tst_msg_store *self);
+void tst_msg_print(const struct tst_msg_store *self);
#endif /* TST_MSG_H */
diff --git a/tests/framework/tst_preload.c b/tests/framework/tst_preload.c
index 7241926..aec364f 100644
--- a/tests/framework/tst_preload.c
+++ b/tests/framework/tst_preload.c
@@ -146,7 +146,7 @@ void free(void *ptr)
real_free(ptr);
}
-void tst_malloc_print(struct malloc_stats *stats)
+void tst_malloc_print(const struct malloc_stats *stats)
{
fprintf(stderr, "Total size %zu chunks %u, lost size %zu chunks %un",
stats->total_size, stats->total_chunks,
diff --git a/tests/framework/tst_preload.h b/tests/framework/tst_preload.h
index d103e8c..0c44d3d 100644
--- a/tests/framework/tst_preload.h
+++ b/tests/framework/tst_preload.h
@@ -65,6 +65,6 @@ void tst_malloc_check_report(struct malloc_stats *stats);
/*
* Prints malloc statistics.
*/
-void tst_malloc_print(struct malloc_stats *stats);
+void tst_malloc_print(const struct malloc_stats *stats);
#endif /* TST_PRELOAD_H */
diff --git a/tests/framework/tst_suite.c b/tests/framework/tst_suite.c
new file mode 100644
index 0000000..1c0440b
--- /dev/null
+++ b/tests/framework/tst_suite.c
@@ -0,0 +1,195 @@
+/*****************************************************************************
+ * This file is part of gfxprim library. *
+ * *
+ * Gfxprim is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2.1 of the License, or (at your option) any later version. *
+ * *
+ * Gfxprim is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with gfxprim; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301 USA *
+ * *
+ * Copyright (C) 2009-2012 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "tst_log.h"
+#include "tst_job.h"
+#include "tst_test.h"
+#include "tst_preload.h"
+#include "tst_timespec.h"
+
+#define NAME_PADD 35
+
+int tst_suite_verbose = 0;
+
+static void test_job_report(const struct tst_job *job)
+{
+ const char *name = job->test->name;
+ int sec, nsec;
+ const char *result = "";
+
+ if ((job->result == TST_SUCCESS || job->result == TST_SKIPPED)
+ && !tst_suite_verbose)
+ return;
+
+ timespec_diff(&sec, &nsec, &job->start_time, &job->stop_time);
+
+ switch (job->result) {
+ case TST_SUCCESS:
+ result = "[ e[1;32mSUCCESSe[0m ]";
+ break;
+ case TST_SKIPPED:
+ result = "[ e[1;30mSKIPPEDe[0m ]";
+ break;
+ case TST_UNTESTED:
+ result = "[ e[1;34mUNTESTEDe[0m ]";
+ break;
+ case TST_INTERR:
+ result = "[ e[1;31mINTERNAL ERRORe[0m ]";
+ break;
+ case TST_SIGSEGV:
+ result = "[ e[1;31mSEGFAULTe[0m ]";
+ break;
+ case TST_TIMEOUT:
+ result = "[ e[1;35mTIMEOUTe[0m ]";
+ break;
+ case TST_ABORTED:
+ result = "[ e[1;31mABORTEDe[0m ]";
+ break;
+ case TST_FPE:
+ result = "[ e[1;31mFP EXCEPTIONe[0m ]";
+ break;
+ case TST_MEMLEAK:
+ result = "[ e[1;33mMEMLEAKe[0m ]";
+ break;
+ case TST_FAILED:
+ result = "[ e[1;31mFAILUREe[0m ]";
+ break;
+ case TST_MAX:
+ break;
+ }
+
+ fprintf(stderr, "e[1;37m%se[0m", name);
+
+ int i;
+
+ for (i = strlen(name); i < NAME_PADD; i++)
+ fprintf(stderr, " ");
+
+ fprintf(stderr, " finished (Time %3i.%03is) %sn",
+ sec, nsec/1000000, result);
+
+ if (job->bench_iter) {
+ for (i = 0; i < NAME_PADD; i++)
+ fprintf(stderr, " ");
+
+ fprintf(stderr, " bench CPU time %i.%06is +/- %i.%06isn",
+ (int)job->bench_mean.tv_sec,
+ (int)job->bench_mean.tv_nsec/1000,
+ (int)job->bench_var.tv_sec,
+ (int)job->bench_var.tv_nsec/1000);
+ }
+
+ if (job->result == TST_MEMLEAK)
+ tst_malloc_print(&job->malloc_stats);
+
+ /* Now print test message store */
+ tst_msg_print(&job->store);
+
+ fprintf(stderr, "------------------------------------------------------"
+ "------------------------- n");
+}
+
+static int run_test(const struct tst_test *test, FILE *html, FILE *json)
+{
+ struct tst_job job;
+
+ job.test = test;
+
+ /*
+ * Flush the file before forking, otherwise
+ * there would be a copy of its buffers in both
+ * child and parent and the lines in the resulting
+ * file would be repeated several times.
+ */
+ fflush(html);
+ fflush(json);
+
+ tst_job_run(&job);
+ tst_job_wait(&job);
+
+ /* report result into stdout */
+ test_job_report(&job);
+
+ tst_log_append(&job, html, TST_LOG_HTML);
+ tst_log_append(&job, json, TST_LOG_JSON);
+
+ /* Free the test message store */
+ tst_msg_clear(&job.store);
+
+ return job.result;
+}
+
+void tst_run_suite(const struct tst_suite *suite, const char *tst_name)
+{
+ unsigned int i;
+ unsigned int counters[TST_MAX] = {};
+ unsigned int counter = 0;
+ int ret;
+
+ fprintf(stderr, "Running e[1;37m%se[0mnn", suite->suite_name);
+
+ //TODO:
+ FILE *html = tst_log_open(suite, "log.html", TST_LOG_HTML);
+ FILE *json = tst_log_open(suite, "log.json", TST_LOG_JSON);
+
+ for (i = 0; suite->tests[i].name != NULL; i++) {
+ if (tst_name == NULL || !strcmp(tst_name, suite->tests[i].name)) {
+ ret = run_test(&suite->tests[i], html, json);
+ counters[ret]++;
+
+ if (ret != TST_SKIPPED)
+ counter++;
+ }
+ }
+
+ tst_log_close(html, TST_LOG_HTML);
+ tst_log_close(json, TST_LOG_JSON);
+
+ float percents;
+
+ if (counter == 0)
+ percents = 100;
+ else
+ percents = 100.00 * counters[0] / counter;
+
+ fprintf(stderr, "nSummary: succedded %u out of "
+ "%u %.2f%% (skipped %u)n",
+ counters[0], counter, percents,
+ counters[TST_SKIPPED]);
+}
+
+void tst_list_suite(const struct tst_suite *suite)
+{
+ int i;
+
+ fprintf(stderr, "Testsuite: e[1;37m%se[0mnn", suite->suite_name);
+
+ for (i = 0; suite->tests[i].name != NULL; i++)
+ fprintf(stderr, "Test: e[1;37m%se[0mn", suite->tests[i].name);
+}
diff --git a/tests/framework/tst_test.c b/tests/framework/tst_test.c
deleted file mode 100644
index 62666da..0000000
--- a/tests/framework/tst_test.c
+++ /dev/null
@@ -1,108 +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-2012 Cyril Hrubis <metan(a)ucw.cz> *
- * *
- *****************************************************************************/
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "tst_log.h"
-#include "tst_job.h"
-#include "tst_test.h"
-
-static int run_test(const struct tst_test *test, FILE *html, FILE *json)
-{
- struct tst_job job;
-
- job.test = test;
-
- /*
- * Flush the file before forking, otherwise
- * there would be a copy of its buffers in both
- * child and parent and the lines in the resulting
- * file would be repeated several times.
- */
- fflush(html);
- fflush(json);
-
- tst_job_run(&job);
- tst_job_wait(&job);
-
- tst_log_append(&job, html, TST_LOG_HTML);
- tst_log_append(&job, json, TST_LOG_JSON);
-
- /* Free the test message store */
- tst_msg_clear(&job.store);
-
- return job.result;
-}
-
-void tst_run_suite(const struct tst_suite *suite, const char *tst_name)
-{
- unsigned int i;
- unsigned int counters[TST_MAX] = {};
- unsigned int counter = 0;
- int ret;
-
- fprintf(stderr, "Running e[1;37m%se[0mnn", suite->suite_name);
-
- //TODO:
- FILE *html = tst_log_open(suite, "log.html", TST_LOG_HTML);
- FILE *json = tst_log_open(suite, "log.json", TST_LOG_JSON);
-
- for (i = 0; suite->tests[i].name != NULL; i++) {
- if (tst_name == NULL || !strcmp(tst_name, suite->tests[i].name)) {
- ret = run_test(&suite->tests[i], html, json);
- counters[ret]++;
-
- if (ret != TST_SKIPPED)
- counter++;
- }
- }
-
- tst_log_close(html, TST_LOG_HTML);
- tst_log_close(json, TST_LOG_JSON);
-
- float percents;
-
- if (counter == 0)
- percents = 100;
- else
- percents = 100.00 * counters[0] / counter;
-
- fprintf(stderr, "nSummary: succedded %u out of "
- "%u %.2f%% (skipped %u)n",
- counters[0], counter, percents,
- counters[TST_SKIPPED]);
-}
-
-void tst_list_suite(const struct tst_suite *suite)
-{
- int i;
-
- fprintf(stderr, "Testsuite: e[1;37m%se[0mnn", suite->suite_name);
-
- for (i = 0; suite->tests[i].name != NULL; i++)
- fprintf(stderr, "Test: e[1;37m%se[0mn", suite->tests[i].name);
-}
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index 186d497..937f1cf 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -75,6 +75,7 @@ struct tst_test {
struct tst_suite {
const char *suite_name;
+ int verbose:1;
struct tst_test tests[];
};
diff --git a/tests/framework/tst_timespec.c b/tests/framework/tst_timespec.c
index d388502..233095c 100644
--- a/tests/framework/tst_timespec.c
+++ b/tests/framework/tst_timespec.c
@@ -24,6 +24,19 @@
#define NSEC_IN_SEC 1000000000
+void timespec_diff(int *sec, int *nsec,
+ const struct timespec *start,
+ const struct timespec *stop)
+{
+ if (stop->tv_nsec < start->tv_nsec) {
+ *sec = stop->tv_sec - start->tv_sec - 1;
+ *nsec = stop->tv_nsec + 1000000000 - start->tv_nsec;
+ } else {
+ *sec = stop->tv_sec - start->tv_sec;
+ *nsec = stop->tv_nsec - start->tv_nsec;
+ }
+}
+
double timespec_to_double(const struct timespec *t)
{
double res;
diff --git a/tests/framework/tst_timespec.h b/tests/framework/tst_timespec.h
index 25d010c..27ab5cb 100644
--- a/tests/framework/tst_timespec.h
+++ b/tests/framework/tst_timespec.h
@@ -31,6 +31,10 @@
#include <time.h>
+void timespec_diff(int *sec, int *nsec,
+ const struct timespec *start,
+ const struct timespec *stop);
+
double timespec_to_double(const struct timespec *t);
void double_to_timespec(const double time, struct timespec *res);
diff --git a/tests/runtests.sh b/tests/runtests.sh
new file mode 100755
index 0000000..f15668b
--- /dev/null
+++ b/tests/runtests.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+DIRS="core loaders gfx"
+
+for i in $DIRS; do
+ cd $i
+ ./runtest.sh $@
+ cd ..
+done
-----------------------------------------------------------------------
Summary of changes:
tests/framework/Makefile | 2 +-
tests/framework/tst_job.c | 100 --------------------
tests/framework/tst_job.h | 3 -
tests/framework/tst_log.c | 5 +-
tests/framework/tst_main.c | 9 ++-
tests/framework/tst_msg.c | 2 +-
tests/framework/tst_msg.h | 2 +-
tests/framework/tst_preload.c | 2 +-
tests/framework/tst_preload.h | 2 +-
tests/framework/tst_suite.c | 195 ++++++++++++++++++++++++++++++++++++++++
tests/framework/tst_test.c | 108 ----------------------
tests/framework/tst_test.h | 1 +
tests/framework/tst_timespec.c | 13 +++
tests/framework/tst_timespec.h | 4 +
tests/runtests.sh | 9 ++
15 files changed, 238 insertions(+), 219 deletions(-)
create mode 100644 tests/framework/tst_suite.c
delete mode 100644 tests/framework/tst_test.c
create mode 100755 tests/runtests.sh
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: f7e6f933c737b7904e59d85438747f27785a89ac
by metan 02 Nov '12
by metan 02 Nov '12
02 Nov '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 f7e6f933c737b7904e59d85438747f27785a89ac (commit)
via 6bb7181dfe0c836adde74679982b8e66584d4c29 (commit)
from 019030bda9e79cde4165d8a9f9ca78be39a5ea28 (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/f7e6f933c737b7904e59d85438747f27785a…
commit f7e6f933c737b7904e59d85438747f27785a89ac
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Nov 2 16:01:18 2012 +0100
tests: Fixup messages API and return values.
diff --git a/tests/core/Context.c b/tests/core/Context.c
index ec83876..4e05306 100644
--- a/tests/core/Context.c
+++ b/tests/core/Context.c
@@ -40,50 +40,50 @@ static int Context_Alloc_Free(void)
c = GP_ContextAlloc(100, 200, GP_PIXEL_RGB888);
if (c == NULL) {
- tst_report(0, "GP_ContextAlloc() failed");
+ tst_msg("GP_ContextAlloc() failed");
return TST_FAILED;
}
/* Assert context properties */
if (c->bpp != 24) {
- tst_report(0, "Context->bpp != 24 (== %i)", c->bpp);
+ tst_msg("Context->bpp != 24 (== %i)", c->bpp);
return TST_FAILED;
}
if (c->bytes_per_row != 3 * c->w) {
- tst_report(0, "Context->bytes_per_row != %i (== %i)",
- 3 * c->w, c->bytes_per_row);
+ tst_msg("Context->bytes_per_row != %i (== %i)",
+ 3 * c->w, c->bytes_per_row);
return TST_FAILED;
}
if (c->w != 100) {
- tst_report(0, "Context->w != 100 (== %i)", c->w);
+ tst_msg("Context->w != 100 (== %i)", c->w);
return TST_FAILED;
}
if (c->h != 200) {
- tst_report(0, "Context->h != 200 (== %i)", c->h);
+ tst_msg("Context->h != 200 (== %i)", c->h);
return TST_FAILED;
}
if (c->offset != 0) {
- tst_report(0, "Context->offset != 0");
+ tst_msg("Context->offset != 0");
return TST_FAILED;
}
if (c->pixel_type != GP_PIXEL_RGB888) {
- tst_report(0, "Context->pixel_type != GP_PIXEL_RGB888");
+ tst_msg("Context->pixel_type != GP_PIXEL_RGB888");
return TST_FAILED;
}
if (c->gamma != NULL) {
- tst_report(0, "Context->gamma != NULL");
+ tst_msg("Context->gamma != NULL");
return TST_FAILED;
}
if (c->axes_swap != 0 || c->x_swap != 0 || c->y_swap != 0) {
- tst_report(0, "Wrong default orientation %i %i %i",
- c->axes_swap, c->x_swap, c->y_swap);
+ tst_msg("Wrong default orientation %i %i %i",
+ c->axes_swap, c->x_swap, c->y_swap);
return TST_FAILED;
}
@@ -101,7 +101,6 @@ const struct tst_suite tst_suite = {
.tests = {
{.name = "Context Alloc Free", .tst_fn = Context_Alloc_Free,
.flags = TST_CHECK_MALLOC},
-
{.name = NULL},
}
};
diff --git a/tests/core/GetPutPixel.gen.c.t b/tests/core/GetPutPixel.gen.c.t
index 5f1354a..05ffbdd 100644
--- a/tests/core/GetPutPixel.gen.c.t
+++ b/tests/core/GetPutPixel.gen.c.t
@@ -50,7 +50,7 @@ static int check_filled(GP_Context *c)
for (x = 0; x < (GP_Coord)c->w; x++)
for (y = 0; y < (GP_Coord)c->h; y++)
if (p != GP_GetPixel(c, x, y)) {
- tst_report(0, "Pixels different %i %i", x, y);
+ tst_msg("Pixels different %i %i", x, y);
return 1;
}
@@ -61,7 +61,7 @@ static int try_pattern(GP_Context *c, GP_Pixel p)
{
fill_context(c, p);
- tst_report(0, "Filling pattern 0x%x", p);
+ tst_msg("Filling pattern 0x%x", p);
if (check_filled(c))
return 1;
@@ -79,7 +79,7 @@ static int GetPutPixel_{{ pt.name }}(void)
c = GP_ContextAlloc(100, 100, GP_PIXEL_{{ pt.name }});
if (c == NULL) {
- tst_report(0, "GP_ContextAlloc() failed");
+ tst_msg("GP_ContextAlloc() failed");
return TST_UNTESTED;
}
@@ -114,7 +114,7 @@ static int GetPutPixel_Clipping_{{ pt.name }}(void)
c = GP_ContextAlloc(100, 100, GP_PIXEL_{{ pt.name }});
if (c == NULL) {
- tst_report(0, "GP_ContextAlloc() failed");
+ tst_msg("GP_ContextAlloc() failed");
return TST_UNTESTED;
}
@@ -133,8 +133,8 @@ static int GetPutPixel_Clipping_{{ pt.name }}(void)
/* Must return 0 */
if (GP_GetPixel(c, x, y) != 0) {
- tst_report(0, "GP_GetPixel returned non-zero "
- "at %i %i", x, y);
+ tst_msg("GP_GetPixel returned non-zero "
+ "at %i %i", x, y);
err++;
}
}
diff --git a/tests/core/WritePixel_testsuite.gen.c.t b/tests/core/WritePixel_testsuite.gen.c.t
index a554e9b..365c247 100644
--- a/tests/core/WritePixel_testsuite.gen.c.t
+++ b/tests/core/WritePixel_testsuite.gen.c.t
@@ -58,7 +58,7 @@ static void dump_buffer(const char *name, char *buf, unsigned int buf_len)
unsigned int i; if (buf1_len != buf2_len) { - tst_report(0, "Invalid buffers"); + tst_msg("Invalid buffers"); return TST_FAILED; } @@ -67,7 +67,7 @@ static void dump_buffer(const char *name, char *buf, unsigned int buf_len)
printf("%sn", id); dump_buffer("wrote", buf1, buf1_len); dump_buffer("gen", buf2, buf2_len); - tst_report(0, "Buffers are different"); + tst_msg("Buffers are different"); return TST_FAILED; } diff --git a/tests/filters/LinearConvolution.c b/tests/filters/LinearConvolution.c
index 78d1bd4..0264ddd 100644
--- a/tests/filters/LinearConvolution.c
+++ b/tests/filters/LinearConvolution.c
@@ -37,8 +37,8 @@ static int load_resources(const char *path1, const char *path2,
*c2 = GP_LoadImage(path2, NULL);
if (*c1 == NULL || *c2 == NULL) {
- tst_report(0, "Failed to load resource");
- return TST_INTERR;
+ tst_err("Failed to load resource");
+ return TST_UNTESTED;
}
return TST_SUCCESS;
diff --git a/tests/framework/test.c b/tests/framework/test.c
index ccef65d..8111855 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -32,8 +32,8 @@
int success_fn(void)
{
- tst_report(0, "This test does nothing");
- tst_report(0, "But successfully");
+ tst_msg("This test does nothing");
+ tst_msg("But successfully");
return TST_SUCCESS;
}
@@ -57,7 +57,7 @@ int stack_overflow_fn(void)
int timeout_fn(void)
{
- tst_report(0, "Sleeping for ten seconds");
+ tst_msg("Sleeping for ten seconds");
sleep(10);
return TST_SUCCESS;
}
@@ -68,7 +68,7 @@ int temp_dir_fn(void)
/* log current working directory */
res = getcwd(buf, sizeof(buf));
- tst_report(0, "CWD is '%s'", res);
+ tst_msg("CWD is '%s'", res);
return TST_SUCCESS;
}
@@ -86,7 +86,7 @@ int malloc_leak_fn(void)
free(q);
free(r);
- tst_report(0, "Leaking 1 chunks 4 bytes total");
+ tst_msg("Leaking 1 chunks 4 bytes total");
return TST_SUCCESS;
}
@@ -129,11 +129,11 @@ int barrier_allocation(void)
for (i = 0; i < 31; i++)
buf[i] = 0;
- tst_report(0, "About to use address after the buffer with barrier");
+ tst_msg("About to use address after the buffer with barrier");
buf[31] = 0;
- tst_report(0, "This is not printed at all");
+ tst_msg("This is not printed at all");
return TST_SUCCESS;
}
@@ -154,31 +154,31 @@ int fail_FILE(void)
f = fopen("test_fail_fclose", "w");
if (f == NULL) {
- tst_report(0, "Failed to open 'test_fail_fclose' for writing: %s",
+ tst_msg("Failed to open 'test_fail_fclose' for writing: %s",
strerror(errno));
fail = 1;
}
- tst_report(0, "Correctly opened 'test_fail_fclose'");
+ tst_msg("Correctly opened 'test_fail_fclose'");
int ret = fclose(f);
if (ret == 0 || errno != ENOSPC) {
- tst_report(0, "Failed to fail to close 'test_fail_fclose'");
+ tst_msg("Failed to fail to close 'test_fail_fclose'");
fail = 1;
}
- tst_report(0, "Correctly failed to close 'test_fail_fclose'");
+ tst_msg("Correctly failed to close 'test_fail_fclose'");
f = fopen("test_fail_fopen", "w");
if (f != NULL && errno != EPERM) {
- tst_report(0, "Failed to fail to open 'test_fail_fopen'");
+ tst_msg("Failed to fail to open 'test_fail_fopen'");
fclose(f);
fail = 1;
}
- tst_report(0, "Correctly failed to open 'test_fail_fopen'");
+ tst_msg("Correctly failed to open 'test_fail_fopen'");
if (fail)
return TST_FAILED;
@@ -186,6 +186,19 @@ int fail_FILE(void)
return TST_SUCCESS;
}
+static int messages_test_fn(void)
+{
+ /* stdout and stderr capture test */
+ printf("This is stdoutn");
+ fprintf(stderr, "This is stderrn");
+
+ tst_msg("This is message");
+ tst_warn("This is a warning");
+ tst_err("This is an error");
+
+ return TST_SUCCESS;
+}
+
/*
* This status is returned when the could not be started
* because of unsufficient configuration
@@ -208,7 +221,7 @@ static int untested_fn(void)
static int res_fn(void)
{
if (access("test.c", R_OK) == 0)
- tst_report(0, "File correctly copied");
+ tst_msg("File correctly copied");
return TST_SUCCESS;
}
@@ -254,6 +267,7 @@ const struct tst_suite tst_suite = {
{.name = "Resource", .tst_fn = res_fn, .flags = TST_TMPDIR,
.res_path = "test.c"},
{.name = "FP exception", .tst_fn = fpe_fn},
+ {.name = "Messages test", .tst_fn = messages_test_fn},
{.name = "Benchmark test", .tst_fn = benchmark_fn, .bench_iter = 10},
{.name = NULL},
}
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index 889cc45..ce39d41 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -312,6 +312,23 @@ int tst_report(int level, const char *fmt, ...)
return ret;
}
+int tst_msg(const char *fmt, ...)
+{
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+
+ if (in_child())
+ return tst_vreport(TST_MSG, fmt, va);
+
+ fprintf(stderr, "MSG: ");
+ ret = vfprintf(stderr, fmt, va);
+ va_end(va);
+
+ return ret;
+}
+
int tst_warn(const char *fmt, ...)
{
va_list va;
@@ -320,8 +337,26 @@ int tst_warn(const char *fmt, ...)
va_start(va, fmt);
if (in_child())
- return tst_vreport(-1, fmt, va);
+ return tst_vreport(TST_WARN, fmt, va);
+
+ fprintf(stderr, "WARN: ");
+ ret = vfprintf(stderr, fmt, va);
+ va_end(va);
+
+ return ret;
+}
+
+int tst_err(const char *fmt, ...)
+{
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+
+ if (in_child())
+ return tst_vreport(TST_ERR, fmt, va);
+ fprintf(stderr, "ERR: ");
ret = vfprintf(stderr, fmt, va);
va_end(va);
diff --git a/tests/framework/tst_msg.c b/tests/framework/tst_msg.c
index 2d46338..852fb81 100644
--- a/tests/framework/tst_msg.c
+++ b/tests/framework/tst_msg.c
@@ -71,10 +71,24 @@ int tst_msg_append(struct tst_msg_store *self, int type, const char *msg_text)
return 0;
}
+static char type_to_char(enum tst_report_type type)
+{
+ switch (type) {
+ case TST_MSG:
+ return 'M';
+ case TST_WARN:
+ return 'W';
+ case TST_ERR:
+ return 'E';
+ default:
+ return '?';
+ }
+}
+
void tst_msg_print(struct tst_msg_store *self)
{
struct tst_msg *msg;
for (msg = self->first; msg != NULL; msg = msg->next)
- fprintf(stderr, "%i: %sn", msg->type, msg->msg);
+ fprintf(stderr, "%c: %sn", type_to_char(msg->type), msg->msg);
}
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index c6ef4fe..186d497 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -27,7 +27,7 @@ enum tst_ret {
TST_SUCCESS, /* Test succedded */
TST_SKIPPED, /* Test skipped due to not enough memory, ENOSYS ... */
TST_UNTESTED, /* Test not finished because of failure */
- TST_INTERR, /* Test framework error */
+ TST_INTERR, /* Test framework error, do not use */
TST_SIGSEGV, /* Test ended with SIGSEGV */
TST_TIMEOUT, /* Test hasn't finished in time */
TST_ABORTED, /* The abort() was called (possible double free) */
@@ -91,10 +91,29 @@ void tst_list_suite(const struct tst_suite *suite);
/*
* Printf-like reporting function.
*/
+enum tst_report_type {
+ TST_MSG,
+ TST_WARN,
+ TST_ERR,
+};
+
+/* general report function - do not use */
int tst_report(int level, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
+/* informative message */
+int tst_msg(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+/*
+ * Warning and Error are used in test framework to distinguish the type of test
+ * internal problem. You shouldn't use this one unless the test exited with
+ * TST_UNTESTED.
+ */
int tst_warn(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
+int tst_err(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
#endif /* TST_TEST_H */
diff --git a/tests/gfx/Circle.c b/tests/gfx/Circle.c
index d159632..34637bc 100644
--- a/tests/gfx/Circle.c
+++ b/tests/gfx/Circle.c
@@ -110,7 +110,7 @@ static int test_circle(const char *pattern, GP_Size w, GP_Size h,
c = GP_ContextAlloc(w, h, GP_PIXEL_G8);
if (c == NULL) {
- tst_report(0, "Failed to allocate context");
+ tst_err("Failed to allocate context");
return TST_UNTESTED;
}
@@ -122,7 +122,7 @@ static int test_circle(const char *pattern, GP_Size w, GP_Size h,
err = compare_buffers(pattern, c);
if (err) {
- tst_report(0, "Patterns are different");
+ tst_msg("Patterns are different");
return TST_FAILED;
}
diff --git a/tests/gfx/CircleSeg.c b/tests/gfx/CircleSeg.c
index 69767ec..dfb099b 100644
--- a/tests/gfx/CircleSeg.c
+++ b/tests/gfx/CircleSeg.c
@@ -166,7 +166,7 @@ static int test_circle(const char *pattern, GP_Size w, GP_Size h,
c = GP_ContextAlloc(w, h, GP_PIXEL_G8);
if (c == NULL) {
- tst_report(0, "Failed to allocate context");
+ tst_err("Failed to allocate context");
return TST_UNTESTED;
}
@@ -178,7 +178,7 @@ static int test_circle(const char *pattern, GP_Size w, GP_Size h,
err = compare_buffers(pattern, c);
if (err) {
- tst_report(0, "Patterns are different");
+ tst_msg("Patterns are different");
return TST_FAILED;
}
diff --git a/tests/gfx/Line.c b/tests/gfx/Line.c
index 5821b25..4c15718 100644
--- a/tests/gfx/Line.c
+++ b/tests/gfx/Line.c
@@ -73,6 +73,20 @@ static const char line_0_0_10_10_11x11[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
};
+static const char line_0_0_11_5_11x11[] = {
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
static int test_line(const char *pattern, GP_Size w, GP_Size h,
GP_Coord x0, GP_Coord y0, GP_Coord x1, GP_Coord y1)
{
@@ -82,7 +96,7 @@ static int test_line(const char *pattern, GP_Size w, GP_Size h,
c = GP_ContextAlloc(w, h, GP_PIXEL_G8);
if (c == NULL) {
- tst_report(0, "Failed to allocate context");
+ tst_err("Failed to allocate context");
return TST_UNTESTED;
}
@@ -94,7 +108,7 @@ static int test_line(const char *pattern, GP_Size w, GP_Size h,
err = compare_buffers(pattern, c);
if (err) {
- tst_report(0, "Patterns are different");
+ tst_msg("Patterns are different");
return TST_FAILED;
}
@@ -121,12 +135,18 @@ static int test_line__1__1_11_11(void)
return test_line(line_0_0_10_10_11x11, 11, 11, -1, -1, 11, 11);
}
+static int test_line_0_0_11_5(void)
+{
+ return test_line(line_0_0_11_5_11x11, 11, 11, 0, 0, 11, 5);
+}
+
const struct tst_suite tst_suite = {
.suite_name = "GFX Line Testsuite",
.tests = {
{.name = "Line 5x5 - 5x5", .tst_fn = test_line_5_5_5_5},
{.name = "Line 1x5 - 9x5", .tst_fn = test_line_1_5_9_5},
{.name = "Line 0x0 - 10x10", .tst_fn = test_line_0_0_10_10},
+ {.name = "Line 0x0 - 11x5", .tst_fn = test_line_0_0_11_5},
{.name = "Line -1x-1 - 11x11", .tst_fn = test_line__1__1_11_11},
{.name = NULL}
}
diff --git a/tests/gfx/gfx_benchmark.c b/tests/gfx/gfx_benchmark.c
index 0ec61c6..c4cff7a 100644
--- a/tests/gfx/gfx_benchmark.c
+++ b/tests/gfx/gfx_benchmark.c
@@ -30,8 +30,8 @@ static int bench_line(GP_PixelType type)
GP_Context *img = GP_ContextAlloc(800, 600, type);
if (img == NULL) {
- tst_report(0, "Malloc failed");
- return TST_INTERR;
+ tst_err("Malloc failed");
+ return TST_UNTESTED;
}
unsigned int i;
@@ -74,8 +74,8 @@ static int bench_circle(GP_PixelType type)
GP_Context *img = GP_ContextAlloc(800, 600, type);
if (img == NULL) {
- tst_report(0, "Malloc failed");
- return TST_INTERR;
+ tst_err("Malloc failed");
+ return TST_UNTESTED;
}
unsigned int i;
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index c87c6f9..3d9fed4 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -64,8 +64,8 @@ static int save_img(enum fmt fmt, const GP_Context *img, const char *name)
case JPG:
return GP_SaveJPG(img, buf, NULL);
default:
- tst_report(0, "WARNING: trying to save %s", strfmt(fmt));
- exit(TST_INTERR);
+ tst_err("Trying to save %s image", strfmt(fmt));
+ exit(TST_UNTESTED);
}
}
@@ -85,8 +85,8 @@ static GP_Context *load(enum fmt fmt, const char *name)
case BMP:
return GP_LoadBMP(buf, NULL);
default:
- tst_report(0, "WARNING: trying to load %s", strfmt(fmt));
- exit(TST_INTERR);
+ tst_err("Trying to load %s image", strfmt(fmt));
+ exit(TST_UNTESTED);
}
}
@@ -97,19 +97,19 @@ static int save_load(enum fmt fmt, GP_Size w, GP_Size h)
img = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
if (img == NULL) {
- tst_report(0, "GP_ContextAlloc failed");
- return TST_INTERR;
+ tst_warn("GP_ContextAlloc failed");
+ return TST_UNTESTED;
}
int ret = save_img(fmt, img, "test");
if (ret) {
if (errno == ENOSYS) {
- tst_report(0, "Save %s: ENOSYS", strfmt(fmt));
+ tst_msg("Save %s: ENOSYS", strfmt(fmt));
return TST_SKIPPED;
}
- tst_report(0, "Failed to save %s: %s",
+ tst_msg("Failed to save %s: %s",
strfmt(fmt), strerror(errno));
return TST_FAILED;
}
@@ -117,7 +117,7 @@ static int save_load(enum fmt fmt, GP_Size w, GP_Size h)
res = load(fmt, "test");
if (res == NULL) {
- tst_report(0, "Failed to load %s: %s",
+ tst_msg("Failed to load %s: %s",
strfmt(fmt), strerror(errno));
return TST_FAILED;
}
@@ -155,18 +155,17 @@ static int load_enoent(enum fmt fmt)
img = load(fmt, "nonexistent");
if (img != NULL) {
- tst_report(0, "Test succedded unexpectedly");
+ tst_msg("Test succedded unexpectedly");
return TST_FAILED;
}
if (errno == ENOSYS) {
- tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ tst_msg("Load %s: ENOSYS", strfmt(fmt));
return TST_SKIPPED;
}
if (errno != ENOENT) {
- tst_report(0, "Expected errno = ENOENT, have %s",
- strerror(errno));
+ tst_msg("Expected errno = ENOENT, have %s", strerror(errno));
return TST_FAILED;
}
@@ -203,31 +202,31 @@ static int load_eacces(enum fmt fmt)
FILE *f = fopen(buf, "w");
if (f == NULL) {
- tst_report(0, "Failed to create file 'test'");
- return TST_INTERR;
+ tst_err("Failed to create file 'test': %s", strerror(errno));
+ return TST_UNTESTED;
}
fclose(f);
if (chmod(buf, 200)) {
- tst_report(0, "chmod failed: %s", strerror(errno));
- return TST_INTERR;
+ tst_err("chmod failed: %s", strerror(errno));
+ return TST_UNTESTED;
}
img = load(fmt, "test");
if (img != NULL) {
- tst_report(0, "Test succedded unexpectedly");
+ tst_msg("Test succedded unexpectedly");
return TST_FAILED;
}
if (errno == ENOSYS) {
- tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ tst_msg("Load %s: ENOSYS", strfmt(fmt));
return TST_SKIPPED;
}
if (errno != EACCES) {
- tst_report(0, "Expected errno = EACCES, have %s",
+ tst_msg("Expected errno = EACCES, have %s",
strerror(errno));
return TST_FAILED;
}
@@ -265,8 +264,8 @@ static int load_eio(enum fmt fmt)
FILE *f = fopen(buf, "w");
if (f == NULL) {
- tst_report(0, "Failed to create file 'test'");
- return TST_INTERR;
+ tst_err("Failed to create file 'test': %s", strerror(errno));
+ return TST_UNTESTED;
}
fclose(f);
@@ -274,17 +273,17 @@ static int load_eio(enum fmt fmt)
img = load(fmt, "test");
if (img != NULL) {
- tst_report(0, "Test succedded unexpectedly");
+ tst_msg("Test succedded unexpectedly");
return TST_FAILED;
}
if (errno == ENOSYS) {
- tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ tst_msg("Load %s: ENOSYS", strfmt(fmt));
return TST_SKIPPED;
}
if (errno != EIO) {
- tst_report(0, "Expected errno = EIO, have %s",
+ tst_msg("Expected errno = EIO, have %s",
strerror(errno));
return TST_FAILED;
}
@@ -330,17 +329,17 @@ static int test_PNG_Save_abort(void)
GP_ProgressCallback callback = {.callback = abort_callback};
if (GP_SavePNG(img, "test.png", &callback) == 0) {
- tst_report(0, "Failed to save PNG saving");
+ tst_msg("Failed to save PNG saving");
return TST_FAILED;
}
if (errno == ENOSYS) {
- tst_report(0, "Load PNG: ENOSYS");
+ tst_msg("Load PNG: ENOSYS");
return TST_SKIPPED;
}
if (errno != ECANCELED) {
- tst_report(0, "Expected errno = ECANCELED, have %s",
+ tst_msg("Expected errno = ECANCELED, have %s",
strerror(errno));
return TST_FAILED;
}
@@ -359,11 +358,11 @@ static int test_PNG_Load_abort(void)
if (GP_SavePNG(img, "test.png", NULL)) {
if (errno == ENOSYS) {
- tst_report(0, "Save PNG: ENOSYS");
+ tst_msg("Save PNG: ENOSYS");
return TST_SKIPPED;
}
- tst_report(0, "Failed to save PNG: %s", strerror(errno));
+ tst_msg("Failed to save PNG: %s", strerror(errno));
return TST_FAILED;
}
@@ -376,12 +375,12 @@ static int test_PNG_Load_abort(void)
int saved_errno = errno;
if (img != NULL) {
- tst_report(0, "Failed to abort PNG loading");
+ tst_msg("Failed to abort PNG loading");
return TST_FAILED;
}
if (saved_errno != ECANCELED) {
- tst_report(0, "Expected errno = ECANCELED, have %s",
+ tst_msg("Expected errno = ECANCELED, have %s",
strerror(saved_errno));
return TST_FAILED;
}
@@ -458,25 +457,25 @@ static int test_Load(void)
int saved_errno = errno;
if (ret != NULL) {
- tst_report(0, "GP_LoadImage('%s') succeeded "
- "unexpectedly", file_testcases[i].filename);
+ tst_msg("GP_LoadImage('%s') succeeded unexpectedly",
+ file_testcases[i].filename);
fail++;
continue;
}
if (file_testcases[i].expected_errno != ENOSYS && errno == ENOSYS) {
- tst_report(0, "Load Image '%s': ENOSYS",
- file_testcases[i].filename);
+ tst_msg("Load Image '%s': ENOSYS",
+ file_testcases[i].filename);
continue;
}
if (file_testcases[i].expected_errno != errno) {
- tst_report(0, "Expected errno %i (%s) got %i (%s) on '%s'",
- file_testcases[i].expected_errno,
- strerror(file_testcases[i].expected_errno),
- saved_errno,
- strerror(saved_errno),
- file_testcases[i].filename);
+ tst_msg("Expected errno %i (%s) got %i (%s) on '%s'",
+ file_testcases[i].expected_errno,
+ strerror(file_testcases[i].expected_errno),
+ saved_errno,
+ strerror(saved_errno),
+ file_testcases[i].filename);
fail++;
continue;
}
@@ -502,10 +501,10 @@ static int test_load_BMP(const char *path)
if (img == NULL) {
switch (errno) {
case ENOSYS:
- tst_report(0, "Not Implemented");
+ tst_msg("Not Implemented");
return TST_SKIPPED;
default:
- tst_report(0, "Got %s", strerror(errno));
+ tst_msg("Got %s", strerror(errno));
return TST_FAILED;
}
}
@@ -570,10 +569,10 @@ static int test_load_PNG(const char *path)
if (img == NULL) {
switch (errno) {
case ENOSYS:
- tst_report(0, "Not Implemented");
+ tst_msg("Not Implemented");
return TST_SKIPPED;
default:
- tst_report(0, "Got %s", strerror(errno));
+ tst_msg("Got %s", strerror(errno));
return TST_FAILED;
}
}
@@ -605,10 +604,10 @@ static int test_load_JPEG(const char *path)
if (img == NULL) {
switch (errno) {
case ENOSYS:
- tst_report(0, "Not Implemented");
+ tst_msg("Not Implemented");
return TST_SKIPPED;
default:
- tst_report(0, "Got %s", strerror(errno));
+ tst_msg("Got %s", strerror(errno));
return TST_FAILED;
}
}
http://repo.or.cz/w/gfxprim.git/commit/6bb7181dfe0c836adde74679982b8e66584d…
commit 6bb7181dfe0c836adde74679982b8e66584d4c29
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Nov 2 15:30:34 2012 +0100
tests: framework: Propagate tst_warn() from child.
This has been broken for quite some time.
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index d208b66..889cc45 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -43,6 +43,11 @@
*/
static struct tst_job *my_job = NULL;
+static int in_child(void)
+{
+ return my_job != NULL;
+}
+
static void start_test(struct tst_job *job)
{
(void)job;
@@ -271,15 +276,12 @@ static void child_write(struct tst_job *job, char ch, void *ptr, ssize_t size)
}
}
-int tst_report(int level, const char *fmt, ...)
+static int tst_vreport(int level, const char *fmt, va_list va)
{
- va_list va;
int ret;
char buf[258];
- va_start(va, fmt);
ret = vsnprintf(buf+3, sizeof(buf) - 3, fmt, va);
- va_end(va);
ssize_t size = ret > 255 ? 255 : ret + 1;
@@ -287,9 +289,41 @@ int tst_report(int level, const char *fmt, ...)
buf[1] = level;
((unsigned char*)buf)[2] = size;
- if (my_job != NULL)
+ if (in_child()) {
if (write(my_job->pipefd, buf, size + 3) != size + 3)
tst_warn("Failed to write msg to pipe.");
+ } else {
+ tst_warn("tst_report() called from parent, msg: '%s'",
+ buf + 3);
+ }
+
+ return ret;
+}
+
+int tst_report(int level, const char *fmt, ...)
+{
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+ ret = tst_vreport(level, fmt, va);
+ va_end(va);
+
+ return ret;
+}
+
+int tst_warn(const char *fmt, ...)
+{
+ va_list va;
+ int ret;
+
+ va_start(va, fmt);
+
+ if (in_child())
+ return tst_vreport(-1, fmt, va);
+
+ ret = vfprintf(stderr, fmt, va);
+ va_end(va);
return ret;
}
@@ -403,11 +437,11 @@ void tst_job_run(struct tst_job *job)
}
/* Redirect stderr/stdout TODO: catch its output */
- if (freopen("/dev/null", "w", stderr))
+ if (freopen("/dev/null", "w", stderr) == NULL)
tst_warn("freopen(stderr) failed: %s", strerror(errno));
- if (freopen("/dev/null", "w", stdout))
- tst_warn("freopen(stderr) failed: %s", strerror(errno));
+ if (freopen("/dev/null", "w", stdout) == NULL)
+ tst_warn("freopen(stdout) failed: %s", strerror(errno));
/* Create directory in /tmp/ and chdir into it. */
if (job->test->flags & TST_TMPDIR)
diff --git a/tests/framework/tst_test.c b/tests/framework/tst_test.c
index 4df0ef1..62666da 100644
--- a/tests/framework/tst_test.c
+++ b/tests/framework/tst_test.c
@@ -31,18 +31,6 @@
#include "tst_job.h"
#include "tst_test.h"
-int tst_warn(const char *fmt, ...)
-{
- va_list va;
- int ret;
-
- va_start(va, fmt);
- ret = vfprintf(stderr, fmt, va);
- va_end(va);
-
- return ret;
-}
-
static int run_test(const struct tst_test *test, FILE *html, FILE *json)
{
struct tst_job job;
-----------------------------------------------------------------------
Summary of changes:
tests/core/Context.c | 23 ++++----
tests/core/GetPutPixel.gen.c.t | 12 ++--
tests/core/WritePixel_testsuite.gen.c.t | 4 +-
tests/filters/LinearConvolution.c | 4 +-
tests/framework/test.c | 42 +++++++++-----
tests/framework/tst_job.c | 85 +++++++++++++++++++++++++---
tests/framework/tst_msg.c | 16 +++++-
tests/framework/tst_test.c | 12 ----
tests/framework/tst_test.h | 21 +++++++-
tests/gfx/Circle.c | 4 +-
tests/gfx/CircleSeg.c | 4 +-
tests/gfx/Line.c | 24 +++++++-
tests/gfx/gfx_benchmark.c | 8 +-
tests/loaders/loaders_suite.c | 95 +++++++++++++++----------------
14 files changed, 238 insertions(+), 116 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