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: 8caa76a32fdad0cc36b1a4ac6038b205f17b504e
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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
discards 7a5c61ef4059b02a846cdce2e19943dd1150d261 (commit)
via 8caa76a32fdad0cc36b1a4ac6038b205f17b504e (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (7a5c61ef4059b02a846cdce2e19943dd1150d261)
N -- N -- N (8caa76a32fdad0cc36b1a4ac6038b205f17b504e)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/8caa76a32fdad0cc36b1a4ac6038b205f17b…
commit 8caa76a32fdad0cc36b1a4ac6038b205f17b504e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 20:07:08 2012 +0200
tests: loaders: Make use of some bmp images.
diff --git a/tests/Makefile b/tests/Makefile
index f4fc735..6181430 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,5 +5,6 @@ SUBDIRS=core SDL drivers framework loaders gfx
loaders: framework
gfx: framework
+core: framework
include $(TOPDIR)/post.mk
diff --git a/tests/loaders/Makefile b/tests/loaders/Makefile
index 8fb8b15..f076cd7 100644
--- a/tests/loaders/Makefile
+++ b/tests/loaders/Makefile
@@ -12,7 +12,7 @@ APPS=loaders_suite
$(APPS): ../framework/libtst.a
-CLEAN+=libtst_preload.so log.html log.json
+CLEAN+=log.html log.json
include $(TOPDIR)/app.mk
include $(TOPDIR)/post.mk
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index aa2fa92..de84a8e 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -493,6 +493,74 @@ static int test_Load(void)
return TST_SKIPPED;
}
+static int test_load_BMP(const char *path)
+{
+ GP_Context *img;
+
+ img = GP_LoadBMP(path, NULL);
+
+ if (img == NULL) {
+ switch (errno) {
+ case ENOSYS:
+ tst_report(0, "Not Implemented");
+ return TST_SKIPPED;
+ default:
+ tst_report(0, "Got %s", strerror(errno));
+ return TST_FAILED;
+ }
+ }
+
+ /*
+ * TODO: check correct data.
+ */
+
+ GP_ContextFree(img);
+
+ return TST_SUCCESS;
+}
+
+/* Basic loading tests */
+
+static int test_load_BMP_1bpp_1x1(void)
+{
+ return test_load_BMP("1bpp-1x1.bmp");
+}
+
+static int test_load_BMP_4bpp_1x1(void)
+{
+ return test_load_BMP("4bpp-1x1.bmp");
+}
+
+static int test_load_BMP_8bpp_1x1(void)
+{
+ return test_load_BMP("8bpp-1x1.bmp");
+}
+
+static int test_load_BMP_24bpp_1x1(void)
+{
+ return test_load_BMP("24bpp-1x1.bmp");
+}
+
+static int test_load_BMP_32bpp_1x1(void)
+{
+ return test_load_BMP("32bpp-1x1.bmp");
+}
+
+static int test_load_BMP_555_1x1(void)
+{
+ return test_load_BMP("555-1x1.bmp");
+}
+
+static int test_load_BMP_565_1x1(void)
+{
+ return test_load_BMP("565-1x1.bmp");
+}
+
+static int test_load_BMP_8bpp_1x64000(void)
+{
+ return test_load_BMP("8bpp-1x64000.bmp");
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Image Loaders testsuite",
.tests = {
@@ -545,7 +613,32 @@ const struct tst_suite tst_suite = {
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "JPG Stress", .tst_fn = test_JPG_stress,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
+
+ /* BPM loader tests */
+ {.name = "BMP Load 1bpp 1x1", .tst_fn = test_load_BMP_1bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/1bpp-1x1.bmp"},
+
+ {.name = "BMP Load 4bpp 1x1", .tst_fn = test_load_BMP_4bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/4bpp-1x1.bmp"},
+ {.name = "BMP Load 8bpp 1x1", .tst_fn = test_load_BMP_8bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/8bpp-1x1.bmp"},
+
+ {.name = "BMP 24bpp 1x1", .tst_fn = test_load_BMP_24bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/24bpp-1x1.bmp"},
+
+ {.name = "BMP 32bpp 1x1", .tst_fn = test_load_BMP_32bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/32bpp-1x1.bmp"},
+
+ {.name = "BMP 555 1x1", .tst_fn = test_load_BMP_555_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/555-1x1.bmp"},
+
+ {.name = "BMP 565 1x1", .tst_fn = test_load_BMP_565_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/565-1x1.bmp"},
+
+ {.name = "BMP 8bpp 1x64000", .tst_fn = test_load_BMP_8bpp_1x64000,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/bitmaps/valid/8bpp-1x64000.bmp"},
+
{.name = NULL},
}
};
-----------------------------------------------------------------------
Summary of changes:
tests/loaders/loaders_suite.c | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
[repo.or.cz] gfxprim.git branch master updated: 7a5c61ef4059b02a846cdce2e19943dd1150d261
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 7a5c61ef4059b02a846cdce2e19943dd1150d261 (commit)
via b27ea6e7962b7a22dbd9fdf48e9ffe2358c88097 (commit)
from d20862dc07b9b8858ca929d9b91caa1eb6d88bbc (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/7a5c61ef4059b02a846cdce2e19943dd1150…
commit 7a5c61ef4059b02a846cdce2e19943dd1150d261
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 20:07:08 2012 +0200
tests: loaders: Make use of some bmp images.
diff --git a/tests/Makefile b/tests/Makefile
index f4fc735..6181430 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,5 +5,6 @@ SUBDIRS=core SDL drivers framework loaders gfx
loaders: framework
gfx: framework
+core: framework
include $(TOPDIR)/post.mk
diff --git a/tests/loaders/Makefile b/tests/loaders/Makefile
index 8fb8b15..f076cd7 100644
--- a/tests/loaders/Makefile
+++ b/tests/loaders/Makefile
@@ -12,7 +12,7 @@ APPS=loaders_suite
$(APPS): ../framework/libtst.a
-CLEAN+=libtst_preload.so log.html log.json
+CLEAN+=log.html log.json
include $(TOPDIR)/app.mk
include $(TOPDIR)/post.mk
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index aa2fa92..41ab097 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -493,6 +493,74 @@ static int test_Load(void)
return TST_SKIPPED;
}
+static int test_load_BMP(const char *path)
+{
+ GP_Context *img;
+
+ img = GP_LoadBMP(path, NULL);
+
+ if (img == NULL) {
+ switch (errno) {
+ case ENOSYS:
+ tst_report(0, "Not Implemented");
+ return TST_SKIPPED;
+ default:
+ tst_report(0, "Got %s", strerror(errno));
+ return TST_FAILED;
+ }
+ }
+
+ /*
+ * TODO: check correct data.
+ */
+
+ GP_ContextFree(img);
+
+ return TST_SUCCESS;
+}
+
+/* Basic loading tests */
+
+static int test_load_BMP_1bpp_1x1(void)
+{
+ return test_load_BMP("1bpp-1x1.bmp");
+}
+
+static int test_load_BMP_4bpp_1x1(void)
+{
+ return test_load_BMP("4bpp-1x1.bmp");
+}
+
+static int test_load_BMP_8bpp_1x1(void)
+{
+ return test_load_BMP("8bpp-1x1.bmp");
+}
+
+static int test_load_BMP_24bpp_1x1(void)
+{
+ return test_load_BMP("24bpp-1x1.bmp");
+}
+
+static int test_load_BMP_32bpp_1x1(void)
+{
+ return test_load_BMP("32bpp-1x1.bmp");
+}
+
+static int test_load_BMP_555_1x1(void)
+{
+ return test_load_BMP("555-1x1.bmp");
+}
+
+static int test_load_BMP_565_1x1(void)
+{
+ return test_load_BMP("565-1x1.bmp");
+}
+
+static int test_load_BMP_8bpp_1x64000(void)
+{
+ return test_load_BMP("8bpp-1x64000.bmp");
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Image Loaders testsuite",
.tests = {
@@ -545,7 +613,32 @@ const struct tst_suite tst_suite = {
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "JPG Stress", .tst_fn = test_JPG_stress,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
+
+ /* BPM loader tests */
+ {.name = "BMP Load 1bpp 1x1", .tst_fn = test_load_BMP_1bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/1bpp-1x1.bmp"},
+
+ {.name = "BMP Load 4bpp 1x1", .tst_fn = test_load_BMP_4bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/4bpp-1x1.bmp"},
+ {.name = "BMP Load 8bpp 1x1", .tst_fn = test_load_BMP_8bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/8bpp-1x1.bmp"},
+
+ {.name = "BMP 24bpp 1x1", .tst_fn = test_load_BMP_24bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/24bpp-1x1.bmp"},
+
+ {.name = "BMP 32bpp 1x1", .tst_fn = test_load_BMP_32bpp_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/32bpp-1x1.bmp"},
+
+ {.name = "BMP 555 1x1", .tst_fn = test_load_BMP_555_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/555-1x1.bmp"},
+
+ {.name = "BMP 565 1x1", .tst_fn = test_load_BMP_565_1x1,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/565-1x1.bmp"},
+
+ {.name = "BMP 8bpp 1x64000", .tst_fn = test_load_BMP_8bpp_1x64000,
+ .flags = TST_TMPDIR, .res_path = "data/bmp/valid/8bpp-1x64000.bmp"},
+
{.name = NULL},
}
};
http://repo.or.cz/w/gfxprim.git/commit/b27ea6e7962b7a22dbd9fdf48e9ffe2358c8…
commit b27ea6e7962b7a22dbd9fdf48e9ffe2358c88097
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 20:06:10 2012 +0200
tests: loaders: Add generator + bmp images.
diff --git a/tests/loaders/data/bmp/README b/tests/loaders/data/bmp/README
new file mode 100644
index 0000000..470df6a
--- /dev/null
+++ b/tests/loaders/data/bmp/README
@@ -0,0 +1,4 @@
+Run the script to regenerate bitmaps.
+
+The script is not python 3 ready
+(although I've fixed most of the problems)
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-no-palette.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-no-palette.bmp
new file mode 100644
index 0000000..24f46bd
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-no-palette.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-pixeldata-cropped.bmp
new file mode 100644
index 0000000..488bd4e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/1bpp-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/24bpp-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/24bpp-pixeldata-cropped.bmp
new file mode 100644
index 0000000..248bef4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/24bpp-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/32bpp-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/32bpp-pixeldata-cropped.bmp
new file mode 100644
index 0000000..11a37e0
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/32bpp-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-no-palette.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-no-palette.bmp
new file mode 100644
index 0000000..667ee63
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-no-palette.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-pixeldata-cropped.bmp
new file mode 100644
index 0000000..ffa50ae
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/4bpp-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/555-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/555-pixeldata-cropped.bmp
new file mode 100644
index 0000000..2d08d35
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/555-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-large.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-large.bmp
new file mode 100644
index 0000000..249c090
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-negative.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-negative.bmp
new file mode 100644
index 0000000..1dfe0e9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-large.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-large.bmp
new file mode 100644
index 0000000..2a3195b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-negative.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-negative.bmp
new file mode 100644
index 0000000..f8e0fab
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-no-palette.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-no-palette.bmp
new file mode 100644
index 0000000..e8eafa4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-no-palette.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-pixeldata-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-pixeldata-cropped.bmp
new file mode 100644
index 0000000..5fcdcba
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/8bpp-pixeldata-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-large.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-large.bmp
new file mode 100644
index 0000000..3e4777f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-odd.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-odd.bmp
new file mode 100644
index 0000000..912c845
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-odd.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-zero.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-zero.bmp
new file mode 100644
index 0000000..fa9a92a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-cropped.bmp
new file mode 100644
index 0000000..c11133c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-missing.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-missing.bmp
new file mode 100644
index 0000000..228c5c9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/colormasks-missing.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle4-for-8bpp.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle4-for-8bpp.bmp
new file mode 100644
index 0000000..045b861
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle4-for-8bpp.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle8-for-4bpp.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle8-for-4bpp.bmp
new file mode 100644
index 0000000..03d4cb7
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle8-for-4bpp.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/compression-unknown.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/compression-unknown.bmp
new file mode 100644
index 0000000..3465800
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/compression-unknown.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/emptyfile.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/emptyfile.bmp
new file mode 100644
index 0000000..e69de29
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/fileinfoheader-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/fileinfoheader-cropped.bmp
new file mode 100644
index 0000000..f7ff95e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/fileinfoheader-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/height-zero.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/height-zero.bmp
new file mode 100644
index 0000000..b07834b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/height-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/index.html b/tests/loaders/data/bmp/bitmaps/corrupt/index.html
new file mode 100644
index 0000000..e42e718
--- /dev/null
+++ b/tests/loaders/data/bmp/bitmaps/corrupt/index.html
@@ -0,0 +1,444 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Directory Listing</title>
+ </head>
+ <body>
+ <table border="1">
+
+ <tr>
+ <th>Filename</th>
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-no-palette.bmp">1bpp-no-palette.bmp</a></td>
+ <td>
+ A bitmap that has 1 bit per pixel and no palette.
+ This is technically invalid, but a bitmap processor could default to black and white.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-pixeldata-cropped.bmp">1bpp-pixeldata-cropped.bmp</a></td>
+ <td>
+ A 1 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-pixeldata-cropped.bmp">24bpp-pixeldata-cropped.bmp</a></td>
+ <td>
+ A 24 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-pixeldata-cropped.bmp">32bpp-pixeldata-cropped.bmp</a></td>
+ <td>
+ A 32 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-no-palette.bmp">4bpp-no-palette.bmp</a></td>
+ <td>
+ A bitmap that has 4 bit per pixel and no palette.
+ This is an invalid bitmap, but a bitmap processor could use default colors.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-pixeldata-cropped.bmp">4bpp-pixeldata-cropped.bmp</a></td>
+ <td>
+ An 4 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="555-pixeldata-cropped.bmp">555-pixeldata-cropped.bmp</a></td>
+ <td>
+ A 5-5-5 16 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsimportant-large.bmp">8bpp-colorsimportant-large.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with five colors, but a very large 'biColorsImportant' field.
+ This is invalid--biColorsImportant shouldn't exceed biColorsUsed.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsimportant-negative.bmp">8bpp-colorsimportant-negative.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a negative 'biColorsImportant' field.
+ This is invalid--biColorsImportant can't be below 0.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsused-large.bmp">8bpp-colorsused-large.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a very large 'biColorsUsed' field.
+ This is invalid--biColorsImportant shouldn't exceed 256.
+ This attempts to trick the bitmap processor into accessing invalid memory.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsused-negative.bmp">8bpp-colorsused-negative.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a negative 'biColorsUsed' field.
+ This is invalid--biColorsImportant can't be below 0.
+ This attempts to trick the bitmap processor into accessing invalid memory.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-no-palette.bmp">8bpp-no-palette.bmp</a></td>
+ <td>
+ A bitmap that has 8 bits per pixel and no palette.
+ This is an invalid bitmap, but a bitmap processor could use default colors.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-pixeldata-cropped.bmp">8bpp-pixeldata-cropped.bmp</a></td>
+ <td>
+ An 8 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="bitdepth-large.bmp">bitdepth-large.bmp</a></td>
+ <td>
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is very large.
+ This attempts to trick the bitmap processor into thinking the bit depth is negative.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="bitdepth-odd.bmp">bitdepth-odd.bmp</a></td>
+ <td>
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is odd.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="bitdepth-zero.bmp">bitdepth-zero.bmp</a></td>
+ <td>
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is 0.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="colormasks-cropped.bmp">colormasks-cropped.bmp</a></td>
+ <td>
+ A BI_BITFIELDS bitmap that is one byte short of having a complete
+ colormask array.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="colormasks-missing.bmp">colormasks-missing.bmp</a></td>
+ <td>
+ A BI_BITFIELDS bitmap file that is so short that it doesn't include the
+ colormask array.
+ This tests that what happens when a call to fread() fails.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="compression-bad-rle4-for-8bpp.bmp">compression-bad-rle4-for-8bpp.bmp</a></td>
+ <td>
+ A 4 bpp bitmap with a 'biCompression' field of BI_RLE8.
+ Only 8 bpp bitmaps may use BI_RLE8.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="compression-bad-rle8-for-4bpp.bmp">compression-bad-rle8-for-4bpp.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a 'biCompression' field of BI_RLE4.
+ Only 4 bpp bitmaps may use BI_RLE4.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="compression-unknown.bmp">compression-unknown.bmp</a></td>
+ <td>
+ A bitmap with an unrecognized 'biCompression' field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="emptyfile.bmp">emptyfile.bmp</a></td>
+ <td>
+ A zero-byte file.
+ This tests that what happens when the first call to fread() fails.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="fileinfoheader-cropped.bmp">fileinfoheader-cropped.bmp</a></td>
+ <td>
+ A bitmap that is one byte short of having a complete fileinfoheader.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="height-zero.bmp">height-zero.bmp</a></td>
+ <td>
+ A bitmap with a 'biHeight' field in its BMPINFOHEADER that is 0.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="infoheader-cropped.bmp">infoheader-cropped.bmp</a></td>
+ <td>
+ A bitmap that is one byte short of having a complete BITMAPINFOHEADER.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="infoheader-missing.bmp">infoheader-missing.bmp</a></td>
+ <td>
+ A bitmap file that is so short that it doesn't include a BITMAPINFOHEADER.
+ This tests that what happens when a call to fread() fails.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="infoheadersize-large.bmp">infoheadersize-large.bmp</a></td>
+ <td>
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is too large.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="infoheadersize-small.bmp">infoheadersize-small.bmp</a></td>
+ <td>
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is too small.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="infoheadersize-zero.bmp">infoheadersize-zero.bmp</a></td>
+ <td>
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is 0.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="magicnumber-bad.bmp">magicnumber-bad.bmp</a></td>
+ <td>
+ A bitmap with an invalid magic number (it uses 'Bm' instead of 'BM')
+ A bitmap processor that ignores this field is probably trusting the file extension
+ or doing a case-insensitive compare.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="magicnumber-cropped.bmp">magicnumber-cropped.bmp</a></td>
+ <td>
+ A one byte bitmap that only contains the 'B' of the magic number.
+ This tests that what happens when the first call to fread() returns
+ fewer bytes than expected.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="offbits-large.bmp">offbits-large.bmp</a></td>
+ <td>
+ A bitmap with an 'dwOffBits' field that is larger than the file size.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="offbits-negative.bmp">offbits-negative.bmp</a></td>
+ <td>
+ A bitmap with an 'dwOffBits' field that is -1.
+ This is supposed to be interpreted as an unsigned value, so it will
+ either be understood as a very large (illegal) value,
+ or a negative value (also illegal).
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="offbits-zero.bmp">offbits-zero.bmp</a></td>
+ <td>
+ A bitmap with an 'dwOffBits' field that is 0.
+ A bitmap processor may recover from this by assuming that the pixel data
+ immediately follows the palette.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="palette-cropped.bmp">palette-cropped.bmp</a></td>
+ <td>
+ A bitmap that is one byte short of having a complete palette.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="palette-missing.bmp">palette-missing.bmp</a></td>
+ <td>
+ A bitmap file that is so short that it doesn't include the palette.
+ This tests that what happens when a call to fread() fails.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="palette-too-big.bmp">palette-too-big.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel that has a palette with 5000 colors.</td>
+ </tr>
+
+ <tr>
+ <td><a href="pixeldata-missing.bmp">pixeldata-missing.bmp</a></td>
+ <td>
+ A bitmap file that doesn't include any of the pixel data.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-absolute-cropped.bmp">rle4-absolute-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ The pixel data ends prematurely--in the middle of an absolute
+ escape sequence.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-delta-cropped.bmp">rle4-delta-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ The file ends in the middle of a delta escape.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-no-end-of-line-marker.bmp">rle4-no-end-of-line-marker.bmp</a></td>
+ <td>
+ An RLE4 compressed bitmap with no end-of-line sequences.
+ It is unclear if a bitmap processor should implicitly add
+ end-of-line markers when the pixel run the row's width,
+ or if it should ignore all pixel data beyond the row's width.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-runlength-cropped.bmp">rle4-runlength-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The pixel data ends prematurely--in the middle of an encoded
+ escape sequence.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-absolute-cropped.bmp">rle8-absolute-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ The pixel data ends prematurely--in the middle of an absolute
+ escape sequence.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-delta-cropped.bmp">rle8-delta-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ The file ends in the middle of a delta escape.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-deltaleavesimage.bmp">rle8-deltaleavesimage.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap contains 'delta' escape sequences the leave the image.
+ The intent is to trick the processor into accessing invalid memory.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-no-end-of-line-marker.bmp">rle8-no-end-of-line-marker.bmp</a></td>
+ <td>
+ An RLE8 compressed bitmap with no end-of-line sequences.
+ It is unclear if a bitmap processor should implicitly add
+ end-of-line markers when the pixel run the row's width,
+ or if it should ignore all pixel data beyond the row's width.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-runlength-cropped.bmp">rle8-runlength-cropped.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The pixel data ends prematurely--in the middle of an encoded
+ escape sequence.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="width-negative.bmp">width-negative.bmp</a></td>
+ <td>
+ A bitmap with a negative 'biWidth' field in its BMPINFOHEADER.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="width-times-height-overflow.bmp">width-times-height-overflow.bmp</a></td>
+ <td>
+ A bitmap whose reported width and height cause a 32bit overflow when
+ they are multiplied together.
+ This tries to trick the image processor into allocating a very small
+ buffer that it thinks is very large.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="width-zero.bmp">width-zero.bmp</a></td>
+ <td>
+ A bitmap with a 'biWidth' field in its BMPINFOHEADER that is 0.
+ </td>
+ </tr>
+
+ </table>
+ </body>
+</html>
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-cropped.bmp
new file mode 100644
index 0000000..2b35780
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-missing.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-missing.bmp
new file mode 100644
index 0000000..bcd3d00
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/infoheader-missing.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-large.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-large.bmp
new file mode 100644
index 0000000..80a3892
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-small.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-small.bmp
new file mode 100644
index 0000000..f5186f9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-small.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-zero.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-zero.bmp
new file mode 100644
index 0000000..bdbcd45
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-bad.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-bad.bmp
new file mode 100644
index 0000000..82c0cde
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-bad.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-cropped.bmp
new file mode 100644
index 0000000..7371f47
--- /dev/null
+++ b/tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-cropped.bmp
@@ -0,0 +1 @@
+B
No newline at end of file
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/offbits-large.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-large.bmp
new file mode 100644
index 0000000..431701e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/offbits-negative.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-negative.bmp
new file mode 100644
index 0000000..26c9a79
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/offbits-zero.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-zero.bmp
new file mode 100644
index 0000000..4e05c3e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/offbits-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/palette-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/palette-cropped.bmp
new file mode 100644
index 0000000..6ae6b13
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/palette-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/palette-missing.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/palette-missing.bmp
new file mode 100644
index 0000000..e3e73b1
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/palette-missing.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/palette-too-big.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/palette-too-big.bmp
new file mode 100644
index 0000000..d04a3d3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/palette-too-big.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/pixeldata-missing.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/pixeldata-missing.bmp
new file mode 100644
index 0000000..159289f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/pixeldata-missing.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle4-absolute-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-absolute-cropped.bmp
new file mode 100644
index 0000000..4fdfd9b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-absolute-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle4-delta-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-delta-cropped.bmp
new file mode 100644
index 0000000..9eefe97
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-delta-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle4-no-end-of-line-marker.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-no-end-of-line-marker.bmp
new file mode 100644
index 0000000..dc3e4d9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-no-end-of-line-marker.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle4-runlength-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-runlength-cropped.bmp
new file mode 100644
index 0000000..f68d342
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle4-runlength-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle8-absolute-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-absolute-cropped.bmp
new file mode 100644
index 0000000..1776407
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-absolute-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle8-delta-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-delta-cropped.bmp
new file mode 100644
index 0000000..273cb20
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-delta-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle8-deltaleavesimage.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-deltaleavesimage.bmp
new file mode 100644
index 0000000..b531946
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-deltaleavesimage.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle8-no-end-of-line-marker.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-no-end-of-line-marker.bmp
new file mode 100644
index 0000000..f6eab23
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-no-end-of-line-marker.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/rle8-runlength-cropped.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-runlength-cropped.bmp
new file mode 100644
index 0000000..4db7a93
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/rle8-runlength-cropped.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/width-negative.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/width-negative.bmp
new file mode 100644
index 0000000..044b647
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/width-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/width-times-height-overflow.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/width-times-height-overflow.bmp
new file mode 100644
index 0000000..c4775d9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/width-times-height-overflow.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/corrupt/width-zero.bmp b/tests/loaders/data/bmp/bitmaps/corrupt/width-zero.bmp
new file mode 100644
index 0000000..2e8cb8a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/corrupt/width-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x0.bmp b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x0.bmp
new file mode 100644
index 0000000..9e59a47
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x0.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x240.bmp b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x240.bmp
new file mode 100644
index 0000000..ee541ee
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/32bpp-320x0.bmp b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-320x0.bmp
new file mode 100644
index 0000000..522dfc3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/32bpp-320x0.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/8bpp-pixels-not-in-palette.bmp b/tests/loaders/data/bmp/bitmaps/questionable/8bpp-pixels-not-in-palette.bmp
new file mode 100644
index 0000000..63cc2a3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/8bpp-pixels-not-in-palette.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/filesize-bad.bmp b/tests/loaders/data/bmp/bitmaps/questionable/filesize-bad.bmp
new file mode 100644
index 0000000..610a910
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/filesize-bad.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/filesize-zero.bmp b/tests/loaders/data/bmp/bitmaps/questionable/filesize-zero.bmp
new file mode 100644
index 0000000..cfad0ff
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/filesize-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/index.html b/tests/loaders/data/bmp/bitmaps/questionable/index.html
new file mode 100644
index 0000000..536805f
--- /dev/null
+++ b/tests/loaders/data/bmp/bitmaps/questionable/index.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Directory Listing</title>
+ </head>
+ <body>
+ <table border="1">
+
+ <tr>
+ <th>Filename</th>
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-0x0.bmp">32bpp-0x0.bmp</a></td>
+ <td>A bitmap that is 32 bpp uncompressed RGB. The image is 0 pixels wide and 0 pixels high. Even though this is technically valid, most bitmap procesors consider it to be corrupt.</td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-0x240.bmp">32bpp-0x240.bmp</a></td>
+ <td>A bitmap that is 32 bpp uncompressed RGB. The image is 0 pixels wide and 240 pixels high. This is a sneaky way of making a 0x0 bitmap. Even though this is technically valid, most bitmap procesors consider it to be corrupt.</td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-320x0.bmp">32bpp-320x0.bmp</a></td>
+ <td>A bitmap that is 32 bpp uncompressed RGB. The image is 320 pixels wide and zero pixels high. This is a sneaky way of making a 0x0 bitmap. Even though this is technically valid, most bitmap procesors consider it to be corrupt.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-pixels-not-in-palette.bmp">8bpp-pixels-not-in-palette.bmp</a></td>
+ <td>
+ A bitmap that is 8 bits per pixel uncompressed RGB.
+ Many of the pixels are indexes that don't exist in the palette.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="filesize-bad.bmp">filesize-bad.bmp</a></td>
+ <td>
+ A bitmap with a filesize that's half of what it should be.
+ Most bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="filesize-zero.bmp">filesize-zero.bmp</a></td>
+ <td>
+ A bitmap with an filesize of 0.
+ Most bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-x-large.bmp">pels-per-meter-x-large.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a large 'biXPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-x-negative.bmp">pels-per-meter-x-negative.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a negative 'biXPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-x-zero.bmp">pels-per-meter-x-zero.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a 'biXPelsPerMeter' field of 0.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-y-large.bmp">pels-per-meter-y-large.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a large 'biYPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-y-negative.bmp">pels-per-meter-y-negative.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a negative 'biYPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pels-per-meter-y-zero.bmp">pels-per-meter-y-zero.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a 'biYPelsPerMeter' field of 0.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pixeldata-rle8-toomuch.bmp">pixeldata-rle8-toomuch.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ It has twice as much data as it should.
+ Since the RLE8 format is mostly a series of drawing directives,
+ this tests that the RLE8 processor keeps memory access within
+ the size of the image.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="pixeldata-toomuch.bmp">pixeldata-toomuch.bmp</a></td>
+ <td>
+ A bitmap with twice as much payload as expected.
+ This attempts to overflow an internal buffer.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="planes-large.bmp">planes-large.bmp</a></td>
+ <td>
+ A bitmap with a 'biPlanes' field in its BMPINFOHEADER that is large.
+ This is an invalid bitmap, but many bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="planes-zero.bmp">planes-zero.bmp</a></td>
+ <td>
+ A bitmap with a 'biPlanes' field in its BMPINFOHEADER that is zero.
+ This is an invalid bitmap, but many bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="reserved1-bad.bmp">reserved1-bad.bmp</a></td>
+ <td>
+ A bitmap with an 'wReserved1' field that is not 0.
+ This is technically illegal, but most bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="reserved2-bad.bmp">reserved2-bad.bmp</a></td>
+ <td>
+ A bitmap with an 'wReserved2' field that is not 0.
+ This is technically illegal, but most bitmap processors ignore this field.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-height-negative.bmp">rle4-height-negative.bmp</a></td>
+ <td>
+ An RLE4 compressed bitmap with a negative height.
+ This is an illegal bitmap: top-down images cannot be compressed.
+ Still, many bitmap processors can understand it.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-no-end-of-bitmap-marker.bmp">rle4-no-end-of-bitmap-marker.bmp</a></td>
+ <td>
+ An RLE4 compressed bitmap with no end-of-bitmap sequence.
+ This is techinically invalid, but the bitmap processor should
+ be able to treat the end-of-file as an end-of-bitmap.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-height-negative.bmp">rle8-height-negative.bmp</a></td>
+ <td>
+ An RLE8 compressed bitmap with a negative height.
+ This is an illegal value: top-down images cannot be compressed.
+ However, many bitmap processors allow top-down compressed images.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-no-end-of-bitmap-marker.bmp">rle8-no-end-of-bitmap-marker.bmp</a></td>
+ <td>
+ An RLE8 compressed bitmap with no end-of-bitmap sequence.
+ This is techinically invalid, but the bitmap processor should
+ be able to treat the end-of-file as an end-of-bitmap.
+ </td>
+ </tr>
+
+ </table>
+ </body>
+</html>
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-large.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-large.bmp
new file mode 100644
index 0000000..bccf281
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-negative.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-negative.bmp
new file mode 100644
index 0000000..538c440
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-zero.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-zero.bmp
new file mode 100644
index 0000000..3818535
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-large.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-large.bmp
new file mode 100644
index 0000000..09fc3fb
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-negative.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-negative.bmp
new file mode 100644
index 0000000..4280173
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-zero.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-zero.bmp
new file mode 100644
index 0000000..7e2a5f4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-rle8-toomuch.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-rle8-toomuch.bmp
new file mode 100644
index 0000000..1590b53
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-rle8-toomuch.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-toomuch.bmp b/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-toomuch.bmp
new file mode 100644
index 0000000..33256c1
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/pixeldata-toomuch.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/planes-large.bmp b/tests/loaders/data/bmp/bitmaps/questionable/planes-large.bmp
new file mode 100644
index 0000000..2c9314e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/planes-large.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/planes-zero.bmp b/tests/loaders/data/bmp/bitmaps/questionable/planes-zero.bmp
new file mode 100644
index 0000000..4709c1a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/planes-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/reserved1-bad.bmp b/tests/loaders/data/bmp/bitmaps/questionable/reserved1-bad.bmp
new file mode 100644
index 0000000..7332e92
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/reserved1-bad.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/reserved2-bad.bmp b/tests/loaders/data/bmp/bitmaps/questionable/reserved2-bad.bmp
new file mode 100644
index 0000000..b3de5d8
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/reserved2-bad.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/rle4-height-negative.bmp b/tests/loaders/data/bmp/bitmaps/questionable/rle4-height-negative.bmp
new file mode 100644
index 0000000..2c8b2bf
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/rle4-height-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/rle4-no-end-of-bitmap-marker.bmp b/tests/loaders/data/bmp/bitmaps/questionable/rle4-no-end-of-bitmap-marker.bmp
new file mode 100644
index 0000000..6f0c703
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/rle4-no-end-of-bitmap-marker.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/rle8-height-negative.bmp b/tests/loaders/data/bmp/bitmaps/questionable/rle8-height-negative.bmp
new file mode 100644
index 0000000..4fec6ee
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/rle8-height-negative.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/questionable/rle8-no-end-of-bitmap-marker.bmp b/tests/loaders/data/bmp/bitmaps/questionable/rle8-no-end-of-bitmap-marker.bmp
new file mode 100644
index 0000000..fcc3a84
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/questionable/rle8-no-end-of-bitmap-marker.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-1x1.bmp
new file mode 100644
index 0000000..508b73c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-color.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-color.bmp
new file mode 100644
index 0000000..282498d
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-color.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-overlappingcolor.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-overlappingcolor.bmp
new file mode 100644
index 0000000..1b1fe08
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-overlappingcolor.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240.bmp
new file mode 100644
index 0000000..19ebb36
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-321x240.bmp
new file mode 100644
index 0000000..754c829
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-322x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-322x240.bmp
new file mode 100644
index 0000000..caedf4b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-322x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-323x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-323x240.bmp
new file mode 100644
index 0000000..4006075
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-323x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-324x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-324x240.bmp
new file mode 100644
index 0000000..d555e8b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-324x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-325x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-325x240.bmp
new file mode 100644
index 0000000..314eec2
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-325x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-326x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-326x240.bmp
new file mode 100644
index 0000000..4a077fe
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-326x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-327x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-327x240.bmp
new file mode 100644
index 0000000..18eed54
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-327x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-328x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-328x240.bmp
new file mode 100644
index 0000000..94c6fa4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-328x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-329x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-329x240.bmp
new file mode 100644
index 0000000..7486b3b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-329x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-330x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-330x240.bmp
new file mode 100644
index 0000000..cabb99f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-330x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-331x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-331x240.bmp
new file mode 100644
index 0000000..328e619
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-331x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-332x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-332x240.bmp
new file mode 100644
index 0000000..de3c493
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-332x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-333x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-333x240.bmp
new file mode 100644
index 0000000..a17ba37
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-333x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-334x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-334x240.bmp
new file mode 100644
index 0000000..c330ffc
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-334x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-335x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-335x240.bmp
new file mode 100644
index 0000000..457533c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-335x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/1bpp-topdown-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/1bpp-topdown-320x240.bmp
new file mode 100644
index 0000000..605f292
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/1bpp-topdown-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-1x1.bmp
new file mode 100644
index 0000000..fa6c104
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-320x240.bmp
new file mode 100644
index 0000000..9d4a983
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-321x240.bmp
new file mode 100644
index 0000000..9925d29
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-322x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-322x240.bmp
new file mode 100644
index 0000000..10616fe
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-322x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-323x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-323x240.bmp
new file mode 100644
index 0000000..c5138f4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-323x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-imagesize-zero.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-imagesize-zero.bmp
new file mode 100644
index 0000000..578eaf5
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-imagesize-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/24bpp-topdown-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/24bpp-topdown-320x240.bmp
new file mode 100644
index 0000000..b50375e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/24bpp-topdown-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-101110-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-101110-320x240.bmp
new file mode 100644
index 0000000..b75d4db
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-101110-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-1x1.bmp
new file mode 100644
index 0000000..d1b33e4
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-320x240.bmp
new file mode 100644
index 0000000..9b63573
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-888-optimalpalette-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-888-optimalpalette-320x240.bmp
new file mode 100644
index 0000000..77deadb
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-888-optimalpalette-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-optimalpalette-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-optimalpalette-320x240.bmp
new file mode 100644
index 0000000..4f5929a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-optimalpalette-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/32bpp-topdown-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/32bpp-topdown-320x240.bmp
new file mode 100644
index 0000000..e8a388c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/32bpp-topdown-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-1x1.bmp
new file mode 100644
index 0000000..edc72d8
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-320x240.bmp
new file mode 100644
index 0000000..9f95294
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-321x240.bmp
new file mode 100644
index 0000000..9afaa79
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-322x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-322x240.bmp
new file mode 100644
index 0000000..dc84792
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-322x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-323x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-323x240.bmp
new file mode 100644
index 0000000..158fcab
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-323x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-324x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-324x240.bmp
new file mode 100644
index 0000000..b5416d5
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-324x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-325x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-325x240.bmp
new file mode 100644
index 0000000..b768df9
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-325x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-326x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-326x240.bmp
new file mode 100644
index 0000000..1dd42b7
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-326x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-327x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-327x240.bmp
new file mode 100644
index 0000000..1bc4613
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-327x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/4bpp-topdown-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/4bpp-topdown-320x240.bmp
new file mode 100644
index 0000000..6ddbad0
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/4bpp-topdown-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/555-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/555-1x1.bmp
new file mode 100644
index 0000000..b85d03c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/555-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/555-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/555-320x240.bmp
new file mode 100644
index 0000000..3696dd3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/555-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/555-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/555-321x240.bmp
new file mode 100644
index 0000000..f03b839
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/555-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-1x1.bmp
new file mode 100644
index 0000000..cb669e3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-320x240-topdown.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-320x240-topdown.bmp
new file mode 100644
index 0000000..e12ab81
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-320x240-topdown.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-320x240.bmp
new file mode 100644
index 0000000..1ac488e
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-321x240-topdown.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-321x240-topdown.bmp
new file mode 100644
index 0000000..1b1d482
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-321x240-topdown.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-321x240.bmp
new file mode 100644
index 0000000..d60b99a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-322x240-topdown.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-322x240-topdown.bmp
new file mode 100644
index 0000000..060a969
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-322x240-topdown.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/565-322x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/565-322x240.bmp
new file mode 100644
index 0000000..7555072
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/565-322x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x1.bmp
new file mode 100644
index 0000000..27ec19a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x64000.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x64000.bmp
new file mode 100644
index 0000000..47ce803
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-1x64000.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-320x240.bmp
new file mode 100644
index 0000000..0b4d52c
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-321x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-321x240.bmp
new file mode 100644
index 0000000..e3157dd
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-321x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-322x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-322x240.bmp
new file mode 100644
index 0000000..dc8774a
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-322x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-323x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-323x240.bmp
new file mode 100644
index 0000000..6daae0b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-323x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsimportant-two.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsimportant-two.bmp
new file mode 100644
index 0000000..dc8005f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsimportant-two.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsused-zero.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsused-zero.bmp
new file mode 100644
index 0000000..b40ba16
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsused-zero.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/8bpp-topdown-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/8bpp-topdown-320x240.bmp
new file mode 100644
index 0000000..27d40fd
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/8bpp-topdown-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/index.html b/tests/loaders/data/bmp/bitmaps/valid/index.html
new file mode 100644
index 0000000..94674e1
--- /dev/null
+++ b/tests/loaders/data/bmp/bitmaps/valid/index.html
@@ -0,0 +1,421 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>Directory Listing</title>
+ </head>
+ <body>
+ <table border="1">
+
+ <tr>
+ <th>Filename</th>
+ <th>Description</th>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-1x1.bmp">1bpp-1x1.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. The image is a single black pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-320x240-color.bmp">1bpp-320x240-color.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel and a color palette.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-320x240-overlappingcolor.bmp">1bpp-320x240-overlappingcolor.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel and a color palette with colors that overlap.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-320x240.bmp">1bpp-320x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 0 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-321x240.bmp">1bpp-321x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 1 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-322x240.bmp">1bpp-322x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 2 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-323x240.bmp">1bpp-323x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 3 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-324x240.bmp">1bpp-324x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 4 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-325x240.bmp">1bpp-325x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 5 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-326x240.bmp">1bpp-326x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 6 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-327x240.bmp">1bpp-327x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 7 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-328x240.bmp">1bpp-328x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 8 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-329x240.bmp">1bpp-329x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 9 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-330x240.bmp">1bpp-330x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 10 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-331x240.bmp">1bpp-331x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 11 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-332x240.bmp">1bpp-332x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 12 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-333x240.bmp">1bpp-333x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 13 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-334x240.bmp">1bpp-334x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 14 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-335x240.bmp">1bpp-335x240.bmp</a></td>
+ <td>A bitmap that has 1 bit per pixel. Each scanline has 15 bits of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="1bpp-topdown-320x240.bmp">1bpp-topdown-320x240.bmp</a></td>
+ <td>A 'top down' uncompressed RGB bitmap that has 1 bit per pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-1x1.bmp">24bpp-1x1.bmp</a></td>
+ <td>An uncompressed bitmap with 24 bits per pixel. The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-320x240.bmp">24bpp-320x240.bmp</a></td>
+ <td>An uncompressed bitmap with 24 bits per pixel. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-321x240.bmp">24bpp-321x240.bmp</a></td>
+ <td>An uncompressed bitmap with 24 bits per pixel. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-322x240.bmp">24bpp-322x240.bmp</a></td>
+ <td>An uncompressed bitmap with 24 bits per pixel. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-323x240.bmp">24bpp-323x240.bmp</a></td>
+ <td>An uncompressed bitmap with 24 bits per pixel. Each scanline has 1 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-imagesize-zero.bmp">24bpp-imagesize-zero.bmp</a></td>
+ <td>
+ An uncompressed RGB bitmaps that has 24 bits-per-pixel.
+ The bitmap has a biSizeImage field of 0.
+ The bitmap specification allows the biSizeImage field to be zero
+ for uncompressed images.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="24bpp-topdown-320x240.bmp">24bpp-topdown-320x240.bmp</a></td>
+ <td>A 'top down' bitmap that has 24 bits per pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-101110-320x240.bmp">32bpp-101110-320x240.bmp</a></td>
+ <td>
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap uses 10-11-10 RGB color masks.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-1x1.bmp">32bpp-1x1.bmp</a></td>
+ <td>A bitmap that is 32 bpp uncompressed RGB. The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-320x240.bmp">32bpp-320x240.bmp</a></td>
+ <td>A bitmap that is 32 bpp uncompressed RGB.</td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-888-optimalpalette-320x240.bmp">32bpp-888-optimalpalette-320x240.bmp</a></td>
+ <td>
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap has three DWORD color masks, followed by an 'optimal color palette',
+ which is used for optimizing colors on palette-based devices.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-optimalpalette-320x240.bmp">32bpp-optimalpalette-320x240.bmp</a></td>
+ <td>
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap has an 'optimal color palette', which is used for optimizing colors on
+ palette-based devices, but does NOT have any color masks.
+ It's unclear to me if this is well-formed or not.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="32bpp-topdown-320x240.bmp">32bpp-topdown-320x240.bmp</a></td>
+ <td>A 'top down' uncompressed RGB bitmap that has 32 bits per pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-1x1.bmp">4bpp-1x1.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-320x240.bmp">4bpp-320x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 0 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-321x240.bmp">4bpp-321x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 1 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-322x240.bmp">4bpp-322x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 2 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-323x240.bmp">4bpp-323x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 3 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-324x240.bmp">4bpp-324x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 4 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-325x240.bmp">4bpp-325x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 5 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-326x240.bmp">4bpp-326x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 6 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-327x240.bmp">4bpp-327x240.bmp</a></td>
+ <td>An uncompressed bitmap that has 4 bits per pixel. Each scanline has 7 nibbles of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="4bpp-topdown-320x240.bmp">4bpp-topdown-320x240.bmp</a></td>
+ <td>A 'top down' uncompressed RGB bitmap that has 4 bits per pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="555-1x1.bmp">555-1x1.bmp</a></td>
+ <td>A bitmap that is 5-5-5 uncompressed RGB The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="555-320x240.bmp">555-320x240.bmp</a></td>
+ <td>A bitmap that is 5-5-5 uncompressed RGB Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="555-321x240.bmp">555-321x240.bmp</a></td>
+ <td>A bitmap that is 5-5-5 uncompressed RGB Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-1x1.bmp">565-1x1.bmp</a></td>
+ <td>A bitmap that is 5-6-5 uncompressed RGB The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-320x240-topdown.bmp">565-320x240-topdown.bmp</a></td>
+ <td>A 'top down' bitmap that is 5-6-5 uncompressed RGB. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-320x240.bmp">565-320x240.bmp</a></td>
+ <td>A bitmap that is 5-6-5 uncompressed RGB Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-321x240-topdown.bmp">565-321x240-topdown.bmp</a></td>
+ <td>A 'top down' bitmap that is 5-6-5 uncompressed RGB. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-321x240.bmp">565-321x240.bmp</a></td>
+ <td>A bitmap that is 5-6-5 uncompressed RGB Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-322x240-topdown.bmp">565-322x240-topdown.bmp</a></td>
+ <td>A 'top down' bitmap that is 5-6-5 uncompressed RGB. Each scanline has 1 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="565-322x240.bmp">565-322x240.bmp</a></td>
+ <td>A bitmap that is 5-6-5 uncompressed RGB Each scanline has 1 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-1x1.bmp">8bpp-1x1.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. The image is a single blue pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-1x64000.bmp">8bpp-1x64000.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. The image is a very long, blue vertical line.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-320x240.bmp">8bpp-320x240.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. Each scanline has 0 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-321x240.bmp">8bpp-321x240.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. Each scanline has 1 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-322x240.bmp">8bpp-322x240.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. Each scanline has 2 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-323x240.bmp">8bpp-323x240.bmp</a></td>
+ <td>An uncompressed RGB bitmap that has 8 bits per pixel. Each scanline has 3 bytes of padding.</td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsimportant-two.bmp">8bpp-colorsimportant-two.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with five colors, but a 'biColorsImportant' field of 2.
+ This indicates that only black and white are important.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-colorsused-zero.bmp">8bpp-colorsused-zero.bmp</a></td>
+ <td>
+ An 8 bpp bitmap with a 'biColorsUsed' field of 0.
+ This indicates that the palette contains 256 entries, which it does.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="8bpp-topdown-320x240.bmp">8bpp-topdown-320x240.bmp</a></td>
+ <td>A 'top down' uncompressed RGB bitmap that has 8 bits per pixel.</td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-absolute-320x240.bmp">rle4-absolute-320x240.bmp</a></td>
+ <td>
+ A run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-alternate-320x240.bmp">rle4-alternate-320x240.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The runs encode alternating pixel colors, such as dithering would create.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-delta-320x240.bmp">rle4-delta-320x240.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle4-encoded-320x240.bmp">rle4-encoded-320x240.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-64000x1.bmp">rle8-64000x1.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The image is a very long red, green, and blue horizontal line.</td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-absolute-320x240.bmp">rle8-absolute-320x240.bmp</a></td>
+ <td>
+ A run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-blank-160x120.bmp">rle8-blank-160x120.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap consists of just an end-of-bitmap marker.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-delta-320x240.bmp">rle8-delta-320x240.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ </td>
+ </tr>
+
+ <tr>
+ <td><a href="rle8-encoded-320x240.bmp">rle8-encoded-320x240.bmp</a></td>
+ <td>
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ </td>
+ </tr>
+
+ </table>
+ </body>
+</html>
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle4-absolute-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle4-absolute-320x240.bmp
new file mode 100644
index 0000000..a08745f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle4-absolute-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle4-alternate-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle4-alternate-320x240.bmp
new file mode 100644
index 0000000..51eda52
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle4-alternate-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle4-delta-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle4-delta-320x240.bmp
new file mode 100644
index 0000000..78a0927
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle4-delta-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle4-encoded-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle4-encoded-320x240.bmp
new file mode 100644
index 0000000..2848dc0
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle4-encoded-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle8-64000x1.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle8-64000x1.bmp
new file mode 100644
index 0000000..6ded0a3
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle8-64000x1.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle8-absolute-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle8-absolute-320x240.bmp
new file mode 100644
index 0000000..0f65e0b
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle8-absolute-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle8-blank-160x120.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle8-blank-160x120.bmp
new file mode 100644
index 0000000..ca8736f
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle8-blank-160x120.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle8-delta-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle8-delta-320x240.bmp
new file mode 100644
index 0000000..8007c55
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle8-delta-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bitmaps/valid/rle8-encoded-320x240.bmp b/tests/loaders/data/bmp/bitmaps/valid/rle8-encoded-320x240.bmp
new file mode 100644
index 0000000..15e6313
Binary files /dev/null and b/tests/loaders/data/bmp/bitmaps/valid/rle8-encoded-320x240.bmp differ
diff --git a/tests/loaders/data/bmp/bmptestsuite.py b/tests/loaders/data/bmp/bmptestsuite.py
new file mode 100644
index 0000000..9997fcd
--- /dev/null
+++ b/tests/loaders/data/bmp/bmptestsuite.py
@@ -0,0 +1,3639 @@
+#!/usr/bin/env python
+#
+# Heavily based on http://sourceforge.net/projects/bmptestsuite/
+# by David Costanzo
+#
+# Redistributed under GPLv2
+#
+# Copyright (C) 2012 Cyril Hrubis <metan(a)ucw.cz>
+#
+
+import struct
+import os
+import stat
+import errno
+import string
+import sys
+
+def _safe_create_dir(dirname):
+ "Create a directory named dirname, if it doesn't already exist"
+ try:
+ os.stat(dirname)
+
+ except OSError as info:
+ if info.errno == errno.ENOENT:
+ os.mkdir(dirname)
+ else:
+ raise
+
+
+def _safe_unlink(filename):
+ "Remove a file if it exists"
+ try:
+ os.unlink(filename)
+
+ except OSError as info:
+ if info.errno != errno.ENOENT:
+ raise
+
+TOP_LEFT_LOGO = []
+TOP_LEFT_LOGO.append("........................................................")
+TOP_LEFT_LOGO.append("........................................................")
+TOP_LEFT_LOGO.append("...#######..###...####......#.....####..####..#######...")
+TOP_LEFT_LOGO.append("......#....#...#..#...#.....#.....#.....#........#......")
+TOP_LEFT_LOGO.append("......#....#...#..#...#.....#.....#.....#........#......")
+TOP_LEFT_LOGO.append("......#....#...#..####......#.....###...###......#......")
+TOP_LEFT_LOGO.append("......#....#...#..#.........#.....#.....#........#......")
+TOP_LEFT_LOGO.append("......#....#...#..#.........#.....#.....#........#......")
+TOP_LEFT_LOGO.append("......#.....###...#.........####..####..#........#......")
+TOP_LEFT_LOGO.append("........................................................")
+TOP_LEFT_LOGO.append("........................................................")
+
+class bitmap:
+ "The base class for all test bitmaps"
+
+ SIZEOF_FILEINFOHEADER = 14
+
+ # values for Compression
+ BI_RGB = 0
+ BI_RLE8 = 1
+ BI_RLE4 = 2
+ BI_BITFIELDS = 3
+ BI_JPEG = 4
+ BI_PNG = 5
+ BI_ALPHABITFIELDS = 6
+
+ def __init__(self, bits_per_pixel, width, height):
+ self.bits_per_pixel = bits_per_pixel
+ self.width = width
+ self.height = height
+ self.palette = []
+ self.pixeldata = ''
+
+ # methods that make up the FILEINFOHEADER
+ def get_magic_number(self):
+ return b'BM'
+
+ def get_filesize(self):
+ sizeof_fileinfoheader = self.SIZEOF_FILEINFOHEADER
+ sizeof_bitmapinfoheader = self.get_bitmap_info_header_size()
+ sizeof_palette = len(self.get_palette())
+ sizeof_pixeldata = len(self.get_pixeldata())
+
+ return sizeof_fileinfoheader + sizeof_bitmapinfoheader + sizeof_palette + sizeof_pixeldata
+
+ def get_reserved1(self):
+ return 0
+
+ def get_reserved2(self):
+ return 0
+
+ def get_offset_of_bitmap_data(self):
+ sizeof_fileinfoheader = self.SIZEOF_FILEINFOHEADER
+ sizeof_bitmapinfoheader = self.get_bitmap_info_header_size()
+ sizeof_palette = len(self.get_palette())
+
+ return sizeof_fileinfoheader + sizeof_bitmapinfoheader + sizeof_palette
+
+
+ def get_fileinfoheader(self):
+ "Return the packed BMPFILEINFOHEADER structure"
+
+ magic_number = self.get_magic_number()
+ filesize = self.get_filesize()
+ reserved1 = self.get_reserved1()
+ reserved2 = self.get_reserved2()
+ offbits = self.get_offset_of_bitmap_data()
+
+ fileinfoheader = struct.pack(
+ '<2sIHHi',
+ magic_number,
+ filesize,
+ reserved1,
+ reserved2,
+ offbits)
+
+ return fileinfoheader
+
+
+ def get_bitmap_info_header_size(self):
+ return 40
+
+ def get_bits_per_pixel(self):
+ """
+ Return the biBitCount to put into the BITMAPINFOHEADER.
+ This should be 1, 4, 8, or 24.
+ """
+ return self.bits_per_pixel
+
+ def get_width(self):
+ """
+ Return the biWidth to put into the BITMAPINFOHEADER.
+ This is equal to the width of the bitmap, in pixels.
+ """
+ return self.width
+
+ def get_height(self):
+ "Return the height of bitmap to put into the BITMAPINFOHEADER"
+ return self.height
+
+ def get_planes(self):
+ "Return the value of biPlanes in BITMAPINFOHEADER"
+ return 1
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ return self.BI_RGB
+
+ def get_image_size(self):
+ "Return the biSizeImage to put into the BITMAPINFOHEADER"
+ return len(self.get_pixeldata())
+
+ def get_pixels_per_meter_x(self):
+ "Return the biXPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 1000
+
+ def get_pixels_per_meter_y(self):
+ "Return the biYPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 1000
+
+ def get_colors_used(self):
+ "Return the biClrUsed to put into the BITMAPINFOHEADER"
+ # assume that we use all colors
+ return len(self.palette)
+
+ def get_colors_important(self):
+ "Return the biClrImportant to put into the BITMAPINFOHEADER"
+ # assume that all colors are important
+ return 0
+
+ def get_bitmapinfoheader(self):
+ "Return the BITMAPINFOHEADER"
+
+ size = self.get_bitmap_info_header_size()
+ width = self.get_width()
+ height = self.get_height()
+ planes = self.get_planes()
+ bits_per_pixel = self.get_bits_per_pixel()
+ compression = self.get_compression()
+ image_size = self.get_image_size()
+ pixels_per_meter_x = self.get_pixels_per_meter_x()
+ pixels_per_meter_y = self.get_pixels_per_meter_y()
+ colors_used = self.get_colors_used()
+ colors_important = self.get_colors_important()
+
+ bitmapinfoheader = struct.pack(
+ '<IiihHIIiiII',
+ size,
+ width,
+ height,
+ planes,
+ bits_per_pixel,
+ compression,
+ image_size,
+ pixels_per_meter_x,
+ pixels_per_meter_y,
+ colors_used,
+ colors_important)
+
+ return bitmapinfoheader
+
+ def get_palette(self):
+ "Return the palette for bit depths <= 8"
+
+ # Generate the packed palette from self.palette
+ # This will be the empty string if self.palette == []
+ pack_string = '<' + 'I' * len(self.palette)
+ pack_params = [pack_string] + self.palette
+
+ palette = struct.pack(pack_string, *self.palette)
+
+ return palette
+
+ def create_pixeldata(self):
+ "Return the pixel data"
+
+ raise 'bitmap.create_pixeldata() should never be called'
+
+ def create_raster(self):
+ "Return the image as a raster"
+
+ raise 'bitmap.create_pixeldata() should never be called'
+
+ def get_pixeldata(self):
+ """
+ Create and cache the pixel data on the first call.
+ Return the cached value on all subsequent calls.
+ """
+
+ if not self.pixeldata:
+ self.pixeldata = self.create_pixeldata()
+
+ return self.pixeldata
+
+
+ def get_scanline_padding_bits(self):
+ "Return how many bits are used to pad each scanline"
+
+ alignment = 32 # All bitmap scanlines are DWORD aligned
+
+ # start with the number of bits in all pixels in a row
+ padding_bits = alignment - (self.width * self.bits_per_pixel) % alignment
+ padding_bits = padding_bits % alignment
+
+ return padding_bits
+
+
+ def apply_top_left_logo(self, image, on_value, off_value):
+ "Draw the TOP_LEFT_LOGO if there's enough room"
+
+ # leave enough space for the 2 pixel border
+ x_offset = 2
+ y_offset = 2
+
+ # only draw the logo if there's enough room
+ if len(TOP_LEFT_LOGO[0]) + x_offset <= self.width:
+ if len(TOP_LEFT_LOGO) + y_offset <= self.height:
+
+ for row in range(0, len(TOP_LEFT_LOGO)):
+ # find the current row from the top of the image,
+ # based on if this is a top-down or a bottom-up raster
+ if (self.get_height() < 0):
+ # top-down image
+ current_row = image[row + y_offset]
+ else:
+ # bottom-up image
+ current_row = image[self.height - 1 - row - y_offset]
+
+
+ # set the pixels to "on" or "off"
+ for col in range(0, len(TOP_LEFT_LOGO[row])):
+ if (TOP_LEFT_LOGO[row][col] == '.'):
+ # change this pixel to black
+ current_row[col + x_offset] = on_value
+ else:
+ # change this pixel to white
+ current_row[col + x_offset] = off_value
+
+
+ def draw_double_border(self, image, outer_value, inner_value):
+ "Draw two single-pixel borders around the image"
+
+ # image must be at least 5 x 5 to draw the border
+ if 5 <= self.height and 5 <= self.width:
+
+ # draw the outer border
+ for col in range(0, self.width):
+ # top border
+ image[0][col] = outer_value
+
+ # bottom border
+ image[self.height - 1][col] = outer_value
+
+ for row in range(0, self.height):
+ # left border
+ image[row][0] = outer_value
+
+ # right border
+ image[row][self.width - 1] = outer_value
+
+
+ # draw the inner border around the image
+ for col in range(1, self.width - 1):
+ # top border
+ image[1][col] = inner_value
+
+ # bottom border
+ image[self.height - 2][col] = inner_value
+
+ for row in range(1, self.height - 1):
+ # left border
+ image[row][1] = inner_value
+
+ # right border
+ image[row][self.width - 2] = inner_value
+
+
+ def write(self, filename):
+ "Write the bitmap out to a file"
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ palette = self.get_palette()
+ bmpfile.write(palette)
+
+ pixeldata = self.get_pixeldata()
+ bmpfile.write(pixeldata)
+
+ bmpfile.close()
+
+ def write_croppped_bitmap(self, filename):
+ """
+ Write the bitmap out to a file, but end the file short in the
+ middle of scaneline.
+ """
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ palette = self.get_palette()
+ bmpfile.write(palette)
+
+ # crop the pixel data roughly in half
+ # really, crop it in the middle of a scanline
+ pixeldata = self.get_pixeldata()
+ crop_point = len(pixeldata) // 2 - (self.width * self.bits_per_pixel // 8) // 2 - 1
+ content = pixeldata[0 : crop_point]
+ bmpfile.write(content)
+
+ bmpfile.close()
+
+
+class bitmap_32bpp(bitmap):
+ "A bitmap that is 32 bpp uncompressed RGB."
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 32, width, height)
+
+ def create_raster(self):
+ "Return the rasterized form of the canonical image in 32 bpp"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [struct.pack('<I', 0x00FF0000)] * red_width
+ row += [struct.pack('<I', 0x0000FF00)] * green_width
+ row += [struct.pack('<I', 0x000000FF)] * blue_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ struct.pack('<I', 0x00000000),
+ struct.pack('<I', 0x00FFFFFF))
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ struct.pack('<I', 0x00000000),
+ struct.pack('<I', 0x00FFFFFF))
+
+ return raster
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 32 bpp RGB"
+
+ raster = self.create_raster()
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_32bpp_topdown(bitmap_32bpp):
+ "A 'top down' uncompressed RGB bitmap that has 32 bits per pixel."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+
+class bitmap_32bpp_colortable(bitmap_32bpp):
+ """
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap has an 'optimal color palette', which is used for optimizing colors on
+ palette-based devices, but does NOT have any color masks.
+ It's unclear to me if this is well-formed or not.
+ """
+
+ def __init__(self, width, height):
+ bitmap_32bpp.__init__(self, width, height)
+
+ self.palette = [
+ 0x00FF00FF, # magenta
+ 0x00000000, # black
+ 0x00FF0000, # red
+ 0x0000FF00, # green
+ 0x000000FF, # blue
+ 0x00FFFFFF] # white
+
+
+class bitmap_32bpp_888_colortable(bitmap_32bpp):
+ """
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap has three DWORD color masks, followed by an 'optimal color palette',
+ which is used for optimizing colors on palette-based devices.
+ """
+
+ def __init__(self, width, height):
+ bitmap_32bpp.__init__(self, width, height)
+
+ self.palette = [
+ 0x00FF0000, # red mask
+ 0x0000FF00, # green mask
+ 0x000000FF, # blue mask
+
+ 0x00FF00FF, # magenta
+ 0x00000000, # black
+ 0x00FF0000, # red
+ 0x0000FF00, # green
+ 0x000000FF, # blue
+ 0x00FFFFFF] # white
+
+ def get_colors_used(self):
+ "Return the biClrUsed to put into the BITMAPINFOHEADER"
+ # This only includes the optimized color palette--not the color masks.
+ return 6
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ # must be BI_BITFIELDS because we have color masks
+ return self.BI_BITFIELDS
+
+class bitmap_32bpp_101110(bitmap):
+ """
+ A bitmap that is 32 bpp uncompressed RGB.
+ This bitmap uses 10-11-10 RGB color masks.
+ """
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 32, width, height)
+
+ self.palette = [
+ 0x7FE00000, # red mask (10 bits)
+ 0x001FFC00, # green mask (11 bits)
+ 0x000003FF] # blue mask (10 bits)
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ return self.BI_BITFIELDS
+
+ def get_colors_used(self):
+ "Return the biClrUsed to put into the BITMAPINFOHEADER"
+ return 0
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 32 bpp RGB"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [struct.pack('<I', 0x7FE00000)] * red_width
+ row += [struct.pack('<I', 0x001FFC00)] * green_width
+ row += [struct.pack('<I', 0x000003FF)] * blue_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ struct.pack('<I', 0x00000000),
+ struct.pack('<I', 0x7FFFFFFF))
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ struct.pack('<I', 0x00000000),
+ struct.pack('<I', 0x7FFFFFFF))
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+class bitmap_32bpp_croppedpixeldata(bitmap_32bpp):
+ """
+ A 32 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+class bitmap_24bpp(bitmap):
+ "An uncompressed bitmap with 24 bits per pixel. "
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 24, width, height)
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 24 bpp RGB"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ pad_width_in_bytes = self.get_scanline_padding_bits() / 8
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += ['x00x00xFF'] * red_width
+ row += ['x00xFFx00'] * green_width
+ row += ['xFFx00x00'] * blue_width
+
+ # pad the scanline to the nearest DWORD boundry
+ row += ['xCC'] * pad_width_in_bytes
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ 'x00x00x00',
+ 'xFFxFFxFF')
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ 'x00x00x00',
+ 'xFFxFFxFF')
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_24bpp_topdown(bitmap_24bpp):
+ "A 'top down' bitmap that has 24 bits per pixel."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+class bitmap_24bpp_zeroimagesize(bitmap_24bpp):
+ """
+ An uncompressed RGB bitmaps that has 24 bits-per-pixel.
+ The bitmap has a biSizeImage field of 0.
+ The bitmap specification allows the biSizeImage field to be zero
+ for uncompressed images.
+ """
+
+ def get_image_size(self):
+ "Return the biSizeImage to put into the BITMAPINFOHEADER"
+ return 0
+
+class bitmap_24bpp_croppedpixeldata(bitmap_24bpp):
+ """
+ A 24 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+class bitmap_555(bitmap):
+ "A bitmap that is 5-5-5 uncompressed RGB"
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 16, width, height)
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 5-5-5 RGB"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ pad_width_in_bytes = self.get_scanline_padding_bits() / 8
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [struct.pack('<H', 0x7C00)] * red_width
+ row += [struct.pack('<H', 0x03E0)] * green_width
+ row += [struct.pack('<H', 0x001F)] * blue_width
+
+ # pad the scanline to the nearest DWORD boundry
+ row += ['xCC'] * pad_width_in_bytes
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ 'x00x00',
+ 'xFFxFF')
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ 'x00x00',
+ 'xFFxFF')
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_555_croppedpixeldata(bitmap_555):
+ """
+ A 5-5-5 16 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+class bitmap_565(bitmap):
+ "A bitmap that is 5-6-5 uncompressed RGB"
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 16, width, height)
+
+ # This is the bitfields (or bitmasks)
+ self.palette = [
+ 0xF800, # 5 bits for red
+ 0x07E0, # 6 bits for green
+ 0x001F] # 5 bits for blue
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ return self.BI_BITFIELDS
+
+ def get_colors_used(self):
+ "Return the biClrUsed to put into the BITMAPINFOHEADER"
+ return 0
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 5-6-5 RGB"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ pad_width_in_bytes = self.get_scanline_padding_bits() / 8
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [struct.pack('<H', 0xF800)] * red_width
+ row += [struct.pack('<H', 0x07E0)] * green_width
+ row += [struct.pack('<H', 0x001F)] * blue_width
+
+ # pad the scanline to the nearest DWORD boundry
+ row += ['xCC'] * pad_width_in_bytes
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ 'x00x00',
+ 'xFFxFF')
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ 'x00x00',
+ 'xFFxFF')
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_565_topdown(bitmap_565):
+ "A 'top down' bitmap that is 5-6-5 uncompressed RGB."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+
+
+class bitmap_8bpp(bitmap):
+ "An uncompressed RGB bitmap that has 8 bits per pixel."
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 8, width, height)
+
+ # Set the "0" pixel to magenta so we can test the
+ # difference between pixels we deliberately set to
+ # black and pixels that the bitmap processor left at 0.
+ self.palette = [
+ 0x00FF00FF, # magenta
+ 0x00000000, # black
+ 0x00FF0000, # red
+ 0x0000FF00, # green
+ 0x000000FF, # blue
+ 0x00FFFFFF] # white
+
+ self.INDEX_MAGENTA = 0
+ self.INDEX_BLACK = 1
+ self.INDEX_RED = 2
+ self.INDEX_GREEN = 3
+ self.INDEX_BLUE = 4
+ self.INDEX_WHITE = 5
+
+ # TRANSPARENT_PIXEL is a special value that means
+ # "use a delta to skip beyond this pixel"
+ self.TRANSPARENT_PIXEL = -2
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 8 bpp"
+
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ pad_width_in_bytes = self.get_scanline_padding_bits() / 8
+
+ # draw the color pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [chr(self.INDEX_RED)] * red_width
+ row += [chr(self.INDEX_GREEN)] * green_width
+ row += [chr(self.INDEX_BLUE)] * blue_width
+ row += [chr(self.INDEX_MAGENTA)] * pad_width_in_bytes
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ chr(self.INDEX_BLACK),
+ chr(self.INDEX_WHITE))
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ chr(self.INDEX_BLACK),
+ chr(self.INDEX_WHITE))
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_8bpp_topdown(bitmap_8bpp):
+ "A 'top down' uncompressed RGB bitmap that has 8 bits per pixel."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+
+
+class bitmap_8bpp_pixelnotinpalette(bitmap_8bpp):
+ """
+ A bitmap that is 8 bits per pixel uncompressed RGB.
+ Many of the pixels are indexes that don't exist in the palette.
+ """
+
+ def __init__(self, width, height):
+ bitmap_8bpp.__init__(self, width, height)
+
+ self.palette = [
+ 0x00000000, # black
+ 0x00FFFFFF] # white
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 8 bpp"
+
+ pad_width_in_bytes = self.get_scanline_padding_bits() / 8
+
+ palette_length = len(self.palette)
+
+ # the raster loops through all 256 possible indices
+ raster = []
+ for row in range(0, self.height):
+
+ new_row = []
+ for col in range(0, self.width + pad_width_in_bytes):
+ # don't draw anything in the palette
+ value = chr((col % (256 - palette_length) + palette_length))
+ new_row.append(value)
+
+ raster.append(new_row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ chr(self.INDEX_BLACK),
+ chr(self.INDEX_WHITE))
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ chr(self.INDEX_BLACK),
+ chr(self.INDEX_WHITE))
+
+ # concatenate the rows in the raster image into a flat buffer
+ pixeldata = ''
+ for row in raster:
+ pixeldata += string.join(row, '')
+
+ return pixeldata
+
+
+class bitmap_8bpp_nopalette(bitmap_8bpp):
+ """
+ A bitmap that has 8 bits per pixel and no palette.
+ This is an invalid bitmap, but a bitmap processor could use default colors.
+ """
+
+ def __init__(self, width, height):
+ bitmap_8bpp.__init__(self, width, height)
+
+ # empty the palette
+ self.palette = []
+
+class bitmap_8bpp_zerocolorsused(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a 'biColorsUsed' field of 0.
+ This indicates that the palette contains 256 entries, which it does.
+ """
+
+ def __init__(self, width, height):
+ bitmap_8bpp.__init__(self, width, height)
+
+ # fill the palette
+ while len(self.palette) < 256:
+ self.palette.append(0x00CCCCCC)
+
+ def get_colors_used(self):
+ return 0
+
+class bitmap_8bpp_largecolorsused(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a very large 'biColorsUsed' field.
+ This is invalid--biColorsImportant shouldn't exceed 256.
+ This attempts to trick the bitmap processor into accessing invalid memory.
+ """
+ def get_colors_used(self):
+ return 0xFFFFFFFF
+
+class bitmap_8bpp_negativecolorsused(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a negative 'biColorsUsed' field.
+ This is invalid--biColorsImportant can't be below 0.
+ This attempts to trick the bitmap processor into accessing invalid memory.
+ """
+ def get_colors_used(self):
+ # -1024 in 32 bit two complement
+ return 0xFFFFFC00
+
+class bitmap_8bpp_twocolorsimportant(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with five colors, but a 'biColorsImportant' field of 2.
+ This indicates that only black and white are important.
+ """
+ def get_colors_important(self):
+ return 2
+
+class bitmap_8bpp_largecolorsimportant(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with five colors, but a very large 'biColorsImportant' field.
+ This is invalid--biColorsImportant shouldn't exceed biColorsUsed.
+ """
+ def get_colors_important(self):
+ return 0xFFFFFFFF
+
+class bitmap_8bpp_negativecolorsimportant(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a negative 'biColorsImportant' field.
+ This is invalid--biColorsImportant can't be below 0.
+ """
+ def get_colors_used(self):
+ # -1024 in 32 bit two complement
+ return 0xFFFFFC0
+
+class bitmap_8bpp_croppedpixeldata(bitmap_8bpp):
+ """
+ An 8 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+class bitmap_rle8(bitmap_8bpp):
+ "A base class for RLE8 bitmaps that implements some helpers routines."
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ return self.BI_RLE8
+
+ def create_absolute_run(self, row, offset, length):
+ "Return the 'absolute mode' encoding of a run of pixels"
+
+ if length < 3:
+ raise 'bad length: %d' % length
+
+ if 255 < length:
+ raise 'bad length: %d' % length
+
+ # There are between 3 and 255 pixels left in this row.
+
+ # Mark this run as an absolute encoding
+ encoded_run = 'x00' + chr(length)
+
+ for i in range(0, length):
+ # Encode each pixel with absolute encoding.
+ encoded_run += chr(row[offset + i])
+
+ if len(encoded_run) % 2 != 0:
+ # pad the encoded run out to the nearest word boundry
+ encoded_run += 'x00'
+
+ return encoded_run
+
+ def create_encoded_run(self, run_length, pixel):
+ "Return the 'encoded mode' encoding of a run of pixels"
+ return chr(run_length) + chr(pixel)
+
+ def create_end_of_line(self):
+ "Return the end-of-line escape sequence"
+ return 'x00x00'
+
+ def create_end_of_bitmap(self):
+ "Return the end-of-bitmap escape sequence"
+ return 'x00x01'
+
+ def create_delta(self, right, down):
+ "Return a delta escape sequence"
+ return 'x00x02' + chr(right) + chr(down)
+
+ def create_pixeldata(self):
+ raise "this should not be called"
+
+ def create_raster(self):
+ "Return a rasterized version of the 8bpp canonical image"
+
+ # widths are in bytes (pixels)
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [self.INDEX_RED] * red_width
+ row += [self.INDEX_GREEN] * green_width
+ row += [self.INDEX_BLUE] * blue_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(
+ raster,
+ self.INDEX_BLACK,
+ self.INDEX_WHITE)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ self.INDEX_BLACK,
+ self.INDEX_WHITE)
+
+ return raster
+
+
+class bitmap_rle8_encoded(bitmap_rle8):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 4 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle8_delta(bitmap_rle8):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ """
+
+ def __init__(self, width, height):
+ bitmap_rle8.__init__(self, width, height)
+
+ # fill the rest of the palette with grey
+ for i in range(len(self.palette), 256):
+ self.palette.append(0x00CCCCCC)
+
+ def create_raster(self):
+ "Return a rastersized form of a bitmap that is good for making deltas"
+
+ # widths are in bytes (pixels)
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [self.INDEX_RED] * red_width
+ row += [self.TRANSPARENT_PIXEL] * green_width
+ row += [self.INDEX_BLUE] * blue_width
+
+ raster.append(row)
+
+ # draw an invisible border
+ self.draw_double_border(
+ raster,
+ self.TRANSPARENT_PIXEL,
+ self.TRANSPARENT_PIXEL)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ self.INDEX_BLACK,
+ self.INDEX_WHITE)
+
+ return raster
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+
+ # check if the row contains nothing but transparent pixels
+ row_is_all_transparent = 1
+ for col in range(0, len(raster[row])):
+ if raster[row][col] != self.TRANSPARENT_PIXEL:
+ row_is_all_transparent = 0
+ break
+
+ if row_is_all_transparent:
+ # the entire row is entirely transparent. Do a delta.
+ pixeldata += self.create_delta(0, 1)
+
+ else:
+ # there are some non-transparent pixels in this row.
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ if prev_pixel == self.TRANSPARENT_PIXEL:
+ # this run is encoded as a delta
+ pixeldata += self.create_delta(
+ run_length,
+ 0)
+ else:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+
+ # We don't have to write a delta for transparent
+ # pixels because the end-of-line marker will take
+ # care of that.
+ if prev_pixel != self.TRANSPARENT_PIXEL:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle8_absolute(bitmap_rle8):
+ """
+ A run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as an RLE8 in absolute mode (uncompressed)"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ for row in range(0, len(raster)):
+
+ cur_row = raster[row]
+
+ col = 0
+ while col < len(cur_row):
+ remaining = len(cur_row) - col
+ if 255 < remaining:
+ # There are more than 255 pixels left in this row.
+ # Encode all 255 pixels.
+ pixeldata += self.create_absolute_run(cur_row, col, 255)
+ col += 255
+
+ elif 3 <= remaining:
+ # There are between 3 and 255 pixels left in this row.
+ # Encode them all with absolute encoding.
+ pixeldata += self.create_absolute_run(cur_row, col, remaining)
+ col += remaining
+
+ else:
+ raise 'Unsupported width: %d' % remaining
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle8_blank(bitmap_rle8):
+ """
+ A simple run-length encoded bitmap consists of just an end-of-bitmap marker.
+ """
+
+ def __init__(self, width, height):
+ bitmap_rle8.__init__(self, width, height)
+
+ # fill the rest of the palette with grey
+ # so that we can see the difference between uninitialized
+ # memory and pixels that should be unspecified.
+ for i in range(len(self.palette), 256):
+ self.palette.append(0x00CCCCCC)
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ return self.create_end_of_bitmap()
+
+
+class bitmap_rle8_noendofbitmap(bitmap_rle8_encoded):
+ """
+ An RLE8 compressed bitmap with no end-of-bitmap sequence.
+ This is techinically invalid, but the bitmap processor should
+ be able to treat the end-of-file as an end-of-bitmap.
+ """
+
+ def create_end_of_bitmap(self):
+ return ''
+
+
+class bitmap_rle8_topdown(bitmap_rle8_encoded):
+ """
+ An RLE8 compressed bitmap with a negative height.
+ This is an illegal value: top-down images cannot be compressed.
+ However, many bitmap processors allow top-down compressed images.
+ """
+
+ def get_height(self):
+ return -self.height
+
+
+class bitmap_rle8_toomuchdata(bitmap_rle8_encoded):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ It has twice as much data as it should.
+ Since the RLE8 format is mostly a series of drawing directives,
+ this tests that the RLE8 processor keeps memory access within
+ the size of the image.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded in 8 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # double the height of the image.
+ pixeldata *= 2
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle8_deltaleavesimage(bitmap_rle8_encoded):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap contains 'delta' escape sequences the leave the image.
+ The intent is to trick the processor into accessing invalid memory.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ # Tell the image processor to move off of the image
+ # before drawing anything.
+ pixeldata = ''
+ i = 0
+ while i < self.height:
+ pixeldata += self.create_delta(255, 0)
+ i += 255
+
+ # draw the image
+ pixeldata += bitmap_rle8_encoded.create_pixeldata(self)
+
+ return pixeldata
+
+
+class bitmap_rle8_croppedrun(bitmap_rle8):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The pixel data ends prematurely--in the middle of an encoded
+ escape sequence.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster) / 2):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(run_length, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # append the cropped run
+ last_run = self.create_encoded_run(100, 2)
+ cropped_run = last_run[0 : len(last_run) - 1]
+ pixeldata += cropped_run
+
+ return pixeldata
+
+
+class bitmap_rle8_croppedabsolute(bitmap_rle8):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ The pixel data ends prematurely--in the middle of an absolute
+ escape sequence.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as RLE8 encoded in 'absolute mode' (uncompressed)"
+ raster = self.create_raster()
+
+ pixeldata = ''
+ for row in range(0, len(raster)):
+
+ cur_row = raster[row]
+
+ col = 0
+ while col < len(cur_row):
+ remaining = len(cur_row) - col
+ if 255 < remaining:
+ # There are more than 255 pixels left in this row.
+ # Encode all 255 pixels.
+ absolute_run = self.create_absolute_run(cur_row, col, 255)
+ col += 255
+
+ elif 3 <= remaining:
+ # There are between 3 and 255 pixels left in this row.
+ # Encode them all with absolute encoding.
+ absolute_run = self.create_absolute_run(cur_row, col, remaining)
+ col += remaining
+
+ else:
+ raise 'Unsupported width: %d' % remaining
+
+ if len(raster) / 2 <= row:
+ # crop this encoding and return
+ cropped_run = absolute_run[0 : len(absolute_run) - 1]
+ pixeldata += cropped_run
+ return pixeldata
+
+ # append this encoding and keep processing the current row
+ pixeldata += absolute_run
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ return pixeldata
+
+class bitmap_rle8_croppeddelta(bitmap_rle8_delta):
+ """
+ A simple run-length encoded bitmap that has 8 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ The file ends in the middle of a delta escape.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+
+ # check if the row contains nothing but transparent pixels
+ row_is_all_transparent = 1
+ for col in range(0, len(raster[row])):
+ if raster[row][col] != self.TRANSPARENT_PIXEL:
+ row_is_all_transparent = 0
+ break
+
+ if row_is_all_transparent:
+ # the entire row is entirely transparent. Do a delta.
+ pixeldata += self.create_delta(0, 1)
+
+ else:
+ # there are some non-transparent pixels in this row.
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ if prev_pixel == self.TRANSPARENT_PIXEL:
+ # this run is encoded as a delta
+ delta = self.create_delta(
+ run_length,
+ 0)
+
+ if len(raster) / 2 <= row:
+ # we are half-way through the image.
+ # crop the delta and return what we have
+ cropped_delta = delta[0 : len(delta) - 1]
+ pixeldata += cropped_delta
+ return pixeldata
+
+ pixeldata += delta
+
+ else:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+
+ # We don't have to write a delta for transparent
+ # pixels because the end-of-line marker will take
+ # care of that.
+ if prev_pixel != self.TRANSPARENT_PIXEL:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle8_noendofline(bitmap_rle8_encoded):
+ """
+ An RLE8 compressed bitmap with no end-of-line sequences.
+ It is unclear if a bitmap processor should implicitly add
+ end-of-line markers when the pixel run the row's width,
+ or if it should ignore all pixel data beyond the row's width.
+ """
+
+ def create_end_of_line(self):
+ return ''
+
+
+class bitmap_4bpp(bitmap):
+ "An uncompressed bitmap that has 4 bits per pixel."
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 4, width, height)
+
+ # Set the "0" pixel to magenta so we can test the
+ # difference between pixels we deliberately set to
+ # black and pixels that the bitmap processor left at 0.
+ self.palette = [
+ 0x00FF00FF, # magenta
+ 0x00000000, # black
+ 0x00FF0000, # red
+ 0x0000FF00, # green
+ 0x000000FF, # blue
+ 0x00FFFFFF] # white
+
+ self.INDEX_MAGENTA = 0
+ self.INDEX_BLACK = 1
+ self.INDEX_RED = 2
+ self.INDEX_GREEN = 3
+ self.INDEX_BLUE = 4
+ self.INDEX_WHITE = 5
+
+ # TRANSPARENT_PIXEL is a special value that means
+ # "use a delta to skip beyond this pixel"
+ self.TRANSPARENT_PIXEL = -2
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 4 bpp"
+
+ # widths are in nibbles (pixels)
+ red_width = self.width // 3
+ green_width = self.width // 3
+ blue_width = self.width - (red_width + green_width)
+
+ pad_width = self.get_scanline_padding_bits() // 4
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [self.INDEX_RED] * red_width
+ row += [self.INDEX_GREEN] * green_width
+ row += [self.INDEX_BLUE] * blue_width
+ row += [self.INDEX_MAGENTA] * pad_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(raster, self.INDEX_BLACK, self.INDEX_WHITE)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(raster, self.INDEX_BLACK, self.INDEX_WHITE)
+
+ pixeldata = ''
+ for row in range(0, len(raster)):
+
+ # a closure for helping to add runs to the image
+ class nibblestream:
+ def __init__(self):
+ self.nextByte = 0
+ self.index = 0
+ self.scanline = ''
+
+ def appendnibble(self, value):
+ # shift the byte over and OR-in the low bit
+ self.nextByte = (self.nextByte << 4) | value
+ self.index += 4
+
+ if (self.index == 8):
+ # this byte is full--write it
+ self.scanline += chr(self.nextByte)
+ self.nextByte = 0
+ self.index = 0
+
+ appender = nibblestream()
+ for col in range(0, len(raster[row])):
+ appender.appendnibble(raster[row][col])
+ pixeldata += appender.scanline
+
+ return pixeldata
+
+
+class bitmap_4bpp_topdown(bitmap_4bpp):
+ "A 'top down' uncompressed RGB bitmap that has 4 bits per pixel."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+class bitmap_4bpp_croppedpixeldata(bitmap_4bpp):
+ """
+ An 4 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+
+class bitmap_rle4(bitmap_4bpp):
+ "A base class for RLE4 bitmaps that implements some helpers routines."
+
+ def get_compression(self):
+ "Return the biCompression to put into the BITMAPINFOHEADER"
+ return self.BI_RLE4
+
+ def create_absolute_run(self, row, offset, length):
+ "Return the 'absolute mode' encoding of a run of pixels"
+
+ if length < 3:
+ raise 'bad length: %d' % length
+
+ if 255 < length:
+ raise 'bad length: %d' % length
+
+ # There are between 3 and 255 pixels left in this row.
+
+ # Mark this run as an absolute encoding
+ encoded_run = 'x00' + chr(length)
+
+ for i in range(0, length / 2):
+ # Encode each pixel with absolute encoding.
+ byte = (row[offset + 2 * i] << 4) | (row[offset + 2 * i + 1])
+ encoded_run += chr(byte)
+
+ if length % 2 != 0:
+ # We have one pixel left, which fills half a byte.
+ byte = row[offset + length - 1] << 4
+ encoded_run += chr(byte)
+
+ if len(encoded_run) % 2 != 0:
+ # pad the encoded run out to the nearest word boundry
+ encoded_run += 'x00'
+
+ return encoded_run
+
+ def create_encoded_run(self, run_length, pixel1, pixel2):
+ "Return the 'encoded mode' encoding of a run of pixels"
+ return chr(run_length) + chr((pixel1 << 4) | pixel2)
+
+ def create_end_of_line(self):
+ "Return the end-of-line escape sequence"
+ return 'x00x00'
+
+ def create_end_of_bitmap(self):
+ "Return the end-of-bitmap escape sequence"
+ return 'x00x01'
+
+ def create_delta(self, down, right):
+ "Return a delta escape sequence"
+ return 'x00x02' + chr(down) + chr(right)
+
+ def create_pixeldata(self):
+ raise "this should not be called"
+
+ def create_raster(self):
+ "Return a rasterized version of the 4bpp canonical image"
+
+ # widths are in nibbles (pixels)
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [self.INDEX_RED] * red_width
+ row += [self.INDEX_GREEN] * green_width
+ row += [self.INDEX_BLUE] * blue_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(raster, self.INDEX_BLACK, self.INDEX_WHITE)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(raster, self.INDEX_BLACK, self.INDEX_WHITE)
+
+ return raster
+
+
+class bitmap_rle4_encoded(bitmap_rle4):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 4 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(run_length, prev_pixel, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(run_length, prev_pixel, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle4_absolute(bitmap_rle4):
+ """
+ A run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as RLE4 encoded in 'absolute mode' (uncompressed)"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ for row in range(0, len(raster)):
+
+ cur_row = raster[row]
+
+ col = 0
+ while col < len(cur_row):
+ remaining = len(cur_row) - col
+ if 255 < remaining:
+ # There are more than 255 pixels left in this row.
+ # Encode all 255 pixels.
+ pixeldata += self.create_absolute_run(cur_row, col, 255)
+ col += 255
+
+ elif 3 <= remaining:
+ # There are between 3 and 255 pixels left in this row.
+ # Encode them all with absolute encoding.
+ pixeldata += self.create_absolute_run(cur_row, col, remaining)
+ col += remaining
+
+ else:
+ raise 'Unsupported width: %d' % remaining
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+
+class bitmap_rle4_alternate(bitmap_rle4):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The runs encode alternating pixel colors, such as dithering would create.
+ """
+
+ def __init__(self, width, height):
+ bitmap_rle4.__init__(self, width, height)
+
+ self.palette = [
+ 0x00000000, # black
+ 0x00000000, # black
+ 0x00FF0000, # red
+ 0x0000FF00, # green
+ 0x000000FF, # blue
+ 0x00FF0000, # red
+ 0x00FFFFFF, # white
+ 0x00FFFFFF] # white
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 4 bpp"
+
+ # widths are in nibbles (pixels)
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [2] * red_width
+ row += [3] * green_width
+ row += [4] * blue_width
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(raster, 0, 6)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(raster, 0, 6)
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel + 1)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel + 1)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_rle4_delta(bitmap_rle4):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ """
+
+ def __init__(self, width, height):
+ bitmap_rle4.__init__(self, width, height)
+
+ # fill the rest of the palette with grey
+ # so that we can see the difference between uninitialized
+ # memory and pixels that should be unspecified.
+ for i in range(len(self.palette), 16):
+ self.palette.append(0x00CCCCCC)
+
+ def create_raster(self):
+ "Return a raster that is suitable for creating an RLE image with deltas"
+
+ # widths are in bytes (pixels)
+ red_width = self.width / 3
+ green_width = self.width / 3
+ blue_width = self.width - (red_width + green_width)
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [self.INDEX_RED] * red_width
+ row += [self.TRANSPARENT_PIXEL] * green_width
+ row += [self.INDEX_BLUE] * blue_width
+
+ raster.append(row)
+
+ # draw an invisible border
+ self.draw_double_border(
+ raster,
+ self.TRANSPARENT_PIXEL,
+ self.TRANSPARENT_PIXEL)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(
+ raster,
+ self.INDEX_BLACK,
+ self.INDEX_WHITE)
+
+ return raster
+
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 8 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+
+ # check if the row contains nothing but transparent pixels
+ row_is_all_transparent = 1
+ for col in range(0, len(raster[row])):
+ if raster[row][col] != self.TRANSPARENT_PIXEL:
+ row_is_all_transparent = 0
+ break
+
+ if row_is_all_transparent:
+ # the entire row is entirely transparent. Do a delta.
+ pixeldata += self.create_delta(0, 1)
+
+ else:
+ # there are some non-transparent pixels in this row.
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ if prev_pixel == self.TRANSPARENT_PIXEL:
+ # this run is encoded as a delta
+ pixeldata += self.create_delta(
+ run_length,
+ 0)
+ else:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+
+ # We don't have to write a delta for transparent
+ # pixels because the end-of-line marker will take
+ # care of that.
+ if prev_pixel != self.TRANSPARENT_PIXEL:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+class bitmap_rle4_topdown(bitmap_rle4_encoded):
+ """
+ An RLE4 compressed bitmap with a negative height.
+ This is an illegal bitmap: top-down images cannot be compressed.
+ Still, many bitmap processors can understand it.
+ """
+
+ def get_height(self):
+ return -self.height
+
+
+class bitmap_rle4_noendofline(bitmap_rle4_encoded):
+ """
+ An RLE4 compressed bitmap with no end-of-line sequences.
+ It is unclear if a bitmap processor should implicitly add
+ end-of-line markers when the pixel run the row's width,
+ or if it should ignore all pixel data beyond the row's width.
+ """
+
+ def create_end_of_line(self):
+ return ''
+
+class bitmap_rle4_noendofbitmap(bitmap_rle4_encoded):
+ """
+ An RLE4 compressed bitmap with no end-of-bitmap sequence.
+ This is techinically invalid, but the bitmap processor should
+ be able to treat the end-of-file as an end-of-bitmap.
+ """
+
+ def create_end_of_bitmap(self):
+ return ''
+
+
+class bitmap_rle4_croppedrun(bitmap_rle4):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'encoded mode'.
+ The pixel data ends prematurely--in the middle of an encoded
+ escape sequence.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as run-length encoded 4 bpp"
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster) / 2):
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ pixeldata += self.create_encoded_run(run_length, prev_pixel, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+ pixeldata += self.create_encoded_run(run_length, prev_pixel, prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # append the cropped run
+ last_run = self.create_encoded_run(100, 1, 2)
+ cropped_run = last_run[0 : len(last_run) - 1]
+ pixeldata += cropped_run
+
+ return pixeldata
+
+class bitmap_rle4_croppedabsolute(bitmap_rle4):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The entire bitmap is in 'absolute mode'.
+ The pixel data ends prematurely--in the middle of an absolute
+ escape sequence.
+ """
+
+ def create_pixeldata(self):
+ "Return the pixel data as RLE4 encoded in 'absolute mode' (uncompressed)"
+ raster = self.create_raster()
+
+ pixeldata = ''
+ for row in range(0, len(raster)):
+
+ cur_row = raster[row]
+
+ col = 0
+ while col < len(cur_row):
+ remaining = len(cur_row) - col
+ if 255 < remaining:
+ # There are more than 255 pixels left in this row.
+ # Encode all 255 pixels.
+ absolute_run = self.create_absolute_run(cur_row, col, 255)
+ col += 255
+
+ elif 3 <= remaining:
+ # There are between 3 and 255 pixels left in this row.
+ # Encode them all with absolute encoding.
+ absolute_run = self.create_absolute_run(cur_row, col, remaining)
+ col += remaining
+
+ else:
+ raise 'Unsupported width: %d' % remaining
+
+ if len(raster) / 2 <= row:
+ # crop this encoding and return
+ cropped_run = absolute_run[0 : len(absolute_run) - 1]
+ pixeldata += cropped_run
+ return pixeldata
+
+ # append this encoding and keep processing the current row
+ pixeldata += absolute_run
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ return pixeldata
+
+class bitmap_rle4_croppeddelta(bitmap_rle4_delta):
+ """
+ A simple run-length encoded bitmap that has 4 bits per pixel.
+ The bitmap uses 'delta escapes'.
+ The file ends in the middle of a delta escape.
+ """
+
+ def create_pixeldata(self):
+ """
+ Return the pixel data as run-length encoded 4 bpp that ends in the
+ middle of a delta escape sequence
+ """
+
+ raster = self.create_raster()
+
+ pixeldata = ''
+ run_length = 0
+ prev_pixel = -1
+ for row in range(0, len(raster)):
+
+ # check if the row contains nothing but transparent pixels
+ row_is_all_transparent = 1
+ for col in range(0, len(raster[row])):
+ if raster[row][col] != self.TRANSPARENT_PIXEL:
+ row_is_all_transparent = 0
+ break
+
+ if row_is_all_transparent:
+ # the entire row is entirely transparent. Do a delta.
+ pixeldata += self.create_delta(0, 1)
+
+ else:
+ # there are some non-transparent pixels in this row.
+ for col in range(0, len(raster[row])):
+
+ cur_pixel = raster[row][col]
+
+ if run_length == 255 or (run_length != 0 and prev_pixel != cur_pixel):
+ # There's no more room on this run OR
+ # The current run has ended.
+
+ # Write the run and start a new one
+ if prev_pixel == self.TRANSPARENT_PIXEL:
+ # this run is encoded as a delta
+ delta = self.create_delta(
+ run_length,
+ 0)
+
+ if len(raster) / 2 <= row:
+ # we are half-way through the image.
+ # crop the delta and return what we have
+ cropped_delta = delta[0 : len(delta) - 1]
+ pixeldata += cropped_delta
+ return pixeldata
+
+ pixeldata += delta
+
+ else:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+
+ if run_length == 0:
+ # start a new run
+ prev_pixel = cur_pixel
+ run_length = 1
+
+ elif prev_pixel == raster[row][col]:
+ # continue this run
+ run_length += 1
+
+ # flush the last run
+ if run_length != 0:
+
+ # We don't have to write a delta for transparent
+ # pixels because the end-of-line marker will take
+ # care of that.
+ if prev_pixel != self.TRANSPARENT_PIXEL:
+ # this run is encoded as a regular run
+ pixeldata += self.create_encoded_run(
+ run_length,
+ prev_pixel,
+ prev_pixel)
+
+ run_length = 0
+ prev_pixel = -1
+
+ # end-of-line
+ pixeldata += self.create_end_of_line()
+
+ # end-of-bitmap
+ pixeldata += self.create_end_of_bitmap()
+
+ return pixeldata
+
+
+class bitmap_4bpp_nopalette(bitmap_4bpp):
+ """
+ A bitmap that has 4 bit per pixel and no palette.
+ This is an invalid bitmap, but a bitmap processor could use default colors.
+ """
+
+ def __init__(self, width, height):
+ bitmap_4bpp.__init__(self, width, height)
+
+ # empty the palette
+ self.palette = []
+
+
+class bitmap_1bpp(bitmap):
+ "A bitmap that has 1 bit per pixel."
+
+ def __init__(self, width, height):
+ bitmap.__init__(self, 1, width, height)
+
+ self.palette = [
+ 0x00000000, # black
+ 0x00FFFFFF] # white
+
+ def create_pixeldata(self):
+ "Return the pixel data as uncompressed 1 bpp."
+
+ # widths are in bits (pixels)
+ stripe1_width = self.width // 3
+ stripe2_width = self.width // 3
+ stripe3_width = self.width - (stripe1_width + stripe2_width)
+
+ pad_width_in_bits = self.get_scanline_padding_bits()
+
+ # draw the pattern
+ raster = []
+ for i in range(0, self.height):
+
+ row = []
+ row += [0] * stripe1_width
+ row += [1] * stripe2_width
+ row += [0] * stripe3_width
+ row += [1] * pad_width_in_bits
+
+ raster.append(row)
+
+ # draw a border
+ self.draw_double_border(raster, 0, 1)
+
+ # add in the TOP_LEFT_LOGO
+ self.apply_top_left_logo(raster, 0, 1)
+
+
+ pixeldata = b''
+ for row in range(0, len(raster)):
+
+ # a closure for helping to add runs to the image
+ class bitstream:
+ def __init__(self):
+ self.nextByte = 0
+ self.index = 0
+ self.scanline = b''
+
+ def appendbit(self, value):
+ # shift the byte over and OR-in the low bit
+ self.nextByte = (self.nextByte << 1) | value
+ self.index += 1
+
+ if (self.index == 8):
+ # this byte is full--write it
+ self.scanline += chr(self.nextByte)
+ self.nextByte = 0
+ self.index = 0
+
+ appender = bitstream()
+ for col in range(0, len(raster[row])):
+ appender.appendbit(raster[row][col])
+ pixeldata += appender.scanline
+
+ return pixeldata
+
+class bitmap_1bpp_topdown(bitmap_1bpp):
+ "A 'top down' uncompressed RGB bitmap that has 1 bit per pixel."
+
+ def get_height(self):
+ # a negative value makes a bitmap top-down
+ return -self.height
+
+
+class bitmap_1bpp_color(bitmap_1bpp):
+ "A bitmap that has 1 bit per pixel and a color palette."
+
+ def __init__(self, width, height):
+ bitmap_1bpp.__init__(self, width, height)
+
+ self.palette = [
+ 0x00FFF000, # yellow
+ 0x00000FFF] # mostly blue
+
+class bitmap_1bpp_overlappingcolor(bitmap_1bpp):
+ "A bitmap that has 1 bit per pixel and a color palette with colors that overlap."
+
+ def __init__(self, width, height):
+ bitmap_1bpp.__init__(self, width, height)
+
+ self.palette = [
+ 0x00FFFF00, # yellow
+ 0x0000FFFF] # cyan
+
+class bitmap_1bpp_nopalette(bitmap_1bpp):
+ """
+ A bitmap that has 1 bit per pixel and no palette.
+ This is technically invalid, but a bitmap processor could default to black and white.
+ """
+
+ def __init__(self, width, height):
+ bitmap_1bpp.__init__(self, width, height)
+
+ # empty the palette
+ self.palette = []
+
+
+class bitmap_1bpp_palettetoobig(bitmap_1bpp):
+ "A bitmap that has 1 bit per pixel that has a palette with 5000 colors."
+
+ def __init__(self, width, height):
+ bitmap_1bpp.__init__(self, width, height)
+
+ for i in range(0,5000):
+ self.palette.append(i)
+
+class bitmap_1bpp_croppedpixeldata(bitmap_1bpp):
+ """
+ A 1 bpp bitmap that ends in the middle of the pixel data.
+ This tests that what happens when a call to fread() fails.
+ This bitmap processor should probably process the data that
+ it does have AND display a diagnostic.
+ """
+
+ def write(self, filename):
+ self.write_croppped_bitmap(filename)
+
+
+class bitmap_width_height_overflow(bitmap_565):
+ """
+ A bitmap whose reported width and height cause a 32bit overflow when
+ they are multiplied together.
+ This tries to trick the image processor into allocating a very small
+ buffer that it thinks is very large.
+ """
+
+ def get_width(self):
+ return 0x10000
+
+ def get_height(self):
+ return 0x10000
+
+class bitmap_emptyfile(bitmap_1bpp):
+ """
+ A zero-byte file.
+ This tests that what happens when the first call to fread() fails.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+ bmpfile.close()
+
+class bitmap_badmagicnumber(bitmap_1bpp):
+ """
+ A bitmap with an invalid magic number (it uses 'Bm' instead of 'BM')
+ A bitmap processor that ignores this field is probably trusting the file extension
+ or doing a case-insensitive compare.
+ """
+
+ def get_magic_number(self):
+ "return the bad magic number"
+ return 'Bm'
+
+
+class bitmap_croppedmagicnumber(bitmap_1bpp):
+ """
+ A one byte bitmap that only contains the 'B' of the magic number.
+ This tests that what happens when the first call to fread() returns
+ fewer bytes than expected.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+ bmpfile.write('B')
+ bmpfile.close()
+
+class bitmap_badfilesize(bitmap_1bpp):
+ """
+ A bitmap with a filesize that's half of what it should be.
+ Most bitmap processors ignore this field.
+ """
+
+ def get_filesize(self):
+ "Return a filesize that is half of what it should be"
+ return bitmap_1bpp.get_filesize(self) / 2
+
+
+class bitmap_zerofilesize(bitmap_1bpp):
+ """
+ A bitmap with an filesize of 0.
+ Most bitmap processors ignore this field.
+ """
+
+ def get_filesize(self):
+ return 0
+
+class bitmap_badreserved1(bitmap_1bpp):
+ """
+ A bitmap with an 'wReserved1' field that is not 0.
+ This is technically illegal, but most bitmap processors ignore this field.
+ """
+
+ def get_reserved1(self):
+ return 1
+
+class bitmap_badreserved2(bitmap_1bpp):
+ """
+ A bitmap with an 'wReserved2' field that is not 0.
+ This is technically illegal, but most bitmap processors ignore this field.
+ """
+
+ def get_reserved2(self):
+ return 1
+
+class bitmap_negativeoffbits(bitmap_1bpp):
+ """
+ A bitmap with an 'dwOffBits' field that is -1.
+ This is supposed to be interpreted as an unsigned value, so it will
+ either be understood as a very large (illegal) value,
+ or a negative value (also illegal).
+ """
+
+ def get_offset_of_bitmap_data(self):
+ return -1
+
+class bitmap_largeoffbits(bitmap_1bpp):
+ """
+ A bitmap with an 'dwOffBits' field that is larger than the file size.
+ """
+
+ def get_offset_of_bitmap_data(self):
+ return self.get_filesize() + 1
+
+
+class bitmap_zerooffbits(bitmap_1bpp):
+ """
+ A bitmap with an 'dwOffBits' field that is 0.
+ A bitmap processor may recover from this by assuming that the pixel data
+ immediately follows the palette.
+ """
+
+ def get_offset_of_bitmap_data(self):
+ return 0
+
+class bitmap_croppedfileinfoheader(bitmap_1bpp):
+ """
+ A bitmap that is one byte short of having a complete fileinfoheader.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+
+ # remove the last byte of the FILEINFOHEADER
+ content = fileinfoheader[0 : len(fileinfoheader) - 1]
+ bmpfile.write(content)
+
+ # don't write anything else.
+ bmpfile.close()
+
+class bitmap_missinginfoheader(bitmap_1bpp):
+ """
+ A bitmap file that is so short that it doesn't include a BITMAPINFOHEADER.
+ This tests that what happens when a call to fread() fails.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_croppedinfoheader(bitmap_1bpp):
+ """
+ A bitmap that is one byte short of having a complete BITMAPINFOHEADER.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+
+ # remove the last byte of the BITMAPINFOHEADER
+ content = bmpinfoheader[0 : len(bmpinfoheader) - 1]
+ bmpfile.write(content)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_smallbmpinfoheadersize(bitmap_1bpp):
+ """
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is too small.
+ """
+
+ def get_bitmap_info_header_size(self):
+ return 24
+
+ def get_bitmapinfoheader(self):
+ "Return the short BITMAPINFOHEADER"
+
+ size = self.get_bitmap_info_header_size()
+ width = self.get_width()
+ height = self.get_height()
+ planes = self.get_planes()
+ bits_per_pixel = self.get_bits_per_pixel()
+ compression = self.get_compression()
+ image_size = self.get_image_size()
+
+ bitmapinfoheader = struct.pack(
+ '<IiihhII',
+ size,
+ width,
+ height,
+ planes,
+ bits_per_pixel,
+ compression,
+ image_size)
+
+ return bitmapinfoheader
+
+class bitmap_largebmpinfoheadersize(bitmap_1bpp):
+ """
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is too large.
+ """
+
+ def get_bitmap_info_header_size(self):
+ return 64 * 1024 * 1024
+
+class bitmap_zerobmpinfoheadersize(bitmap_1bpp):
+ """
+ A bitmap with a 'biSize' field in its BMPINFOHEADER that is 0.
+ """
+
+ def get_bitmap_info_header_size(self):
+ return 0
+
+
+class bitmap_zeroheight(bitmap_1bpp):
+ """
+ A bitmap with a 'biHeight' field in its BMPINFOHEADER that is 0.
+ """
+
+ def get_height(self):
+ return 0
+
+class bitmap_zerowidth(bitmap_1bpp):
+ """
+ A bitmap with a 'biWidth' field in its BMPINFOHEADER that is 0.
+ """
+
+ def get_width(self):
+ return 0
+
+class bitmap_negativewidth(bitmap_1bpp):
+ """
+ A bitmap with a negative 'biWidth' field in its BMPINFOHEADER.
+ """
+
+ def get_width(self):
+ return -self.width
+
+class bitmap_zeroplanes(bitmap_1bpp):
+ """
+ A bitmap with a 'biPlanes' field in its BMPINFOHEADER that is zero.
+ This is an invalid bitmap, but many bitmap processors ignore this field.
+ """
+
+ def get_planes(self):
+ return 0
+
+class bitmap_largeplanes(bitmap_1bpp):
+ """
+ A bitmap with a 'biPlanes' field in its BMPINFOHEADER that is large.
+ This is an invalid bitmap, but many bitmap processors ignore this field.
+ """
+
+ def get_planes(self):
+ return 5000
+
+
+class bitmap_oddbitdepth(bitmap_8bpp):
+ """
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is odd.
+ """
+
+ def get_bits_per_pixel(self):
+ return 7
+
+class bitmap_zerobitdepth(bitmap_1bpp):
+ """
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is 0.
+ """
+
+ def get_bits_per_pixel(self):
+ return 0
+
+class bitmap_largebitdepth(bitmap_1bpp):
+ """
+ A bitmap with a 'biBitCount' field in its BMPINFOHEADER that is very large.
+ This attempts to trick the bitmap processor into thinking the bit depth is negative.
+ """
+
+ def get_bits_per_pixel(self):
+ return 0xFFFF
+
+class bitmap_unknowncompression(bitmap_1bpp):
+ """
+ A bitmap with an unrecognized 'biCompression' field.
+ """
+
+ def get_compression(self):
+ return 0xFFFFFFFF
+
+class bitmap_4bpp_rle8compression(bitmap_rle4_encoded):
+ """
+ A 4 bpp bitmap with a 'biCompression' field of BI_RLE8.
+ Only 8 bpp bitmaps may use BI_RLE8.
+ """
+
+ def get_compression(self):
+ return self.BI_RLE8
+
+
+class bitmap_8bpp_rle4compression(bitmap_rle8_encoded):
+ """
+ An 8 bpp bitmap with a 'biCompression' field of BI_RLE4.
+ Only 4 bpp bitmaps may use BI_RLE4.
+ """
+
+ def get_compression(self):
+ return self.BI_RLE4
+
+class bitmap_8bpp_zeroxpelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a 'biXPelsPerMeter' field of 0.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_x(self):
+ "Return the biXPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 0
+
+class bitmap_8bpp_negativexpelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a negative 'biXPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_x(self):
+ "Return the biXPelsPerMeter to put into the BITMAPINFOHEADER"
+ return -10000
+
+class bitmap_8bpp_largexpelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a large 'biXPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_x(self):
+ "Return the biXPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 0x7FFFFFFF
+
+class bitmap_8bpp_zeroypelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a 'biYPelsPerMeter' field of 0.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_y(self):
+ "Return the biYPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 0
+
+class bitmap_8bpp_negativeypelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a negative 'biYPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_y(self):
+ "Return the biYPelsPerMeter to put into the BITMAPINFOHEADER"
+ return -10000
+
+class bitmap_8bpp_largeypelspermeter(bitmap_8bpp):
+ """
+ An 8 bpp bitmap with a large 'biYPelsPerMeter' field.
+ Most bitmap processors ignore this field, but it is most likely used when
+ printing the image.
+ """
+
+ def get_pixels_per_meter_y(self):
+ "Return the biYPelsPerMeter to put into the BITMAPINFOHEADER"
+ return 0x7FFFFFF
+
+
+
+class bitmap_missingpalette(bitmap_1bpp):
+ """
+ A bitmap file that is so short that it doesn't include the palette.
+ This tests that what happens when a call to fread() fails.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_croppedpalette(bitmap_1bpp):
+ """
+ A bitmap that is one byte short of having a complete palette.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ palette = self.get_palette()
+
+ # remove the last byte of the BITMAPINFOHEADER
+ content = palette[0 : len(palette) - 1]
+ bmpfile.write(content)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_missingcolormasks(bitmap_565):
+ """
+ A BI_BITFIELDS bitmap file that is so short that it doesn't include the
+ colormask array.
+ This tests that what happens when a call to fread() fails.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_croppedcolormasks(bitmap_565):
+ """
+ A BI_BITFIELDS bitmap that is one byte short of having a complete
+ colormask array.
+ This tests that what happens when fread() returns fewer bytes
+ than expected.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ palette = self.get_palette()
+
+ # remove the last byte of the BITMAPINFOHEADER
+ content = palette[0 : len(palette) - 1]
+ bmpfile.write(content)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+
+class bitmap_missingpixeldata(bitmap_24bpp):
+ """
+ A bitmap file that doesn't include any of the pixel data.
+ """
+
+ def write(self, filename):
+
+ _safe_unlink(filename)
+
+ bmpfile = open(filename, 'wb')
+
+ fileinfoheader = self.get_fileinfoheader()
+ bmpfile.write(fileinfoheader)
+
+ bmpinfoheader = self.get_bitmapinfoheader()
+ bmpfile.write(bmpinfoheader)
+
+ palette = self.get_palette()
+ bmpfile.write(palette)
+
+ # don't write any other part of the bitmap
+ bmpfile.close()
+
+class bitmap_toomuchdata(bitmap_1bpp):
+ """
+ A bitmap with twice as much payload as expected.
+ This attempts to overflow an internal buffer.
+ """
+
+ def create_pixeldata(self):
+ return bitmap_1bpp.create_pixeldata(self) * 2
+
+
+class testcase_logger:
+ def __init__(self, path):
+ # a map from filename to English description of the file.
+ self.descriptions = {}
+
+ # the file path to the directory containing the bitmap
+ self.path = path
+
+ def write_index(self, basename):
+ keys = self.descriptions.keys()
+ keys.sort()
+
+ index_filename = self.path + '/' + basename
+ _safe_unlink(index_filename)
+ indexfile = open(index_filename, 'wb')
+
+ indexfile.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">n')
+ indexfile.write('<html>n')
+ indexfile.write(' <head>n')
+ indexfile.write(' <title>Directory Listing</title>n')
+ indexfile.write(' </head>n')
+ indexfile.write(' <body>n')
+ indexfile.write(' <table border="1">n')
+ indexfile.write('n')
+ indexfile.write(' <tr>n')
+ indexfile.write(' <th>Filename</th>n')
+ indexfile.write(' <th>Description</th>n')
+ indexfile.write(' </tr>n')
+ indexfile.write('n')
+
+ for key in keys:
+ indexfile.write(' <tr>n')
+ indexfile.write(' <td><a href="' + key + '">' + key + '</a></td>n')
+ indexfile.write(' <td>' + self.descriptions[key] + '</td>n')
+ indexfile.write(' </tr>n')
+ indexfile.write('n')
+
+ indexfile.write(' </table>n')
+ indexfile.write(' </body>n')
+ indexfile.write('</html>n')
+
+ indexfile.close()
+
+
+ def do_testcase(self, filename, bitmap, *rest):
+ bitmap.write(self.path + '/' + filename)
+
+ # Figure out the bitmap's English description.
+ # Start with the doc string and append the optional
+ # complementary description argument.
+ description = bitmap.__doc__
+ if len(rest) != 0:
+ description += ' ' + rest[0]
+
+ self.descriptions[filename] = description
+
+def generate_valid_bitmaps():
+ """
+ Create valid bitmaps of various encodings.
+ """
+
+ _safe_create_dir('bitmaps')
+ _safe_create_dir('bitmaps/valid')
+
+ log = testcase_logger('bitmaps/valid')
+
+ # valid 1 bpp bitmaps
+ for width in range(320,336):
+ log.do_testcase(
+ '1bpp-%ix240.bmp' % width,
+ bitmap_1bpp(width, 240),
+ 'Each scanline has %i bits of padding.' % (width - 320))
+
+ log.do_testcase(
+ '1bpp-1x1.bmp',
+ bitmap_1bpp(1, 1),
+ 'The image is a single black pixel.')
+
+ log.do_testcase(
+ '1bpp-320x240-color.bmp',
+ bitmap_1bpp_color(320, 240))
+
+ log.do_testcase(
+ '1bpp-320x240-overlappingcolor.bmp',
+ bitmap_1bpp_overlappingcolor(320, 240))
+
+ log.do_testcase(
+ '1bpp-topdown-320x240.bmp',
+ bitmap_1bpp_topdown(320, 240))
+
+ # valid 4 bpp bitmaps
+ for width in range(320,328):
+ log.do_testcase(
+ '4bpp-%ix240.bmp' % width,
+ bitmap_4bpp(width, 240),
+ 'Each scanline has %i nibbles of padding.' % (width - 320))
+
+ for width in range (320, 321):
+ log.do_testcase(
+ 'rle4-encoded-%ix240.bmp' % width,
+ bitmap_rle4_encoded(width, 240))
+
+ for width in range (320, 321):
+ log.do_testcase(
+ 'rle4-absolute-%ix240.bmp' % width,
+ bitmap_rle4_absolute(width, 240))
+
+ for width in range (320, 321):
+ log.do_testcase(
+ 'rle4-alternate-%ix240.bmp' % width,
+ bitmap_rle4_alternate(width, 240))
+
+ log.do_testcase(
+ 'rle4-delta-320x240.bmp',
+ bitmap_rle4_delta(320, 240))
+
+ log.do_testcase(
+ '4bpp-1x1.bmp',
+ bitmap_4bpp(1, 1),
+ 'The image is a single blue pixel.')
+
+ log.do_testcase(
+ '4bpp-topdown-320x240.bmp',
+ bitmap_4bpp_topdown(320, 240))
+
+
+ # valid 8 bpp bitmaps
+ for width in range(320,324):
+ log.do_testcase(
+ '8bpp-%ix240.bmp' % width,
+ bitmap_8bpp(width, 240),
+ 'Each scanline has %i bytes of padding.' % (width - 320))
+
+ for width in range (320, 321):
+ log.do_testcase(
+ 'rle8-encoded-%ix240.bmp' % width,
+ bitmap_rle8_encoded(width, 240))
+
+ for width in range (320, 321):
+ log.do_testcase(
+ 'rle8-absolute-%ix240.bmp' % width,
+ bitmap_rle8_absolute(width, 240))
+
+ log.do_testcase(
+ 'rle8-delta-320x240.bmp',
+ bitmap_rle8_delta(320, 240))
+
+ log.do_testcase(
+ 'rle8-blank-160x120.bmp',
+ bitmap_rle8_blank(160, 120))
+
+ log.do_testcase(
+ '8bpp-1x1.bmp',
+ bitmap_8bpp(1, 1),
+ 'The image is a single blue pixel.')
+
+ log.do_testcase(
+ 'rle8-64000x1.bmp',
+ bitmap_rle8_encoded(64000, 1),
+ 'The image is a very long red, green, and blue horizontal line.')
+
+ log.do_testcase(
+ '8bpp-1x64000.bmp',
+ bitmap_8bpp(1, 64000),
+ 'The image is a very long, blue vertical line.')
+
+ log.do_testcase(
+ '8bpp-colorsused-zero.bmp',
+ bitmap_8bpp_zerocolorsused(320, 240))
+
+ log.do_testcase(
+ '8bpp-colorsimportant-two.bmp',
+ bitmap_8bpp_twocolorsimportant(320, 240))
+
+ log.do_testcase(
+ '8bpp-topdown-320x240.bmp',
+ bitmap_8bpp_topdown(320, 240))
+
+ # valid 5-5-5 bitmaps
+ for width in range(320,322):
+ log.do_testcase(
+ '555-%ix240.bmp' % width,
+ bitmap_555(width, 240),
+ 'Each scanline has %i bytes of padding.' % ((width - 320) / 2))
+
+ log.do_testcase(
+ '555-1x1.bmp',
+ bitmap_555(1, 1),
+ 'The image is a single blue pixel.')
+
+ # valid 5-6-5 bitmaps
+ for width in range(320,323):
+ log.do_testcase(
+ '565-%ix240.bmp' % width,
+ bitmap_565(width, 240),
+ 'Each scanline has %i bytes of padding.' % ((width - 320) / 2))
+
+ log.do_testcase(
+ '565-%ix240-topdown.bmp' % width,
+ bitmap_565_topdown(width, 240),
+ 'Each scanline has %i bytes of padding.' % ((width - 320) / 2))
+
+ log.do_testcase(
+ '565-1x1.bmp',
+ bitmap_565(1, 1),
+ 'The image is a single blue pixel.')
+
+
+ # valid 24 bpp bitmaps
+ for width in range(320,324):
+ log.do_testcase(
+ '24bpp-%ix240.bmp' % width,
+ bitmap_24bpp(width, 240),
+ 'Each scanline has %i bytes of padding.' % ((width - 320) / 3))
+
+ log.do_testcase(
+ '24bpp-topdown-320x240.bmp',
+ bitmap_24bpp_topdown(320, 240))
+
+ log.do_testcase(
+ '24bpp-1x1.bmp',
+ bitmap_24bpp(1, 1),
+ 'The image is a single blue pixel.')
+
+ log.do_testcase(
+ '24bpp-imagesize-zero.bmp',
+ bitmap_24bpp_zeroimagesize(320, 240))
+
+ # valid 32 bpp bitmaps
+ log.do_testcase(
+ '32bpp-320x240.bmp',
+ bitmap_32bpp(320, 240))
+
+ log.do_testcase(
+ '32bpp-topdown-320x240.bmp',
+ bitmap_32bpp_topdown(320, 240))
+
+ log.do_testcase(
+ '32bpp-optimalpalette-320x240.bmp',
+ bitmap_32bpp_colortable(320, 240))
+
+ log.do_testcase(
+ '32bpp-888-optimalpalette-320x240.bmp',
+ bitmap_32bpp_888_colortable(320, 240))
+
+ log.do_testcase(
+ '32bpp-101110-320x240.bmp',
+ bitmap_32bpp_101110(320, 240))
+
+ log.do_testcase(
+ '32bpp-1x1.bmp',
+ bitmap_32bpp(1, 1),
+ 'The image is a single blue pixel.')
+
+ # write out the HTML index
+ log.write_index('index.html')
+
+
+def generate_questionable_bitmaps():
+ """
+ Create bitmaps that are technically invalid, but which most
+ bitmap processors can process, anyway.
+ """
+
+ _safe_create_dir('bitmaps')
+ _safe_create_dir('bitmaps/questionable')
+
+ log = testcase_logger('bitmaps/questionable')
+
+ log.do_testcase(
+ 'filesize-bad.bmp',
+ bitmap_badfilesize(320, 240))
+
+ log.do_testcase(
+ 'filesize-zero.bmp',
+ bitmap_zerofilesize(320, 240))
+
+ log.do_testcase(
+ 'reserved1-bad.bmp',
+ bitmap_badreserved1(320, 240))
+
+ log.do_testcase(
+ 'reserved2-bad.bmp',
+ bitmap_badreserved2(320, 240))
+
+ log.do_testcase(
+ 'rle8-height-negative.bmp',
+ bitmap_rle8_topdown(320, 240))
+
+ log.do_testcase(
+ 'rle4-height-negative.bmp',
+ bitmap_rle4_topdown(320, 240))
+
+ log.do_testcase(
+ 'planes-zero.bmp',
+ bitmap_zeroplanes(320, 240))
+
+ log.do_testcase(
+ 'planes-large.bmp',
+ bitmap_largeplanes(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-x-zero.bmp',
+ bitmap_8bpp_zeroxpelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-x-negative.bmp',
+ bitmap_8bpp_negativexpelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-x-large.bmp',
+ bitmap_8bpp_largexpelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-y-zero.bmp',
+ bitmap_8bpp_zeroypelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-y-negative.bmp',
+ bitmap_8bpp_negativeypelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pels-per-meter-y-large.bmp',
+ bitmap_8bpp_largeypelspermeter(320, 240))
+
+ log.do_testcase(
+ 'pixeldata-toomuch.bmp',
+ bitmap_toomuchdata(320, 240))
+
+ log.do_testcase(
+ 'pixeldata-rle8-toomuch.bmp',
+ bitmap_rle8_toomuchdata(320, 240))
+
+ log.do_testcase(
+ 'rle8-no-end-of-bitmap-marker.bmp',
+ bitmap_rle8_noendofbitmap(320, 240))
+
+ log.do_testcase(
+ '8bpp-pixels-not-in-palette.bmp',
+ bitmap_8bpp_pixelnotinpalette(254, 128))
+
+ log.do_testcase(
+ '32bpp-0x0.bmp',
+ bitmap_32bpp(0, 0),
+ 'The image is 0 pixels wide and 0 pixels high. Even though this is technically valid, most bitmap procesors consider it to be corrupt.')
+
+ log.do_testcase(
+ '32bpp-320x0.bmp',
+ bitmap_32bpp(320, 0),
+ 'The image is 320 pixels wide and zero pixels high. This is a sneaky way of making a 0x0 bitmap. Even though this is technically valid, most bitmap procesors consider it to be corrupt.')
+
+ log.do_testcase(
+ '32bpp-0x240.bmp',
+ bitmap_32bpp(0, 240),
+ 'The image is 0 pixels wide and 240 pixels high. This is a sneaky way of making a 0x0 bitmap. Even though this is technically valid, most bitmap procesors consider it to be corrupt.')
+
+ log.do_testcase(
+ 'rle4-no-end-of-bitmap-marker.bmp',
+ bitmap_rle4_noendofbitmap(320, 240))
+
+ # write out the HTML index
+ log.write_index('index.html')
+
+
+
+def generate_corrupt_bitmaps():
+ """
+ Create corrupt/malicious bitmaps that are either impossible to process,
+ or that most bitmap processors will refuse to process.
+ For most of these files, the best a bitmap processor can do is
+ display an informative diagnostic and not crash or leak memory.
+ """
+
+ _safe_create_dir('bitmaps')
+ _safe_create_dir('bitmaps/corrupt')
+
+ log = testcase_logger('bitmaps/corrupt')
+
+ # invalid images
+ log.do_testcase(
+ 'emptyfile.bmp',
+ bitmap_emptyfile(320, 240))
+
+ log.do_testcase(
+ 'fileinfoheader-cropped.bmp',
+ bitmap_croppedfileinfoheader(320, 240))
+
+ log.do_testcase(
+ 'magicnumber-cropped.bmp',
+ bitmap_croppedmagicnumber(320, 240))
+
+ log.do_testcase(
+ 'magicnumber-bad.bmp',
+ bitmap_badmagicnumber(320, 240))
+
+ log.do_testcase(
+ 'offbits-zero.bmp',
+ bitmap_zerooffbits(320, 240))
+
+ log.do_testcase(
+ 'offbits-negative.bmp',
+ bitmap_negativeoffbits(320, 240))
+
+ log.do_testcase(
+ 'offbits-large.bmp',
+ bitmap_largeoffbits(320, 240))
+
+ log.do_testcase(
+ 'infoheader-missing.bmp',
+ bitmap_missinginfoheader(320, 240))
+
+ log.do_testcase(
+ 'infoheader-cropped.bmp',
+ bitmap_croppedinfoheader(320, 240))
+
+ log.do_testcase(
+ 'infoheadersize-small.bmp',
+ bitmap_smallbmpinfoheadersize(320, 240))
+
+ log.do_testcase(
+ 'infoheadersize-large.bmp',
+ bitmap_largebmpinfoheadersize(320, 240))
+
+ log.do_testcase(
+ 'infoheadersize-zero.bmp',
+ bitmap_zerobmpinfoheadersize(320, 240))
+
+ log.do_testcase(
+ 'height-zero.bmp',
+ bitmap_zeroheight(320, 240))
+
+ log.do_testcase(
+ 'width-zero.bmp',
+ bitmap_zerowidth(320, 240))
+
+ log.do_testcase(
+ 'width-negative.bmp',
+ bitmap_negativewidth(320, 240))
+
+ log.do_testcase(
+ 'width-times-height-overflow.bmp',
+ bitmap_width_height_overflow(320, 240))
+
+ log.do_testcase(
+ 'bitdepth-zero.bmp',
+ bitmap_zerobitdepth(320, 240))
+
+ log.do_testcase(
+ 'bitdepth-odd.bmp',
+ bitmap_oddbitdepth(320, 240))
+
+ log.do_testcase(
+ 'bitdepth-large.bmp',
+ bitmap_largebitdepth(320, 240))
+
+ log.do_testcase(
+ 'compression-unknown.bmp',
+ bitmap_unknowncompression(320, 240))
+
+ log.do_testcase(
+ 'compression-bad-rle4-for-8bpp.bmp',
+ bitmap_4bpp_rle8compression(320, 240))
+
+ log.do_testcase(
+ 'compression-bad-rle8-for-4bpp.bmp',
+ bitmap_8bpp_rle4compression(320, 240))
+
+ log.do_testcase(
+ '8bpp-colorsused-large.bmp',
+ bitmap_8bpp_largecolorsused(320, 240))
+
+ log.do_testcase(
+ '8bpp-colorsused-negative.bmp',
+ bitmap_8bpp_negativecolorsused(320, 240))
+
+ log.do_testcase(
+ '8bpp-colorsimportant-large.bmp',
+ bitmap_8bpp_largecolorsimportant(320, 240))
+
+ log.do_testcase(
+ '8bpp-colorsimportant-negative.bmp',
+ bitmap_8bpp_negativecolorsimportant(320, 240))
+
+ log.do_testcase(
+ 'rle8-deltaleavesimage.bmp',
+ bitmap_rle8_deltaleavesimage(320, 240))
+
+ log.do_testcase(
+ 'palette-too-big.bmp',
+ bitmap_1bpp_palettetoobig(320, 240))
+
+ log.do_testcase(
+ '1bpp-no-palette.bmp',
+ bitmap_1bpp_nopalette(320, 240))
+
+ log.do_testcase(
+ '4bpp-no-palette.bmp',
+ bitmap_4bpp_nopalette(320, 240))
+
+ log.do_testcase(
+ '8bpp-no-palette.bmp',
+ bitmap_8bpp_nopalette(320, 240))
+
+ log.do_testcase(
+ 'palette-missing.bmp',
+ bitmap_missingpalette(320, 240))
+
+ log.do_testcase(
+ 'palette-cropped.bmp',
+ bitmap_croppedpalette(320, 240))
+
+ log.do_testcase(
+ 'colormasks-missing.bmp',
+ bitmap_missingcolormasks(320, 240))
+
+ log.do_testcase(
+ 'colormasks-cropped.bmp',
+ bitmap_croppedcolormasks(320, 240))
+
+ log.do_testcase(
+ 'pixeldata-missing.bmp',
+ bitmap_missingpixeldata(320, 240))
+
+ log.do_testcase(
+ '32bpp-pixeldata-cropped.bmp',
+ bitmap_32bpp_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ '24bpp-pixeldata-cropped.bmp',
+ bitmap_24bpp_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ '555-pixeldata-cropped.bmp',
+ bitmap_555_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ '8bpp-pixeldata-cropped.bmp',
+ bitmap_8bpp_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ '4bpp-pixeldata-cropped.bmp',
+ bitmap_4bpp_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ '1bpp-pixeldata-cropped.bmp',
+ bitmap_1bpp_croppedpixeldata(320, 240))
+
+ log.do_testcase(
+ 'rle4-runlength-cropped.bmp',
+ bitmap_rle4_croppedrun(320, 240))
+
+ log.do_testcase(
+ 'rle4-absolute-cropped.bmp',
+ bitmap_rle4_croppedabsolute(320, 240))
+
+ log.do_testcase(
+ 'rle4-delta-cropped.bmp',
+ bitmap_rle4_croppeddelta(320, 240))
+
+ log.do_testcase(
+ 'rle4-no-end-of-line-marker.bmp',
+ bitmap_rle4_noendofline(320, 240))
+
+ log.do_testcase(
+ 'rle8-runlength-cropped.bmp',
+ bitmap_rle8_croppedrun(320, 240))
+
+ log.do_testcase(
+ 'rle8-absolute-cropped.bmp',
+ bitmap_rle8_croppedabsolute(320, 240))
+
+ log.do_testcase(
+ 'rle8-delta-cropped.bmp',
+ bitmap_rle8_croppeddelta(320, 240))
+
+ log.do_testcase(
+ 'rle8-no-end-of-line-marker.bmp',
+ bitmap_rle8_noendofline(320, 240))
+
+ # write out the HTML index
+ log.write_index('index.html')
+
+if __name__ == "__main__":
+
+ generate_valid_bitmaps()
+ generate_questionable_bitmaps()
+ generate_corrupt_bitmaps()
-----------------------------------------------------------------------
Summary of changes:
tests/Makefile | 1 +
tests/loaders/Makefile | 2 +-
tests/loaders/data/bmp/README | 4 +
.../data/bmp/bitmaps/corrupt/1bpp-no-palette.bmp | Bin 0 -> 9654 bytes
.../bmp/bitmaps/corrupt/1bpp-pixeldata-cropped.bmp | Bin 0 -> 4841 bytes
.../bitmaps/corrupt/24bpp-pixeldata-cropped.bmp | Bin 0 -> 114773 bytes
.../bitmaps/corrupt/32bpp-pixeldata-cropped.bmp | Bin 0 -> 153013 bytes
.../data/bmp/bitmaps/corrupt/4bpp-no-palette.bmp | Bin 0 -> 38454 bytes
.../bmp/bitmaps/corrupt/4bpp-pixeldata-cropped.bmp | Bin 0 -> 19197 bytes
.../bmp/bitmaps/corrupt/555-pixeldata-cropped.bmp | Bin 0 -> 76533 bytes
.../bitmaps/corrupt/8bpp-colorsimportant-large.bmp | Bin 0 -> 76878 bytes
.../corrupt/8bpp-colorsimportant-negative.bmp | Bin 0 -> 76878 bytes
.../bmp/bitmaps/corrupt/8bpp-colorsused-large.bmp | Bin 0 -> 76878 bytes
.../bitmaps/corrupt/8bpp-colorsused-negative.bmp | Bin 0 -> 76878 bytes
.../data/bmp/bitmaps/corrupt/8bpp-no-palette.bmp | Bin 0 -> 76854 bytes
.../bmp/bitmaps/corrupt/8bpp-pixeldata-cropped.bmp | Bin 0 -> 38317 bytes
.../data/bmp/bitmaps/corrupt/bitdepth-large.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/corrupt/bitdepth-odd.bmp | Bin 0 -> 76878 bytes
.../data/bmp/bitmaps/corrupt/bitdepth-zero.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/corrupt/colormasks-cropped.bmp | Bin 0 -> 65 bytes
.../bmp/bitmaps/corrupt/colormasks-missing.bmp | Bin 0 -> 54 bytes
.../corrupt/compression-bad-rle4-for-8bpp.bmp | Bin 0 -> 4134 bytes
.../corrupt/compression-bad-rle8-for-4bpp.bmp | Bin 0 -> 4134 bytes
.../bmp/bitmaps/corrupt/compression-unknown.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/corrupt/fileinfoheader-cropped.bmp | Bin 0 -> 13 bytes
.../data/bmp/bitmaps/corrupt/height-zero.bmp | Bin 0 -> 9662 bytes
tests/loaders/data/bmp/bitmaps/corrupt/index.html | 444 +++
.../bmp/bitmaps/corrupt/infoheader-cropped.bmp | Bin 0 -> 53 bytes
.../bmp/bitmaps/corrupt/infoheader-missing.bmp | Bin 0 -> 14 bytes
.../bmp/bitmaps/corrupt/infoheadersize-large.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/corrupt/infoheadersize-small.bmp | Bin 0 -> 9646 bytes
.../bmp/bitmaps/corrupt/infoheadersize-zero.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/corrupt/magicnumber-bad.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/corrupt/magicnumber-cropped.bmp | 1 +
.../data/bmp/bitmaps/corrupt/offbits-large.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/corrupt/offbits-negative.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/corrupt/offbits-zero.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/corrupt/palette-cropped.bmp | Bin 0 -> 61 bytes
.../data/bmp/bitmaps/corrupt/palette-missing.bmp | Bin 0 -> 54 bytes
.../data/bmp/bitmaps/corrupt/palette-too-big.bmp | Bin 0 -> 29662 bytes
.../data/bmp/bitmaps/corrupt/pixeldata-missing.bmp | Bin 0 -> 54 bytes
.../bmp/bitmaps/corrupt/rle4-absolute-cropped.bmp | Bin 0 -> 20367 bytes
.../bmp/bitmaps/corrupt/rle4-delta-cropped.bmp | Bin 0 -> 1781 bytes
.../bitmaps/corrupt/rle4-no-end-of-line-marker.bmp | Bin 0 -> 3654 bytes
.../bmp/bitmaps/corrupt/rle4-runlength-cropped.bmp | Bin 0 -> 1983 bytes
.../bmp/bitmaps/corrupt/rle8-absolute-cropped.bmp | Bin 0 -> 39695 bytes
.../bmp/bitmaps/corrupt/rle8-delta-cropped.bmp | Bin 0 -> 2741 bytes
.../bmp/bitmaps/corrupt/rle8-deltaleavesimage.bmp | Bin 0 -> 4138 bytes
.../bitmaps/corrupt/rle8-no-end-of-line-marker.bmp | Bin 0 -> 3654 bytes
.../bmp/bitmaps/corrupt/rle8-runlength-cropped.bmp | Bin 0 -> 1983 bytes
.../data/bmp/bitmaps/corrupt/width-negative.bmp | Bin 0 -> 9662 bytes
.../corrupt/width-times-height-overflow.bmp | Bin 0 -> 153666 bytes
.../data/bmp/bitmaps/corrupt/width-zero.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/questionable/32bpp-0x0.bmp | Bin 0 -> 54 bytes
.../data/bmp/bitmaps/questionable/32bpp-0x240.bmp | Bin 0 -> 54 bytes
.../data/bmp/bitmaps/questionable/32bpp-320x0.bmp | Bin 0 -> 54 bytes
.../questionable/8bpp-pixels-not-in-palette.bmp | Bin 0 -> 32830 bytes
.../data/bmp/bitmaps/questionable/filesize-bad.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/questionable/filesize-zero.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/questionable/index.html | 197 ++
.../questionable/pels-per-meter-x-large.bmp | Bin 0 -> 76878 bytes
.../questionable/pels-per-meter-x-negative.bmp | Bin 0 -> 76878 bytes
.../bitmaps/questionable/pels-per-meter-x-zero.bmp | Bin 0 -> 76878 bytes
.../questionable/pels-per-meter-y-large.bmp | Bin 0 -> 76878 bytes
.../questionable/pels-per-meter-y-negative.bmp | Bin 0 -> 76878 bytes
.../bitmaps/questionable/pels-per-meter-y-zero.bmp | Bin 0 -> 76878 bytes
.../questionable/pixeldata-rle8-toomuch.bmp | Bin 0 -> 8188 bytes
.../bmp/bitmaps/questionable/pixeldata-toomuch.bmp | Bin 0 -> 19262 bytes
.../data/bmp/bitmaps/questionable/planes-large.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/questionable/planes-zero.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/questionable/reserved1-bad.bmp | Bin 0 -> 9662 bytes
.../bmp/bitmaps/questionable/reserved2-bad.bmp | Bin 0 -> 9662 bytes
.../bitmaps/questionable/rle4-height-negative.bmp | Bin 0 -> 4134 bytes
.../questionable/rle4-no-end-of-bitmap-marker.bmp | Bin 0 -> 4132 bytes
.../bitmaps/questionable/rle8-height-negative.bmp | Bin 0 -> 4134 bytes
.../questionable/rle8-no-end-of-bitmap-marker.bmp | Bin 0 -> 4132 bytes
tests/loaders/data/bmp/bitmaps/valid/1bpp-1x1.bmp | Bin 0 -> 66 bytes
.../data/bmp/bitmaps/valid/1bpp-320x240-color.bmp | Bin 0 -> 9662 bytes
.../valid/1bpp-320x240-overlappingcolor.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/valid/1bpp-320x240.bmp | Bin 0 -> 9662 bytes
.../data/bmp/bitmaps/valid/1bpp-321x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-322x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-323x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-324x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-325x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-326x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-327x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-328x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-329x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-330x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-331x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-332x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-333x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-334x240.bmp | Bin 0 -> 10622 bytes
.../data/bmp/bitmaps/valid/1bpp-335x240.bmp | Bin 0 -> 10622 bytes
.../bmp/bitmaps/valid/1bpp-topdown-320x240.bmp | Bin 0 -> 9662 bytes
tests/loaders/data/bmp/bitmaps/valid/24bpp-1x1.bmp | Bin 0 -> 58 bytes
.../data/bmp/bitmaps/valid/24bpp-320x240.bmp | Bin 0 -> 230454 bytes
.../data/bmp/bitmaps/valid/24bpp-321x240.bmp | Bin 0 -> 231414 bytes
.../data/bmp/bitmaps/valid/24bpp-322x240.bmp | Bin 0 -> 232374 bytes
.../data/bmp/bitmaps/valid/24bpp-323x240.bmp | Bin 0 -> 233334 bytes
.../bmp/bitmaps/valid/24bpp-imagesize-zero.bmp | Bin 0 -> 230454 bytes
.../bmp/bitmaps/valid/24bpp-topdown-320x240.bmp | Bin 0 -> 230454 bytes
.../bmp/bitmaps/valid/32bpp-101110-320x240.bmp | Bin 0 -> 307266 bytes
tests/loaders/data/bmp/bitmaps/valid/32bpp-1x1.bmp | Bin 0 -> 58 bytes
.../data/bmp/bitmaps/valid/32bpp-320x240.bmp | Bin 0 -> 307254 bytes
.../valid/32bpp-888-optimalpalette-320x240.bmp | Bin 0 -> 307290 bytes
.../bitmaps/valid/32bpp-optimalpalette-320x240.bmp | Bin 0 -> 307278 bytes
.../bmp/bitmaps/valid/32bpp-topdown-320x240.bmp | Bin 0 -> 307254 bytes
tests/loaders/data/bmp/bitmaps/valid/4bpp-1x1.bmp | Bin 0 -> 82 bytes
.../data/bmp/bitmaps/valid/4bpp-320x240.bmp | Bin 0 -> 38478 bytes
.../data/bmp/bitmaps/valid/4bpp-321x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-322x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-323x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-324x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-325x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-326x240.bmp | Bin 0 -> 39438 bytes
.../data/bmp/bitmaps/valid/4bpp-327x240.bmp | Bin 0 -> 39438 bytes
.../bmp/bitmaps/valid/4bpp-topdown-320x240.bmp | Bin 0 -> 38478 bytes
tests/loaders/data/bmp/bitmaps/valid/555-1x1.bmp | Bin 0 -> 58 bytes
.../loaders/data/bmp/bitmaps/valid/555-320x240.bmp | Bin 0 -> 153654 bytes
.../loaders/data/bmp/bitmaps/valid/555-321x240.bmp | Bin 0 -> 154614 bytes
tests/loaders/data/bmp/bitmaps/valid/565-1x1.bmp | Bin 0 -> 70 bytes
.../data/bmp/bitmaps/valid/565-320x240-topdown.bmp | Bin 0 -> 153666 bytes
.../loaders/data/bmp/bitmaps/valid/565-320x240.bmp | Bin 0 -> 153666 bytes
.../data/bmp/bitmaps/valid/565-321x240-topdown.bmp | Bin 0 -> 154626 bytes
.../loaders/data/bmp/bitmaps/valid/565-321x240.bmp | Bin 0 -> 154626 bytes
.../data/bmp/bitmaps/valid/565-322x240-topdown.bmp | Bin 0 -> 154626 bytes
.../loaders/data/bmp/bitmaps/valid/565-322x240.bmp | Bin 0 -> 154626 bytes
tests/loaders/data/bmp/bitmaps/valid/8bpp-1x1.bmp | Bin 0 -> 82 bytes
.../data/bmp/bitmaps/valid/8bpp-1x64000.bmp | Bin 0 -> 256078 bytes
.../data/bmp/bitmaps/valid/8bpp-320x240.bmp | Bin 0 -> 76878 bytes
.../data/bmp/bitmaps/valid/8bpp-321x240.bmp | Bin 0 -> 77838 bytes
.../data/bmp/bitmaps/valid/8bpp-322x240.bmp | Bin 0 -> 77838 bytes
.../data/bmp/bitmaps/valid/8bpp-323x240.bmp | Bin 0 -> 77838 bytes
.../bmp/bitmaps/valid/8bpp-colorsimportant-two.bmp | Bin 0 -> 76878 bytes
.../bmp/bitmaps/valid/8bpp-colorsused-zero.bmp | Bin 0 -> 77878 bytes
.../bmp/bitmaps/valid/8bpp-topdown-320x240.bmp | Bin 0 -> 76878 bytes
tests/loaders/data/bmp/bitmaps/valid/index.html | 421 +++
.../bmp/bitmaps/valid/rle4-absolute-320x240.bmp | Bin 0 -> 40400 bytes
.../bmp/bitmaps/valid/rle4-alternate-320x240.bmp | Bin 0 -> 4142 bytes
.../data/bmp/bitmaps/valid/rle4-delta-320x240.bmp | Bin 0 -> 3686 bytes
.../bmp/bitmaps/valid/rle4-encoded-320x240.bmp | Bin 0 -> 4134 bytes
.../data/bmp/bitmaps/valid/rle8-64000x1.bmp | Bin 0 -> 586 bytes
.../bmp/bitmaps/valid/rle8-absolute-320x240.bmp | Bin 0 -> 78800 bytes
.../data/bmp/bitmaps/valid/rle8-blank-160x120.bmp | Bin 0 -> 1080 bytes
.../data/bmp/bitmaps/valid/rle8-delta-320x240.bmp | Bin 0 -> 4646 bytes
.../bmp/bitmaps/valid/rle8-encoded-320x240.bmp | Bin 0 -> 4134 bytes
tests/loaders/data/bmp/bmptestsuite.py | 3639 ++++++++++++++++++++
tests/loaders/loaders_suite.c | 93 +
150 files changed, 4801 insertions(+), 1 deletions(-)
create mode 100644 tests/loaders/data/bmp/README
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/1bpp-no-palette.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/1bpp-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/24bpp-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/32bpp-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/4bpp-no-palette.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/4bpp-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/555-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsimportant-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-colorsused-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-no-palette.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/8bpp-pixeldata-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-odd.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/bitdepth-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/colormasks-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/colormasks-missing.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle4-for-8bpp.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/compression-bad-rle8-for-4bpp.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/compression-unknown.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/emptyfile.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/fileinfoheader-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/height-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/index.html
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/infoheader-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/infoheader-missing.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-small.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/infoheadersize-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-bad.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/magicnumber-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/offbits-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/offbits-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/offbits-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/palette-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/palette-missing.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/palette-too-big.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/pixeldata-missing.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle4-absolute-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle4-delta-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle4-no-end-of-line-marker.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle4-runlength-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle8-absolute-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle8-delta-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle8-deltaleavesimage.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle8-no-end-of-line-marker.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/rle8-runlength-cropped.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/width-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/width-times-height-overflow.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/corrupt/width-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x0.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/32bpp-0x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/32bpp-320x0.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/8bpp-pixels-not-in-palette.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/filesize-bad.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/filesize-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/index.html
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-x-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pels-per-meter-y-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pixeldata-rle8-toomuch.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/pixeldata-toomuch.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/planes-large.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/planes-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/reserved1-bad.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/reserved2-bad.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/rle4-height-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/rle4-no-end-of-bitmap-marker.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/rle8-height-negative.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/questionable/rle8-no-end-of-bitmap-marker.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-color.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240-overlappingcolor.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-322x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-323x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-324x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-325x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-326x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-327x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-328x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-329x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-330x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-331x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-332x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-333x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-334x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-335x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/1bpp-topdown-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-322x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-323x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-imagesize-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/24bpp-topdown-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-101110-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-888-optimalpalette-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-optimalpalette-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/32bpp-topdown-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-322x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-323x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-324x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-325x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-326x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-327x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/4bpp-topdown-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/555-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/555-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/555-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-320x240-topdown.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-321x240-topdown.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-322x240-topdown.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/565-322x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-1x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-1x64000.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-321x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-322x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-323x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsimportant-two.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-colorsused-zero.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/8bpp-topdown-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/index.html
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle4-absolute-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle4-alternate-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle4-delta-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle4-encoded-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle8-64000x1.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle8-absolute-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle8-blank-160x120.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle8-delta-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bitmaps/valid/rle8-encoded-320x240.bmp
create mode 100644 tests/loaders/data/bmp/bmptestsuite.py
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: d20862dc07b9b8858ca929d9b91caa1eb6d88bbc
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 d20862dc07b9b8858ca929d9b91caa1eb6d88bbc (commit)
from 9ac2eb1478d0582c8e52b467aab9bf5a40a33fd2 (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/d20862dc07b9b8858ca929d9b91caa1eb6d8…
commit d20862dc07b9b8858ca929d9b91caa1eb6d88bbc
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 18:23:39 2012 +0200
tests: core: Start core tests using new framework.
diff --git a/tests/core/Makefile b/tests/core/Makefile
index c848cb0..bafa3c2 100644
--- a/tests/core/Makefile
+++ b/tests/core/Makefile
@@ -2,14 +2,24 @@ TOPDIR=../..
include $(TOPDIR)/pre.mk
+#CSOURCES=$(shell echo *.c)
+
+# hack
LIBNAME=core
-TESTSUITE=core_suite
-LDLIBS+=-lGP -L$(TOPDIR)/build/ -lcheck -lm -lSDL
-GENSOURCES+=GP_Convert.test.gen.c GP_WritePixel.test.gen.c - GP_MixPixels.test.gen.c
-all: $(TESTSUITE)
+LDFLAGS+=-L../framework/ -L$(TOPDIR)/build/
+LDLIBS+=$(shell $(TOPDIR)/gfxprim-config --libs --libs-loaders)
+LDLIBS+=-ltst_preload -ldl -ltst
+CFLAGS+=-I../framework/
-include $(TOPDIR)/tests.mk
-include $(TOPDIR)/post.mk
+GENSOURCES+=WritePixel_testsuite.gen.c
+
+APPS=WritePixel_testsuite.gen
+$(APPS): ../framework/libtst.a
+
+CLEAN+=log.html log.json
+
+include $(TOPDIR)/gen.mk
+include $(TOPDIR)/app.mk
+include $(TOPDIR)/post.mk
diff --git a/tests/core/WritePixel_testsuite.gen.c.t b/tests/core/WritePixel_testsuite.gen.c.t
new file mode 100644
index 0000000..a554e9b
--- /dev/null
+++ b/tests/core/WritePixel_testsuite.gen.c.t
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ * 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> *
+ * *
+ *****************************************************************************/
+
+%% extends "base.test.c.t"
+
+%% block body
+
+#include <stdio.h>
+
+#include "GP_WritePixel.h"
+
+#include "tst_test.h"
+
+static void dump_buffer(const char *name, char *buf, unsigned int buf_len)
+{
+ unsigned int i;
+
+ printf("%s:n{", name);
+
+ for (i = 0; i < buf_len; i++) {
+ printf("%i", !!buf[i]);
+
+ if (i != buf_len - 1)
+ printf(", ");
+
+ if (i % 26 == 25)
+ printf("n ");
+ }
+
+ printf("}n");
+}
+
+/*
+ * Compares two statically defined buffers
+ */
+#define COMPARE_BUFFERS(id, buf1, buf2) do { + unsigned int buf1_len = sizeof(buf1)/sizeof(*buf1); + unsigned int buf2_len = sizeof(buf2)/sizeof(*buf2); + unsigned int i; + + if (buf1_len != buf2_len) { + tst_report(0, "Invalid buffers"); + return TST_FAILED; + } + + for (i = 0; i < buf1_len; i++) + if(buf1[i] != buf2[i]) { + printf("%sn", id); + dump_buffer("wrote", buf1, buf1_len); + dump_buffer("gen", buf2, buf2_len); + tst_report(0, "Buffers are different"); + return TST_FAILED; + } + + return
TST_SUCCESS; +} while (0)
+
+%% for pixelsize in [8, 16, 24, 32]
+%% for offset in range(0, 4)
+%% for len in range(0, 6)
+%% for aligment in [0, 1]
+static int WritePixel{{ "_%i_%i_%i_%i"|format(pixelsize, offset, len, aligment) }}(void)
+//, {{ ""offset=%i, len=%i, aligment=%i,""|format(offset, len, aligment) }})
+{
+ char write_buf[{{ 25 * pixelsize//8 }}] = {};
+ char gen_buf[{{ 25 * pixelsize//8 }}] = {};
+
+ /*
+ * Fill the compare buffer
+ */
+%% for i in range(0, len)
+%% for j in range(0, pixelsize//8)
+ gen_buf[{{aligment + offset * pixelsize//8 + i * pixelsize//8 + j}}] = 0xff;
+%% endfor
+%% endfor
+
+ GP_WritePixels{{ pixelsize }}bpp(write_buf + {{aligment + offset * pixelsize//8}}, {{ len }}, 0xffffffff>>{{32 - pixelsize}});
+
+ COMPARE_BUFFERS({{""p=%i o=%i l=%i a=%i""|format(pixelsize, offset, len, aligment)}}, write_buf, gen_buf);
+}
+%% endfor
+%% endfor
+%% endfor
+%% endfor
+
+const struct tst_suite tst_suite = {
+ .suite_name = "WritePixel Testsuite",
+ .tests = {
+%% for pixelsize in [8, 16, 24, 32]
+%% for offset in range(0, 4)
+%% for len in range(0, 6)
+%% for aligment in [0, 1]
+ {.name = "WritePixel {{ pixelsize }} {{ offset }} {{ len }} {{ aligment }}",
+ .tst_fn = WritePixel{{ "_%i_%i_%i_%i"|format(pixelsize, offset, len, aligment) }}},
+%% endfor
+%% endfor
+%% endfor
+%% endfor
+ {.name = NULL}
+ }
+};
+
+%% endblock body
diff --git a/tests/core/runtest.sh b/tests/core/runtest.sh
new file mode 100755
index 0000000..0a9821e
--- /dev/null
+++ b/tests/core/runtest.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+#
+# By default the glibc __libc_message() writes to /dev/tty before calling
+# the abort(). Exporting this macro makes it to use stderr instead.
+#
+# The main usage of the function are malloc assertions, so this makes us catch
+# the malloc error message by catching stderr output.
+#
+export LIBC_FATAL_STDERR_=1
+
+LD_PRELOAD=`pwd`/../framework/libtst_preload.so LD_LIBRARY_PATH=../../build/ ./WritePixel_testsuite.gen "$@"
diff --git a/tests/core/GP_Blit.test.c b/tests/core_old/GP_Blit.test.c
similarity index 100%
rename from tests/core/GP_Blit.test.c
rename to tests/core_old/GP_Blit.test.c
diff --git a/tests/core/GP_Common.test.c b/tests/core_old/GP_Common.test.c
similarity index 100%
rename from tests/core/GP_Common.test.c
rename to tests/core_old/GP_Common.test.c
diff --git a/tests/core/GP_Convert.test.c b/tests/core_old/GP_Convert.test.c
similarity index 100%
rename from tests/core/GP_Convert.test.c
rename to tests/core_old/GP_Convert.test.c
diff --git a/tests/core/GP_Convert.test.gen.c.t b/tests/core_old/GP_Convert.test.gen.c.t
similarity index 100%
rename from tests/core/GP_Convert.test.gen.c.t
rename to tests/core_old/GP_Convert.test.gen.c.t
diff --git a/tests/core/GP_Counter.test.c b/tests/core_old/GP_Counter.test.c
similarity index 100%
rename from tests/core/GP_Counter.test.c
rename to tests/core_old/GP_Counter.test.c
diff --git a/tests/core/GP_MixPixels.test.gen.c.t b/tests/core_old/GP_MixPixels.test.gen.c.t
similarity index 100%
rename from tests/core/GP_MixPixels.test.gen.c.t
rename to tests/core_old/GP_MixPixels.test.gen.c.t
diff --git a/tests/core/GP_WritePixel.test.gen.c.t b/tests/core_old/GP_WritePixel.test.gen.c.t
similarity index 100%
rename from tests/core/GP_WritePixel.test.gen.c.t
rename to tests/core_old/GP_WritePixel.test.gen.c.t
diff --git a/tests/core/Makefile b/tests/core_old/Makefile
similarity index 100%
copy from tests/core/Makefile
copy to tests/core_old/Makefile
-----------------------------------------------------------------------
Summary of changes:
tests/core/Makefile | 24 +++-
tests/core/WritePixel_testsuite.gen.c.t | 122 ++++++++++++++++++++
tests/{loaders => core}/runtest.sh | 2 +-
tests/{core => core_old}/GP_Blit.test.c | 0
tests/{core => core_old}/GP_Common.test.c | 0
tests/{core => core_old}/GP_Convert.test.c | 0
tests/{core => core_old}/GP_Convert.test.gen.c.t | 0
tests/{core => core_old}/GP_Counter.test.c | 0
tests/{core => core_old}/GP_MixPixels.test.gen.c.t | 0
.../{core => core_old}/GP_WritePixel.test.gen.c.t | 0
tests/{core => core_old}/Makefile | 0
11 files changed, 140 insertions(+), 8 deletions(-)
create mode 100644 tests/core/WritePixel_testsuite.gen.c.t
copy tests/{loaders => core}/runtest.sh (89%)
rename tests/{core => core_old}/GP_Blit.test.c (100%)
rename tests/{core => core_old}/GP_Common.test.c (100%)
rename tests/{core => core_old}/GP_Convert.test.c (100%)
rename tests/{core => core_old}/GP_Convert.test.gen.c.t (100%)
rename tests/{core => core_old}/GP_Counter.test.c (100%)
rename tests/{core => core_old}/GP_MixPixels.test.gen.c.t (100%)
rename tests/{core => core_old}/GP_WritePixel.test.gen.c.t (100%)
copy tests/{core => core_old}/Makefile (100%)
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: 9ac2eb1478d0582c8e52b467aab9bf5a40a33fd2
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 9ac2eb1478d0582c8e52b467aab9bf5a40a33fd2 (commit)
from 727d637ad22f615be1b18741e3efd9a829dfed2b (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/9ac2eb1478d0582c8e52b467aab9bf5a40a3…
commit 9ac2eb1478d0582c8e52b467aab9bf5a40a33fd2
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 17:52:26 2012 +0200
tests: framework: Fix stupid typo.
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index ad71ba8..a1f7272 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -333,7 +333,7 @@ static int tst_job_benchmark(struct tst_job *job)
/* Send data to parent */
write_timespec(job, 'M', &sum);
- write_timespec(job, 'D', &dev);
+ write_timespec(job, 'V', &dev);
return TST_SUCCESS;
}
@@ -522,7 +522,7 @@ void tst_job_wait(struct tst_job *job)
sizeof(job->malloc_stats));
break;
default:
- //TODO: internal error
+ tst_warn("parent: Invalid characters received");
break;
}
}
-----------------------------------------------------------------------
Summary of changes:
tests/framework/tst_job.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
[repo.or.cz] gfxprim.git branch master updated: 727d637ad22f615be1b18741e3efd9a829dfed2b
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 727d637ad22f615be1b18741e3efd9a829dfed2b (commit)
from c86751325f6076b6ea840a1a689b99e30f6c35ca (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/727d637ad22f615be1b18741e3efd9a829df…
commit 727d637ad22f615be1b18741e3efd9a829dfed2b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 17:12:42 2012 +0200
tests: framework: A little cleanup.
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index c02fa9f..ad71ba8 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -60,7 +60,7 @@ void tst_diff_timespec(int *sec, int *nsec, struct timespec *start,
}
}
-#define NAME_PADD 23
+#define NAME_PADD 21
static void stop_test(struct tst_job *job)
{
@@ -109,7 +109,7 @@ static void stop_test(struct tst_job *job)
for (i = strlen(name); i < NAME_PADD; i++)
fprintf(stderr, " ");
- fprintf(stderr, " finished (Time %2i.%03is, CPU %2i.%03is) %sn",
+ fprintf(stderr, " finished (Time %3i.%03is, CPU %3i.%03is) %sn",
sec, nsec/1000000,
(int)job->cpu_time.tv_sec,
(int)job->cpu_time.tv_nsec/1000000,
@@ -215,14 +215,12 @@ static void prepare_tmpdir(const char *name, const char *res_path,
static void write_timespec(struct tst_job *job, char type,
struct timespec *time)
{
- char buf[1 + sizeof(time_t) + sizeof(long)];
+ char buf[1 + sizeof(struct timespec)];
char *ptr = buf;
*(ptr++) = type;
-
- *((time_t*)ptr) = time->tv_sec;
- ptr += sizeof(time_t);
- *((long*)ptr) = time->tv_nsec;
+
+ memcpy(ptr, time, sizeof(*time));
if (write(job->pipefd, buf, sizeof(buf)) != sizeof(buf))
tst_warn("write(timespec) failed: %s", strerror(errno));
@@ -233,15 +231,14 @@ static void write_timespec(struct tst_job *job, char type,
*/
static void read_timespec(struct tst_job *job, struct timespec *time)
{
- char buf[sizeof(time_t) + sizeof(long)];
- char *ptr = buf;
+ int ret;
- if (read(job->pipefd, buf, sizeof(buf)) != sizeof(buf))
- tst_warn("read(timespec) failed: %s", strerror(errno));
+ do {
+ ret = read(job->pipefd, time, sizeof(*time));
+ } while (ret == 0);
- time->tv_sec = *((time_t*)ptr);
- ptr += sizeof(time_t);
- time->tv_nsec = *(long*)(ptr);
+ if (ret < 0 || ret != sizeof(*time))
+ tst_warn("read(timespec) failed: %s", strerror(errno));
}
static void child_write(struct tst_job *job, char ch, void *ptr, ssize_t size)
-----------------------------------------------------------------------
Summary of changes:
tests/framework/tst_job.c | 25 +++++++++++--------------
1 files changed, 11 insertions(+), 14 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: c86751325f6076b6ea840a1a689b99e30f6c35ca
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 c86751325f6076b6ea840a1a689b99e30f6c35ca (commit)
via 8bb3bbff3bf468349be5b2fdd18a3faf4e17a5cb (commit)
via 39db9b12008710da657d2fe0aaf3486a2a497a8f (commit)
from f6e4b62561d2fa6b7bcc94a24ba3fdaa1763aafe (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/c86751325f6076b6ea840a1a689b99e30f6c…
commit c86751325f6076b6ea840a1a689b99e30f6c35ca
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 15:26:19 2012 +0200
tests: Sketch gfx benchmarks.
diff --git a/tests/Makefile b/tests/Makefile
index f965da6..f4fc735 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,8 +1,9 @@
TOPDIR=..
include $(TOPDIR)/pre.mk
-SUBDIRS=core SDL drivers framework loaders
+SUBDIRS=core SDL drivers framework loaders gfx
loaders: framework
+gfx: framework
include $(TOPDIR)/post.mk
diff --git a/tests/gfx/Makefile b/tests/gfx/Makefile
new file mode 100644
index 0000000..ec97b78
--- /dev/null
+++ b/tests/gfx/Makefile
@@ -0,0 +1,18 @@
+TOPDIR=../..
+include $(TOPDIR)/pre.mk
+
+CSOURCES=$(shell echo *.c)
+
+LDFLAGS+=-L../framework/ -L$(TOPDIR)/build/
+LDLIBS+=$(shell $(TOPDIR)/gfxprim-config --libs --libs-loaders)
+LDLIBS+=-ltst_preload -ldl -ltst
+CFLAGS+=-I../framework/
+
+APPS=gfx_benchmark
+
+$(APPS): ../framework/libtst.a
+
+CLEAN+=log.html log.json
+
+include $(TOPDIR)/app.mk
+include $(TOPDIR)/post.mk
diff --git a/tests/gfx/gfx_benchmark.c b/tests/gfx/gfx_benchmark.c
new file mode 100644
index 0000000..0ec61c6
--- /dev/null
+++ b/tests/gfx/gfx_benchmark.c
@@ -0,0 +1,142 @@
+/*****************************************************************************
+ * 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 <core/GP_Context.h>
+#include <gfx/GP_Gfx.h>
+
+#include "tst_test.h"
+
+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;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < 100000; i++) {
+ GP_Line(img, 0 + i % 100, 0 - i % 100,
+ 800 - i%200, 600 + i%200, i % 0xff);
+ }
+
+ return TST_SUCCESS;
+}
+
+static int bench_line_1bpp(void)
+{
+ return bench_line(GP_PIXEL_G1);
+}
+
+static int bench_line_2bpp(void)
+{
+ return bench_line(GP_PIXEL_G2);
+}
+
+static int bench_line_4bpp(void)
+{
+ return bench_line(GP_PIXEL_G4);
+}
+
+static int bench_line_8bpp(void)
+{
+ return bench_line(GP_PIXEL_G8);
+}
+
+static int bench_line_32bpp(void)
+{
+ return bench_line(GP_PIXEL_RGB888);
+}
+
+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;
+ }
+
+ unsigned int i;
+
+ for (i = 0; i < 100000; i++) {
+ GP_Circle(img, img->w/2, img->h/2, i % 1000, i%0xff);
+ }
+
+ return TST_SUCCESS;
+}
+
+static int bench_circle_1bpp(void)
+{
+ return bench_circle(GP_PIXEL_G1);
+}
+
+static int bench_circle_2bpp(void)
+{
+ return bench_circle(GP_PIXEL_G2);
+}
+
+static int bench_circle_4bpp(void)
+{
+ return bench_circle(GP_PIXEL_G4);
+}
+
+static int bench_circle_8bpp(void)
+{
+ return bench_circle(GP_PIXEL_G8);
+}
+
+static int bench_circle_32bpp(void)
+{
+ return bench_circle(GP_PIXEL_RGB888);
+}
+
+const struct tst_suite tst_suite = {
+ .suite_name = "GFX Benchmark",
+ .tests = {
+ {.name = "Line 1BPP", .tst_fn = bench_line_1bpp,
+ .bench_iter = 10},
+ {.name = "Line 2BPP", .tst_fn = bench_line_2bpp,
+ .bench_iter = 10},
+ {.name = "Line 4BPP", .tst_fn = bench_line_4bpp,
+ .bench_iter = 10},
+ {.name = "Line 8BPP", .tst_fn = bench_line_8bpp,
+ .bench_iter = 10},
+ {.name = "Line 32BPP", .tst_fn = bench_line_32bpp,
+ .bench_iter = 10},
+
+ {.name = "Circle 1BPP", .tst_fn = bench_circle_1bpp,
+ .bench_iter = 10},
+ {.name = "Circle 2BPP", .tst_fn = bench_circle_2bpp,
+ .bench_iter = 10},
+ {.name = "Circle 4BPP", .tst_fn = bench_circle_4bpp,
+ .bench_iter = 10},
+ {.name = "Circle 8BPP", .tst_fn = bench_circle_8bpp,
+ .bench_iter = 10},
+ {.name = "Circle 32BPP", .tst_fn = bench_circle_32bpp,
+ .bench_iter = 10},
+
+ {.name = NULL},
+ }
+};
diff --git a/tests/gfx/runtest.sh b/tests/gfx/runtest.sh
new file mode 100755
index 0000000..71a411b
--- /dev/null
+++ b/tests/gfx/runtest.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+#
+# By default the glibc __libc_message() writes to /dev/tty before calling
+# the abort(). Exporting this macro makes it to use stderr instead.
+#
+# The main usage of the function are malloc assertions, so this makes us catch
+# the malloc error message by catching stderr output.
+#
+export LIBC_FATAL_STDERR_=1
+
+LD_PRELOAD=`pwd`/../framework/libtst_preload.so LD_LIBRARY_PATH=../../build/ ./gfx_benchmark "$@"
http://repo.or.cz/w/gfxprim.git/commit/8bb3bbff3bf468349be5b2fdd18a3faf4e17…
commit 8bb3bbff3bf468349be5b2fdd18a3faf4e17a5cb
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 15:21:58 2012 +0200
tests: framework: Fix test job log output.
Aling better the output on runtime >= 10 sec.
diff --git a/tests/framework/test.c b/tests/framework/test.c
index 69a9978..f4a8692 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -238,7 +238,7 @@ const struct tst_suite tst_suite = {
{.name = "Failed FILE", .tst_fn = fail_FILE, .flags = TST_TMPDIR},
{.name = "Resource", .tst_fn = res_fn, .flags = TST_TMPDIR,
.res_path = "test.c"},
- {.name = "Floating point exception", .tst_fn = fpe_fn},
+ {.name = "FP exception", .tst_fn = fpe_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 a075c5f..c02fa9f 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -60,7 +60,7 @@ void tst_diff_timespec(int *sec, int *nsec, struct timespec *start,
}
}
-#define NAME_PADD 24
+#define NAME_PADD 23
static void stop_test(struct tst_job *job)
{
@@ -109,7 +109,7 @@ static void stop_test(struct tst_job *job)
for (i = strlen(name); i < NAME_PADD; i++)
fprintf(stderr, " ");
- fprintf(stderr, " finished (Time %i.%03is, CPU %i.%03is) %sn",
+ fprintf(stderr, " finished (Time %2i.%03is, CPU %2i.%03is) %sn",
sec, nsec/1000000,
(int)job->cpu_time.tv_sec,
(int)job->cpu_time.tv_nsec/1000000,
@@ -119,7 +119,7 @@ static void stop_test(struct tst_job *job)
for (i = 0; i < NAME_PADD; i++)
fprintf(stderr, " ");
- fprintf(stderr, " bench CPU %i.%06is +/- %i.%06isn",
+ 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,
http://repo.or.cz/w/gfxprim.git/commit/39db9b12008710da657d2fe0aaf3486a2a49…
commit 39db9b12008710da657d2fe0aaf3486a2a497a8f
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 15:01:33 2012 +0200
tests: framework: Add benchmark logic.
Now test could be marked as benchmark.
Such functions is executed several times
and mean and standard deviation are computed.
diff --git a/tests/framework/Makefile b/tests/framework/Makefile
index 709f907..7169bb7 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
+libtst.a: tst_test.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/test.c b/tests/framework/test.c
index 48fa872..69a9978 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -207,6 +207,20 @@ static int fpe_fn(void)
return 1/i;
}
+/*
+ * Let's benchmark memset.
+ */
+static int benchmark_fn(void)
+{
+ char buf[256];
+ unsigned int i;
+
+ for (i = 0; i < 4000000; i++)
+ memset(buf, i%100, sizeof(buf));
+
+ return TST_SUCCESS;
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Testing Framework Example",
.tests = {
@@ -225,6 +239,7 @@ const struct tst_suite tst_suite = {
{.name = "Resource", .tst_fn = res_fn, .flags = TST_TMPDIR,
.res_path = "test.c"},
{.name = "Floating point exception", .tst_fn = fpe_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 b27b358..a075c5f 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -30,10 +30,12 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <stdarg.h>
+#include <math.h>
#include "tst_preload.h"
#include "tst_test.h"
#include "tst_job.h"
+#include "tst_timespec.h"
/*
* Once we child forks to do a job, this points to its job structure.
@@ -112,6 +114,17 @@ static void stop_test(struct tst_job *job)
(int)job->cpu_time.tv_sec,
(int)job->cpu_time.tv_nsec/1000000,
result);
+
+ if (job->bench_iter) {
+ for (i = 0; i < NAME_PADD; i++)
+ fprintf(stderr, " ");
+
+ fprintf(stderr, " bench CPU %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);
@@ -265,6 +278,69 @@ int tst_report(int level, const char *fmt, ...)
return ret;
}
+/*
+ * Run benchmark job and compute result
+ */
+static int tst_job_benchmark(struct tst_job *job)
+{
+ unsigned int i, iter = job->test->bench_iter;
+ struct timespec cputime_start;
+ struct timespec cputime_stop;
+ struct timespec bench[iter];
+ struct timespec sum = {.tv_sec = 0, .tv_nsec = 0};
+ struct timespec dev = {.tv_sec = 0, .tv_nsec = 0};
+ int ret;
+
+ /* Warm up */
+ ret = job->test->tst_fn();
+
+ if (ret)
+ return ret;
+
+ /* Collect the data */
+ for (i = 0; i < iter; i++) {
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cputime_start);
+
+ ret = job->test->tst_fn();
+
+ if (ret)
+ return ret;
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cputime_stop);
+
+ timespec_sub(&cputime_stop, &cputime_start, &bench[i]);
+
+ timespec_add(&bench[i], &sum);
+ }
+
+ /* Compute mean */
+ timespec_div(&sum, iter);
+
+ double sum_d = timespec_to_double(&sum);
+ double dev_d = 0;
+
+ /* And standard deviation */
+ for (i = 0; i < iter; i++) {
+ double b = timespec_to_double(&bench[i]);
+
+ b -= sum_d;
+ b = b * b;
+
+ dev_d += b;
+ }
+
+ dev_d /= iter;
+ dev_d = sqrt(dev_d);
+
+ double_to_timespec(dev_d, &dev);
+
+ /* Send data to parent */
+ write_timespec(job, 'M', &sum);
+ write_timespec(job, 'D', &dev);
+
+ return TST_SUCCESS;
+}
+
void tst_job_run(struct tst_job *job)
{
int ret;
@@ -280,6 +356,9 @@ void tst_job_run(struct tst_job *job)
/* marks test as started */
start_test(job);
+ /* copy benchmark interation */
+ job->bench_iter = job->test->bench_iter;
+
if (pipe(pipefd)) {
tst_warn("pipefd() failed: %s", strerror(errno));
job->running = 0;
@@ -335,7 +414,10 @@ void tst_job_run(struct tst_job *job)
tst_malloc_check_start();
/* Run test */
- ret = job->test->tst_fn();
+ if (job->test->bench_iter)
+ ret = tst_job_benchmark(job);
+ else
+ ret = job->test->tst_fn();
if (job->test->flags & TST_CHECK_MALLOC) {
tst_malloc_check_stop();
@@ -426,6 +508,13 @@ void tst_job_wait(struct tst_job *job)
case 'C':
read_timespec(job, &job->cpu_time);
break;
+ /* benchmark data */
+ case 'M':
+ read_timespec(job, &job->bench_mean);
+ break;
+ case 'V':
+ read_timespec(job, &job->bench_var);
+ break;
/* test message as generated by tst_report() */
case 'm':
parent_read_msg(job);
diff --git a/tests/framework/tst_job.h b/tests/framework/tst_job.h
index 2e74a7d..76984e5 100644
--- a/tests/framework/tst_job.h
+++ b/tests/framework/tst_job.h
@@ -64,6 +64,11 @@ struct tst_job {
/* test result */
enum tst_ret result;
+ /* additional benchmark data */
+ unsigned int bench_iter;
+ struct timespec bench_mean;
+ struct timespec bench_var;
+
/*
* test malloc statistics, filled if TST_MALLOC_CHECK was set.
*/
diff --git a/tests/framework/tst_log.c b/tests/framework/tst_log.c
index 2991c0a..b1e43b8 100644
--- a/tests/framework/tst_log.c
+++ b/tests/framework/tst_log.c
@@ -186,6 +186,58 @@ static void malloc_stats_html(struct tst_job *job, FILE *f, const char *padd)
fprintf(f, "%s</tr>n", padd);
}
+static void benchmark_stats_html(struct tst_job *job, FILE *f, const char *padd)
+{
+ /* Create innter table */
+ fprintf(f, "%s<tr>n", padd);
+ fprintf(f, "%s <td bgcolor="#fd8" colspan="3">n", padd);
+ fprintf(f, "%s <center>n", padd);
+ fprintf(f, "%s <table>n", padd);
+
+ /* Create header */
+ fprintf(f, "%s <tr>n", padd);
+
+ fprintf(f, "%s <td colspan="2" bgcolor="#fb2">n", padd);
+ fprintf(f, "%s <center><small>Benchmark data", padd);
+ fprintf(f, "</small></center>n");
+ fprintf(f, "%s </td>n", padd);
+
+ fprintf(f, "%s </tr>n", padd);
+ fprintf(f, "%s <tr>n", padd);
+
+ fprintf(f, "%s <td bgcolor="#fc4">n", padd);
+ fprintf(f, "%s <center><small>Iterations", padd);
+ fprintf(f, "</small></center>n");
+ fprintf(f, "%s </td>n", padd);
+
+ fprintf(f, "%s <td bgcolor="#fc4">n", padd);
+ fprintf(f, "%s <center><small>Mean ∓ Variance", padd);
+ fprintf(f, "</small></center>n");
+ fprintf(f, "%s </td>n", padd);
+
+ fprintf(f, "%s </tr>n", padd);
+
+ /* Create data */
+ fprintf(f, "%s <tr>n", padd);
+
+ fprintf(f, "%s <td bgcolor="#fc4">n", padd);
+ fprintf(f, "%s <center>%i</center>n", padd, job->bench_iter);
+ fprintf(f, "%s </td>n", padd);
+
+ fprintf(f, "%s <td bgcolor="#fc4">n", padd);
+ fprintf(f, "%s <center>%i.%06is ∓ %i.%06is</center>n", padd,
+ (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);
+ fprintf(f, "%s </td>n", padd);
+
+ fprintf(f, "%s </tr>n", padd);
+
+ fprintf(f, "%s </table>n", padd);
+ fprintf(f, "%s </center>n", padd);
+ fprintf(f, "%s </td>n", padd);
+ fprintf(f, "%s</tr>n", padd);
+}
+
static int append_html(struct tst_job *job, FILE *f)
{
const char *padd = " ";
@@ -201,12 +253,15 @@ static int append_html(struct tst_job *job, FILE *f)
bgcol = "#ddddee";
fprintf(f, "%s<tr>n", padd);
- fprintf(f, "%s <td bgcolor="%s">%s </td>n", padd, bgcol, job->test->name);
+ fprintf(f, "%s <td bgcolor="%s">%s </td>n",
+ padd, bgcol, job->test->name);
fprintf(f, "%s <td bgcolor="%s">n", padd, bgcol);
- fprintf(f, "%s <center><small><font color="#222">%i.%03is %i.%03is</font></small></center>",
- padd, sec, nsec/1000000, (int)job->cpu_time.tv_sec, (int)job->cpu_time.tv_nsec/1000000);
+ fprintf(f, "%s <center><small><font color="#222">%i.%03is %i.%03is"
+ "</font></small></center>n", padd, sec, nsec/1000000,
+ (int)job->cpu_time.tv_sec, (int)job->cpu_time.tv_nsec/1000000);
fprintf(f, "%s </td>n", padd);
- fprintf(f, "%s <td bgcolor="%s"><center><font color="white"> %s </td></center>n", padd,
+ fprintf(f, "%s <td bgcolor="%s"><center><font color="white">"
+ " %s </td></center>n", padd,
ret_to_bg_color(job->result), ret_to_str(job->result));
struct tst_msg *msg;
@@ -215,10 +270,14 @@ static int append_html(struct tst_job *job, FILE *f)
if (job->test->flags & TST_CHECK_MALLOC)
malloc_stats_html(job, f, padd);
+ if (job->bench_iter)
+ benchmark_stats_html(job, f, padd);
+
for (msg = job->store.first; msg != NULL; msg = msg->next) {
fprintf(f, "%s<tr>n", padd);
fprintf(f, "%s <td colspan="3" bgcolor="#eeeeee">n", padd);
- fprintf(f, "%s <small>%s</small>n", padd, msg->msg);
+ fprintf(f, "%s <small>%s</small>n",
+ padd, msg->msg);
fprintf(f, "%s </td>n", padd);
fprintf(f, "%s</tr>n", padd);
}
@@ -268,6 +327,23 @@ static int append_malloc_stats_json(struct tst_job *job, FILE *f)
return 0;
}
+static void append_benchmark_json(struct tst_job *job, FILE *f)
+{
+ fprintf(f, "ttt"Benchmark": {n");
+
+ fprintf(f, "tttt"Time Mean": %i.%09i,n",
+ (int)job->bench_mean.tv_sec,
+ (int)job->bench_mean.tv_nsec);
+
+ fprintf(f, "tttt"Time Variance": %i.%09i,n",
+ (int)job->bench_var.tv_sec,
+ (int)job->bench_var.tv_nsec);
+
+ fprintf(f, "tttt"Iterations": %in", job->bench_iter);
+
+ fprintf(f, "ttt}n");
+}
+
static int hack_json_start = 0;
static int append_json(struct tst_job *job, FILE *f)
@@ -287,7 +363,11 @@ static int append_json(struct tst_job *job, FILE *f)
/* If calculated include malloc report */
if (job->test->flags & TST_CHECK_MALLOC)
append_malloc_stats_json(job, f);
-
+
+ /* If benchmark data were created */
+ if (job->bench_iter)
+ append_benchmark_json(job, f);
+
/* Time statistics */
int sec, nsec;
@@ -328,7 +408,8 @@ FILE *open_html(const struct tst_suite *suite, const char *path)
if (f == NULL)
return NULL;
- fprintf(f, "<html>n <head>n </head>n <body>n <table bgcolor="#99a">n");
+ fprintf(f, "<html>n <head>n </head>n <body>n "
+ "<table bgcolor="#99a">n");
fprintf(f, " <tr><td colspan="3" bgcolor="#bbbbff"><center><b>%s"
"</b></center></td></tr>n", suite->suite_name);
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index 195b040..b9a0c17 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -57,6 +57,13 @@ struct tst_test {
* test directory before test is executed.
*/
const char *res_path;
+ /*
+ * If not zero, the test is benchmark.
+ *
+ * The test_fn is executed bench_iter times and bench
+ * data are filled.
+ */
+ unsigned int bench_iter;
/* test function */
int (*tst_fn)(void);
/* time limit in seconds 0 == unlimited */
diff --git a/tests/framework/tst_job.h b/tests/framework/tst_timespec.c
similarity index 58%
copy from tests/framework/tst_job.h
copy to tests/framework/tst_timespec.c
index 2e74a7d..d388502 100644
--- a/tests/framework/tst_job.h
+++ b/tests/framework/tst_timespec.c
@@ -20,72 +20,58 @@
* *
*****************************************************************************/
- /*
-
- Test job is an instance of running test.
+#include "tst_timespec.h"
- */
+#define NSEC_IN_SEC 1000000000
-#ifndef TST_JOB_H
-#define TST_JOB_H
+double timespec_to_double(const struct timespec *t)
+{
+ double res;
+
+ res = t->tv_sec;
+ res *= NSEC_IN_SEC;
+ res += t->tv_nsec;
-#include <time.h>
+ return res;
+}
-#include "tst_msg.h"
-#include "tst_preload.h"
-#include "tst_test.h"
+void double_to_timespec(const double time, struct timespec *res)
+{
+ res->tv_sec = time / NSEC_IN_SEC;
+ res->tv_nsec = time - res->tv_sec * NSEC_IN_SEC;
+}
-struct tst_job {
- const struct tst_test *test;
-
- /*
- * Pipe fd.
- *
- * In parent this points to the read side of the pipe so the parent
- * recieves data from child.
- *
- * In child this points to the write side of the pipe so child can
- * send data to parent.
- */
- int pipefd;
-
- int running:1;
-
- /* test execution time */
- struct timespec start_time;
- struct timespec stop_time;
-
- /* test cpu time */
- struct timespec cpu_time;
+void timespec_sub(const struct timespec *a, const struct timespec *b,
+ struct timespec *res)
+{
+ res->tv_sec = a->tv_sec - b->tv_sec;
+ time_t nsec = a->tv_nsec;
- /* test pid */
- int pid;
-
- /* test result */
- enum tst_ret result;
+ if (b->tv_nsec > a->tv_nsec) {
+ res->tv_sec--;
+ nsec += NSEC_IN_SEC;
+ }
- /*
- * test malloc statistics, filled if TST_MALLOC_CHECK was set.
- */
- struct malloc_stats malloc_stats;
+ res->tv_nsec = nsec - b->tv_nsec;
+}
- /* store for test messages */
- struct tst_msg_store store;
-};
+void timespec_add(const struct timespec *a, struct timespec *res)
+{
+ res->tv_sec += a->tv_sec;
+ res->tv_nsec += a->tv_nsec;
-/*
- * Runs a test job as a separate process.
- *
- * The test field must point to correct test.
- */
-void tst_job_run(struct tst_job *job);
+ if (res->tv_nsec >= NSEC_IN_SEC) {
+ res->tv_sec += res->tv_nsec / NSEC_IN_SEC;
+ res->tv_nsec %= NSEC_IN_SEC;
+ }
+}
-/*
- * Waits for the test to finish.
- */
-void tst_job_wait(struct tst_job *job);
+void timespec_div(struct timespec *res, unsigned int div)
+{
+ long sec = res->tv_sec;
-void tst_diff_timespec(int *sec, int *nsec, struct timespec *start,
- struct timespec *stop);
+ res->tv_sec /= div;
+ sec %= div;
-#endif /* TST_JOB_H */
+ res->tv_nsec = (sec * NSEC_IN_SEC + res->tv_nsec)/div;
+}
diff --git a/tests/framework/tst_job.h b/tests/framework/tst_timespec.h
similarity index 58%
copy from tests/framework/tst_job.h
copy to tests/framework/tst_timespec.h
index 2e74a7d..25d010c 100644
--- a/tests/framework/tst_job.h
+++ b/tests/framework/tst_timespec.h
@@ -22,70 +22,24 @@
/*
- Test job is an instance of running test.
+ Timespec manipulation utils.
*/
-#ifndef TST_JOB_H
-#define TST_JOB_H
+#ifndef TST_TIMESPEC_H
+#define TST_TIMESPEC_H
#include <time.h>
-#include "tst_msg.h"
-#include "tst_preload.h"
-#include "tst_test.h"
+double timespec_to_double(const struct timespec *t);
-struct tst_job {
- const struct tst_test *test;
-
- /*
- * Pipe fd.
- *
- * In parent this points to the read side of the pipe so the parent
- * recieves data from child.
- *
- * In child this points to the write side of the pipe so child can
- * send data to parent.
- */
- int pipefd;
-
- int running:1;
-
- /* test execution time */
- struct timespec start_time;
- struct timespec stop_time;
-
- /* test cpu time */
- struct timespec cpu_time;
+void double_to_timespec(const double time, struct timespec *res);
- /* test pid */
- int pid;
-
- /* test result */
- enum tst_ret result;
+void timespec_sub(const struct timespec *a, const struct timespec *b,
+ struct timespec *res);
- /*
- * test malloc statistics, filled if TST_MALLOC_CHECK was set.
- */
- struct malloc_stats malloc_stats;
+void timespec_add(const struct timespec *a, struct timespec *res);
- /* store for test messages */
- struct tst_msg_store store;
-};
+void timespec_div(struct timespec *res, unsigned int div);
-/*
- * Runs a test job as a separate process.
- *
- * The test field must point to correct test.
- */
-void tst_job_run(struct tst_job *job);
-
-/*
- * Waits for the test to finish.
- */
-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 */
+#endif /* TST_TIMESPEC_H */
-----------------------------------------------------------------------
Summary of changes:
tests/Makefile | 3 +-
tests/framework/Makefile | 2 +-
tests/framework/test.c | 17 +++-
tests/framework/tst_job.c | 95 +++++++++++++-
tests/framework/tst_job.h | 5 +
tests/framework/tst_log.c | 95 ++++++++++++-
tests/framework/tst_test.h | 7 +
tests/framework/{tst_msg.c => tst_timespec.c} | 77 +++++------
.../cpu_timer.h => tests/framework/tst_timespec.h | 39 +++---
tests/{loaders => gfx}/Makefile | 4 +-
tests/gfx/gfx_benchmark.c | 142 ++++++++++++++++++++
tests/{loaders => gfx}/runtest.sh | 2 +-
12 files changed, 409 insertions(+), 79 deletions(-)
copy tests/framework/{tst_msg.c => tst_timespec.c} (61%)
copy demos/spiv/cpu_timer.h => tests/framework/tst_timespec.h (78%)
copy tests/{loaders => gfx}/Makefile (83%)
create mode 100644 tests/gfx/gfx_benchmark.c
copy tests/{loaders => gfx}/runtest.sh (91%)
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: f6e4b62561d2fa6b7bcc94a24ba3fdaa1763aafe
by metan 13 Oct '12
by metan 13 Oct '12
13 Oct '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 f6e4b62561d2fa6b7bcc94a24ba3fdaa1763aafe (commit)
via bd67135bcd6d8ac8a8df924588988663837be998 (commit)
via bbb09186311fc102ad68bfd94156ba4982176b83 (commit)
from 9e00a730ea2ab2545b46298056b32841ad3500d4 (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/f6e4b62561d2fa6b7bcc94a24ba3fdaa1763…
commit f6e4b62561d2fa6b7bcc94a24ba3fdaa1763aafe
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Oct 13 09:34:46 2012 +0200
tests: framework: Count correctly passed and skipped.
diff --git a/tests/framework/tst_test.c b/tests/framework/tst_test.c
index 2cc94a5..1981302 100644
--- a/tests/framework/tst_test.c
+++ b/tests/framework/tst_test.c
@@ -87,15 +87,19 @@ void tst_run_suite(const struct tst_suite *suite, const char *tst_name)
if (tst_name == NULL || !strcmp(tst_name, suite->tests[i].name)) {
ret = run_test(&suite->tests[i], html, json);
counters[ret]++;
- counter++;
+
+ if (ret != TST_SKIPPED)
+ counter++;
}
}
tst_log_close(html, TST_LOG_HTML);
tst_log_close(json, TST_LOG_JSON);
- fprintf(stderr, "nSummary: succedded %u out of %u (%.2f%%)n",
- counters[0], counter, 100.00 * counters[0] / counter);
+ fprintf(stderr, "nSummary: succedded %u out of "
+ "%u %.2f%% (skipped %u)n",
+ counters[0], counter, 100.00 * counters[0] / counter,
+ counters[TST_SKIPPED]);
}
void tst_list_suite(const struct tst_suite *suite)
http://repo.or.cz/w/gfxprim.git/commit/bd67135bcd6d8ac8a8df924588988663837b…
commit bd67135bcd6d8ac8a8df924588988663837be998
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Oct 12 23:44:37 2012 +0200
tests: framework: Add Floating Point Exception error.
diff --git a/tests/framework/test.c b/tests/framework/test.c
index a47d67d..48fa872 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -199,6 +199,14 @@ static int res_fn(void)
return TST_SUCCESS;
}
+static int fpe_fn(void)
+{
+ /* its volatile so compiler doesn't detect the division by zero */
+ volatile int i = 0;
+
+ return 1/i;
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Testing Framework Example",
.tests = {
@@ -216,6 +224,7 @@ const struct tst_suite tst_suite = {
{.name = "Failed FILE", .tst_fn = fail_FILE, .flags = TST_TMPDIR},
{.name = "Resource", .tst_fn = res_fn, .flags = TST_TMPDIR,
.res_path = "test.c"},
+ {.name = "Floating point exception", .tst_fn = fpe_fn},
{.name = NULL},
}
};
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index 79ae3e2..b27b358 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -87,6 +87,9 @@ static void stop_test(struct tst_job *job)
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;
@@ -455,6 +458,13 @@ void tst_job_wait(struct tst_job *job)
case SIGALRM:
job->result = TST_TIMEOUT;
break;
+ /*
+ * Floating point exception, most likely
+ * division by zero (including integer division)
+ */
+ case SIGFPE:
+ job->result = TST_FPE;
+ break;
/*
* abort() called most likely double free or malloc data
* corruption
diff --git a/tests/framework/tst_log.c b/tests/framework/tst_log.c
index 5ab46a6..2991c0a 100644
--- a/tests/framework/tst_log.c
+++ b/tests/framework/tst_log.c
@@ -44,6 +44,8 @@ static const char *ret_to_bg_color(enum tst_ret ret)
return "#800080";
case TST_ABORTED:
return "#e00000";
+ case TST_FPE:
+ return "#e00000";
case TST_MEMLEAK:
return "#a0a000";
case TST_FAILED:
@@ -70,6 +72,8 @@ static const char *ret_to_str(enum tst_ret ret)
return "Timeout";
case TST_ABORTED:
return "Aborted";
+ case TST_FPE:
+ return "FP Exception";
case TST_MEMLEAK:
return "Memory Leak";
case TST_FAILED:
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index c329112..195b040 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -30,6 +30,7 @@ enum tst_ret {
TST_SIGSEGV, /* Test ended with SIGSEGV */
TST_TIMEOUT, /* Test hasn't finished in time */
TST_ABORTED, /* The abort() was called (possible double free) */
+ TST_FPE, /* Floating point exception */
TST_MEMLEAK, /* Memory leak was detected */
TST_FAILED, /* Test failed */
TST_MAX = TST_FAILED+1,
http://repo.or.cz/w/gfxprim.git/commit/bbb09186311fc102ad68bfd94156ba498217…
commit bbb09186311fc102ad68bfd94156ba4982176b83
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Oct 12 22:32:59 2012 +0200
tests: framework: Add resource path.
diff --git a/tests/framework/test.c b/tests/framework/test.c
index 0e9e9df..a47d67d 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -191,6 +191,14 @@ static int skipped_fn(void)
return TST_SKIPPED;
}
+static int res_fn(void)
+{
+ if (access("test.c", R_OK) == 0)
+ tst_report(0, "File correctly copied");
+
+ return TST_SUCCESS;
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Testing Framework Example",
.tests = {
@@ -206,6 +214,8 @@ const struct tst_suite tst_suite = {
{.name = "Double free()", .tst_fn = double_free},
{.name = "Barrier allocation", .tst_fn = barrier_allocation},
{.name = "Failed FILE", .tst_fn = fail_FILE, .flags = TST_TMPDIR},
+ {.name = "Resource", .tst_fn = res_fn, .flags = TST_TMPDIR,
+ .res_path = "test.c"},
{.name = NULL},
}
};
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index 227edd5..79ae3e2 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -146,16 +146,18 @@ static void remove_tmpdir(const char *path)
}
/*
- * Create temp directory and cd into it
+ * Create temp directory and cd into it, copy resources if needed
*/
-static void create_tmpdir(const char *name, char *template, size_t size)
+static void prepare_tmpdir(const char *name, const char *res_path,
+ char *template, size_t size)
{
- char safe_name[256];
+ char tmp[256];
+ int ret;
/* Fix any funny characters in the test name */
- snprintf(safe_name, sizeof(safe_name), "%s", name);
+ snprintf(tmp, sizeof(tmp), "%s", name);
- char *s = safe_name;
+ char *s = tmp;
while (*s != '0') {
if (!isalnum(*s))
@@ -164,13 +166,27 @@ static void create_tmpdir(const char *name, char *template, size_t size)
}
/* Create template from test name */
- snprintf(template, size, "/tmp/ctest_%s_XXXXXX", safe_name);
+ snprintf(template, size, "/tmp/ctest_%s_XXXXXX", tmp);
if (mkdtemp(template) == NULL) {
tst_warn("mkdtemp(%s) failed: %s", template, strerror(errno));
exit(TST_INTERR);
}
+ /* Copy resources if needed */
+ if (res_path != NULL) {
+ snprintf(tmp, sizeof(tmp), "cp -r '%s' '%s'",
+ res_path, template);
+
+ ret = system(tmp);
+
+ if (ret) {
+ tst_warn("failed to copy resource '%s'", res_path);
+ exit(TST_INTERR);
+ }
+ }
+
+
if (chdir(template)) {
tst_warn("chdir(%s) failed: %s", template, strerror(errno));
exit(TST_INTERR);
@@ -297,7 +313,8 @@ void tst_job_run(struct tst_job *job)
/* Create directory in /tmp/ and chdir into it. */
if (job->test->flags & TST_TMPDIR)
- create_tmpdir(job->test->name, template, sizeof(template));
+ prepare_tmpdir(job->test->name, job->test->res_path,
+ template, sizeof(template));
/*
* If timeout is specified, setup alarm.
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index 4eb97e0..c329112 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -49,7 +49,13 @@ enum tst_flags {
};
struct tst_test {
+ /* test name */
const char *name;
+ /*
+ * Resurce path, file or directory which is copied to
+ * test directory before test is executed.
+ */
+ const char *res_path;
/* test function */
int (*tst_fn)(void);
/* time limit in seconds 0 == unlimited */
-----------------------------------------------------------------------
Summary of changes:
tests/framework/test.c | 19 +++++++++++++++++++
tests/framework/tst_job.c | 41 ++++++++++++++++++++++++++++++++++-------
tests/framework/tst_log.c | 4 ++++
tests/framework/tst_test.c | 10 +++++++---
tests/framework/tst_test.h | 7 +++++++
5 files changed, 71 insertions(+), 10 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: 9e00a730ea2ab2545b46298056b32841ad3500d4
by metan 09 Oct '12
by metan 09 Oct '12
09 Oct '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 9e00a730ea2ab2545b46298056b32841ad3500d4 (commit)
from 2370df5de0e544ff861f5c18a9ddb430d306301e (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/9e00a730ea2ab2545b46298056b32841ad35…
commit 9e00a730ea2ab2545b46298056b32841ad3500d4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Wed Oct 3 16:44:29 2012 +0200
tests: framework: Fix typos & warnings.
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index f483578..227edd5 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -116,7 +116,8 @@ static void stop_test(struct tst_job *job)
/* Now print test message store */
tst_msg_print(&job->store);
- fprintf(stderr, "------------------------------------------------------------------------------- n");
+ fprintf(stderr, "------------------------------------------------------"
+ "------------------------- n");
}
/*
@@ -129,14 +130,19 @@ static void remove_tmpdir(const char *path)
*/
if (!strncmp("/tmp/", path, sizeof("/tmp/"))) {
tst_warn("Path '%s' doesn't start with /tmp/, "
- "ommiting cleanup", path);
+ "omitting cleanup", path);
return;
}
//TODO: Cleaner solution?
char buf[256];
+ int ret;
+
snprintf(buf, sizeof(buf), "rm -rf '%s'", path);
- (void)system(buf);
+ ret = system(buf);
+
+ if (ret)
+ tst_warn("Failed to clean temp dir.");
}
/*
@@ -146,7 +152,7 @@ static void create_tmpdir(const char *name, char *template, size_t size)
{
char safe_name[256];
- /* Fix any funny characters in test name */
+ /* Fix any funny characters in the test name */
snprintf(safe_name, sizeof(safe_name), "%s", name);
char *s = safe_name;
@@ -160,7 +166,6 @@ static void create_tmpdir(const char *name, char *template, size_t size)
/* Create template from test name */
snprintf(template, size, "/tmp/ctest_%s_XXXXXX", safe_name);
-
if (mkdtemp(template) == NULL) {
tst_warn("mkdtemp(%s) failed: %s", template, strerror(errno));
exit(TST_INTERR);
@@ -227,13 +232,16 @@ int tst_report(int level, const char *fmt, ...)
va_start(va, fmt);
ret = vsnprintf(buf+3, sizeof(buf) - 3, fmt, va);
va_end(va);
+
+ ssize_t size = ret > 255 ? 255 : ret + 1;
buf[0] = 'm';
buf[1] = level;
- ((unsigned char*)buf)[2] = ret > 255 ? 255 : ret + 1;
+ ((unsigned char*)buf)[2] = size;
if (my_job != NULL)
- write(my_job->pipefd, buf, (int)buf[2] + 3);
+ if (write(my_job->pipefd, buf, size + 3) != size + 3)
+ tst_warn("Failed to write msg to pipe.");
return ret;
}
@@ -250,6 +258,7 @@ 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);
if (pipe(pipefd)) {
@@ -312,7 +321,8 @@ void tst_job_run(struct tst_job *job)
tst_malloc_check_stop();
tst_malloc_check_report(&job->malloc_stats);
- child_write(job, 's', &job->malloc_stats, sizeof(job->malloc_stats));
+ child_write(job, 's', &job->malloc_stats,
+ sizeof(job->malloc_stats));
if (job->malloc_stats.lost_chunks != 0 && ret == TST_SUCCESS)
ret = TST_MEMLEAK;
@@ -344,7 +354,7 @@ static void parent_read_msg(struct tst_job *job)
char buf[header[1]];
- if (read(job->pipefd, buf, sizeof(buf)) != sizeof(buf))
+ if (read(job->pipefd, buf, sizeof(buf)) != (ssize_t)sizeof(buf))
tst_warn("parent: read(message) failed: %s", strerror(errno));
/* null-terminated the string, to be extra sure */
-----------------------------------------------------------------------
Summary of changes:
tests/framework/tst_job.c | 28 +++++++++++++++++++---------
1 files changed, 19 insertions(+), 9 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
1
0
[repo.or.cz] gfxprim.git branch master updated: 2370df5de0e544ff861f5c18a9ddb430d306301e
by metan 27 Sep '12
by metan 27 Sep '12
27 Sep '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 2370df5de0e544ff861f5c18a9ddb430d306301e (commit)
via 62334a32c731a5452fb460a76373c7ee7e241d8b (commit)
via 78a4c679dd65e8dca7ffedc1e58357036baf9917 (commit)
via 9134135c2343714cde81a93c58cee3111d80aa48 (commit)
via ea25d6c8a8b8ecb3a1f874d05a2c5705de7b8837 (commit)
via 8fa145ac2bca9ebb15fd25965c6d9afe5b2de7a0 (commit)
via 94aa52632f9ade7a52a8e419b9e2d1b6309e57a2 (commit)
via f8b2d14ae8aa2c8fb6f64ccae23cc8298eea3381 (commit)
via e4a59032ce9295e40e84c5003d5e813553b52f2e (commit)
via c643ecb4b3d832e7b3afeff095c3f453ee3d573f (commit)
via b3b68550f6431afd3dd5a441e38212d09b22bdda (commit)
via 3095a596cffe0dca94e5a773828af6fc0365f9d4 (commit)
from f7abc056071b6987bd8ddf3b3e21b76fb2faa593 (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/2370df5de0e544ff861f5c18a9ddb430d306…
commit 2370df5de0e544ff861f5c18a9ddb430d306301e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 14:10:53 2012 +0200
doc: Cleaned up loaders docs, more to come.
diff --git a/doc/loaders.txt b/doc/loaders.txt
index 0f31498..99ed35d 100644
--- a/doc/loaders.txt
+++ b/doc/loaders.txt
@@ -1,18 +1,26 @@
Context loaders
---------------
-This part of gfxprim library aims to create API to load/save images from/to
-common image file formats.
+This part of GFXprim library aims to create API to load and save images
+from/to common image file formats.
All loading functions returns a pointer to allocated and loaded image or upon
-a failure 'NULL' is returned and 'errno' is set.
+a failure 'NULL' and 'errno' is set.
-The possible errno values are:
+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.
-* anything returned by fopen(), fclose(), fseek(), ...
-* 'ENOSYS' if library wasn't compiled with particular library support
-* 'ENOMEM' as returned by malloc()
-* 'EIO'/'EILSEQ' invalid image data
-* 'ECANCELED' loading canceled from callback
+The possible 'errno' values (for both loading and saving) are:
+
+* anything returned by +open()+, +close()+, +lseek()+, +read()+, +write()+, ...
+ - 'ENOENT' if file doesn't exist
+ - 'EACCES' if process doesn't have rights
+ - etc.
+
+* 'ENOSYS' if GFXprim wasn't compiled with particular library support
+* 'ENOMEM' if returned by +malloc()+
+* 'EIO' invalid image data (wrong signature, header or image data)
+* 'ECANCELED' action canceled by returning non-zero from within a callback
Common Loader
~~~~~~~~~~~~~
@@ -27,7 +35,8 @@ 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.
-File signature loading method is on the TODO.
+Fallback to file signature if file content doesn't match it's extension is on
+the TODO.
[source,c]
-------------------------------------------------------------------------------
@@ -44,16 +53,11 @@ 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'.
-Returns zero on success and non-zero on failure and 'errno' is set. The
-possible errno values are 'ENOSYS' for unknown format and anything that could
-be returned by 'fopen()', 'open()', 'fwrite()', 'write()', 'seek()', etc...
-
PNG
~~~
-The 'PNG' loading support is optionally implemented by libpng.
+The 'PNG' image support is implemented by the libpng library.
-Just now, the 'PNG' support is not fully finished. Images with alpha channel
-are not supported yet.
+WARNING: PNG images with alpha channel are not supported yet.
[source,c]
-------------------------------------------------------------------------------
@@ -68,8 +72,6 @@ Opens file and checks for 'PNG' signature. Returns zero on success (file
could be opened, signature matches), the opened file is returned and the file
position points right after the end of the 'PNG' signature.
-Upon failure 'errno' is filled.
-
This function is semi-internal, you should rather use functions listed below.
[source,c]
@@ -108,17 +110,13 @@ int GP_SavePNG(const GP_Context *src, const char *dst_path,
GP_ProgressCallback *callback);
-------------------------------------------------------------------------------
-Writes a Context into a 'PNG' image. If aborted by a callback, the opened file
-is closed and removed before the call returns non-zero and 'errno' is set to
-'ECANCELED'.
-
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
~~~~
-The 'JPEG' loading support is optionally implemented by jpeg library.
+The 'JPEG' image support is implemented by the jpeg library.
[source,c]
-------------------------------------------------------------------------------
@@ -185,7 +183,7 @@ convert the context into one of them before this functions is called.
GIF
~~~
-The 'GIF' format is supported optionally by giflib library.
+The 'GIF' image support is implemented by the giflib library.
[source,c]
-------------------------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/62334a32c731a5452fb460a76373c7ee7e24…
commit 62334a32c731a5452fb460a76373c7ee7e241d8b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 13:31:13 2012 +0200
tests: framework: slight change in html output.
diff --git a/tests/framework/tst_log.c b/tests/framework/tst_log.c
index 7c6a82c..5ab46a6 100644
--- a/tests/framework/tst_log.c
+++ b/tests/framework/tst_log.c
@@ -186,12 +186,19 @@ static int append_html(struct tst_job *job, FILE *f)
{
const char *padd = " ";
int sec, nsec;
+ static int hack_counter = 0;
+ const char *bgcol;
tst_diff_timespec(&sec, &nsec, &job->start_time, &job->stop_time);
+ if (hack_counter)
+ bgcol = "#ccccee";
+ else
+ bgcol = "#ddddee";
+
fprintf(f, "%s<tr>n", padd);
- fprintf(f, "%s <td bgcolor="#ccccee">%s </td>n", padd, job->test->name);
- fprintf(f, "%s <td bgcolor="#ccccee">n", padd);
+ fprintf(f, "%s <td bgcolor="%s">%s </td>n", padd, bgcol, job->test->name);
+ fprintf(f, "%s <td bgcolor="%s">n", padd, bgcol);
fprintf(f, "%s <center><small><font color="#222">%i.%03is %i.%03is</font></small></center>",
padd, sec, nsec/1000000, (int)job->cpu_time.tv_sec, (int)job->cpu_time.tv_nsec/1000000);
fprintf(f, "%s </td>n", padd);
@@ -213,7 +220,9 @@ static int append_html(struct tst_job *job, FILE *f)
}
fprintf(f, "%s</tr>n", padd);
-
+
+ hack_counter = !hack_counter;
+
return 0;
}
http://repo.or.cz/w/gfxprim.git/commit/78a4c679dd65e8dca7ffedc1e58357036baf…
commit 78a4c679dd65e8dca7ffedc1e58357036baf9917
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 13:18:45 2012 +0200
loaders: bmp: Fix errno on invalid signature.
diff --git a/libs/loaders/GP_BMP.c b/libs/loaders/GP_BMP.c
index d7ac6c5..0b1f7f5 100644
--- a/libs/loaders/GP_BMP.c
+++ b/libs/loaders/GP_BMP.c
@@ -535,7 +535,7 @@ int GP_OpenBMP(const char *src_path, FILE **f,
GP_DEBUG(1, "Unexpected bitmap header 0x%02x (%c) 0x%02x (%c)",
ch1, isascii(ch1) ? ch1 : ' ',
ch2, isascii(ch2) ? ch2 : ' ');
- err = EILSEQ;
+ err = EIO;
goto err1;
}
http://repo.or.cz/w/gfxprim.git/commit/9134135c2343714cde81a93c58cee3111d80…
commit 9134135c2343714cde81a93c58cee3111d80aa48
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 13:18:04 2012 +0200
tests: loaders: Add tests for EIO.
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index b35b855..aa2fa92 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -58,8 +58,6 @@ static int save_img(enum fmt fmt, const GP_Context *img, const char *name)
snprintf(buf, sizeof(buf), "%s.%s", name, strfmt(fmt));
- tst_report(0, "Saving %s", buf);
-
switch (fmt) {
case PNG:
return GP_SavePNG(img, buf, NULL);
@@ -257,6 +255,63 @@ static int test_BMP_Load_EACCES(void)
return load_eacces(BMP);
}
+static int load_eio(enum fmt fmt)
+{
+ char buf[256];
+ GP_Context *img;
+
+ snprintf(buf, sizeof(buf), "test.%s", strfmt(fmt));
+
+ FILE *f = fopen(buf, "w");
+
+ if (f == NULL) {
+ tst_report(0, "Failed to create file 'test'");
+ return TST_INTERR;
+ }
+
+ fclose(f);
+
+ img = load(fmt, "test");
+
+ if (img != NULL) {
+ tst_report(0, "Test succedded unexpectedly");
+ return TST_FAILED;
+ }
+
+ if (errno == ENOSYS) {
+ tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ return TST_SKIPPED;
+ }
+
+ if (errno != EIO) {
+ tst_report(0, "Expected errno = EIO, have %s",
+ strerror(errno));
+ return TST_FAILED;
+ }
+
+ return TST_SUCCESS;
+}
+
+static int test_PNG_Load_EIO(void)
+{
+ return load_eio(PNG);
+}
+
+static int test_JPG_Load_EIO(void)
+{
+ return load_eio(JPG);
+}
+
+static int test_GIF_Load_EIO(void)
+{
+ return load_eio(GIF);
+}
+
+static int test_BMP_Load_EIO(void)
+{
+ return load_eio(BMP);
+}
+
/*
* We test that a correct cleanup is done after aborting the image load from a
* callback.
@@ -460,6 +515,15 @@ const struct tst_suite tst_suite = {
{.name = "BMP Load EACCES", .tst_fn = test_BMP_Load_EACCES,
.flags = TST_TMPDIR},
+ {.name = "PNG Load EIO", .tst_fn = test_PNG_Load_EIO,
+ .flags = TST_TMPDIR},
+ {.name = "JPG Load EIO", .tst_fn = test_JPG_Load_EIO,
+ .flags = TST_TMPDIR},
+ {.name = "GIF Load EIO", .tst_fn = test_GIF_Load_EIO,
+ .flags = TST_TMPDIR},
+ {.name = "BMP Load EIO", .tst_fn = test_BMP_Load_EIO,
+ .flags = TST_TMPDIR},
+
/* Generic GP_LoadImage test */
{.name = "Image Load", .tst_fn = test_Load,
.flags = TST_TMPDIR},
http://repo.or.cz/w/gfxprim.git/commit/ea25d6c8a8b8ecb3a1f874d05a2c5705de7b…
commit ea25d6c8a8b8ecb3a1f874d05a2c5705de7b8837
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 13:11:16 2012 +0200
loaders: gif: Fix errno handling.
diff --git a/libs/loaders/GP_GIF.c b/libs/loaders/GP_GIF.c
index 15e0c44..262e5d9 100644
--- a/libs/loaders/GP_GIF.c
+++ b/libs/loaders/GP_GIF.c
@@ -48,11 +48,21 @@ int GP_OpenGIF(const char *src_path, void **f)
{
GifFileType *gf;
+ errno = 0;
+
gf = DGifOpenFileName(src_path);
if (gf == NULL) {
- //TODO: error handling
- errno = EIO;
+ /*
+ * The giflib uses open() so when we got a failure and errno
+ * is set => open() has failed.
+ *
+ * When errno is not set the file content was not valid so we
+ * set errno to EIO.
+ */
+ if (errno == 0)
+ errno = EIO;
+
return 1;
}
http://repo.or.cz/w/gfxprim.git/commit/8fa145ac2bca9ebb15fd25965c6d9afe5b2d…
commit 8fa145ac2bca9ebb15fd25965c6d9afe5b2de7a0
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 12:58:39 2012 +0200
tests: loaders: Add tests for EACCES + cleanup.
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index 5736829..b35b855 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -22,6 +22,7 @@
#include <string.h>
#include <errno.h>
+#include <sys/stat.h>
#include <core/GP_Context.h>
#include <loaders/GP_Loaders.h>
@@ -32,6 +33,7 @@ enum fmt {
PNG,
JPG,
GIF,
+ BMP,
};
static const char *strfmt(enum fmt fmt)
@@ -43,35 +45,66 @@ static const char *strfmt(enum fmt fmt)
return "JPG";
case GIF:
return "GIF";
+ case BMP:
+ return "BMP";
};
return "INVALID";
}
-static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
+static int save_img(enum fmt fmt, const GP_Context *img, const char *name)
{
- GP_Context *img, *res = NULL;
+ char buf[256];
- img = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
-
- if (img == NULL) {
- tst_report(0, "GP_ContextAlloc failed");
- return TST_FAILED;
+ snprintf(buf, sizeof(buf), "%s.%s", name, strfmt(fmt));
+
+ tst_report(0, "Saving %s", buf);
+
+ switch (fmt) {
+ case PNG:
+ return GP_SavePNG(img, buf, NULL);
+ case JPG:
+ return GP_SaveJPG(img, buf, NULL);
+ default:
+ tst_report(0, "WARNING: trying to save %s", strfmt(fmt));
+ exit(TST_INTERR);
}
+}
+
+static GP_Context *load(enum fmt fmt, const char *name)
+{
+ char buf[256];
- int ret = 1;
+ snprintf(buf, sizeof(buf), "%s.%s", name, strfmt(fmt));
switch (fmt) {
case PNG:
- ret = GP_SavePNG(img, "test.png", NULL);
- break;
+ return GP_LoadPNG(buf, NULL);
case JPG:
- ret = GP_SaveJPG(img, "test.jpg", NULL);
- break;
+ return GP_LoadJPG(buf, NULL);
+ case GIF:
+ return GP_LoadGIF(buf, NULL);
+ case BMP:
+ return GP_LoadBMP(buf, NULL);
default:
+ tst_report(0, "WARNING: trying to load %s", strfmt(fmt));
+ exit(TST_INTERR);
+ }
+}
+
+static int save_load(enum fmt fmt, GP_Size w, GP_Size h)
+{
+ GP_Context *img, *res;
+
+ img = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
+
+ if (img == NULL) {
+ tst_report(0, "GP_ContextAlloc failed");
return TST_INTERR;
}
+ int ret = save_img(fmt, img, "test");
+
if (ret) {
if (errno == ENOSYS) {
tst_report(0, "Save %s: ENOSYS", strfmt(fmt));
@@ -83,16 +116,7 @@ static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
return TST_FAILED;
}
- switch (fmt) {
- case PNG:
- res = GP_LoadPNG("test.png", NULL);
- break;
- case JPG:
- res = GP_LoadJPG("test.jpg", NULL);
- break;
- default:
- return TST_INTERR;
- }
+ res = load(fmt, "test");
if (res == NULL) {
tst_report(0, "Failed to load %s: %s",
@@ -106,41 +130,31 @@ static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
return TST_SUCCESS;
}
-static int test_PNG_Load_Save(void)
+static int test_PNG_Save_Load(void)
{
- return load_save(PNG, 100, 100);
+ return save_load(PNG, 100, 100);
}
-static int test_JPG_Load_Save(void)
+static int test_JPG_Save_Load(void)
{
- return load_save(JPG, 100, 100);
+ return save_load(JPG, 100, 100);
}
static int test_PNG_stress(void)
{
- return load_save(PNG, 2000, 2000);
+ return save_load(PNG, 2000, 2000);
}
static int test_JPG_stress(void)
{
- return load_save(JPG, 2000, 2000);
+ return save_load(JPG, 2000, 2000);
}
static int load_enoent(enum fmt fmt)
{
- GP_Context *img = NULL;
-
- switch (fmt) {
- case PNG:
- img = GP_LoadPNG("nonexistent.png", NULL);
- break;
- case JPG:
- img = GP_LoadJPG("nonexistent.jpg", NULL);
- break;
- case GIF:
- img = GP_LoadGIF("nonexistent.gif", NULL);
- break;
- }
+ GP_Context *img;
+
+ img = load(fmt, "nonexistent");
if (img != NULL) {
tst_report(0, "Test succedded unexpectedly");
@@ -176,15 +190,82 @@ static int test_GIF_Load_ENOENT(void)
return load_enoent(GIF);
}
-static int abort_callback(GP_ProgressCallback *self __attribute__((unused)))
+static int test_BMP_Load_ENOENT(void)
{
- return 1;
+ return load_enoent(BMP);
+}
+
+static int load_eacces(enum fmt fmt)
+{
+ char buf[256];
+ GP_Context *img;
+
+ snprintf(buf, sizeof(buf), "test.%s", strfmt(fmt));
+
+ FILE *f = fopen(buf, "w");
+
+ if (f == NULL) {
+ tst_report(0, "Failed to create file 'test'");
+ return TST_INTERR;
+ }
+
+ fclose(f);
+
+ if (chmod(buf, 200)) {
+ tst_report(0, "chmod failed: %s", strerror(errno));
+ return TST_INTERR;
+ }
+
+ img = load(fmt, "test");
+
+ if (img != NULL) {
+ tst_report(0, "Test succedded unexpectedly");
+ return TST_FAILED;
+ }
+
+ if (errno == ENOSYS) {
+ tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ return TST_SKIPPED;
+ }
+
+ if (errno != EACCES) {
+ tst_report(0, "Expected errno = EACCES, have %s",
+ strerror(errno));
+ return TST_FAILED;
+ }
+
+ return TST_SUCCESS;
+}
+
+static int test_PNG_Load_EACCES(void)
+{
+ return load_eacces(PNG);
+}
+
+static int test_JPG_Load_EACCES(void)
+{
+ return load_eacces(JPG);
+}
+
+static int test_GIF_Load_EACCES(void)
+{
+ return load_eacces(GIF);
+}
+
+static int test_BMP_Load_EACCES(void)
+{
+ return load_eacces(BMP);
}
/*
* We test that a correct cleanup is done after aborting the image load from a
* callback.
*/
+static int abort_callback(GP_ProgressCallback *self __attribute__((unused)))
+{
+ return 1;
+}
+
static int test_PNG_Save_abort(void)
{
GP_Context *img;
@@ -291,7 +372,7 @@ static struct file_testcase file_testcases[] = {
{"not_here.jpg", 0, ENOENT},
- //TODO: EPERM
+ //TODO: EACCES
{NULL, 0, 0}
};
@@ -328,7 +409,7 @@ static int test_Load(void)
continue;
}
- if (errno == ENOSYS) {
+ if (file_testcases[i].expected_errno != ENOSYS && errno == ENOSYS) {
tst_report(0, "Load Image '%s': ENOSYS",
file_testcases[i].filename);
continue;
@@ -360,26 +441,47 @@ static int test_Load(void)
const struct tst_suite tst_suite = {
.suite_name = "Image Loaders testsuite",
.tests = {
- {.name = "PNG Load/Save", .tst_fn = test_PNG_Load_Save,
- .flags = TST_TMPDIR | TST_CHECK_MALLOC},
- {.name = "JPG Load/Save", .tst_fn = test_JPG_Load_Save,
- .flags = TST_TMPDIR | TST_CHECK_MALLOC},
+ /* Correct errno tests */
{.name = "PNG Load ENOENT", .tst_fn = test_PNG_Load_ENOENT,
.flags = TST_TMPDIR},
{.name = "JPG Load ENOENT", .tst_fn = test_JPG_Load_ENOENT,
.flags = TST_TMPDIR},
{.name = "GIF Load ENOENT", .tst_fn = test_GIF_Load_ENOENT,
.flags = TST_TMPDIR},
+ {.name = "BMP Load ENOENT", .tst_fn = test_BMP_Load_ENOENT,
+ .flags = TST_TMPDIR},
+
+ {.name = "PNG Load EACCES", .tst_fn = test_PNG_Load_EACCES,
+ .flags = TST_TMPDIR},
+ {.name = "JPG Load EACCES", .tst_fn = test_JPG_Load_EACCES,
+ .flags = TST_TMPDIR},
+ {.name = "GIF Load EACCES", .tst_fn = test_GIF_Load_EACCES,
+ .flags = TST_TMPDIR},
+ {.name = "BMP Load EACCES", .tst_fn = test_BMP_Load_EACCES,
+ .flags = TST_TMPDIR},
+
+ /* Generic GP_LoadImage test */
+ {.name = "Image Load", .tst_fn = test_Load,
+ .flags = TST_TMPDIR},
+
+ /* Callback abort tests */
{.name = "PNG Load abort", .tst_fn = test_PNG_Load_abort,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "PNG Save abort", .tst_fn = test_PNG_Save_abort,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
- {.name = "Image Load", .tst_fn = test_Load,
- .flags = TST_TMPDIR},
- {.name = "PNG stress", .tst_fn = test_PNG_stress,
+
+ /* Basic Save Load tests */
+ {.name = "PNG Save Load", .tst_fn = test_PNG_Save_Load,
+ .flags = TST_TMPDIR | TST_CHECK_MALLOC},
+ {.name = "JPG Save Load", .tst_fn = test_JPG_Save_Load,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
- {.name = "JPG stress", .tst_fn = test_JPG_stress,
+
+ /* Stress Save Load tests */
+ {.name = "PNG Stress", .tst_fn = test_PNG_stress,
+ .flags = TST_TMPDIR | TST_CHECK_MALLOC},
+ {.name = "JPG Stress", .tst_fn = test_JPG_stress,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
+
{.name = NULL},
}
};
http://repo.or.cz/w/gfxprim.git/commit/94aa52632f9ade7a52a8e419b9e2d1b6309e…
commit 94aa52632f9ade7a52a8e419b9e2d1b6309e57a2
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 12:57:42 2012 +0200
loaders: Fix typo that misidentified BMP as GIF.
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loaders.c
index 4e3c3d6..b142e93 100644
--- a/libs/loaders/GP_Loaders.c
+++ b/libs/loaders/GP_Loaders.c
@@ -158,7 +158,7 @@ GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
case GP_FMT_GIF:
return GP_LoadGIF(src_path, callback);
case GP_FMT_BMP:
- return GP_LoadGIF(src_path, callback);
+ return GP_LoadBMP(src_path, callback);
case GP_FMT_PBM:
return GP_LoadPBM(src_path, callback);
case GP_FMT_PGM:
http://repo.or.cz/w/gfxprim.git/commit/f8b2d14ae8aa2c8fb6f64ccae23cc8298eea…
commit f8b2d14ae8aa2c8fb6f64ccae23cc8298eea3381
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 11:56:54 2012 +0200
tests: loaders: Skip tests on ENOSYS.
Fix the tests to return SKIPPED status when particular library is not
compiled in.
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index 1308737..5736829 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -31,6 +31,7 @@
enum fmt {
PNG,
JPG,
+ GIF,
};
static const char *strfmt(enum fmt fmt)
@@ -40,6 +41,8 @@ static const char *strfmt(enum fmt fmt)
return "PNG";
case JPG:
return "JPG";
+ case GIF:
+ return "GIF";
};
return "INVALID";
@@ -65,9 +68,16 @@ static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
case JPG:
ret = GP_SaveJPG(img, "test.jpg", NULL);
break;
+ default:
+ return TST_INTERR;
}
if (ret) {
+ if (errno == ENOSYS) {
+ tst_report(0, "Save %s: ENOSYS", strfmt(fmt));
+ return TST_SKIPPED;
+ }
+
tst_report(0, "Failed to save %s: %s",
strfmt(fmt), strerror(errno));
return TST_FAILED;
@@ -80,6 +90,8 @@ static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
case JPG:
res = GP_LoadJPG("test.jpg", NULL);
break;
+ default:
+ return TST_INTERR;
}
if (res == NULL) {
@@ -114,20 +126,33 @@ static int test_JPG_stress(void)
return load_save(JPG, 2000, 2000);
}
-static int test_PNG_Load_fail(void)
+static int load_enoent(enum fmt fmt)
{
- GP_Context *img;
-
- img = GP_LoadPNG("nonexistent.png", NULL);
-
- int saved_errno = errno;
+ GP_Context *img = NULL;
+ switch (fmt) {
+ case PNG:
+ img = GP_LoadPNG("nonexistent.png", NULL);
+ break;
+ case JPG:
+ img = GP_LoadJPG("nonexistent.jpg", NULL);
+ break;
+ case GIF:
+ img = GP_LoadGIF("nonexistent.gif", NULL);
+ break;
+ }
+
if (img != NULL) {
tst_report(0, "Test succedded unexpectedly");
return TST_FAILED;
}
+
+ if (errno == ENOSYS) {
+ tst_report(0, "Load %s: ENOSYS", strfmt(fmt));
+ return TST_SKIPPED;
+ }
- if (saved_errno != ENOENT) {
+ if (errno != ENOENT) {
tst_report(0, "Expected errno = ENOENT, have %s",
strerror(errno));
return TST_FAILED;
@@ -136,26 +161,19 @@ static int test_PNG_Load_fail(void)
return TST_SUCCESS;
}
-static int test_JPG_Load_fail(void)
+static int test_PNG_Load_ENOENT(void)
{
- GP_Context *img;
-
- img = GP_LoadJPG("nonexistent.png", NULL);
-
- int saved_errno = errno;
-
- if (img != NULL) {
- tst_report(0, "Test succedded unexpectedly");
- return TST_FAILED;
- }
+ return load_enoent(PNG);
+}
- if (saved_errno != ENOENT) {
- tst_report(0, "Expected errno = ENOENT, have %s",
- strerror(errno));
- return TST_FAILED;
- }
+static int test_JPG_Load_ENOENT(void)
+{
+ return load_enoent(JPG);
+}
- return TST_SUCCESS;
+static int test_GIF_Load_ENOENT(void)
+{
+ return load_enoent(GIF);
}
static int abort_callback(GP_ProgressCallback *self __attribute__((unused)))
@@ -180,11 +198,14 @@ static int test_PNG_Save_abort(void)
return TST_FAILED;
}
- int saved_errno = errno;
-
- if (saved_errno != ECANCELED) {
+ if (errno == ENOSYS) {
+ tst_report(0, "Load PNG: ENOSYS");
+ return TST_SKIPPED;
+ }
+
+ if (errno != ECANCELED) {
tst_report(0, "Expected errno = ECANCELED, have %s",
- strerror(saved_errno));
+ strerror(errno));
return TST_FAILED;
}
@@ -200,6 +221,12 @@ static int test_PNG_Load_abort(void)
img = GP_ContextAlloc(100, 100, GP_PIXEL_RGB888);
if (GP_SavePNG(img, "test.png", NULL)) {
+
+ if (errno == ENOSYS) {
+ tst_report(0, "Save PNG: ENOSYS");
+ return TST_SKIPPED;
+ }
+
tst_report(0, "Failed to save PNG: %s", strerror(errno));
return TST_FAILED;
}
@@ -271,7 +298,7 @@ static struct file_testcase file_testcases[] = {
static int test_Load(void)
{
- unsigned int i, fail = 0;
+ unsigned int i, fail = 0, success = 0;
/* Create empty files */
for (i = 0; file_testcases[i].filename != NULL; i++) {
@@ -298,9 +325,16 @@ static int test_Load(void)
tst_report(0, "GP_LoadImage('%s') succeeded "
"unexpectedly", file_testcases[i].filename);
fail++;
+ continue;
+ }
+
+ if (errno == ENOSYS) {
+ tst_report(0, "Load Image '%s': ENOSYS",
+ file_testcases[i].filename);
+ continue;
}
- if (ret == NULL && file_testcases[i].expected_errno != errno) {
+ 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),
@@ -308,13 +342,19 @@ static int test_Load(void)
strerror(saved_errno),
file_testcases[i].filename);
fail++;
+ continue;
}
+
+ success++;
}
if (fail)
return TST_FAILED;
- return TST_SUCCESS;
+ if (success)
+ return TST_SUCCESS;
+
+ return TST_SKIPPED;
}
const struct tst_suite tst_suite = {
@@ -324,9 +364,11 @@ const struct tst_suite tst_suite = {
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "JPG Load/Save", .tst_fn = test_JPG_Load_Save,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
- {.name = "PNG Load fail", .tst_fn = test_PNG_Load_fail,
+ {.name = "PNG Load ENOENT", .tst_fn = test_PNG_Load_ENOENT,
+ .flags = TST_TMPDIR},
+ {.name = "JPG Load ENOENT", .tst_fn = test_JPG_Load_ENOENT,
.flags = TST_TMPDIR},
- {.name = "JPG Load fail", .tst_fn = test_JPG_Load_fail,
+ {.name = "GIF Load ENOENT", .tst_fn = test_GIF_Load_ENOENT,
.flags = TST_TMPDIR},
{.name = "PNG Load abort", .tst_fn = test_PNG_Load_abort,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
http://repo.or.cz/w/gfxprim.git/commit/e4a59032ce9295e40e84c5003d5e813553b5…
commit e4a59032ce9295e40e84c5003d5e813553b52f2e
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 11:55:39 2012 +0200
loaders: jpg: Fix ENOSYS stubs.
diff --git a/libs/loaders/GP_JPG.c b/libs/loaders/GP_JPG.c
index fbf57c6..bece7d5 100644
--- a/libs/loaders/GP_JPG.c
+++ b/libs/loaders/GP_JPG.c
@@ -418,14 +418,14 @@ GP_Context *GP_LoadJPG(const char GP_UNUSED(*src_path),
int GP_ReadJPGMetaData(FILE GP_UNUSED(*f), GP_MetaData GP_UNUSED(*data))
{
errno = ENOSYS;
- return NULL;
+ return 1;
}
int GP_LoadJPGMetaData(const char GP_UNUSED(*src_path),
GP_MetaData GP_UNUSED(*data))
{
errno = ENOSYS;
- return NULL;
+ return 1;
}
int GP_SaveJPG(const GP_Context GP_UNUSED(*src),
http://repo.or.cz/w/gfxprim.git/commit/c643ecb4b3d832e7b3afeff095c3f453ee3d…
commit c643ecb4b3d832e7b3afeff095c3f453ee3d573f
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 11:35:58 2012 +0200
tests: framework: Introduce SKIPPED test result.
The SKIPPED test result is intended for situations
where current configuration doesn't allow the test
to run (i.e. ENOSYS from libcall, not enough RAM, etc.).
diff --git a/tests/framework/test.c b/tests/framework/test.c
index 914f2d2..0e9e9df 100644
--- a/tests/framework/test.c
+++ b/tests/framework/test.c
@@ -186,10 +186,16 @@ int fail_FILE(void)
return TST_SUCCESS;
}
+static int skipped_fn(void)
+{
+ return TST_SKIPPED;
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Testing Framework Example",
.tests = {
{.name = "Success test", .tst_fn = success_fn},
+ {.name = "Skipped test", .tst_fn = skipped_fn},
{.name = "Sigsegv test", .tst_fn = sigsegv_fn},
{.name = "Failed test", .tst_fn = failed_fn},
{.name = "Stack overflow test", .tst_fn = stack_overflow_fn},
diff --git a/tests/framework/tst_job.c b/tests/framework/tst_job.c
index 652b038..f483578 100644
--- a/tests/framework/tst_job.c
+++ b/tests/framework/tst_job.c
@@ -72,6 +72,9 @@ static void stop_test(struct tst_job *job)
case TST_SUCCESS:
result = "[ e[1;32mSUCCESSe[0m ]";
break;
+ case TST_SKIPPED:
+ result = "[ e[1;30mSKIPPEDe[0m ]";
+ break;
case TST_INTERR:
result = "[ e[1;31mINTERNAL ERRORe[0m ]";
break;
diff --git a/tests/framework/tst_log.c b/tests/framework/tst_log.c
index 6535ae8..7c6a82c 100644
--- a/tests/framework/tst_log.c
+++ b/tests/framework/tst_log.c
@@ -34,6 +34,8 @@ static const char *ret_to_bg_color(enum tst_ret ret)
switch (ret) {
case TST_SUCCESS:
return "#008000";
+ case TST_SKIPPED:
+ return "#888888";
case TST_INTERR:
return "#800000";
case TST_SIGSEGV:
@@ -58,6 +60,8 @@ static const char *ret_to_str(enum tst_ret ret)
switch (ret) {
case TST_SUCCESS:
return "Success";
+ case TST_SKIPPED:
+ return "Skipped";
case TST_INTERR:
return "Internal Error";
case TST_SIGSEGV:
diff --git a/tests/framework/tst_test.h b/tests/framework/tst_test.h
index 27eaff5..4eb97e0 100644
--- a/tests/framework/tst_test.h
+++ b/tests/framework/tst_test.h
@@ -24,13 +24,14 @@
#define TST_TEST_H
enum tst_ret {
- TST_SUCCESS, /* Test succedded */
- TST_INTERR, /* Test framework error */
- TST_SIGSEGV, /* Test ended with SIGSEGV */
- TST_TIMEOUT, /* Test hasn't finished in time */
- TST_ABORTED, /* The abort() was called (possible double free) */
- TST_MEMLEAK, /* Memory leak was detected */
- TST_FAILED, /* Test failed */
+ TST_SUCCESS, /* Test succedded */
+ TST_SKIPPED, /* Test skipped due to not enough memory, ENOSYS ... */
+ TST_INTERR, /* Test framework error */
+ TST_SIGSEGV, /* Test ended with SIGSEGV */
+ TST_TIMEOUT, /* Test hasn't finished in time */
+ TST_ABORTED, /* The abort() was called (possible double free) */
+ TST_MEMLEAK, /* Memory leak was detected */
+ TST_FAILED, /* Test failed */
TST_MAX = TST_FAILED+1,
};
http://repo.or.cz/w/gfxprim.git/commit/b3b68550f6431afd3dd5a441e38212d09b22…
commit b3b68550f6431afd3dd5a441e38212d09b22bdda
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 11:27:14 2012 +0200
loaders: png: Fix ENOSYS stubs.
diff --git a/libs/loaders/GP_PNG.c b/libs/loaders/GP_PNG.c
index 73b129a..7cf7441 100644
--- a/libs/loaders/GP_PNG.c
+++ b/libs/loaders/GP_PNG.c
@@ -570,13 +570,13 @@ GP_Context *GP_LoadPNG(const char GP_UNUSED(*src_path),
int GP_ReadPNGMetaData(FILE GP_UNUSED(*f), GP_MetaData GP_UNUSED(*data))
{
errno = ENOSYS;
- return NULL;
+ return 1;
}
int GP_LoadPNGMetaData(const char GP_UNUSED(*src_path), GP_MetaData GP_UNUSED(*data))
{
errno = ENOSYS;
- return NULL;
+ return 1;
}
int GP_SavePNG(const GP_Context GP_UNUSED(*src),
http://repo.or.cz/w/gfxprim.git/commit/3095a596cffe0dca94e5a773828af6fc0365…
commit 3095a596cffe0dca94e5a773828af6fc0365f9d4
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Sep 27 11:24:43 2012 +0200
tests: loaders: Simplify tests code.
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index 918b139..1308737 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -28,45 +28,63 @@
#include "tst_test.h"
-static int test_PNG_Load_Save(void)
+enum fmt {
+ PNG,
+ JPG,
+};
+
+static const char *strfmt(enum fmt fmt)
{
- GP_Context *img, *res;
+ switch (fmt) {
+ case PNG:
+ return "PNG";
+ case JPG:
+ return "JPG";
+ };
+
+ return "INVALID";
+}
- img = GP_ContextAlloc(100, 100, GP_PIXEL_RGB888);
+static int load_save(enum fmt fmt, GP_Size w, GP_Size h)
+{
+ GP_Context *img, *res = NULL;
- if (GP_SavePNG(img, "test.png", NULL)) {
- tst_report(0, "Failed to save PNG: %s", strerror(errno));
+ img = GP_ContextAlloc(w, h, GP_PIXEL_RGB888);
+
+ if (img == NULL) {
+ tst_report(0, "GP_ContextAlloc failed");
return TST_FAILED;
}
- res = GP_LoadPNG("test.png", NULL);
+ int ret = 1;
- if (res == NULL) {
- tst_report(0, "Failed to load PNG: %s", strerror(errno));
- return TST_FAILED;
+ switch (fmt) {
+ case PNG:
+ ret = GP_SavePNG(img, "test.png", NULL);
+ break;
+ case JPG:
+ ret = GP_SaveJPG(img, "test.jpg", NULL);
+ break;
}
- GP_ContextFree(img);
- GP_ContextFree(res);
-
- return TST_SUCCESS;
-}
-
-static int test_JPG_Load_Save(void)
-{
- GP_Context *img, *res;
-
- img = GP_ContextAlloc(100, 100, GP_PIXEL_RGB888);
-
- if (GP_SaveJPG(img, "test.jpg", NULL)) {
- tst_report(0, "Failed to save JPG: %s", strerror(errno));
+ if (ret) {
+ tst_report(0, "Failed to save %s: %s",
+ strfmt(fmt), strerror(errno));
return TST_FAILED;
}
- res = GP_LoadJPG("test.jpg", NULL);
+ switch (fmt) {
+ case PNG:
+ res = GP_LoadPNG("test.png", NULL);
+ break;
+ case JPG:
+ res = GP_LoadJPG("test.jpg", NULL);
+ break;
+ }
if (res == NULL) {
- tst_report(0, "Failed to load JPG: %s", strerror(errno));
+ tst_report(0, "Failed to load %s: %s",
+ strfmt(fmt), strerror(errno));
return TST_FAILED;
}
@@ -76,6 +94,26 @@ static int test_JPG_Load_Save(void)
return TST_SUCCESS;
}
+static int test_PNG_Load_Save(void)
+{
+ return load_save(PNG, 100, 100);
+}
+
+static int test_JPG_Load_Save(void)
+{
+ return load_save(JPG, 100, 100);
+}
+
+static int test_PNG_stress(void)
+{
+ return load_save(PNG, 2000, 2000);
+}
+
+static int test_JPG_stress(void)
+{
+ return load_save(JPG, 2000, 2000);
+}
+
static int test_PNG_Load_fail(void)
{
GP_Context *img;
@@ -188,38 +226,6 @@ static int test_PNG_Load_abort(void)
return TST_SUCCESS;
}
-/*
- * PNG stress test, let it save and load 10MB image.
- */
-static int test_PNG_stress(void)
-{
- GP_Context *img;
-
- img = GP_ContextAlloc(2000, 2000, GP_PIXEL_RGB888);
-
- if (img == NULL) {
- tst_report(0, "GP_ContextAlloc failed");
- return TST_FAILED;
- }
-
- if (GP_SavePNG(img, "test.png", NULL)) {
- tst_report(0, "GP_SavePNG failed with: %s", strerror(errno));
- return TST_FAILED;
- }
-
- GP_ContextFree(img);
-
- img = GP_LoadPNG("test.png", NULL);
-
- if (img == NULL) {
- tst_report(0, "GP_LoadPNG failed with: %s", strerror(errno));
- return TST_FAILED;
- }
-
- GP_ContextFree(img);
-
- return TST_SUCCESS;
-}
/*
* Loaders test. Hammers the GP_LoadImage() interface with plenty of
@@ -242,6 +248,7 @@ static struct file_testcase file_testcases[] = {
{"jpg.", 1, ENOSYS},
{"gif.", 1, ENOSYS},
{"jpeg.", 1, ENOSYS},
+ {"bmp.", 1, ENOSYS},
{".jpg", 1, EIO},
{"img.jpg", 1, EIO},
@@ -249,12 +256,16 @@ static struct file_testcase file_testcases[] = {
{"img.png", 1, EIO},
{".gif", 1, EIO},
{"img.gif", 1, EIO},
+ {".bmp", 1, EIO},
+ {"img.bmp", 1, EIO},
{".pbm", 1, EIO},
{".pgm", 1, EIO},
{".ppm", 1, EIO},
{"not_here.jpg", 0, ENOENT},
+ //TODO: EPERM
+
{NULL, 0, 0}
};
@@ -321,10 +332,12 @@ const struct tst_suite tst_suite = {
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "PNG Save abort", .tst_fn = test_PNG_Save_abort,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
- {.name = "PNG stress", .tst_fn = test_PNG_stress,
- .flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "Image Load", .tst_fn = test_Load,
.flags = TST_TMPDIR},
+ {.name = "PNG stress", .tst_fn = test_PNG_stress,
+ .flags = TST_TMPDIR | TST_CHECK_MALLOC},
+ {.name = "JPG stress", .tst_fn = test_JPG_stress,
+ .flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = NULL},
}
};
-----------------------------------------------------------------------
Summary of changes:
doc/loaders.txt | 48 +++---
libs/loaders/GP_BMP.c | 2 +-
libs/loaders/GP_GIF.c | 14 ++-
libs/loaders/GP_JPG.c | 4 +-
libs/loaders/GP_Loaders.c | 2 +-
libs/loaders/GP_PNG.c | 4 +-
tests/framework/test.c | 6 +
tests/framework/tst_job.c | 3 +
tests/framework/tst_log.c | 19 ++-
tests/framework/tst_test.h | 15 +-
tests/loaders/loaders_suite.c | 379 ++++++++++++++++++++++++++++++++---------
11 files changed, 374 insertions(+), 122 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: f7abc056071b6987bd8ddf3b3e21b76fb2faa593
by metan 14 Sep '12
by metan 14 Sep '12
14 Sep '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 f7abc056071b6987bd8ddf3b3e21b76fb2faa593 (commit)
via f8f4f70933e49090c3910415315730aaf23cfa71 (commit)
via e09dcfd1600590e8bc57039293fbf39eba0d6fd2 (commit)
from 5e9ae922f961ce558878ad261b34db3dd7a99b6d (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/f7abc056071b6987bd8ddf3b3e21b76fb2fa…
commit f7abc056071b6987bd8ddf3b3e21b76fb2faa593
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Sep 14 17:20:48 2012 +0200
loaders: Small fixes in errno handling code.
diff --git a/libs/loaders/GP_PBM.c b/libs/loaders/GP_PBM.c
index ac7dc30..2c11138 100644
--- a/libs/loaders/GP_PBM.c
+++ b/libs/loaders/GP_PBM.c
@@ -54,28 +54,34 @@ GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback)
FILE *f;
GP_Context *ret;
uint32_t w, h;
+ int err;
f = fopen(src_path, "r");
if (f == NULL)
return NULL;
- if (fgetc(f) != 'P' || fgetc(f) != '1')
+ if (fgetc(f) != 'P' || fgetc(f) != '1') {
+ err = feof(f) ? EIO : EINVAL;
goto err1;
+ }
- if (fscanf(f, "%"PRIu32"%"PRIu32, &w, &h) < 2)
+ if (fscanf(f, "%"PRIu32"%"PRIu32, &w, &h) < 2) {
+ err = EIO;
goto err1;
+ }
ret = GP_ContextAlloc(w, h, GP_PIXEL_G1);
if (ret == NULL) {
- fclose(f);
- errno = ENOMEM;
- return NULL;
+ err = ENOMEM;
+ goto err1;
}
- if (GP_PXMLoad1bpp(f, ret))
+ if (GP_PXMLoad1bpp(f, ret)) {
+ err = EINVAL;
goto err2;
+ }
fclose(f);
return ret;
@@ -83,6 +89,7 @@ err2:
free(ret);
err1:
fclose(f);
+ errno = err;
return NULL;
}
diff --git a/libs/loaders/GP_PGM.c b/libs/loaders/GP_PGM.c
index 9ae8c64..055df97 100644
--- a/libs/loaders/GP_PGM.c
+++ b/libs/loaders/GP_PGM.c
@@ -92,6 +92,11 @@ GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback)
h1 = fgetc(f);
h2 = fgetc(f);
+ if (feof(f)) {
+ err = EIO;
+ goto err1;
+ }
+
if (h1 != 'P' || h2 != '2') {
GP_DEBUG(1, "Invalid PGM header '%c%c' (0x%2x 0x%2x)",
isprint(h1) ? h1 : ' ', isprint(h2) ? h2 : ' ',
diff --git a/libs/loaders/GP_PNG.c b/libs/loaders/GP_PNG.c
index 2d099fd..73b129a 100644
--- a/libs/loaders/GP_PNG.c
+++ b/libs/loaders/GP_PNG.c
@@ -58,7 +58,7 @@ int GP_OpenPNG(const char *src_path, FILE **f)
}
if (fread(sig, 1, 8, *f) <= 0) {
- err = errno;
+ err = EIO;
GP_DEBUG(1, "Failed to read '%s' : %s",
src_path, strerror(errno));
goto err2;
@@ -67,7 +67,7 @@ int GP_OpenPNG(const char *src_path, FILE **f)
if (png_sig_cmp(sig, 0, 8)) {
GP_DEBUG(1, "Invalid file header, '%s' not a PNG image?",
src_path);
- err = EILSEQ;
+ err = EINVAL;
goto err2;
}
diff --git a/libs/loaders/GP_PNM.c b/libs/loaders/GP_PNM.c
index 261b75f..6e7946e 100644
--- a/libs/loaders/GP_PNM.c
+++ b/libs/loaders/GP_PNM.c
@@ -88,7 +88,7 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
uint32_t *w, uint32_t *h, uint32_t *depth)
{
FILE *f = fopen(src_path, "r");
- int ch;
+ int ch, err;
if (f == NULL) {
GP_DEBUG(1, "Failed to open file '%s': %s",
@@ -98,9 +98,15 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
ch = fgetc(f);
+ if (ch == EOF) {
+ err = EIO;
+ goto err1;
+ }
+
if (ch != 'P') {
GP_DEBUG(1, "Invalid PNM header start '%c' (0x%2x) expecting 'P'",
isprint(ch) ? ch : ' ', ch);
+ err = EINVAL;
goto err1;
}
@@ -119,6 +125,7 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
default:
GP_DEBUG(1, "Invalid PNM format 'P%c' (0x%2x)",
isprint(ch) ? ch : ' ', ch);
+ err = EINVAL;
goto err1;
}
@@ -128,6 +135,7 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
if (fscanf(f, "%"PRIu32"n", w) < 1) {
GP_DEBUG(1, "Failed to read PNM header width");
+ err = EINVAL;
goto err1;
}
@@ -135,6 +143,7 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
if (fscanf(f, "%"PRIu32"n", h) < 1) {
GP_DEBUG(1, "Failed to read PNM header height");
+ err = EINVAL;
goto err1;
}
@@ -148,12 +157,14 @@ FILE *GP_ReadPNM(const char *src_path, char *fmt,
if (fscanf(f, "%"PRIu32"n", depth) < 1) {
GP_DEBUG(1, "Failed to read PNM header depth");
+ err = EINVAL;
goto err1;
}
return f;
err1:
fclose(f);
+ errno = err;
return NULL;
}
http://repo.or.cz/w/gfxprim.git/commit/f8f4f70933e49090c3910415315730aaf23c…
commit f8f4f70933e49090c3910415315730aaf23cfa71
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Sep 14 17:15:54 2012 +0200
tests: Add common image loader tests.
diff --git a/tests/loaders/loaders_suite.c b/tests/loaders/loaders_suite.c
index cb7f398..918b139 100644
--- a/tests/loaders/loaders_suite.c
+++ b/tests/loaders/loaders_suite.c
@@ -221,6 +221,91 @@ static int test_PNG_stress(void)
return TST_SUCCESS;
}
+/*
+ * Loaders test. Hammers the GP_LoadImage() interface with plenty of
+ * unexpected filenames.
+ */
+struct file_testcase {
+ const char *filename;
+ int create;
+ int expected_errno;
+};
+
+static struct file_testcase file_testcases[] = {
+ {"a", 1, ENOSYS},
+ {".a", 1, ENOSYS},
+ {"a.", 1, ENOSYS},
+ {".bc", 1, ENOSYS},
+ {"bc", 1, ENOSYS},
+ {"abc", 1, ENOSYS},
+ {"png.", 1, ENOSYS},
+ {"jpg.", 1, ENOSYS},
+ {"gif.", 1, ENOSYS},
+ {"jpeg.", 1, ENOSYS},
+
+ {".jpg", 1, EIO},
+ {"img.jpg", 1, EIO},
+ {".png", 1, EIO},
+ {"img.png", 1, EIO},
+ {".gif", 1, EIO},
+ {"img.gif", 1, EIO},
+ {".pbm", 1, EIO},
+ {".pgm", 1, EIO},
+ {".ppm", 1, EIO},
+
+ {"not_here.jpg", 0, ENOENT},
+
+ {NULL, 0, 0}
+};
+
+static int test_Load(void)
+{
+ unsigned int i, fail = 0;
+
+ /* Create empty files */
+ for (i = 0; file_testcases[i].filename != NULL; i++) {
+
+ if (file_testcases[i].create != 1)
+ continue;
+
+ FILE *f = fopen(file_testcases[i].filename, "w");
+
+ if (f != NULL)
+ fclose(f);
+ }
+
+ for (i = 0; file_testcases[i].filename != NULL; i++) {
+ GP_Context *ret;
+
+ errno = 0;
+
+ ret = GP_LoadImage(file_testcases[i].filename, NULL);
+
+ int saved_errno = errno;
+
+ if (ret != NULL) {
+ tst_report(0, "GP_LoadImage('%s') succeeded "
+ "unexpectedly", file_testcases[i].filename);
+ fail++;
+ }
+
+ if (ret == NULL && 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);
+ fail++;
+ }
+ }
+
+ if (fail)
+ return TST_FAILED;
+
+ return TST_SUCCESS;
+}
+
const struct tst_suite tst_suite = {
.suite_name = "Image Loaders testsuite",
.tests = {
@@ -238,6 +323,8 @@ const struct tst_suite tst_suite = {
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
{.name = "PNG stress", .tst_fn = test_PNG_stress,
.flags = TST_TMPDIR | TST_CHECK_MALLOC},
+ {.name = "Image Load", .tst_fn = test_Load,
+ .flags = TST_TMPDIR},
{.name = NULL},
}
};
http://repo.or.cz/w/gfxprim.git/commit/e09dcfd1600590e8bc57039293fbf39eba0d…
commit e09dcfd1600590e8bc57039293fbf39eba0d6fd2
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Sep 14 16:42:54 2012 +0200
loaders: Simplify the image format detection code.
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loaders.c
index 5700aa4..4e3c3d6 100644
--- a/libs/loaders/GP_Loaders.c
+++ b/libs/loaders/GP_Loaders.c
@@ -34,108 +34,141 @@
#include "GP_Loaders.h"
-GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback)
+enum GP_ImageFmt {
+ GP_FMT_UNKNOWN,
+ GP_FMT_PNG,
+ GP_FMT_JPG,
+ GP_FMT_BMP,
+ GP_FMT_GIF,
+ GP_FMT_PBM,
+ GP_FMT_PGM,
+ GP_FMT_PPM,
+};
+
+enum GP_ImageFmt filename_to_fmt(const char *path)
{
- int len, 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;
- }
-
- len = strlen(src_path);
+ size_t len = strlen(path);
if (len < 3)
- goto skip_filename_check;
+ return GP_FMT_UNKNOWN;
- switch (src_path[len - 1]) {
+ switch (path[len - 1]) {
/* PNG, JPG, JPEG */
case 'g':
case 'G':
- switch (src_path[len - 2]) {
+ switch (path[len - 2]) {
case 'n':
case 'N':
- if (src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P')
- return GP_LoadPNG(src_path, callback);
+ if (path[len - 3] == 'p' ||
+ path[len - 3] == 'P')
+ return GP_FMT_PNG;
break;
case 'p':
case 'P':
- if (src_path[len - 3] == 'j' ||
- src_path[len - 3] == 'J')
- return GP_LoadJPG(src_path, callback);
+ if (path[len - 3] == 'j' ||
+ path[len - 3] == 'J')
+ return GP_FMT_JPG;
break;
case 'e':
case 'E':
- if ((src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P') &&
- (src_path[len - 4] == 'j' ||
- src_path[len - 4] == 'J'))
- return GP_LoadJPG(src_path, callback);
+ if ((path[len - 3] == 'p' ||
+ path[len - 3] == 'P') &&
+ (path[len - 4] == 'j' ||
+ path[len - 4] == 'J'))
+ return GP_FMT_JPG;
break;
}
break;
/* PPM, PGM, PBM, PNM */
case 'm':
case 'M':
- switch (src_path[len - 2]) {
+ switch (path[len - 2]) {
case 'b':
case 'B':
- if (src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P') {
- return GP_LoadPBM(src_path, callback);
- }
+ if (path[len - 3] == 'p' ||
+ path[len - 3] == 'P')
+ return GP_FMT_PBM;
break;
case 'g':
case 'G':
- if (src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P') {
- return GP_LoadPGM(src_path, callback);
- }
+ if (path[len - 3] == 'p' ||
+ path[len - 3] == 'P')
+ return GP_FMT_PGM;
break;
case 'p':
case 'P':
- if (src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P') {
- return GP_LoadPPM(src_path, callback);
- }
+ if (path[len - 3] == 'p' ||
+ path[len - 3] == 'P')
+ return GP_FMT_PPM;
break;
}
break;
/* BMP */
case 'P':
case 'p':
- switch (src_path[len - 2]) {
+ switch (path[len - 2]) {
case 'M':
case 'm':
- if (src_path[len - 3] == 'B' ||
- src_path[len - 3] == 'b')
- return GP_LoadBMP(src_path, callback);
+ if (path[len - 3] == 'B' ||
+ path[len - 3] == 'b')
+ return GP_FMT_BMP;
break;
}
break;
/* GIF */
case 'F':
case 'f':
- switch (src_path[len - 2]) {
+ switch (path[len - 2]) {
case 'I':
case 'i':
- if (src_path[len - 3] == 'G' ||
- src_path[len - 3] == 'g')
- return GP_LoadGIF(src_path, callback);
+ if (path[len - 3] == 'G' ||
+ path[len - 3] == 'g')
+ return GP_FMT_GIF;
break;
}
break;
}
-skip_filename_check:
+ 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_BMP:
+ return GP_LoadGIF(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;
+ }
//TODO file signature based check
errno = ENOSYS;
@@ -144,41 +177,29 @@ skip_filename_check:
int GP_LoadMetaData(const char *src_path, GP_MetaData *data)
{
- int len;
+ int saved_errno;
- len = strlen(src_path);
+ if (access(src_path, R_OK)) {
+
+ saved_errno = errno;
- if (len < 3) {
- errno = ENOSYS;
+ GP_DEBUG(1, "Failed to access file '%s' : %s",
+ src_path, strerror(errno));
+
+ errno = saved_errno;
+
return 1;
}
- switch (src_path[len - 1]) {
- /* PNG, JPG, JPEG */
- case 'g':
- case 'G':
- switch (src_path[len - 2]) {
- case 'n':
- case 'N':
- if (src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P')
- return GP_LoadPNGMetaData(src_path, data);
- break;
- case 'p':
- case 'P':
- if (src_path[len - 3] == 'j' ||
- src_path[len - 3] == 'J')
- return GP_LoadJPGMetaData(src_path, data);
- break;
- case 'e':
- case 'E':
- if ((src_path[len - 3] == 'p' ||
- src_path[len - 3] == 'P') &&
- (src_path[len - 4] == 'j' ||
- src_path[len - 4] == 'J'))
- return GP_LoadJPGMetaData(src_path, data);
- break;
- }
+ enum GP_ImageFmt fmt = filename_to_fmt(src_path);
+
+ switch (fmt) {
+ case GP_FMT_JPG:
+ return GP_LoadJPGMetaData(src_path, data);
+ case GP_FMT_PNG:
+ return GP_LoadPNGMetaData(src_path, data);
+
+ default:
break;
}
@@ -189,41 +210,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)
{
- int len;
-
- len = strlen(dst_path);
+ enum GP_ImageFmt fmt = filename_to_fmt(dst_path);
- if (len < 3) {
- errno = ENOSYS;
- return 1;
- }
+ switch (fmt) {
+ case GP_FMT_JPG:
+ return GP_SaveJPG(src, dst_path, callback);
+ case GP_FMT_PNG:
+ return GP_SavePNG(src, dst_path, callback);
- switch (dst_path[len - 1]) {
- /* PNG, JPG, JPEG */
- case 'g':
- case 'G':
- switch (dst_path[len - 2]) {
- case 'n':
- case 'N':
- if (dst_path[len - 3] == 'p' ||
- dst_path[len - 3] == 'P')
- return GP_SavePNG(src, dst_path, callback);
- break;
- case 'p':
- case 'P':
- if (dst_path[len - 3] == 'j' ||
- dst_path[len - 3] == 'J')
- return GP_SaveJPG(src, dst_path, callback);
- break;
- case 'e':
- case 'E':
- if ((dst_path[len - 3] == 'p' ||
- dst_path[len - 3] == 'P') &&
- (dst_path[len - 4] == 'j' ||
- dst_path[len - 4] == 'J'))
- return GP_SaveJPG(src, dst_path, callback);
- break;
- }
+ default:
break;
}
-----------------------------------------------------------------------
Summary of changes:
libs/loaders/GP_Loaders.c | 225 ++++++++++++++++++++---------------------
libs/loaders/GP_PBM.c | 19 +++-
libs/loaders/GP_PGM.c | 5 +
libs/loaders/GP_PNG.c | 4 +-
libs/loaders/GP_PNM.c | 13 ++-
tests/loaders/loaders_suite.c | 87 ++++++++++++++++
6 files changed, 229 insertions(+), 124 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