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