1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
22 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
24 *****************************************************************************/
28 PGM portable graymap loader/saver.
32 a magick number value of 'P' and '2'
33 whitespace (blanks, TABs, CRs, LFs).
38 maximal gray value (interval is 0 ... max)
39 width * height ascii gray values
41 lines starting with '#' are comments to the end of line
54 #include "GP_PXMCommon.h"
57 static void try_read_comments(FILE *f
)
61 while (isspace(c1
= fgetc(f
)));
65 while ((c1
= fgetc(f
)) == '#') {
68 } while (c2
!= '\n' && c2
!= EOF
);
74 GP_Context
*GP_LoadPGM(const char *src_path
, GP_ProgressCallback
*callback
)
83 f
= fopen(src_path
, "r");
87 GP_DEBUG(1, "Failed to open file '%s': %s",
88 src_path
, strerror(errno
));
100 if (h1
!= 'P' || h2
!= '2') {
101 GP_DEBUG(1, "Invalid PGM header '%c%c' (0x%2x 0x%2x)",
102 isprint(h1
) ? h1
: ' ', isprint(h2
) ? h2
: ' ',
108 try_read_comments(f
);
110 if (fscanf(f
, "%"PRIu32
, &w
) < 1) {
112 GP_DEBUG(1, "Failed to read PGM header width");
116 try_read_comments(f
);
118 if (fscanf(f
, "%"PRIu32
, &h
) < 1) {
120 GP_DEBUG(1, "Failed to read PGM header height");
124 try_read_comments(f
);
126 if (fscanf(f
, "%"PRIu32
, &gray
) < 1) {
128 GP_DEBUG(1, "Failed to read PGM header gray");
146 GP_DEBUG(1, "Invalid number of grays %u", gray
);
151 ret
= GP_ContextAlloc(w
, h
, type
);
161 if (GP_PXMLoad1bpp(f
, ret
))
165 if (GP_PXMLoad2bpp(f
, ret
))
169 if (GP_PXMLoad4bpp(f
, ret
))
173 if (GP_PXMLoad8bpp(f
, ret
))
189 int GP_SavePGM(const GP_Context
*src
, const char *res_path
,
190 GP_ProgressCallback
*callback
)
196 switch (src
->pixel_type
) {
210 GP_DEBUG(1, "Invalid pixel type '%s'",
211 GP_PixelTypeName(src
->pixel_type
));
216 f
= fopen(res_path
, "w");
220 GP_DEBUG(1, "Failed to open file '%s': %s",
221 res_path
, strerror(errno
));
225 if (fprintf(f
, "P2\n%u %u\n%u\n# Generated by gfxprim\n",
226 (unsigned int) src
->w
, (unsigned int) src
->h
, gray
) < 3)
232 if (GP_PXMSave1bpp(f
, src
))
236 if (GP_PXMSave2bpp(f
, src
))
241 if (GP_PXMSave8bpp(f
, src
))
251 GP_DEBUG(1, "Failed to close file '%s': %s",
252 res_path
, strerror(errno
));