Coverage Report

Created: 2026-08-13 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libgd/src/wbmp.c
Line
Count
Source
1
/* WBMP
2
 * ----
3
 * WBMP Level 0: B/W, Uncompressed
4
 * This implements the WBMP format as specified in WAPSpec 1.1 and 1.2.
5
 * It does not support ExtHeaders as defined in the spec. The spec states
6
 * that a WAP client does not need to implement ExtHeaders.
7
 *
8
 * (c) 2000 Johan Van den Brande <johan@vandenbrande.com>
9
 */
10
11
#ifdef HAVE_CONFIG_H
12
#include "config.h"
13
#endif
14
15
#include <stddef.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include "gd.h"
21
#include "gdhelpers.h"
22
#include "wbmp.h"
23
24
#ifdef NOTDEF
25
#define __TEST  /* Compile with main function */
26
#define __DEBUG /* Extra verbose when with __TEST */
27
#define __WRITE /* readwbmp and writewbmp(stdout) */
28
#define __VIEW  /* view the wbmp on stdout */
29
#endif
30
31
/* getmbi
32
 * ------
33
 * Get a multibyte integer from a generic getin function
34
 * 'getin' can be getc, with in = NULL
35
 * you can find getin as a function just above the main function
36
 * This way you gain a lot of flexibility about how this package
37
 * reads a wbmp file.
38
 */
39
int getmbi(int (*getin)(void *in), void *in)
40
509
{
41
509
    unsigned int mbi = 0;
42
509
    int i;
43
44
4.13M
    do {
45
4.13M
        i = getin(in);
46
4.13M
        if (i < 0) {
47
104
            return (-1);
48
104
        }
49
4.13M
        mbi = (mbi << 7) | (i & 0x7f);
50
4.13M
    } while (i & 0x80);
51
52
405
    return mbi;
53
509
}
54
55
/* putmbi
56
 * ------
57
 * Put a multibyte intgerer in some kind of output stream
58
 * I work here with a function pointer, to make it as generic
59
 * as possible. Look at this function as an iterator on the
60
 * mbi integers it spits out.
61
 *
62
 */
63
void putmbi(int i, void (*putout)(int c, void *out), void *out)
64
0
{
65
0
    int cnt, l, accu;
66
67
    /* Get number of septets */
68
0
    accu = cnt = 0;
69
0
    while (accu != i) {
70
0
        accu += i & 0x7f << 7 * cnt++;
71
0
    }
72
73
    /* Produce the multibyte output */
74
0
    for (l = cnt - 1; l > 0; l--) {
75
0
        putout(0x80 | (i & 0x7f << 7 * l) >> 7 * l, out);
76
0
    }
77
78
0
    putout(i & 0x7f, out);
79
0
}
80
81
/* skipheader
82
 * ----------
83
 * Skips the ExtHeader. Not needed for the moment
84
 */
85
int skipheader(int (*getin)(void *in), void *in)
86
278
{
87
278
    int i;
88
89
45.7k
    do {
90
45.7k
        i = getin(in);
91
45.7k
        if (i < 0) {
92
15
            return (-1);
93
15
        }
94
45.7k
    } while (i & 0x80);
95
96
263
    return 0;
97
278
}
98
99
/* create wbmp
100
 * -----------
101
 * create an empty wbmp
102
 */
103
Wbmp *createwbmp(int width, int height, int color)
104
0
{
105
0
    int i;
106
0
    Wbmp *wbmp;
107
108
0
    if ((wbmp = (Wbmp *)gdMalloc(sizeof(Wbmp))) == NULL) {
109
0
        return (NULL);
110
0
    }
111
112
0
    if (overflow2(sizeof(int), width)) {
113
0
        gdFree(wbmp);
114
0
        return NULL;
115
0
    }
116
117
0
    if (overflow2(sizeof(int) * width, height)) {
118
0
        gdFree(wbmp);
119
0
        return NULL;
120
0
    }
121
122
0
    if ((wbmp->bitmap = (int *)gdMalloc(sizeof(int) * width * height)) == NULL) {
123
0
        gdFree(wbmp);
124
0
        return NULL;
125
0
    }
126
127
0
    wbmp->width = width;
128
0
    wbmp->height = height;
129
130
0
    for (i = 0; i < width * height; wbmp->bitmap[i++] = color)
131
0
        ;
132
133
0
    return wbmp;
134
0
}
135
136
/* readwbmp
137
 * -------
138
 * Actually reads the WBMP format from an open file descriptor
139
 * It goes along by returning a pointer to a WBMP struct.
140
 */
141
int readwbmp(int (*getin)(void *in), void *in, Wbmp **return_wbmp)
142
287
{
143
287
    int row, col, byte, pel, pos;
144
287
    Wbmp *wbmp;
145
146
287
    if ((wbmp = (Wbmp *)gdMalloc(sizeof(Wbmp))) == NULL) {
147
0
        return -1;
148
0
    }
149
150
287
    wbmp->type = getin(in);
151
287
    if (wbmp->type != 0) {
152
9
        gdFree(wbmp);
153
9
        return -1;
154
9
    }
155
156
278
    if (skipheader(getin, in)) {
157
15
        gdFree(wbmp);
158
15
        return -1;
159
15
    }
160
161
263
    wbmp->width = getmbi(getin, in);
162
263
    if (wbmp->width == -1) {
163
17
        gdFree(wbmp);
164
17
        return -1;
165
17
    }
166
167
246
    wbmp->height = getmbi(getin, in);
168
246
    if (wbmp->height == -1) {
169
87
        gdFree(wbmp);
170
87
        return -1;
171
87
    }
172
173
#ifdef __DEBUG
174
    printf("W: %d, H: %d\n", wbmp->width, wbmp->height);
175
#endif
176
177
159
    if (overflow2(sizeof(int), wbmp->width) || overflow2(sizeof(int) * wbmp->width, wbmp->height)) {
178
87
        gdFree(wbmp);
179
87
        return -1;
180
87
    }
181
182
72
    if ((wbmp->bitmap = (int *)gdMalloc(sizeof(int) * wbmp->width * wbmp->height)) == NULL) {
183
0
        gdFree(wbmp);
184
0
        return -1;
185
0
    }
186
187
#ifdef __DEBUG
188
    printf("DATA CONSTRUCTED\n");
189
#endif
190
191
72
    pos = 0;
192
190k
    for (row = 0; row < wbmp->height; row++) {
193
404k
        for (col = 0; col < wbmp->width;) {
194
213k
            byte = getin(in);
195
196
1.92M
            for (pel = 7; pel >= 0; pel--) {
197
1.70M
                if (col++ < wbmp->width) {
198
380k
                    if (byte & 1 << pel) {
199
361k
                        wbmp->bitmap[pos] = WBMP_WHITE;
200
361k
                    } else {
201
18.2k
                        wbmp->bitmap[pos] = WBMP_BLACK;
202
18.2k
                    }
203
380k
                    pos++;
204
380k
                }
205
1.70M
            }
206
213k
        }
207
190k
    }
208
209
72
    *return_wbmp = wbmp;
210
211
72
    return 0;
212
72
}
213
214
/* writewbmp
215
 * ---------
216
 * Write a wbmp to a file descriptor
217
 *
218
 * Why not just giving a filedescriptor to this function?
219
 * Well, the incentive to write this function was the complete
220
 * integration in gd library from www.libgd.org. They use
221
 * their own io functions, so the passing of a function seemed to be
222
 * a logic(?) decision ...
223
 */
224
int writewbmp(Wbmp *wbmp, void (*putout)(int c, void *out), void *out)
225
0
{
226
0
    int row, col;
227
0
    int bitpos, octet;
228
229
    /* Generate the header */
230
0
    putout(0, out); /* WBMP Type 0: B/W, Uncompressed bitmap */
231
0
    putout(0, out); /* FixHeaderField */
232
233
    /* Size of the image */
234
0
    putmbi(wbmp->width, putout, out);  /* width */
235
0
    putmbi(wbmp->height, putout, out); /* height */
236
237
    /* Image data */
238
0
    for (row = 0; row < wbmp->height; row++) {
239
0
        bitpos = 8;
240
0
        octet = 0;
241
242
0
        for (col = 0; col < wbmp->width; col++) {
243
0
            octet |= ((wbmp->bitmap[row * wbmp->width + col] == 1) ? WBMP_WHITE : WBMP_BLACK)
244
0
                     << --bitpos;
245
0
            if (bitpos == 0) {
246
0
                bitpos = 8;
247
0
                putout(octet, out);
248
0
                octet = 0;
249
0
            }
250
0
        }
251
252
0
        if (bitpos != 8) {
253
0
            putout(octet, out);
254
0
        }
255
0
    }
256
257
0
    return 0;
258
0
}
259
260
/* freewbmp
261
 * --------
262
 * gdFrees up memory occupied by a WBMP structure
263
 */
264
void freewbmp(Wbmp *wbmp)
265
72
{
266
72
    gdFree(wbmp->bitmap);
267
72
    gdFree(wbmp);
268
72
}
269
270
/* printwbmp
271
 * ---------
272
 * print a WBMP to stdout for visualisation
273
 */
274
void printwbmp(Wbmp *wbmp)
275
0
{
276
0
    int row, col;
277
278
0
    for (row = 0; row < wbmp->height; row++) {
279
0
        for (col = 0; col < wbmp->width; col++) {
280
0
            if (wbmp->bitmap[wbmp->width * row + col] == WBMP_BLACK) {
281
0
                putchar('#');
282
0
            } else {
283
0
                putchar(' ');
284
0
            }
285
0
        }
286
0
        putchar('\n');
287
0
    }
288
0
}
289
290
#ifdef __TEST
291
292
/* putout to file descriptor
293
 * -------------------------
294
 */
295
int putout(int c, void *out) { return (putc(c, (FILE *)out)); }
296
297
/* getin from file descriptor
298
 * --------------------------
299
 */
300
int getin(void *in) { return (getc((FILE *)in)); }
301
302
/* Main function
303
 * -------------
304
 */
305
int main(int argc, char *argv[])
306
{
307
    FILE *wbmp_file;
308
    Wbmp *wbmp;
309
310
    wbmp_file = fopen(argv[1], "rb");
311
    if (wbmp_file) {
312
        readwbmp(&getin, wbmp_file, &wbmp);
313
#ifdef __VIEW
314
#ifdef __DEBUG
315
        printf("\nVIEWING IMAGE\n");
316
#endif
317
        printwbmp(wbmp);
318
#endif
319
#ifdef __WRITE
320
#ifdef __DEBUG
321
        printf("\nDUMPING WBMP to STDOUT\n");
322
#endif
323
        writewbmp(wbmp, &putout, stdout);
324
#endif
325
        freewbmp(wbmp);
326
        fclose(wbmp_file);
327
    }
328
}
329
#endif