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