Fix the directory layout and build system.
[gfxprim.git] / libs / loaders / GP_PXMCommon.c
blob62ee36bb978236dd9a5426bc90f761a96d4287ce
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
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. *
8 * *
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. *
13 * *
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 *
18 * *
19 * Copyright (C) 2009-2010 Jiri "BlueBear" Dluhos *
20 * <jiri.bluebear.dluhos@gmail.com> *
21 * *
22 * Copyright (C) 2009-2010 Cyril Hrubis <metan@ucw.cz> *
23 * *
24 *****************************************************************************/
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <inttypes.h>
30 #include "GP_PXMCommon.h"
32 static int read_comment(FILE *f)
34 for (;;) {
35 switch (fgetc(f)) {
36 case '\n':
37 return 0;
38 case EOF:
39 return 1;
44 GP_RetCode GP_PXMLoad1bpp(FILE *f, GP_Context *context)
46 uint8_t *pixel = context->pixels;
47 uint32_t x, y;
49 for (y = 0; y < context->h; y++) {
50 for (x = 0; x < context->w;) {
51 int run = 1;
53 while (run) {
54 switch (fgetc(f)) {
55 case EOF:
56 return GP_EBADFILE;
57 case '#':
58 if (read_comment(f))
59 return GP_EBADFILE;
60 break;
61 case '0':
62 *pixel &= ~(0x80>>(x%8));
63 run = 0;
64 break;
65 case '1':
66 *pixel |= 0x80>>(x%8);
67 run = 0;
68 break;
69 default:
70 break;
74 x++;
76 if (x%8 == 0)
77 pixel++;
80 if (context->w%8)
81 pixel++;
84 return GP_ESUCCESS;
87 GP_RetCode GP_PXMLoad2bpp(FILE *f, GP_Context *context)
89 uint8_t *pixel = context->pixels;
90 uint32_t x, y;
92 for (y = 0; y < context->h; y++) {
93 for (x = 0; x < context->w;) {
94 int run = 1;
96 while (run) {
97 switch (fgetc(f)) {
98 case EOF:
99 return GP_EBADFILE;
100 case '#':
101 if (read_comment(f))
102 return GP_EBADFILE;
103 break;
104 case '0':
105 *pixel &= ~(0xc0>>(2*(x%4)));
106 run = 0;
107 break;
108 case '1':
109 *pixel &= ~(0x80>>(2*(x%4)));
110 *pixel |= 0x40>>(2*(x%4));
111 run = 0;
112 break;
113 case '2':
114 *pixel |= 0x80>>(2*(x%4));
115 *pixel &= ~(0x40>>(2*(x%4)));
116 run = 0;
117 break;
118 case '3':
119 *pixel |= 0xc0>>(2*(x%4));
120 run = 0;
121 break;
122 default:
123 break;
127 x++;
129 if (x%4 == 0)
130 pixel++;
133 if (context->w%4)
134 pixel++;
137 return GP_ESUCCESS;
140 GP_RetCode GP_PXMLoad4bpp(FILE *f, GP_Context *context)
142 uint8_t *pixel = context->pixels;
143 uint32_t x, y;
145 for (y = 0; y < context->h; y++) {
146 for (x = 0; x < context->w;) {
147 int run = 1;
148 int val = 0;
149 char ch;
151 while (run) {
152 switch (fgetc(f)) {
153 case EOF:
154 return GP_EBADFILE;
155 case '#':
156 if (read_comment(f))
157 return GP_EBADFILE;
158 break;
159 case '1':
160 ch = fgetc(f);
161 val = 1;
162 if (ch >= 0 && ch <= 5)
163 val = 10 + ch - '0';
164 case '0':
165 run = 0;
167 *pixel = (*pixel & 0xf0>>4*(x%2)) |
168 val<<(4*(!x%2));
169 break;
173 x++;
175 if (x%2 == 0)
176 pixel++;
179 if (context->w%2)
180 pixel++;
183 return GP_ESUCCESS;
186 GP_RetCode GP_PXMLoad8bpp(FILE *f, GP_Context *context)
188 uint8_t *pixel = context->pixels;
189 uint32_t x, y;
191 for (y = 0; y < context->h; y++) {
192 for (x = 0; x < context->w; x++) {
193 int run = 1;
194 int val = 0;
195 char ch;
197 while (run) {
198 switch (ch = fgetc(f)) {
199 case EOF:
200 return GP_EBADFILE;
201 case '#':
202 if (read_comment(f))
203 return GP_EBADFILE;
204 break;
205 case '1' ... '9':
206 val = ch - '0';
207 ch = fgetc(f);
208 if (ch >= '0' && ch <= '9') {
209 val = val * 10 + ch - '0';
210 ch = fgetc(f);
211 if (ch >= '0' && ch <= '9')
212 val = val * 10 + ch - '0';
215 if (val > 255)
216 return GP_EBADFILE;
217 case '0':
218 run = 0;
220 *pixel = val;
221 break;
222 default:
223 break;
227 pixel++;
231 return GP_ESUCCESS;
234 #define BITMASK(byte, bit) (!!((byte)&(0x80>>(bit))))
236 static GP_RetCode write_line_1bpp(FILE *f, const uint8_t *data, GP_Context *src)
238 uint32_t x, max = src->bytes_per_row;
239 int ret;
241 if (src->w % 8)
242 max--;
244 for (x = 0; x < max; x++) {
246 if (x != 0)
247 if (fprintf(f, " ") < 0)
248 return GP_EBADFILE;
250 ret = fprintf(f, "%u %u %u %u %u %u %u %u",
251 BITMASK(data[x], 0),
252 BITMASK(data[x], 1),
253 BITMASK(data[x], 2),
254 BITMASK(data[x], 3),
255 BITMASK(data[x], 4),
256 BITMASK(data[x], 5),
257 BITMASK(data[x], 6),
258 BITMASK(data[x], 7));
259 if (ret < 0)
260 return GP_EBADFILE;
263 for (x = 0; x < (src->w % 8); x++) {
264 ret = fprintf(f, " %u", BITMASK(data[max], x));
266 if (ret < 0)
267 return GP_EBADFILE;
270 if (fprintf(f, "\n") < 0)
271 return GP_EBADFILE;
273 return GP_ESUCCESS;
276 GP_RetCode GP_PXMSave1bpp(FILE *f, GP_Context *context)
278 uint32_t y;
279 GP_RetCode ret;
281 for (y = 0; y < context->h; y++) {
282 ret = write_line_1bpp(f, context->pixels + context->bytes_per_row * y,
283 context);
285 if (ret)
286 return ret;
289 return GP_ESUCCESS;
292 #define MASK_2BPP(byte, pix) (0x03 & (byte>>((3 - pix)<<1)))
294 static GP_RetCode write_line_2bpp(FILE *f, const uint8_t *data, GP_Context *src)
296 uint32_t x, max = src->bytes_per_row;
297 int ret;
299 if (src->w % 4)
300 max--;
302 for (x = 0; x < max; x++) {
304 if (x != 0)
305 if (fprintf(f, " ") < 0)
306 return GP_EBADFILE;
308 ret = fprintf(f, "%u %u %u %u",
309 MASK_2BPP(data[x], 0),
310 MASK_2BPP(data[x], 1),
311 MASK_2BPP(data[x], 2),
312 MASK_2BPP(data[x], 3));
313 if (ret < 0)
314 return GP_EBADFILE;
317 for (x = 0; x < (src->w % 4); x++) {
318 ret = fprintf(f, " %u", MASK_2BPP(data[max], x));
320 if (ret < 0)
321 return GP_EBADFILE;
324 if (fprintf(f, "\n") < 0)
325 return GP_EBADFILE;
327 return GP_ESUCCESS;
330 GP_RetCode GP_PXMSave2bpp(FILE *f, GP_Context *context)
332 uint32_t y;
333 GP_RetCode ret;
335 for (y = 0; y < context->h; y++) {
336 ret = write_line_2bpp(f, context->pixels + context->bytes_per_row * y,
337 context);
339 if (ret)
340 return ret;
343 return GP_ESUCCESS;
346 static GP_RetCode write_line_8bpp(FILE *f, const uint8_t *data, GP_Context *src)
348 uint32_t x;
349 int ret;
351 for (x = 0; x < src->w; x++) {
353 if (x != 0)
354 if (fprintf(f, " ") < 0)
355 return GP_EBADFILE;
357 ret = fprintf(f, "%u", data[x]);
359 if (ret < 0)
360 return GP_EBADFILE;
363 if (fprintf(f, "\n") < 0)
364 return GP_EBADFILE;
366 return GP_ESUCCESS;
369 GP_RetCode GP_PXMSave8bpp(FILE *f, GP_Context *context)
371 uint32_t y;
372 GP_RetCode ret;
374 for (y = 0; y < context->h; y++) {
375 ret = write_line_8bpp(f, context->pixels + context->bytes_per_row * y,
376 context);
378 if (ret)
379 return ret;
382 return GP_ESUCCESS;