/* * xbm.c -- enfle xbm handler * (C)Copyright 1999 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Sun Aug 29 15:33:11 1999. * $Id: xbm.c,v 1.8 1999/08/29 18:49:11 sian Exp $ * * NOTE: This plugin is not optimized for speed. * * Enfle is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Enfle is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include "enfle.h" #include "archive.h" #include "xbm.h" #include "plugin.h" #ifdef PIC int get_plugininfo(PluginInfo *p) #else int loader_xbm_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Loader; p->pluginname = "XBM Format Loader Plugin version 0.2"; p->pluginshortname = FORMAT_NAME; p->author = "Hiroshi Takekawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.loader.load_image = xbm_load_image; return 1; } static int parse_define(char *s) { char *p; if (strncmp(s, "#define", 7) != 0) return -1; p = s + 7; while (*p && isspace(*p)) p++; if (!*p) return -2; while (*p && !isspace(*p)) p++; if (!*p) return -3; while (*p && isspace(*p)) p++; if (!*p) return -4; if (!isdigit(*p)) return -5; return atoi(p); } static int read_char(Archive *ar) { char c; if (archive_read(ar, &c, 1) != 1) return -1; return (int)c; } static char * read_string(Archive *ar, char *buf, int size) { char *p = buf; int len = 0; /* hmm... */ while (len < size - 1) { if (archive_read(ar, p, 1) != 1) { if (len) break; return NULL; } if (*p++ == '\n') break; len++; } *p = '\0'; return buf; } static unsigned char reverse_bit(unsigned char d) { unsigned char r = 0; int i; for (i = 0; i < 8; i++) { r <<= 1; r |= (d & 1) ? 1 : 0; d >>= 1; } return r; } static int xbm_decode_image(Info *info, Image *p) { char s[XBM_BUFFER_SIZE]; int i, c, c1; unsigned char d, *ptr; Archive *ar = info->ar; if (read_string(ar, s, XBM_BUFFER_SIZE) == NULL) return 0; if ((p->width = parse_define(s)) < 0) return 0; if (read_string(ar, s, XBM_BUFFER_SIZE) == NULL) return 0; if ((p->height = parse_define(s)) < 0) return 0; while (read_char(ar) != '{') ; p->ncolors = 2; p->type = _MONO; p->bytes_per_line = image_calculate_bytes_per_line(p->width, p->type); p->image_size = p->bytes_per_line * p->height; if ((ptr = p->image = malloc(p->image_size)) == NULL) return 0; for (i = 0; i < p->image_size; i++) { while ((c = read_char(ar)) >= 0 && c != '0') ; if (c < 0) { free(p->image); fprintf(stderr, "got EOF. corrupted xbm file\n"); return 0; } if ((c = read_char(ar)) != 'x') { free(p->image); fprintf(stderr, "not 0x. corrupted xbm file\n"); return 0; } if ((c = read_char(ar)) < 0) { free(p->image); fprintf(stderr, "got EOF. corrupted xbm file\n"); return 0; } c = toupper(c); if ((c1 = read_char(ar)) < 0) { free(p->image); fprintf(stderr, "got EOF. corrupted xbm file\n"); return 0; } c1 = toupper(c1); if (isxdigit(c1)) { if (isxdigit(c)) { d = ((isdigit(c) ? c - '0' : c - 'A' + 10) << 4) + (isdigit(c1) ? c1 - '0' : c1 - 'A' + 10); } else { free(p->image); fprintf(stderr, "Illegal hexadecimal. corrupted xbm file\n"); return 0; } } else if (!isxdigit(c)) { free(p->image); fprintf(stderr, "Illegal hexadecimal. corrupted xbm file\n"); return 0; } else d = isdigit(c) ? c - '0' : c - 'A' + 10; *ptr++ = reverse_bit(d); } info->format = FORMAT_NAME; return 1; } int xbm_load_image(Info *info, Image *p) { if (!xbm_decode_image(info, p)) return (info->format == NULL) ? PROC_NOT : PROC_ERROR; info->npics = 1; /* set handler */ info->handler.destroy = NULL; info->handler.alarmset = NULL; info->handler.alarm = NULL; info->handler.alarmoff = NULL; return PROC_OK; }