/* * pnm.c -- enfle pnm handler * (C)Copyright 1999 by Hiroshi Takekawa * This file is part of Enfle. * * Last Modified: Tue Aug 15 08:32:29 2000. * $Id: pnm.c,v 1.13 2000/08/17 13:39:38 sian Exp $ * * 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 #include "enfle.h" #include "archive.h" #include "pnm.h" #include "plugin.h" #ifdef PIC int get_plugininfo(PluginInfo *p) #else int loader_pnm_get_plugininfo(PluginInfo *p) #endif { p->version = 1; p->type = _Loader; p->pluginname = "PNM Format Loader Plugin version 0.1.1.1"; p->pluginshortname = FORMAT_NAME; p->author = "Hiroshi Takekawa"; p->dlhandle = NULL; /* set by plugin_load */ p->functions.loader.load_image = pnm_load_image; return 1; } static char * get_token(Archive *ar) { static char line[130]; static int last = 0; static int index = 0; int start, len; char *ret; if (index >= last) { do { if (archive_gets(ar, line, 130) == NULL) fprintf(stderr, "archive_gets() returns NULL\n"); } while (line[0] == '#'); /* No line should be longer than 70 characters (ppm(5)) */ if ((last = strlen(line)) > 128) return NULL; index = 0; } while (index < last && isspace(line[index])) index++; start = index; while (index < last && !isspace(line[index])) index++; len = index - start; if ((ret = malloc(len + 1)) == NULL) return NULL; strncpy(ret, line + start, len); ret[len] = '\0'; while (index < last && isspace(line[index])) index++; return ret; } static int pnm_read_header(Info *info, Image *p, PNMdata *data) { Archive *ar = info->ar; char *token; if ((token = get_token(ar)) == NULL) return 0; if (token[0] != 'P') { free(token); return 0; } switch ((int)token[1]) { case '1': /* ascii bitmap */ p->type = _MONO; p->ncolors = 2; data->encode = _ASCII; break; case '2': /* ascii graymap */ p->type = _GRAY; data->encode = _ASCII; break; case '3': /* ascii pixmap */ p->type = _RGB24; data->encode = _ASCII; break; case '4': /* raw bitmap */ p->type = _MONO; p->ncolors = 2; data->encode = _RAW; break; case '5': /* raw graymap */ p->type = _GRAY; data->encode = _RAW; break; case '6': /* raw pixmap */ p->type = _RGB24; data->encode = _RAW; break; default: free(token); return 0; } free(token); if ((token = get_token(ar)) == NULL) return 0; p->width = atoi(token); free(token); if ((token = get_token(ar)) == NULL) return 0; p->height = atoi(token); free(token); if (p->type != _MONO) { if ((token = get_token(ar)) == NULL) return 0; data->maxval = atoi(token); free(token); } else data->maxval = 1; if (p->type == _GRAY) p->ncolors = data->maxval; else if (p->type == _RGB24) p->ncolors = 1 << 24; if (p->width <= 0 || p->height <= 0 || p->ncolors <= 0) return 0; info->format = FORMAT_NAME; #ifdef DEBUG fprintf(stderr, "pnm_read_header: %d %d %dx%d\n", p->type, p->ncolors, p->width, p->height); #endif return 1; } static int pnm_decode_image(Info *info, Image *p) { Archive *ar = info->ar; PNMdata pnmdata; int i, j, x, y; unsigned char b, *d; #ifdef DEBUG fprintf(stderr, "pnm_decode_image() called\n"); #endif if (!pnm_read_header(info, p, &pnmdata)) return 0; p->bytes_per_line = image_calculate_bytes_per_line(p->width, p->type); p->image_size = p->bytes_per_line * p->height; #ifdef DEBUG fprintf(stderr, "allocate memory %d bytes for image\n", p->image_size); #endif if ((p->image = d = malloc(p->image_size)) == NULL) return 0; switch (pnmdata.encode) { case _RAW: archive_read(ar, p->image, p->image_size); break; case _ASCII: { char *token; if (p->type == _MONO) { for (y = 0; y < p->height; y++) { b = 0; for (x = 0; x < p->width; x++) { if ((token = get_token(ar)) == NULL) { free(p->image); return 0; } j = atoi(token); free(token); if (j == 1) b |= 1; else if (j != 0) { fprintf(stderr, "Illegal PBM file\n"); free(p->image); return 0; } if (x % 8 == 7) { *d++ = b; b = 0; } else b <<= 1; } if (x % 8 != 0) { for (; x % 8 != 7; x++) b <<= 1; *d++ = b; } } } else { for (i = 0; i < p->image_size; i++) { if ((token = get_token(ar)) == NULL) { free(p->image); return 0; } j = atoi(token); free(token); if (j > p->ncolors) { fprintf(stderr, "Illegal PNM file\n"); free(p->image); return 0; } *d++ = j * 255 / pnmdata.maxval; } } } } return 1; } int pnm_load_image(Info *info, Image *p) { if (!pnm_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; }