Blame src/gd_xbm.c

Packit Service df60bb
/**
Packit Service df60bb
 * File: XBM IO
Packit Service df60bb
 *
Packit Service df60bb
 * Read and write XBM images.
Packit Service df60bb
 */
Packit Service df60bb
Packit Service df60bb
#ifdef HAVE_CONFIG_H
Packit Service df60bb
#	include "config.h"
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#include <ctype.h>
Packit Service df60bb
#include <stdio.h>
Packit Service df60bb
#include <math.h>
Packit Service df60bb
#include <string.h>
Packit Service df60bb
#include <stdlib.h>
Packit Service df60bb
#include <stdarg.h>
Packit Service df60bb
#include "gd.h"
Packit Service df60bb
#include "gd_errors.h"
Packit Service df60bb
#include "gdhelpers.h"
Packit Service df60bb
Packit Service df60bb
#ifdef _MSC_VER
Packit Service df60bb
# define strcasecmp _stricmp
Packit Service df60bb
#endif
Packit Service df60bb
Packit Service df60bb
#define MAX_XBM_LINE_SIZE 255
Packit Service df60bb
Packit Service df60bb
Packit Service df60bb
/*
Packit Service df60bb
  Function: gdImageCreateFromXbm
Packit Service df60bb
Packit Service df60bb
    <gdImageCreateFromXbm> is called to load images from X bitmap
Packit Service df60bb
    format files. Invoke <gdImageCreateFromXbm> with an already opened
Packit Service df60bb
    pointer to a file containing the desired
Packit Service df60bb
    image. <gdImageCreateFromXbm> returns a <gdImagePtr> to the new
Packit Service df60bb
    image, or NULL if unable to load the image (most often because the
Packit Service df60bb
    file is corrupt or does not contain an X bitmap format
Packit Service df60bb
    image). <gdImageCreateFromXbm> does not close the file.
Packit Service df60bb
Packit Service df60bb
    You can inspect the sx and sy members of the image to determine
Packit Service df60bb
    its size. The image must eventually be destroyed using
Packit Service df60bb
    <gdImageDestroy>.
Packit Service df60bb
Packit Service df60bb
    X11 X bitmaps (which define a char[]) as well as X10 X bitmaps (which define
Packit Service df60bb
    a short[]) are supported.
Packit Service df60bb
Packit Service df60bb
  Parameters:
Packit Service df60bb
Packit Service df60bb
    fd - The input FILE pointer
Packit Service df60bb
Packit Service df60bb
  Returns:
Packit Service df60bb
Packit Service df60bb
    A pointer to the new image or NULL if an error occurred.
Packit Service df60bb
Packit Service df60bb
  Example:
Packit Service df60bb
    (start code)
Packit Service df60bb
Packit Service df60bb
    gdImagePtr im;
Packit Service df60bb
    FILE *in;
Packit Service df60bb
    in = fopen("myxbm.xbm", "rb");
Packit Service df60bb
    im = gdImageCreateFromXbm(in);
Packit Service df60bb
    fclose(in);
Packit Service df60bb
    // ... Use the image ...
Packit Service df60bb
    gdImageDestroy(im);
Packit Service df60bb
Packit Service df60bb
    (end code)
Packit Service df60bb
*/
Packit Service df60bb
BGD_DECLARE(gdImagePtr) gdImageCreateFromXbm(FILE * fd)
Packit Service df60bb
{
Packit Service df60bb
	char fline[MAX_XBM_LINE_SIZE];
Packit Service df60bb
	char iname[MAX_XBM_LINE_SIZE];
Packit Service df60bb
	char *type;
Packit Service df60bb
	int value;
Packit Service df60bb
	unsigned int width = 0, height = 0;
Packit Service df60bb
	int fail = 0;
Packit Service df60bb
	int max_bit = 0;
Packit Service df60bb
Packit Service df60bb
	gdImagePtr im;
Packit Service df60bb
	int bytes = 0, i;
Packit Service df60bb
	int bit, x = 0, y = 0;
Packit Service df60bb
	int ch;
Packit Service df60bb
	char h[8];
Packit Service df60bb
	unsigned int b;
Packit Service df60bb
Packit Service df60bb
	rewind(fd);
Packit Service df60bb
	while (fgets(fline, MAX_XBM_LINE_SIZE, fd)) {
Packit Service df60bb
		fline[MAX_XBM_LINE_SIZE-1] = '\0';
Packit Service df60bb
		if (strlen(fline) == MAX_XBM_LINE_SIZE-1) {
Packit Service df60bb
			return 0;
Packit Service df60bb
		}
Packit Service df60bb
		if (sscanf(fline, "#define %s %d", iname, &value) == 2) {
Packit Service df60bb
			if (!(type = strrchr(iname, '_'))) {
Packit Service df60bb
				type = iname;
Packit Service df60bb
			} else {
Packit Service df60bb
				type++;
Packit Service df60bb
			}
Packit Service df60bb
Packit Service df60bb
			if (!strcmp("width", type)) {
Packit Service df60bb
				width = (unsigned int) value;
Packit Service df60bb
			}
Packit Service df60bb
			if (!strcmp("height", type)) {
Packit Service df60bb
				height = (unsigned int) value;
Packit Service df60bb
			}
Packit Service df60bb
		} else {
Packit Service df60bb
			if ( sscanf(fline, "static unsigned char %s = {", iname) == 1
Packit Service df60bb
			  || sscanf(fline, "static char %s = {", iname) == 1)
Packit Service df60bb
			{
Packit Service df60bb
				max_bit = 128;
Packit Service df60bb
			} else if (sscanf(fline, "static unsigned short %s = {", iname) == 1
Packit Service df60bb
					|| sscanf(fline, "static short %s = {", iname) == 1)
Packit Service df60bb
			{
Packit Service df60bb
				max_bit = 32768;
Packit Service df60bb
			}
Packit Service df60bb
			if (max_bit) {
Packit Service df60bb
                bytes = (width + 7) / 8 * height;
Packit Service df60bb
				if (!bytes) {
Packit Service df60bb
					return 0;
Packit Service df60bb
				}
Packit Service df60bb
				if (!(type = strrchr(iname, '_'))) {
Packit Service df60bb
					type = iname;
Packit Service df60bb
				} else {
Packit Service df60bb
					type++;
Packit Service df60bb
				}
Packit Service df60bb
				if (!strcmp("bits[]", type)) {
Packit Service df60bb
					break;
Packit Service df60bb
				}
Packit Service df60bb
			}
Packit Service df60bb
 		}
Packit Service df60bb
	}
Packit Service df60bb
	if (!bytes || !max_bit) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	if(!(im = gdImageCreate(width, height))) {
Packit Service df60bb
		return 0;
Packit Service df60bb
	}
Packit Service df60bb
	gdImageColorAllocate(im, 255, 255, 255);
Packit Service df60bb
	gdImageColorAllocate(im, 0, 0, 0);
Packit Service df60bb
	h[2] = '\0';
Packit Service df60bb
	h[4] = '\0';
Packit Service df60bb
	for (i = 0; i < bytes; i++) {
Packit Service df60bb
		while (1) {
Packit Service df60bb
			if ((ch=getc(fd)) == EOF) {
Packit Service df60bb
				fail = 1;
Packit Service df60bb
				break;
Packit Service df60bb
			}
Packit Service df60bb
			if (ch == 'x') {
Packit Service df60bb
				break;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
		if (fail) {
Packit Service df60bb
			break;
Packit Service df60bb
		}
Packit Service df60bb
		/* Get hex value */
Packit Service df60bb
		if ((ch=getc(fd)) == EOF) {
Packit Service df60bb
			break;
Packit Service df60bb
		}
Packit Service df60bb
		h[0] = ch;
Packit Service df60bb
		if ((ch=getc(fd)) == EOF) {
Packit Service df60bb
			break;
Packit Service df60bb
		}
Packit Service df60bb
		h[1] = ch;
Packit Service df60bb
		if (max_bit == 32768) {
Packit Service df60bb
			if ((ch=getc(fd)) == EOF) {
Packit Service df60bb
				break;
Packit Service df60bb
			}
Packit Service df60bb
			h[2] = ch;
Packit Service df60bb
			if ((ch=getc(fd)) == EOF) {
Packit Service df60bb
				break;
Packit Service df60bb
			}
Packit Service df60bb
			h[3] = ch;
Packit Service df60bb
		}
Packit Service df60bb
		sscanf(h, "%x", &b);
Packit Service df60bb
		for (bit = 1; bit <= max_bit; bit = bit << 1) {
Packit Service df60bb
			gdImageSetPixel(im, x++, y, (b & bit) ? 1 : 0);
Packit Service df60bb
			if (x == im->sx) {
Packit Service df60bb
				x = 0;
Packit Service df60bb
				y++;
Packit Service df60bb
				if (y == im->sy) {
Packit Service df60bb
					return im;
Packit Service df60bb
				}
Packit Service df60bb
				break;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	gd_error("EOF before image was complete");
Packit Service df60bb
	gdImageDestroy(im);
Packit Service df60bb
	return 0;
Packit Service df60bb
}
Packit Service df60bb
Packit Service df60bb
Packit Service df60bb
/* {{{ gdCtxPrintf */
Packit Service df60bb
static void gdCtxPrintf(gdIOCtx * out, const char *format, ...)
Packit Service df60bb
{
Packit Service df60bb
	char buf[1024];
Packit Service df60bb
	int len;
Packit Service df60bb
	va_list args;
Packit Service df60bb
Packit Service df60bb
	va_start(args, format);
Packit Service df60bb
	len = vsnprintf(buf, sizeof(buf)-1, format, args);
Packit Service df60bb
	va_end(args);
Packit Service df60bb
	out->putBuf(out, buf, len);
Packit Service df60bb
}
Packit Service df60bb
/* }}} */
Packit Service df60bb
Packit Service df60bb
/* The compiler will optimize strlen(constant) to a constant number. */
Packit Service df60bb
#define gdCtxPuts(out, s) out->putBuf(out, s, strlen(s))
Packit Service df60bb
Packit Service df60bb
Packit Service df60bb
/**
Packit Service df60bb
 * Function: gdImageXbmCtx
Packit Service df60bb
 *
Packit Service df60bb
 *  Writes an image to an IO context in X11 bitmap format.
Packit Service df60bb
 *
Packit Service df60bb
 * Parameters:
Packit Service df60bb
 *
Packit Service df60bb
 *  image     - The <gdImagePtr> to write.
Packit Service df60bb
 *  file_name - The prefix of the XBM's identifiers. Illegal characters are
Packit Service df60bb
 *              automatically stripped.
Packit Service df60bb
 *  gd        - Which color to use as forground color. All pixels with another
Packit Service df60bb
 *              color are unset.
Packit Service df60bb
 *  out       - The <gdIOCtx> to write the image file to.
Packit Service df60bb
 * 
Packit Service df60bb
 */
Packit Service df60bb
BGD_DECLARE(void) gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out)
Packit Service df60bb
{
Packit Service df60bb
	int x, y, c, b, sx, sy, p;
Packit Service df60bb
	char *name, *f;
Packit Service df60bb
	size_t i, l;
Packit Service df60bb
Packit Service df60bb
	name = file_name;
Packit Service df60bb
	if ((f = strrchr(name, '/')) != NULL) name = f+1;
Packit Service df60bb
	if ((f = strrchr(name, '\\')) != NULL) name = f+1;
Packit Service df60bb
	name = strdup(name);
Packit Service df60bb
	if ((f = strrchr(name, '.')) != NULL && !strcasecmp(f, ".XBM")) *f = '\0';
Packit Service df60bb
	if ((l = strlen(name)) == 0) {
Packit Service df60bb
		free(name);
Packit Service df60bb
		name = strdup("image");
Packit Service df60bb
	} else {
Packit Service df60bb
		for (i=0; i
Packit Service df60bb
			/* only in C-locale isalnum() would work */
Packit Service df60bb
			if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) {
Packit Service df60bb
				name[i] = '_';
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
Packit Service df60bb
	/* Since "name" comes from the user, run it through a direct puts.
Packit Service df60bb
	 * Trying to printf it into a local buffer means we'd need a large
Packit Service df60bb
	 * or dynamic buffer to hold it all. */
Packit Service df60bb
Packit Service df60bb
	/* #define <name>_width 1234 */
Packit Service df60bb
	gdCtxPuts(out, "#define ");
Packit Service df60bb
	gdCtxPuts(out, name);
Packit Service df60bb
	gdCtxPuts(out, "_width ");
Packit Service df60bb
	gdCtxPrintf(out, "%d\n", gdImageSX(image));
Packit Service df60bb
Packit Service df60bb
	/* #define <name>_height 1234 */
Packit Service df60bb
	gdCtxPuts(out, "#define ");
Packit Service df60bb
	gdCtxPuts(out, name);
Packit Service df60bb
	gdCtxPuts(out, "_height ");
Packit Service df60bb
	gdCtxPrintf(out, "%d\n", gdImageSY(image));
Packit Service df60bb
Packit Service df60bb
	/* static unsigned char <name>_bits[] = {\n */
Packit Service df60bb
	gdCtxPuts(out, "static unsigned char ");
Packit Service df60bb
	gdCtxPuts(out, name);
Packit Service df60bb
	gdCtxPuts(out, "_bits[] = {\n  ");
Packit Service df60bb
Packit Service df60bb
	free(name);
Packit Service df60bb
Packit Service df60bb
	b = 1;
Packit Service df60bb
	p = 0;
Packit Service df60bb
	c = 0;
Packit Service df60bb
	sx = gdImageSX(image);
Packit Service df60bb
	sy = gdImageSY(image);
Packit Service df60bb
	for (y = 0; y < sy; y++) {
Packit Service df60bb
		for (x = 0; x < sx; x++) {
Packit Service df60bb
			if (gdImageGetPixel(image, x, y) == fg) {
Packit Service df60bb
				c |= b;
Packit Service df60bb
			}
Packit Service df60bb
			if ((b == 128) || (x == sx - 1)) {
Packit Service df60bb
				b = 1;
Packit Service df60bb
				if (p) {
Packit Service df60bb
					gdCtxPuts(out, ", ");
Packit Service df60bb
					if (!(p%12)) {
Packit Service df60bb
						gdCtxPuts(out, "\n  ");
Packit Service df60bb
						p = 12;
Packit Service df60bb
					}
Packit Service df60bb
				}
Packit Service df60bb
				p++;
Packit Service df60bb
				gdCtxPrintf(out, "0x%02X", c);
Packit Service df60bb
				c = 0;
Packit Service df60bb
			} else {
Packit Service df60bb
				b <<= 1;
Packit Service df60bb
			}
Packit Service df60bb
		}
Packit Service df60bb
	}
Packit Service df60bb
	gdCtxPuts(out, "};\n");
Packit Service df60bb
}