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 4e298cb7cb11a0e161a4522d4f5a8496baac8f3c (commit) via 4233e033b8b0c03a3a370a86e1e2d87bd3ba3d40 (commit) from 3354fbc9c92960230a3111ac5ae82064bc8c63a2 (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/4e298cb7cb11a0e161a4522d4f5a8496baac8...
commit 4e298cb7cb11a0e161a4522d4f5a8496baac8f3c Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 16 11:46:48 2013 +0200
tests: loaders: First simple PBM tests.
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/tests/loaders/Makefile b/tests/loaders/Makefile index d8c1fcb..304e956 100644 --- a/tests/loaders/Makefile +++ b/tests/loaders/Makefile @@ -3,7 +3,7 @@ include $(TOPDIR)/pre.mk
CSOURCES=$(shell echo *.c)
-APPS=loaders_suite PNG +APPS=loaders_suite PNG PBM
include ../tests.mk
diff --git a/tests/loaders/PBM.c b/tests/loaders/PBM.c new file mode 100644 index 0000000..2c76792 --- /dev/null +++ b/tests/loaders/PBM.c @@ -0,0 +1,196 @@ +/***************************************************************************** + * 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-2013 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +#include <core/GP_Context.h> +#include <core/GP_GetPutPixel.h> +#include <loaders/GP_Loaders.h> + +#include "tst_test.h" + +struct testcase { + GP_Size w; + GP_Size h; + GP_Pixel pix; + char *path; +}; + +static int test_load_PBM(struct testcase *test) +{ + GP_Context *img; + unsigned int x, y, err = 0; + + errno = 0; + + img = GP_LoadPBM(test->path, NULL); + + if (img == NULL) { + switch (errno) { + case ENOSYS: + tst_msg("Not Implemented"); + return TST_SKIPPED; + default: + tst_msg("Got %s", strerror(errno)); + return TST_FAILED; + } + } + + if (img->w != test->w || img->h != test->h) { + tst_msg("Invalid image size have %ux%u expected %ux%u", + img->w, img->h, test->w, test->h); + GP_ContextFree(img); + return TST_FAILED; + } + + for (x = 0; x < img->w; x++) { + for (y = 0; y < img->h; y++) { + + GP_Pixel pix = GP_GetPixel(img, x, y); + + if (pix != test->pix) { + if (err < 5) + tst_msg("%08x instead of %08x (%ux%u)", + pix, test->pix, x, y); + err++; + } + } + } + + GP_ContextFree(img); + + if (err) + return TST_FAILED; + + return TST_SUCCESS; +} + +static int test_load_fail_PBM(const char *path) +{ + GP_Context *img; + + errno = 0; + + img = GP_LoadPBM(path, NULL); + + if (img != NULL) { + tst_msg("Succeeded unexpectedly"); + GP_ContextFree(img); + return TST_FAILED; + } + + switch (errno) { + case ENOSYS: + tst_msg("Not Implemented"); + return TST_SKIPPED; + default: + tst_msg("Got %s", strerror(errno)); + return TST_SUCCESS; + } +} + +struct testcase black_1x1_1 = { + .w = 1, + .h = 1, + .pix = 0, + .path = "black_1x1_1.pbm", +}; + +struct testcase black_1x1_2 = { + .w = 1, + .h = 1, + .pix = 0, + .path = "black_1x1_2.pbm", +}; + +struct testcase black_1x1_3 = { + .w = 1, + .h = 1, + .pix = 0, + .path = "black_1x1_3.pbm", +}; + +struct testcase black_1x1_4 = { + .w = 1, + .h = 1, + .pix = 0, + .path = "black_1x1_4.pbm", +}; + +struct testcase white_1x1 = { + .w = 1, + .h = 1, + .pix = 1, + .path = "white_1x1.pbm", +}; + +const struct tst_suite tst_suite = { + .suite_name = "PBM", + .tests = { + {.name = "PBM Load 1x1 (black)", + .tst_fn = test_load_PBM, + //TODO: Add copy to to res path + .res_path = "data/pbm/valid/black_1x1_1.pbm", + .data = &black_1x1_1, + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load 1x1 (white)", + .tst_fn = test_load_PBM, + .res_path = "data/pbm/valid/white_1x1.pbm", + .data = &white_1x1, + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load 1x1 +comments", + .tst_fn = test_load_PBM, + .res_path = "data/pbm/valid/black_1x1_2.pbm", + .data = &black_1x1_2, + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load 1x1 +comments +whitespaces", + .tst_fn = test_load_PBM, + .res_path = "data/pbm/valid/black_1x1_3.pbm", + .data = &black_1x1_3, + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load 1x1 (invalid loadable)", + .tst_fn = test_load_PBM, + .res_path = "data/pbm/valid/black_1x1_4.pbm", + .data = &black_1x1_4, + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load corrupt", + .tst_fn = test_load_fail_PBM, + .res_path = "data/pbm/corrupt/short.pbm", + .data = "short.pbm", + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = "PBM Load empty", + .tst_fn = test_load_fail_PBM, + .res_path = "data/pbm/corrupt/empty.pbm", + .data = "empty.pbm", + .flags = TST_TMPDIR | TST_CHECK_MALLOC}, + + {.name = NULL}, + } +}; diff --git a/tests/loaders/data/pbm/corrupt/empty.pbm b/tests/loaders/data/pbm/corrupt/empty.pbm new file mode 100644 index 0000000..e69de29 diff --git a/tests/loaders/data/pbm/corrupt/short.pbm b/tests/loaders/data/pbm/corrupt/short.pbm new file mode 100644 index 0000000..77eee90 --- /dev/null +++ b/tests/loaders/data/pbm/corrupt/short.pbm @@ -0,0 +1,3 @@ +P1 +10 10 +1 0 0 1 diff --git a/tests/loaders/data/pbm/valid/black_1x1_1.pbm b/tests/loaders/data/pbm/valid/black_1x1_1.pbm new file mode 100644 index 0000000..d089e44 --- /dev/null +++ b/tests/loaders/data/pbm/valid/black_1x1_1.pbm @@ -0,0 +1,3 @@ +P1 +1 1 +1 diff --git a/tests/loaders/data/pbm/valid/black_1x1_2.pbm b/tests/loaders/data/pbm/valid/black_1x1_2.pbm new file mode 100644 index 0000000..c0e1188 --- /dev/null +++ b/tests/loaders/data/pbm/valid/black_1x1_2.pbm @@ -0,0 +1,4 @@ +P1 +# Comment +1 1 +1 diff --git a/tests/loaders/data/pbm/valid/black_1x1_3.pbm b/tests/loaders/data/pbm/valid/black_1x1_3.pbm new file mode 100644 index 0000000..85e3a7a --- /dev/null +++ b/tests/loaders/data/pbm/valid/black_1x1_3.pbm @@ -0,0 +1,8 @@ +P1 +# Comment + + + +1 1 +# Comment + 1 diff --git a/tests/loaders/data/pbm/valid/black_1x1_4.pbm b/tests/loaders/data/pbm/valid/black_1x1_4.pbm new file mode 100644 index 0000000..37f4e62 --- /dev/null +++ b/tests/loaders/data/pbm/valid/black_1x1_4.pbm @@ -0,0 +1,4 @@ +P1 invalid but works +1 1 + # invalid comment + 1 diff --git a/tests/loaders/data/pbm/valid/white_1x1.pbm b/tests/loaders/data/pbm/valid/white_1x1.pbm new file mode 100644 index 0000000..d013b84 --- /dev/null +++ b/tests/loaders/data/pbm/valid/white_1x1.pbm @@ -0,0 +1,3 @@ +P1 +1 1 +0 diff --git a/tests/loaders/test_list.txt b/tests/loaders/test_list.txt index f4a8fe1..8a20a1d 100644 --- a/tests/loaders/test_list.txt +++ b/tests/loaders/test_list.txt @@ -1,3 +1,4 @@ # Loaders testsuite loaders_suite PNG +PBM
http://repo.or.cz/w/gfxprim.git/commit/4233e033b8b0c03a3a370a86e1e2d87bd3ba3...
commit 4233e033b8b0c03a3a370a86e1e2d87bd3ba3d40 Author: Cyril Hrubis metan@ucw.cz Date: Sat Jun 15 00:39:13 2013 +0200
lib: loaders: Rewrite PNM loaders.
* Not yet finished
* Loading and saving ASCII format works fine
* Binary are on TODO
Signed-off-by: Cyril Hrubis metan@ucw.cz
diff --git a/build/syms/Loaders_symbols.txt b/build/syms/Loaders_symbols.txt index 683c410..9820d2f 100644 --- a/build/syms/Loaders_symbols.txt +++ b/build/syms/Loaders_symbols.txt @@ -38,25 +38,21 @@ GP_OpenTIFF GP_ReadTIFF GP_LoadTIFF
-GP_SavePPM -GP_LoadPPM +GP_SavePBM +GP_LoadPBM +GP_MatchPBM
GP_SavePGM GP_LoadPGM +GP_MatchPGM
-GP_ReadPNM -GP_WritePNM - -GP_SavePBM -GP_LoadPBM +GP_SavePPM +GP_LoadPPM +GP_MatchPPM
-GP_PXMSave1bpp -GP_PXMSave2bpp -GP_PXMSave8bpp -GP_PXMLoad1bpp -GP_PXMLoad2bpp -GP_PXMLoad4bpp -GP_PXMLoad8bpp +GP_LoadPNM +GP_SavePNM +GP_MatchPNM
GP_SaveTmpFile GP_LoadTmpFile diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c index ee9d349..d74eb0f 100644 --- a/demos/grinder/grinder.c +++ b/demos/grinder/grinder.c @@ -981,7 +981,7 @@ static void save_by_fmt(struct GP_Context *bitmap, const char *name, const char progress_prefix = "Saving Image";
if (!strcmp(fmt, "ppm")) - ret = GP_SavePPM(name, bitmap, "b", progress_callback); + ret = GP_SavePPM(bitmap, name, progress_callback); else if (!strcmp(fmt, "jpg")) ret = GP_SaveJPG(bitmap, name, progress_callback); else if (!strcmp(fmt, "png")) diff --git a/include/loaders/GP_Loaders.h b/include/loaders/GP_Loaders.h index 5ee30b3..31066d3 100644 --- a/include/loaders/GP_Loaders.h +++ b/include/loaders/GP_Loaders.h @@ -35,10 +35,7 @@ #include "core/GP_Context.h" #include "core/GP_ProgressCallback.h"
-#include "GP_PBM.h" -#include "GP_PGM.h" -#include "GP_PPM.h" - +#include "GP_PNM.h" #include "GP_BMP.h" #include "GP_PNG.h" #include "GP_JPG.h" diff --git a/include/loaders/GP_PBM.h b/include/loaders/GP_PBM.h deleted file mode 100644 index 1603aff..0000000 --- a/include/loaders/GP_PBM.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -#ifndef LOADERS_GP_PBM_H -#define LOADERS_GP_PBM_H - -#include "core/GP_Context.h" -#include "core/GP_ProgressCallback.h" - -/* - * Loads 1-bit Grayscale image from portable bitmap format. - */ -GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback); - -/* - * Save 1-bit Grayscale image into portable bitmap format. - * - * On success zero is returned, otherwise non-zero is returned and errno is - * filled: - * - * EINVAL - context pixel type was not 1 bit grayscale. - * - */ -int GP_SavePBM(const GP_Context *src, const char *res_path, - GP_ProgressCallback *callback); - -#endif /* LOADERS_GP_PBM_H */ diff --git a/include/loaders/GP_PGM.h b/include/loaders/GP_PGM.h deleted file mode 100644 index 7b930cd..0000000 --- a/include/loaders/GP_PGM.h +++ /dev/null @@ -1,37 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -#ifndef LOADERS_GP_PGM_H -#define LOADERS_GP_PGM_H - -#include "core/GP_Context.h" - -GP_Context *GP_LoadPGM(const char *src_path, - GP_ProgressCallback *callback); - -int GP_SavePGM(const GP_Context *src, const char *res_path, - GP_ProgressCallback *callback); - -#endif /* LOADERS_GP_PGM_H */ diff --git a/include/loaders/GP_PPM.h b/include/loaders/GP_PPM.h deleted file mode 100644 index 4ac1bf1..0000000 --- a/include/loaders/GP_PPM.h +++ /dev/null @@ -1,37 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -#ifndef LOADERS_GP_PPM_H -#define LOADERS_GP_PPM_H - -#include "core/GP_Context.h" -#include "core/GP_ProgressCallback.h" - -GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback); - -/* - * The fmt may be either "a" for ASCII or "b" for BINARY. - */ -int GP_SavePPM(const char *res_path, GP_Context *src, char *fmt, - GP_ProgressCallback *callback); - -#endif /* LOADERS_GP_PPM_H */ diff --git a/libs/loaders/GP_Loader.c b/libs/loaders/GP_Loader.c index 4e154e9..fb1bee0 100644 --- a/libs/loaders/GP_Loader.c +++ b/libs/loaders/GP_Loader.c @@ -51,8 +51,8 @@ static GP_Loader psp_loader = { static GP_Loader pbm_loader = { .Load = GP_LoadPBM, .Save = GP_SavePBM, - .Match = NULL, - .fmt_name = "Netpbm portable bitmap", + .Match = GP_MatchPBM, + .fmt_name = "Netpbm portable Bitmap", .next = &psp_loader, .extensions = {"pbm", NULL}, }; @@ -60,8 +60,8 @@ static GP_Loader pbm_loader = { static GP_Loader pgm_loader = { .Load = GP_LoadPGM, .Save = GP_SavePGM, - .Match = NULL, - .fmt_name = "Netpbm portable graymap", + .Match = GP_MatchPGM, + .fmt_name = "Netpbm portable Graymap", .next = &pbm_loader, .extensions = {"pgm", NULL}, }; @@ -69,18 +69,31 @@ static GP_Loader pgm_loader = { static GP_Loader ppm_loader = { .Load = GP_LoadPPM, .Save = NULL, - .Match = NULL, - .fmt_name = "Netpbm portable pixmap", + .Match = GP_MatchPPM, + .fmt_name = "Netpbm portable Pixmap", .next = &pgm_loader, .extensions = {"ppm", NULL}, };
+static GP_Loader pnm_loader = { + .Load = GP_LoadPNM, + .Save = NULL, + /* + * Avoid double Match + * This format is covered by PBM, PGM and PPM + */ + .Match = NULL, + .fmt_name = "Netpbm portable Anymap", + .next = &ppm_loader, + .extensions = {"pnm", NULL}, +}; + static GP_Loader bmp_loader = { .Load = GP_LoadBMP, .Save = GP_SaveBMP, .Match = GP_MatchBMP, .fmt_name = "BMP", - .next = &ppm_loader, + .next = &pnm_loader, .extensions = {"bmp", "dib", NULL}, };
diff --git a/libs/loaders/GP_PBM.c b/libs/loaders/GP_PBM.c deleted file mode 100644 index e481684..0000000 --- a/libs/loaders/GP_PBM.c +++ /dev/null @@ -1,127 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -/* - - PBM portable bitmap loader/saver. - - Format: - - a magick number value of 'P' and '1' - whitespace (blanks, TABs, CRs, LFs). - ascii width - whitespace - ascii height - whitespace - width * height symbols '1' or '0' ('1' == black, '0' == white) - - lines starting with '#' are comments to the end of line - - */ - -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <errno.h> - -#include "GP_PXMCommon.h" -#include "GP_PBM.h" - -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') { - err = feof(f) ? EIO : EINVAL; - goto err1; - } - - if (fscanf(f, "%"PRIu32"%"PRIu32, &w, &h) < 2) { - err = EIO; - goto err1; - } - - ret = GP_ContextAlloc(w, h, GP_PIXEL_G1); - - if (ret == NULL) { - err = ENOMEM; - goto err1; - } - - if (GP_PXMLoad1bpp(f, ret)) { - err = EINVAL; - goto err2; - } - - fclose(f); - return ret; -err2: - free(ret); -err1: - fclose(f); - errno = err; - return NULL; -} - -int GP_SavePBM(const GP_Context *src, const char *res_path, - GP_ProgressCallback *callback) -{ - FILE *f; - - if (src->pixel_type != GP_PIXEL_G1) { - errno = EINVAL; - return 1; - } - - f = fopen(res_path, "w"); - - if (f == NULL) - return 1; - - if (fprintf(f, "P1n%u %un# Generated by gfxprimn", - (unsigned int) src->w, (unsigned int) src->h) < 2) - goto err; - - if (GP_PXMSave1bpp(f, src)) - goto err; - - if (fclose(f)) - return 1; - - return 0; -err: - fclose(f); - //TODO: better errors - errno = EIO; - return 1; -} diff --git a/libs/loaders/GP_PGM.c b/libs/loaders/GP_PGM.c deleted file mode 100644 index 4a2321d..0000000 --- a/libs/loaders/GP_PGM.c +++ /dev/null @@ -1,262 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -/* - - PGM portable graymap loader/saver. - - Format: - - a magick number value of 'P' and '2' - whitespace (blanks, TABs, CRs, LFs). - ascii width - whitespace - ascii height - whitespace - maximal gray value (interval is 0 ... max) - width * height ascii gray values - - lines starting with '#' are comments to the end of line - - */ - -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -#include <GP_Debug.h> - -#include "GP_PXMCommon.h" -#include "GP_PGM.h" - -static void try_read_comments(FILE *f) -{ - char c1, c2; - - while (isspace(c1 = fgetc(f))); - - ungetc(c1, f); - - while ((c1 = fgetc(f)) == '#') { - do { - c2 = fgetc(f); - } while (c2 != 'n' && c2 != EOF); - } - - ungetc(c1, f); -} - -GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback) -{ - FILE *f; - GP_Context *ret; - uint32_t w, h, gray; - GP_PixelType type; - char h1, h2; - int err = EIO; - - f = fopen(src_path, "r"); - - if (f == NULL) { - err = errno; - GP_DEBUG(1, "Failed to open file '%s': %s", - src_path, strerror(errno)); - goto err0; - } - - 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 : ' ', - h1, h2); - err = EINVAL; - goto err1; - } - - try_read_comments(f); - - if (fscanf(f, "%"PRIu32, &w) < 1) { - err = errno; - GP_DEBUG(1, "Failed to read PGM header width"); - goto err1; - } - - try_read_comments(f); - - if (fscanf(f, "%"PRIu32, &h) < 1) { - err = errno; - GP_DEBUG(1, "Failed to read PGM header height"); - goto err1; - } - - try_read_comments(f); - - if (fscanf(f, "%"PRIu32, &gray) < 1) { - err = errno; - GP_DEBUG(1, "Failed to read PGM header gray"); - goto err1; - } - - switch (gray) { - case 1: - type = GP_PIXEL_G1; - break; - case 3: - type = GP_PIXEL_G2; - break; - case 15: - type = GP_PIXEL_G4; - break; - case 255: - type = GP_PIXEL_G8; - break; - default: - GP_DEBUG(1, "Invalid number of grays %u", gray); - err = EINVAL; - goto err1; - } - - ret = GP_ContextAlloc(w, h, type); - - if (ret == NULL) { - err = ENOMEM; - goto err1; - } - - //TODO: errno here - switch (gray) { - case 1: - if (GP_PXMLoad1bpp(f, ret)) - goto err2; - break; - case 3: - if (GP_PXMLoad2bpp(f, ret)) - goto err2; - break; - case 15: - if (GP_PXMLoad4bpp(f, ret)) - goto err2; - break; - case 255: - if (GP_PXMLoad8bpp(f, ret)) - goto err2; - break; - } - - fclose(f); - return ret; -err2: - GP_ContextFree(ret); -err1: - fclose(f); -err0: - errno = err; - return NULL; -} - -int GP_SavePGM(const GP_Context *src, const char *res_path, - GP_ProgressCallback *callback) -{ - FILE *f; - uint32_t gray; - int err = EIO; - - switch (src->pixel_type) { - case GP_PIXEL_G1: - gray = 1; - break; - case GP_PIXEL_G2: - gray = 3; - break; - case GP_PIXEL_G4: - gray = 15; - break; - case GP_PIXEL_G8: - gray = 255; - break; - default: - GP_DEBUG(1, "Invalid pixel type '%s'", - GP_PixelTypeName(src->pixel_type)); - errno = EINVAL; - return 1; - } - - f = fopen(res_path, "w"); - - if (f == NULL) { - err = errno; - GP_DEBUG(1, "Failed to open file '%s': %s", - res_path, strerror(errno)); - goto err0; - } - - if (fprintf(f, "P2n%u %un%un# Generated by gfxprimn", - (unsigned int) src->w, (unsigned int) src->h, gray) < 3) - goto err1; - - //TODO: errno - switch (gray) { - case 1: - if (GP_PXMSave1bpp(f, src)) - goto err1; - break; - case 3: - if (GP_PXMSave2bpp(f, src)) - goto err1; - break; - //TODO - case 255: - if (GP_PXMSave8bpp(f, src)) - goto err1; - break; - default: - err = ENOSYS; - goto err1; - } - - if (fclose(f)) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s': %s", - res_path, strerror(errno)); - goto err0; - } - - return 0; -err1: - fclose(f); -err0: - errno = err; - return 1; -} diff --git a/libs/loaders/GP_PNM.c b/libs/loaders/GP_PNM.c index 6e7946e..1104f8f 100644 --- a/libs/loaders/GP_PNM.c +++ b/libs/loaders/GP_PNM.c @@ -16,35 +16,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2010 Cyril Hrubis metan@ucw.cz * + * Copyright (C) 2009-2013 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-#include <stdint.h> -#include <inttypes.h> - -#include <ctype.h> -#include <errno.h> -#include <string.h> - -#include <GP_Debug.h> - -#include "GP_PNM.h" - /*
PNM portable bitmap header -------------------------- - + Format:
- a magick number value of 'P' and one of - '1' - PBM 2bpp gray ASCII - '2' - PGM gray ASCII - '3' - PPM rgb888 ASCII - '4' - PBM 2bpp gray BINARY - '5' - PGM gray BINARY - '6' - PPM rgb888 BINARY + a magic number value of 'P' and one of + '1' - PBM Bitmap ASCII + '2' - PGM Gray ASCII + '3' - PPM RGB ASCII + '4' - PBM Bitmap Binary + '5' - PGM Gray Binary + '6' - PPM RGB Binary whitespace (blanks, TABs, CRs, LFs). ascii width whitespace @@ -57,135 +46,839 @@
*/
-static void try_read_comments(FILE *f) -{ - char c1, c2; +#include <stdio.h> +#include <stdint.h> +#include <inttypes.h> +#include <errno.h> +#include <ctype.h>
- while (isspace(c1 = fgetc(f))); - - ungetc(c1, f); +#include <string.h>
- while ((c1 = fgetc(f)) == '#') { - do { - c2 = fgetc(f); - } while (c2 != 'n' && c2 != EOF); - } +#include "core/GP_Debug.h" +#include "core/GP_Context.h" +#include "core/GP_GetPutPixel.h"
- ungetc(c1, f); -} +#include "loaders/GP_PNM.h"
+struct pnm_header { + char magic; + uint32_t w; + uint32_t h; + uint32_t depth; +};
static char *pnm_names[] = { "ASCII encoded PBM", "ASCII encoded PGM", "ASCII encoded PPM", - "BINARY encoded PBM", - "BINARY encoded PGM", - "BINARY encoded PPM", + "Binary encoded PBM", + "Binary encoded PGM", + "Binary encoded PPM", };
-FILE *GP_ReadPNM(const char *src_path, char *fmt, - uint32_t *w, uint32_t *h, uint32_t *depth) +static const char *pnm_magic_name(char magic) { - FILE *f = fopen(src_path, "r"); - int ch, err; + return pnm_names[magic - '1']; +}
- if (f == NULL) { - GP_DEBUG(1, "Failed to open file '%s': %s", - src_path, strerror(errno)); - return NULL; +/* + * P1 == ascii + * P4 == rawbits + */ +static int is_bitmap(char magic) +{ + return magic == '1' || magic == '4'; +} + +int GP_MatchPBM(const void *buf) +{ + const char *b = buf; + + return b[0] == 'P' && is_bitmap(b[1]); +} + +/* + * P2 == ascii + * P5 == rawbits + */ +static int is_graymap(char magic) +{ + return magic == '2' || magic == '5'; +} + +int GP_MatchPGM(const void *buf) +{ + const char *b = buf; + + return b[0] == 'P' && is_graymap(b[1]); +} + +/* + * P3 == ascii + * P6 == rawbits + */ +static int is_pixmap(char magic) +{ + return magic == '3' || magic == '6'; +} + +int GP_MatchPPM(const void *buf) +{ + const char *b = buf; + + return b[0] == 'P' && is_pixmap(b[1]); +} + +static int magic_is_valid(char magic) +{ + switch (magic) { + case '1' ... '9': + return 1; + default: + return 0; } +}
- ch = fgetc(f); +int GP_MatchPNM(const void *buf) +{ + const char *b = buf;
- if (ch == EOF) { - err = EIO; - goto err1; + return b[0] == 'P' && magic_is_valid(b[1]); +} + +/* + * Header parser + */ +enum state { + S_START, + S_COMMENT, + S_INT, +}; + +static int load_header(FILE *f, struct pnm_header *header) +{ + int h1, h2, c, state = S_START, val = 0, i = 0, err; + + h1 = fgetc(f); + h2 = fgetc(f); + + if (h1 == EOF || h2 == EOF) { + GP_DEBUG(1, "Failed to read header"); + return EIO; }
- if (ch != 'P') { - GP_DEBUG(1, "Invalid PNM header start '%c' (0x%2x) expecting 'P'", - isprint(ch) ? ch : ' ', ch); - err = EINVAL; - goto err1; + if (h1 != 'P' || !magic_is_valid(h2)) { + GP_DEBUG(1, "Invalid magic 0x%02x 0x%02x (%c %c)", + h1, h2, isprint(h1) ? h1 : ' ', isprint(h2) ? h2 : ' '); + return EINVAL; }
- ch = fgetc(f); + header->magic = h2; + header->depth = 1; + header->h = 0; + header->w = 0;
- switch (ch) { - case '4': - case '1': - *depth = 1; - break; - case '2': - case '3': - case '5': - case '6': - break; - default: - GP_DEBUG(1, "Invalid PNM format 'P%c' (0x%2x)", - isprint(ch) ? ch : ' ', ch); - err = EINVAL; - goto err1; + for (;;) { + c = fgetc(f); + + if (c == EOF) { + err = EIO; + goto err; + } + + switch (state) { + case S_START: + switch (c) { + case '#': + state = S_COMMENT; + break; + case '0' ... '9': + val = c - '0'; + state = S_INT; + break; + case 'n': + case 't': + case ' ': + case 'r': + break; + default: + GP_WARN("Ignoring character 0x%02x (%c)", + c, isprint(c) ? c : ' '); + } + break; + case S_COMMENT: + if (c == 'n') + state = S_START; + break; + case S_INT: + switch (c) { + case '0' ... '9': + val *= 10; + val += c - '0'; + break; + default: + switch (i++) { + case 0: + header->w = val; + break; + case 1: + header->h = val; + if (is_bitmap(header->magic)) + goto out; + break; + case 2: + header->depth = val; + goto out; + } + ungetc(c, f); + state = S_START; + break; + } + break; + } + } + +out: + GP_DEBUG(1, "Have header P%c (%s) %"PRIu32"x%"PRIu32" depth=%"PRIu32, + header->magic, pnm_magic_name(header->magic), + header->w, header->h, header->depth); + return 0; +err: + GP_DEBUG(1, "Unexpected end of file when reading header"); + return err; +} + +/* + * ASCII data parser + */ +static int get_ascii_int(FILE *f, int *val) +{ + int c, in_number = 0; + *val = 0; + + for (;;) { + c = fgetc(f); + + switch (c) { + case EOF: + if (!in_number) { + GP_DEBUG(1, "Unexpected end of file"); + return EIO; + } + + return 0; + case '0' ... '9': + *val *= 10; + *val += c - '0'; + in_number = 1; + break; + case 'n': + case 't': + case ' ': + case 'r': + if (in_number) + return 0; + break; + default: + if (in_number) + return 0; + else + GP_WARN("Ignoring unexpected character 0x%02x %c", + c, isprint(c) ? c : ' '); + } + } +} + +static int load_ascii_g1(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int val, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if ((err = get_ascii_int(f, &val))) + return err; + + GP_PutPixel_Raw_1BPP_LE(ctx, x, y, !val); + } + + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + } + + GP_ProgressCallbackDone(cb); + return 0; +} + +static int load_ascii_g2(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int val, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if ((err = get_ascii_int(f, &val))) + return err; + + if (val > 3) { + GP_WARN("Value too large for 2BPP (%i)", val); + val = 3; + } + + GP_PutPixel_Raw_2BPP_LE(ctx, x, y, val); + } + + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + } + + GP_ProgressCallbackDone(cb); + return 0; +} + +static int load_ascii_g4(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int val, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if ((err = get_ascii_int(f, &val))) + return err; + + if (val > 15) { + GP_WARN("Value too large for 4BPP (%i)", val); + val = 3; + } + + GP_PutPixel_Raw_4BPP_LE(ctx, x, y, val); + } + + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } } - - *fmt = ch;
- try_read_comments(f); + GP_ProgressCallbackDone(cb); + return 0; +} + +static int load_ascii_g8(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int val, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if ((err = get_ascii_int(f, &val))) + return err; + + if (val > 15) { + GP_WARN("Value too large for 4BPP (%i)", val); + val = 3; + } + + GP_PutPixel_Raw_8BPP(ctx, x, y, val); + } + + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + } + + GP_ProgressCallbackDone(cb); + return 0; +} + +static int load_ascii_rgb888(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int r, g, b, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if ((err = get_ascii_int(f, &r))) + return err; + + if (r > 255) { + GP_WARN("R value too large (%i)", r); + r = 255; + } + + if ((err = get_ascii_int(f, &g))) + return err; + + if (g > 255) { + GP_WARN("G value too large (%i)", r); + g = 255; + } + + if ((err = get_ascii_int(f, &b))) + return err; + + if (b > 255) { + GP_WARN("G value too large (%i)", r); + b = 255; + } + + GP_PutPixel_Raw_24BPP(ctx, x, y, + GP_Pixel_CREATE_RGB888(r, g, b)); + } + + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + } + + GP_ProgressCallbackDone(cb); + return 0; +} + +static int load_bin_rgb888(FILE *f, GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int r, g, b, err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + r = fgetc(f); + g = fgetc(f); + b = fgetc(f); + + if (r == EOF || g == EOF || b == EOF) { + err = errno; + GP_DEBUG(1, "Unexpected end of PBM file"); + return err; + } + + GP_PutPixel_Raw_24BPP(ctx, x, y, + GP_Pixel_CREATE_RGB888(r, g, b)); + } + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + } + + GP_ProgressCallbackDone(cb); + return 0; +} + +static int save_ascii(FILE *f, const GP_Context *ctx, GP_ProgressCallback *cb) +{ + uint32_t x, y; + int err; + + for (y = 0; y < ctx->h; y++) { + for (x = 0; x < ctx->w; x++) { + + if (fprintf(f, "%i ", GP_GetPixel_Raw(ctx, x, y)) != 1) { + err = errno; + GP_DEBUG(1, "Failed to write data"); + return err; + } + + } + if (GP_ProgressCallbackReport(cb, y, ctx->h, ctx->w)) { + GP_DEBUG(1, "Operation aborted"); + return ECANCELED; + } + fprintf(f, "n"); + }
- if (fscanf(f, "%"PRIu32"n", w) < 1) { - GP_DEBUG(1, "Failed to read PNM header width"); + GP_ProgressCallbackDone(cb); + return 0; +} + +static FILE *read_header(const char *src_path, struct pnm_header *header) +{ + FILE *f; + int err; + + f = fopen(src_path, "r"); + + if (f == NULL) + return NULL; + + if ((err = load_header(f, header))) { + fclose(f); + return NULL; + } + + return f; +} + +static GP_Context *read_bitmap(FILE *f, struct pnm_header *header, int flag, + GP_ProgressCallback *callback) +{ + GP_Context *ret; + int err; + + if (!is_bitmap(header->magic)) { + GP_DEBUG(1, "Invalid Bitmap magic P%c", header->magic); err = EINVAL; + goto err0; + } + + ret = GP_ContextAlloc(header->w, header->h, GP_PIXEL_G1); + + if (ret == NULL) { + err = ENOMEM; goto err1; } + + if ((err = load_ascii_g1(f, ret, callback))) + goto err1; + + if (flag) + fclose(f); + + return ret; +err1: + GP_ContextFree(ret); + + if (flag) + fclose(f); +err0: + errno = err; + return NULL; +} + +GP_Context *GP_LoadPBM(const char *src_path, GP_ProgressCallback *callback) +{ + struct pnm_header header; + FILE *f; + + f = read_header(src_path, &header); + + if (f == NULL) + return NULL; + + return read_bitmap(f, &header, 1, callback); +} + +int GP_SavePBM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + FILE *f; + + if (src->pixel_type != GP_PIXEL_G1) { + errno = EINVAL; + return 1; + } - try_read_comments(f); + f = fopen(dst_path, "w"); + + if (f == NULL) + return 1; + + if (fprintf(f, "P1n%u %u", + (unsigned int) src->w, (unsigned int) src->h) < 2) + goto err; + + if (save_ascii(f, src, callback)) + goto err; + + if (fclose(f)) + return 1; + + return 0; +err: + fclose(f); + errno = EIO; + return 1; +} + +static GP_Pixel depth_to_pixel(int depth) +{ + switch (depth) { + case 1: + return GP_PIXEL_G1; + case 3: + return GP_PIXEL_G2; + case 15: + return GP_PIXEL_G4; + case 255: + return GP_PIXEL_G8; + default: + return GP_PIXEL_UNKNOWN; + } +} + +static GP_Context *read_graymap(FILE *f, struct pnm_header *header, int flag, + GP_ProgressCallback *callback) +{ + GP_Context *ret; + GP_PixelType pixel_type; + int err; - if (fscanf(f, "%"PRIu32"n", h) < 1) { - GP_DEBUG(1, "Failed to read PNM header height"); + if (!is_graymap(header->magic)) { + GP_DEBUG(1, "Invalid graymap magic P%c", header->magic); err = EINVAL; + goto err0; + } + + if ((pixel_type = depth_to_pixel(header->depth)) == GP_PIXEL_UNKNOWN) { + GP_DEBUG(1, "Invalid number of grays %u", header->depth); + err = EINVAL; + goto err0; + } + + ret = GP_ContextAlloc(header->w, header->h, pixel_type); + + if (ret == NULL) { + err = ENOMEM; goto err1; }
- GP_DEBUG(2, "Have %s size %"PRIu32"x%"PRIu32, - pnm_names[*fmt - '1'], *w, *h); + switch (header->depth) { + case 1: + if ((err = load_ascii_g1(f, ret, callback))) + goto err1; + break; + case 3: + if ((err = load_ascii_g2(f, ret, callback))) + goto err1; + break; + case 15: + if ((err = load_ascii_g4(f, ret, callback))) + goto err1; + break; + case 255: + if ((err = load_ascii_g8(f, ret, callback))) + goto err1; + break; + } + + if (flag) + fclose(f);
- if (*fmt == '1' || *fmt == '3') - return f; + return ret; +err1: + GP_ContextFree(ret);
- try_read_comments(f); + if (flag) + fclose(f); +err0: + errno = err; + return NULL; +} + +GP_Context *GP_LoadPGM(const char *src_path, GP_ProgressCallback *callback) +{ + struct pnm_header header; + FILE *f; + + f = read_header(src_path, &header); + + if (f == NULL) + return NULL; + + return read_graymap(f, &header, 1, callback); +} + +static int pixel_to_depth(GP_Pixel pixel) +{ + switch (pixel) { + case GP_PIXEL_G1: + return 1; + case GP_PIXEL_G2: + return 3; + case GP_PIXEL_G4: + return 15; + case GP_PIXEL_G8: + return 255; + default: + return -1; + } +} + +int GP_SavePGM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + FILE *f; + int depth; + int err = EIO; + + if ((depth = pixel_to_depth(src->pixel_type)) == -1) { + GP_DEBUG(1, "Invalid pixel type '%s'", + GP_PixelTypeName(src->pixel_type)); + errno = EINVAL; + return 1; + } - if (fscanf(f, "%"PRIu32"n", depth) < 1) { - GP_DEBUG(1, "Failed to read PNM header depth"); - err = EINVAL; + f = fopen(dst_path, "w"); + + if (f == NULL) { + err = errno; + GP_DEBUG(1, "Failed to open file '%s': %s", + dst_path, strerror(errno)); + goto err0; + } + + if (fprintf(f, "P2n%u %un%un# Generated by gfxprimn", + (unsigned int) src->w, (unsigned int) src->h, depth) < 3) goto err1; + + if ((err = save_ascii(f, src, callback))) + goto err1; + + if (fclose(f)) { + err = errno; + GP_DEBUG(1, "Failed to close file '%s': %s", + dst_path, strerror(errno)); + goto err0; }
- return f; + return 0; err1: fclose(f); +err0: errno = err; - return NULL; + return 1; }
-#define GFXPRIM_SIGNATURE "# Generated by gfxprim http://gfxprim.ucw.czn" - -FILE *GP_WritePNM(const char *dst_path, char fmt, - uint32_t w, uint32_t h, uint32_t depth) +static GP_Context *read_pixmap(FILE *f, struct pnm_header *header, int flag, + GP_ProgressCallback *callback) { - FILE *f = fopen(dst_path, "w"); - int ret; + GP_Context *ret; + int err; + + if (!is_pixmap(header->magic)) { + GP_DEBUG(1, "Invalid Pixmap magic P%c", header->magic); + err = EINVAL; + goto err0; + } + + if (header->depth != 255) { + GP_DEBUG(1, "Unsupported depth %"PRIu32, header->depth); + err = ENOSYS; + goto err0; + }
- ret = fprintf(f, "P%cn"GFXPRIM_SIGNATURE - "%"PRIu32" %"PRIu32"n%"PRIu32"n", - fmt, w, h, depth); + ret = GP_ContextAlloc(header->w, header->h, GP_PIXEL_RGB888); + + if (ret == NULL) { + err = ENOMEM; + goto err0; + }
- if (ret < 0) { - GP_DEBUG(1, "Failed to write PNM header '%s' : %s", - dst_path, strerror(errno)); + switch (header->magic) { + case '3': + if ((err = load_ascii_rgb888(f, ret, callback))) + goto err1; + break; + case '6': + if ((err = load_bin_rgb888(f, ret, callback))) + goto err1; + break; + } + + if (flag) fclose(f); + + return ret; +err1: + GP_ContextFree(ret); + + if (flag) + fclose(f); +err0: + errno = err; + return NULL; +} + +GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback) +{ + struct pnm_header header; + FILE *f; + + f = read_header(src_path, &header); + + if (f == NULL) return NULL; + + return read_pixmap(f, &header, 1, callback); +} + +static int write_binary_ppm(FILE *f, GP_Context *src) +{ + uint32_t x, y; + + for (y = 0; y < src->h; y++) + for (x = 0; x < src->w; x++) { + GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, x, y); + + uint8_t buf[3] = {GP_Pixel_GET_R_RGB888(pix), + GP_Pixel_GET_G_RGB888(pix), + GP_Pixel_GET_B_RGB888(pix)}; + + if (fwrite(buf, 3, 1, f) < 1) + return 1; + } + + return 0; +} + +int GP_SavePPM(GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + errno = ENOSYS; + return -1; +} + +GP_Context *GP_LoadPNM(const char *src_path, GP_ProgressCallback *callback) +{ + + FILE *f; + GP_Context *ret = NULL; + struct pnm_header header; + int err; + + f = fopen(src_path, "r"); + + if (f == NULL) { + err = errno; + GP_DEBUG(1, "Failed to open file '%s': %s", + src_path, strerror(errno)); + goto err0; }
- return f; + if ((err = load_header(f, &header))) + goto err1; + + if (is_bitmap(header.magic)) + ret = read_bitmap(f, &header, 1, callback); + + if (is_graymap(header.magic)) + ret = read_graymap(f, &header, 1, callback); + + if (is_pixmap(header.magic)) + ret = read_pixmap(f, &header, 1, callback); + + return ret; +err1: + fclose(f); +err0: + errno = err; + return NULL; +} + +int GP_SavePNM(const GP_Context *src, const char *dst_path, + GP_ProgressCallback *callback) +{ + errno = ENOSYS; + return -1; } diff --git a/libs/loaders/GP_PNM.h b/libs/loaders/GP_PNM.h deleted file mode 100644 index 2ce48a3..0000000 --- a/libs/loaders/GP_PNM.h +++ /dev/null @@ -1,49 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -/* - - Common PNM functions. - - */ - -#ifndef GP_PNM_H -#define GP_PNM_H - -#include <stdint.h> - -/* - * Loads image header, returns pointer to FILE* (with file position pointing - * to the start of the data stream) on success, fills image metadata into - * arguments. - */ -FILE *GP_ReadPNM(const char *src_path, char *fmt, - uint32_t *w, uint32_t *h, uint32_t *depth); - -/* - * Writes image header. - */ -FILE *GP_WritePNM(const char *dst_path, char fmt, - uint32_t w, uint32_t h, uint32_t depth); - - -#endif /* GP_PNM_H */ diff --git a/libs/loaders/GP_PPM.c b/libs/loaders/GP_PPM.c deleted file mode 100644 index b739b43..0000000 --- a/libs/loaders/GP_PPM.c +++ /dev/null @@ -1,196 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -/* - - PPM portable bitmap loader/saver. - - */ - -#include <stdint.h> -#include <inttypes.h> -#include <errno.h> -#include <string.h> - -#include <GP_Debug.h> -#include <GP_Context.h> -#include <GP_Pixel.h> -#include <GP_GetPutPixel.h> - -#include "GP_PNM.h" -#include "GP_PPM.h" - -static int load_binary_ppm(FILE *f, uint32_t depth __attribute__((unused)), - GP_Context *res) -{ - uint32_t x, y; - int r, g, b; - - for (y = 0; y < res->h; y++) - for (x = 0; x < res->w; x++) { - r = fgetc(f); - g = fgetc(f); - b = fgetc(f); - - if (r == EOF || g == EOF || b == EOF) { - GP_DEBUG(1, "Unexpected end of PBM file"); - return 1; - } - - //TODO depth - GP_Pixel pix = GP_Pixel_CREATE_RGB888(r, g, b); - GP_PutPixel_Raw_24BPP(res, x, y, pix); - } - - return 0; -} - -GP_Context *GP_LoadPPM(const char *src_path, GP_ProgressCallback *callback) -{ - uint32_t w, h, depth; - char fmt; - FILE *f; - GP_Context *ret; - int err; - - f = GP_ReadPNM(src_path, &fmt, &w, &h, &depth); - - if (f == NULL) { - err = errno; - goto err0; - } - - if (fmt != '3' && fmt != '6') { - GP_DEBUG(1, "Asked to load PPM but header is 'P%c'", fmt); - err = EINVAL; - goto err1; - } - - if (depth != 255) { - GP_DEBUG(1, "Unsupported depth %"PRIu32, depth); - err = ENOSYS; - goto err1; - } - - ret = GP_ContextAlloc(w, h, GP_PIXEL_RGB888); - - if (ret == NULL) { - err = ENOMEM; - goto err1; - } - - switch (fmt) { - case '3': - //TODO - err = ENOSYS; - goto err2; - case '6': - //TODO: errno - if (load_binary_ppm(f, depth, ret)) - goto err2; - break; - } - - fclose(f); - return ret; -err2: - GP_ContextFree(ret); -err1: - fclose(f); -err0: - errno = err; - return NULL; -} - -static int write_binary_ppm(FILE *f, GP_Context *src) -{ - uint32_t x, y; - - for (y = 0; y < src->h; y++) - for (x = 0; x < src->w; x++) { - GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, x, y); - - uint8_t buf[3] = {GP_Pixel_GET_R_RGB888(pix), - GP_Pixel_GET_G_RGB888(pix), - GP_Pixel_GET_B_RGB888(pix)}; - - if (fwrite(buf, 3, 1, f) < 1) - return 1; - } - - return 0; -} - -int GP_SavePPM(const char *res_path, GP_Context *src, char *fmt, - GP_ProgressCallback *callback) -{ - char hfmt; - FILE *f; - int err; - - if (src->pixel_type != GP_PIXEL_RGB888) { - errno = EINVAL; - return 1; - } - - switch (*fmt) { - /* ASCII */ - case 'a': - errno = ENOSYS; - return 1; - break; - /* binary */ - case 'b': - hfmt = '6'; - GP_DEBUG(1, "Writing binary PPM %ux%u '%s'", - src->w, src->h, res_path); - break; - default: - errno = EINVAL; - return 1; - } - - f = GP_WritePNM(res_path, hfmt, src->w, src->h, 255); - - if (f == NULL) - return 1; - - if (write_binary_ppm(f, src)) { - GP_DEBUG(1, "Failed to write buffer"); - err = EIO; - goto err1; - } - - if (fclose(f) < 0) { - err = errno; - GP_DEBUG(1, "Failed to close file '%s' : %s", - res_path, strerror(errno)); - goto err0; - } - - return 0; -err1: - fclose(f); -err0: - errno = err; - return 1; -} diff --git a/libs/loaders/GP_PXMCommon.c b/libs/loaders/GP_PXMCommon.c deleted file mode 100644 index e2738ab..0000000 --- a/libs/loaders/GP_PXMCommon.c +++ /dev/null @@ -1,388 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -#include <stdint.h> -#include <inttypes.h> - -#include <ctype.h> -#include <errno.h> -#include <string.h> - -#include <GP_Debug.h> - -#include "GP_PXMCommon.h" - -static int read_comment(FILE *f) -{ - for (;;) { - switch (fgetc(f)) { - case 'n': - return 0; - case EOF: - return 1; - } - } -} - -int GP_PXMLoad1bpp(FILE *f, GP_Context *context) -{ - uint8_t *pixel = context->pixels; - uint32_t x, y; - - for (y = 0; y < context->h; y++) { - for (x = 0; x < context->w;) { - int run = 1; - - while (run) { - switch (fgetc(f)) { - case EOF: - return EIO; - case '#': - if (read_comment(f)) - return EIO; - break; - case '0': - *pixel &= ~(0x80>>(x%8)); - run = 0; - break; - case '1': - *pixel |= 0x80>>(x%8); - run = 0; - break; - default: - break; - } - } - - x++; - - if (x%8 == 0) - pixel++; - } - - if (context->w%8) - pixel++; - } - - return 0; -} - -int GP_PXMLoad2bpp(FILE *f, GP_Context *context) -{ - uint8_t *pixel = context->pixels; - uint32_t x, y; - - for (y = 0; y < context->h; y++) { - for (x = 0; x < context->w;) { - int run = 1; - - while (run) { - switch (fgetc(f)) { - case EOF: - return EIO; - case '#': - if (read_comment(f)) - return EIO; - break; - case '0': - *pixel &= ~(0xc0>>(2*(x%4))); - run = 0; - break; - case '1': - *pixel &= ~(0x80>>(2*(x%4))); - *pixel |= 0x40>>(2*(x%4)); - run = 0; - break; - case '2': - *pixel |= 0x80>>(2*(x%4)); - *pixel &= ~(0x40>>(2*(x%4))); - run = 0; - break; - case '3': - *pixel |= 0xc0>>(2*(x%4)); - run = 0; - break; - default: - break; - } - } - - x++; - - if (x%4 == 0) - pixel++; - } - - if (context->w%4) - pixel++; - } - - return 0; -} - -int GP_PXMLoad4bpp(FILE *f, GP_Context *context) -{ - uint8_t *pixel = context->pixels; - uint32_t x, y; - - for (y = 0; y < context->h; y++) { - for (x = 0; x < context->w;) { - int run = 1; - int val = 0; - char ch; - - while (run) { - switch (fgetc(f)) { - case EOF: - return EIO; - case '#': - if (read_comment(f)) - return EIO; - break; - case '1': - ch = fgetc(f); - val = 1; - if (ch >= 0 && ch <= 5) - val = 10 + ch - '0'; - case '0': - run = 0; - - *pixel = (*pixel & 0xf0>>4*(x%2)) | - val<<(4*(!x%2)); - break; - } - } - - x++; - - if (x%2 == 0) - pixel++; - } - - if (context->w%2) - pixel++; - } - - return 0; -} - -int GP_PXMLoad8bpp(FILE *f, GP_Context *context) -{ - uint8_t *pixel = context->pixels; - uint32_t x, y; - - for (y = 0; y < context->h; y++) { - for (x = 0; x < context->w; x++) { - int run = 1; - int val = 0; - char ch; - - while (run) { - switch (ch = fgetc(f)) { - case EOF: - return EIO; - case '#': - if (read_comment(f)) - return EIO; - break; - case '1' ... '9': - val = ch - '0'; - ch = fgetc(f); - if (ch >= '0' && ch <= '9') { - val = val * 10 + ch - '0'; - ch = fgetc(f); - if (ch >= '0' && ch <= '9') - val = val * 10 + ch - '0'; - } - - if (val > 255) - return EIO; - case '0': - run = 0; - - *pixel = val; - break; - default: - break; - } - } - - pixel++; - } - } - - return 0; -} - -#define BITMASK(byte, bit) (!!((byte)&(0x80>>(bit)))) - -static int write_line_1bpp(FILE *f, const uint8_t *data, const GP_Context *src) -{ - uint32_t x, max = src->bytes_per_row; - int ret; - - if (src->w % 8) - max--; - - for (x = 0; x < max; x++) { - - if (x != 0) - if (fprintf(f, " ") < 0) - return EIO; - - ret = fprintf(f, "%u %u %u %u %u %u %u %u", - BITMASK(data[x], 0), - BITMASK(data[x], 1), - BITMASK(data[x], 2), - BITMASK(data[x], 3), - BITMASK(data[x], 4), - BITMASK(data[x], 5), - BITMASK(data[x], 6), - BITMASK(data[x], 7)); - if (ret < 0) - return EIO; - } - - for (x = 0; x < (src->w % 8); x++) { - ret = fprintf(f, " %u", BITMASK(data[max], x)); - - if (ret < 0) - return EIO; - } - - if (fprintf(f, "n") < 0) - return EIO; - - return 0; -} - -int GP_PXMSave1bpp(FILE *f, const GP_Context *context) -{ - uint32_t y; - int ret; - - for (y = 0; y < context->h; y++) { - ret = write_line_1bpp(f, context->pixels + context->bytes_per_row * y, - context); - - if (ret) - return ret; - } - - return 0; -} - -#define MASK_2BPP(byte, pix) (0x03 & (byte>>((3 - pix)<<1))) - -static int write_line_2bpp(FILE *f, const uint8_t *data, const GP_Context *src) -{ - uint32_t x, max = src->bytes_per_row; - int ret; - - if (src->w % 4) - max--; - - for (x = 0; x < max; x++) { - - if (x != 0) - if (fprintf(f, " ") < 0) - return EIO; - - ret = fprintf(f, "%u %u %u %u", - MASK_2BPP(data[x], 0), - MASK_2BPP(data[x], 1), - MASK_2BPP(data[x], 2), - MASK_2BPP(data[x], 3)); - if (ret < 0) - return EIO; - } - - for (x = 0; x < (src->w % 4); x++) { - ret = fprintf(f, " %u", MASK_2BPP(data[max], x)); - - if (ret < 0) - return EIO; - } - - if (fprintf(f, "n") < 0) - return EIO; - - return EIO; -} - -int GP_PXMSave2bpp(FILE *f, const GP_Context *context) -{ - uint32_t y; - int ret; - - for (y = 0; y < context->h; y++) { - ret = write_line_2bpp(f, context->pixels + context->bytes_per_row * y, - context); - - if (ret) - return ret; - } - - return EIO; -} - -static int write_line_8bpp(FILE *f, const uint8_t *data, const GP_Context *src) -{ - uint32_t x; - int ret; - - for (x = 0; x < src->w; x++) { - - if (x != 0) - if (fprintf(f, " ") < 0) - return EIO; - - ret = fprintf(f, "%u", data[x]); - - if (ret < 0) - return EIO; - } - - if (fprintf(f, "n") < 0) - return EIO; - - return 0; -} - -int GP_PXMSave8bpp(FILE *f, const GP_Context *context) -{ - uint32_t y; - int ret; - - for (y = 0; y < context->h; y++) { - ret = write_line_8bpp(f, context->pixels + context->bytes_per_row * y, - context); - - if (ret) - return ret; - } - - return 0; -} diff --git a/libs/loaders/GP_PXMCommon.h b/libs/loaders/GP_PXMCommon.h deleted file mode 100644 index 1780eec..0000000 --- a/libs/loaders/GP_PXMCommon.h +++ /dev/null @@ -1,67 +0,0 @@ -/***************************************************************************** - * This file is part of gfxprim library. * - * * - * Gfxprim is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * Gfxprim is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with gfxprim; if not, write to the Free Software * - * Foundation, Inc., 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301 USA * - * * - * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * - * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * - * * - *****************************************************************************/ - -/* - - Common bytes to ascci and ascii to bytes functions. - - */ - -#ifndef LOADERS_GP_PXM_COMMON_H -#define LOADERS_GP_PXM_COMMON_H - -#include <stdio.h> -#include "core/GP_Core.h" - -/* - * Save context to ascii file. - * - * The pixel type is not checked here as these are internal funcitons. - */ -int GP_PXMSave1bpp(FILE *f, const GP_Context *context); -int GP_PXMSave2bpp(FILE *f, const GP_Context *context); -int GP_PXMSave4bpp(FILE *f, const GP_Context *context); -int GP_PXMSave8bpp(FILE *f, const GP_Context *context); - -/* - * Load context from ascii file. - */ -int GP_PXMLoad1bpp(FILE *f, GP_Context *context); -int GP_PXMLoad2bpp(FILE *f, GP_Context *context); -int GP_PXMLoad4bpp(FILE *f, GP_Context *context); -int GP_PXMLoad8bpp(FILE *f, GP_Context *context); - -/* - * Loads image header, returns pointer to FILE* on success, fills image - * metadata into arguments. - */ -FILE *GP_ReadHeaderPNM(const char *src_path, char *fmt, - uint32_t *w, uint32_t *h, uint32_t *depth); - -FILE *GP_WriteHeaderPNM(const char *dst_path, char *fmt, - uint32_t w, uint32_t h, uint32_t depth); - - -#endif /* LOADERS_GP_PXM_COMMON_H */ diff --git a/pylib/gfxprim/loaders/loaders.i b/pylib/gfxprim/loaders/loaders.i index 33a2fbd..e651a1c 100644 --- a/pylib/gfxprim/loaders/loaders.i +++ b/pylib/gfxprim/loaders/loaders.i @@ -59,10 +59,10 @@ ERROR_ON_NONZERO(GP_SavePNG); ERROR_ON_NULL(GP_LoadPBM); ERROR_ON_NULL(GP_LoadPGM); ERROR_ON_NULL(GP_LoadPPM); +ERROR_ON_NULL(GP_LoadPNM); ERROR_ON_NONZERO(GP_SavePBM); ERROR_ON_NONZERO(GP_SavePGM); ERROR_ON_NONZERO(GP_SavePPM); +ERROR_ON_NONZERO(GP_SavePNM);
-%include "GP_PBM.h" -%include "GP_PGM.h" -%include "GP_PPM.h" +%include "GP_PNM.h"
-----------------------------------------------------------------------
Summary of changes: build/syms/Loaders_symbols.txt | 24 +- demos/grinder/grinder.c | 2 +- include/loaders/GP_Loaders.h | 5 +- include/loaders/GP_PBM.h | 49 -- include/loaders/GP_PGM.h | 37 - include/loaders/GP_PPM.h | 37 - libs/loaders/GP_Loader.c | 27 +- libs/loaders/GP_PBM.c | 127 --- libs/loaders/GP_PGM.c | 262 ------ libs/loaders/GP_PNM.c | 893 +++++++++++++++++--- libs/loaders/GP_PNM.h | 49 -- libs/loaders/GP_PPM.c | 196 ----- libs/loaders/GP_PXMCommon.c | 388 --------- libs/loaders/GP_PXMCommon.h | 67 -- pylib/gfxprim/loaders/loaders.i | 6 +- tests/loaders/Makefile | 2 +- tests/loaders/PBM.c | 196 +++++ .../emptyfile.bmp => pbm/corrupt/empty.pbm} | 0 tests/loaders/data/pbm/corrupt/short.pbm | 3 + tests/loaders/data/pbm/valid/black_1x1_1.pbm | 3 + tests/loaders/data/pbm/valid/black_1x1_2.pbm | 4 + tests/loaders/data/pbm/valid/black_1x1_3.pbm | 8 + tests/loaders/data/pbm/valid/black_1x1_4.pbm | 4 + tests/loaders/data/pbm/valid/white_1x1.pbm | 3 + tests/loaders/test_list.txt | 1 + 25 files changed, 1051 insertions(+), 1342 deletions(-) delete mode 100644 include/loaders/GP_PBM.h delete mode 100644 include/loaders/GP_PGM.h delete mode 100644 include/loaders/GP_PPM.h delete mode 100644 libs/loaders/GP_PBM.c delete mode 100644 libs/loaders/GP_PGM.c delete mode 100644 libs/loaders/GP_PNM.h delete mode 100644 libs/loaders/GP_PPM.c delete mode 100644 libs/loaders/GP_PXMCommon.c delete mode 100644 libs/loaders/GP_PXMCommon.h create mode 100644 tests/loaders/PBM.c copy tests/loaders/data/{bmp/bitmaps/corrupt/emptyfile.bmp => pbm/corrupt/empty.pbm} (100%) create mode 100644 tests/loaders/data/pbm/corrupt/short.pbm create mode 100644 tests/loaders/data/pbm/valid/black_1x1_1.pbm create mode 100644 tests/loaders/data/pbm/valid/black_1x1_2.pbm create mode 100644 tests/loaders/data/pbm/valid/black_1x1_3.pbm create mode 100644 tests/loaders/data/pbm/valid/black_1x1_4.pbm create mode 100644 tests/loaders/data/pbm/valid/white_1x1.pbm
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.