Blame src/wbmp.c

Packit ed3af9
/* WBMP
Packit ed3af9
 * ----
Packit ed3af9
 * WBMP Level 0: B/W, Uncompressed
Packit ed3af9
 * This implements the WBMP format as specified in WAPSpec 1.1 and 1.2.
Packit ed3af9
 * It does not support ExtHeaders as defined in the spec. The spec states
Packit ed3af9
 * that a WAP client does not need to implement ExtHeaders.
Packit ed3af9
 *
Packit ed3af9
 * (c) 2000 Johan Van den Brande <johan@vandenbrande.com>
Packit ed3af9
 */
Packit ed3af9
Packit ed3af9
#ifdef HAVE_CONFIG_H
Packit ed3af9
#	include "config.h"
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
#include <stdio.h>
Packit ed3af9
#include <stddef.h>
Packit ed3af9
#include <stdlib.h>
Packit ed3af9
#include <string.h>
Packit ed3af9
Packit ed3af9
#include "wbmp.h"
Packit ed3af9
#include "gd.h"
Packit ed3af9
#include "gdhelpers.h"
Packit ed3af9
Packit ed3af9
#ifdef NOTDEF
Packit ed3af9
#	define __TEST	/* Compile with main function */
Packit ed3af9
#	define __DEBUG	/* Extra verbose when with __TEST */
Packit ed3af9
#	define __WRITE	/* readwbmp and writewbmp(stdout) */
Packit ed3af9
#	define __VIEW	/* view the wbmp on stdout */
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
/* getmbi
Packit ed3af9
 * ------
Packit ed3af9
 * Get a multibyte integer from a generic getin function
Packit ed3af9
 * 'getin' can be getc, with in = NULL
Packit ed3af9
 * you can find getin as a function just above the main function
Packit ed3af9
 * This way you gain a lot of flexibilty about how this package
Packit ed3af9
 * reads a wbmp file.
Packit ed3af9
 */
Packit ed3af9
int getmbi(int (*getin) (void *in), void *in)
Packit ed3af9
{
Packit ed3af9
	int i, mbi = 0;
Packit ed3af9
Packit ed3af9
	do {
Packit ed3af9
		i = getin(in);
Packit ed3af9
		if(i < 0) {
Packit ed3af9
			return (-1);
Packit ed3af9
		}
Packit ed3af9
		mbi = (mbi << 7) | (i & 0x7f);
Packit ed3af9
	} while(i & 0x80);
Packit ed3af9
Packit ed3af9
	return mbi;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* putmbi
Packit ed3af9
 * ------
Packit ed3af9
 * Put a multibyte intgerer in some kind of output stream
Packit ed3af9
 * I work here with a function pointer, to make it as generic
Packit ed3af9
 * as possible. Look at this function as an iterator on the
Packit ed3af9
 * mbi integers it spits out.
Packit ed3af9
 *
Packit ed3af9
 */
Packit ed3af9
void putmbi(int i, void (*putout)(int c, void *out), void *out)
Packit ed3af9
{
Packit ed3af9
	int cnt, l, accu;
Packit ed3af9
Packit ed3af9
	/* Get number of septets */
Packit ed3af9
	accu = cnt = 0;
Packit ed3af9
	while(accu != i) {
Packit ed3af9
		accu += i & 0x7f << 7 * cnt++;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	/* Produce the multibyte output */
Packit ed3af9
	for(l = cnt - 1; l > 0; l--) {
Packit ed3af9
		putout(0x80 | (i & 0x7f << 7 * l) >> 7 * l, out);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	putout(i & 0x7f, out);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* skipheader
Packit ed3af9
 * ----------
Packit ed3af9
 * Skips the ExtHeader. Not needed for the moment
Packit ed3af9
 */
Packit ed3af9
int skipheader(int (*getin)(void *in), void *in)
Packit ed3af9
{
Packit ed3af9
	int i;
Packit ed3af9
Packit ed3af9
	do {
Packit ed3af9
		i = getin(in);
Packit ed3af9
		if(i < 0) {
Packit ed3af9
			return (-1);
Packit ed3af9
		}
Packit ed3af9
	} while(i & 0x80);
Packit ed3af9
Packit ed3af9
	return 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* create wbmp
Packit ed3af9
 * -----------
Packit ed3af9
 * create an empty wbmp
Packit ed3af9
 */
Packit ed3af9
Wbmp *createwbmp(int width, int height, int color)
Packit ed3af9
{
Packit ed3af9
	int i;
Packit ed3af9
	Wbmp *wbmp;
Packit ed3af9
Packit ed3af9
	if((wbmp = (Wbmp *)gdMalloc(sizeof (Wbmp))) == NULL) {
Packit ed3af9
		return (NULL);
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if(overflow2(sizeof(int), width)) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if(overflow2(sizeof(int) * width, height)) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if((wbmp->bitmap = (int *)gdMalloc(sizeof(int) * width * height)) == NULL) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return NULL;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	wbmp->width = width;
Packit ed3af9
	wbmp->height = height;
Packit ed3af9
Packit ed3af9
	for(i = 0; i < width * height; wbmp->bitmap[i++] = color);
Packit ed3af9
Packit ed3af9
	return wbmp;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* readwbmp
Packit ed3af9
 * -------
Packit ed3af9
 * Actually reads the WBMP format from an open file descriptor
Packit ed3af9
 * It goes along by returning a pointer to a WBMP struct.
Packit ed3af9
 */
Packit ed3af9
int readwbmp(int (*getin) (void *in), void *in, Wbmp **return_wbmp)
Packit ed3af9
{
Packit ed3af9
	int row, col, byte, pel, pos;
Packit ed3af9
	Wbmp *wbmp;
Packit ed3af9
Packit ed3af9
	if((wbmp = (Wbmp *)gdMalloc(sizeof(Wbmp))) == NULL) {
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	wbmp->type = getin(in);
Packit ed3af9
	if(wbmp->type != 0) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if(skipheader(getin, in)) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	wbmp->width = getmbi(getin, in);
Packit ed3af9
	if(wbmp->width == -1) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	wbmp->height = getmbi(getin, in);
Packit ed3af9
	if(wbmp->height == -1) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
#ifdef __DEBUG
Packit ed3af9
	printf("W: %d, H: %d\n", wbmp->width, wbmp->height);
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	if(	overflow2(sizeof(int), wbmp->width) ||
Packit ed3af9
		overflow2(sizeof(int) * wbmp->width, wbmp->height)) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	if((wbmp->bitmap = (int *)gdMalloc(sizeof(int) * wbmp->width * wbmp->height)) == NULL) {
Packit ed3af9
		gdFree(wbmp);
Packit ed3af9
		return -1;
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
#ifdef __DEBUG
Packit ed3af9
	printf("DATA CONSTRUCTED\n");
Packit ed3af9
#endif
Packit ed3af9
Packit ed3af9
	pos = 0;
Packit ed3af9
	for(row = 0; row < wbmp->height; row++) {
Packit ed3af9
		for(col = 0; col < wbmp->width;) {
Packit ed3af9
			byte = getin(in);
Packit ed3af9
Packit ed3af9
			for(pel = 7; pel >= 0; pel--) {
Packit ed3af9
				if(col++ < wbmp->width) {
Packit ed3af9
					if(byte & 1 << pel) {
Packit ed3af9
						wbmp->bitmap[pos] = WBMP_WHITE;
Packit ed3af9
					} else {
Packit ed3af9
						wbmp->bitmap[pos] = WBMP_BLACK;
Packit ed3af9
					}
Packit ed3af9
					pos++;
Packit ed3af9
				}
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	*return_wbmp = wbmp;
Packit ed3af9
Packit ed3af9
	return 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* writewbmp
Packit ed3af9
 * ---------
Packit ed3af9
 * Write a wbmp to a file descriptor
Packit ed3af9
 *
Packit ed3af9
 * Why not just giving a filedescriptor to this function?
Packit ed3af9
 * Well, the incentive to write this function was the complete
Packit ed3af9
 * integration in gd library from www.libgd.org. They use
Packit ed3af9
 * their own io functions, so the passing of a function seemed to be
Packit ed3af9
 * a logic(?) decision ...
Packit ed3af9
 */
Packit ed3af9
int writewbmp(Wbmp *wbmp, void (*putout)(int c, void *out), void *out)
Packit ed3af9
{
Packit ed3af9
	int row, col;
Packit ed3af9
	int bitpos, octet;
Packit ed3af9
Packit ed3af9
	/* Generate the header */
Packit ed3af9
	putout(0, out); /* WBMP Type 0: B/W, Uncompressed bitmap */
Packit ed3af9
	putout(0, out); /* FixHeaderField */
Packit ed3af9
Packit ed3af9
	/* Size of the image */
Packit ed3af9
	putmbi(wbmp->width, putout, out);	/* width */
Packit ed3af9
	putmbi(wbmp->height, putout, out);	/* height */
Packit ed3af9
Packit ed3af9
Packit ed3af9
	/* Image data */
Packit ed3af9
	for(row = 0; row < wbmp->height; row++) {
Packit ed3af9
		bitpos = 8;
Packit ed3af9
		octet = 0;
Packit ed3af9
Packit ed3af9
		for(col = 0; col < wbmp->width; col++) {
Packit ed3af9
			octet |= ((wbmp->bitmap[row * wbmp->width + col] == 1) ? WBMP_WHITE : WBMP_BLACK) << --bitpos;
Packit ed3af9
			if(bitpos == 0) {
Packit ed3af9
				bitpos = 8;
Packit ed3af9
				putout(octet, out);
Packit ed3af9
				octet = 0;
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
Packit ed3af9
		if(bitpos != 8) {
Packit ed3af9
			putout(octet, out);
Packit ed3af9
		}
Packit ed3af9
	}
Packit ed3af9
Packit ed3af9
	return 0;
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* freewbmp
Packit ed3af9
 * --------
Packit ed3af9
 * gdFrees up memory occupied by a WBMP structure
Packit ed3af9
 */
Packit ed3af9
void freewbmp(Wbmp *wbmp)
Packit ed3af9
{
Packit ed3af9
	gdFree(wbmp->bitmap);
Packit ed3af9
	gdFree(wbmp);
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* printwbmp
Packit ed3af9
 * ---------
Packit ed3af9
 * print a WBMP to stdout for visualisation
Packit ed3af9
 */
Packit ed3af9
void printwbmp(Wbmp *wbmp)
Packit ed3af9
{
Packit ed3af9
	int row, col;
Packit ed3af9
Packit ed3af9
	for(row = 0; row < wbmp->height; row++) {
Packit ed3af9
		for(col = 0; col < wbmp->width; col++) {
Packit ed3af9
			if(wbmp->bitmap[wbmp->width * row + col] == WBMP_BLACK) {
Packit ed3af9
				putchar('#');
Packit ed3af9
			} else {
Packit ed3af9
				putchar(' ');
Packit ed3af9
			}
Packit ed3af9
		}
Packit ed3af9
		putchar('\n');
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
#ifdef __TEST
Packit ed3af9
Packit ed3af9
/* putout to file descriptor
Packit ed3af9
 * -------------------------
Packit ed3af9
 */
Packit ed3af9
int putout(int c, void *out)
Packit ed3af9
{
Packit ed3af9
	return (putc(c, (FILE *)out));
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* getin from file descriptor
Packit ed3af9
 * --------------------------
Packit ed3af9
 */
Packit ed3af9
int getin(void *in)
Packit ed3af9
{
Packit ed3af9
	return (getc((FILE *)in));
Packit ed3af9
}
Packit ed3af9
Packit ed3af9
/* Main function
Packit ed3af9
 * -------------
Packit ed3af9
 */
Packit ed3af9
int main(int argc, char *argv[])
Packit ed3af9
{
Packit ed3af9
	FILE *wbmp_file;
Packit ed3af9
	Wbmp *wbmp;
Packit ed3af9
Packit ed3af9
	wbmp_file = fopen(argv[1], "rb");
Packit ed3af9
	if(wbmp_file) {
Packit ed3af9
		readwbmp(&getin, wbmp_file, &wbmp);
Packit ed3af9
#ifdef __VIEW
Packit ed3af9
#ifdef __DEBUG
Packit ed3af9
		printf("\nVIEWING IMAGE\n");
Packit ed3af9
#endif
Packit ed3af9
		printwbmp(wbmp);
Packit ed3af9
#endif
Packit ed3af9
#ifdef __WRITE
Packit ed3af9
#ifdef __DEBUG
Packit ed3af9
		printf("\nDUMPING WBMP to STDOUT\n");
Packit ed3af9
#endif
Packit ed3af9
		writewbmp(wbmp, &putout, stdout);
Packit ed3af9
#endif
Packit ed3af9
		freewbmp(wbmp);
Packit ed3af9
		fclose(wbmp_file);
Packit ed3af9
	}
Packit ed3af9
}
Packit ed3af9
#endif