ab6aec1997-02-11Fredrik Hübinette (Hubbe) /* $Id: pnm.c,v 1.1 1997/02/11 08:35:45 hubbe Exp $ */ #include "global.h" #include <math.h> #include <ctype.h> #include "stralloc.h" #include "global.h" #include "types.h" #include "macros.h" #include "object.h" #include "constants.h" #include "interpret.h" #include "svalue.h" #include "array.h" #include "error.h" #include "image.h" #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) #define pixel(_img,x,y) ((_img)->img[(x)+(y)*(_img)->xsize]) static INLINE unsigned char getnext(struct pike_string *s,INT32 *pos) { if (*pos>=s->len) return 0; if (s->str[(*pos)]=='#') for (;*pos<s->len && ISSPACE(s->str[*pos]);(*pos)++); return s->str[(*pos)++]; } static INLINE void skip_to_eol(struct pike_string *s,INT32 *pos) { for (;*pos<s->len && s->str[*pos]!=10;(*pos)++); } static INLINE unsigned char getnext_skip_comment(struct pike_string *s,INT32 *pos) { unsigned char c; while ((c=getnext(s,pos))=='#') skip_to_eol(s,pos); return c; } static INLINE void skipwhite(struct pike_string *s,INT32 *pos) { while (*pos<s->len && ( ISSPACE(s->str[*pos]) || s->str[*pos]=='#')) getnext_skip_comment(s,pos); } static INLINE INT32 getnextnum(struct pike_string *s,INT32 *pos) { INT32 i; skipwhite(s,pos); i=0; while (*pos<s->len && s->str[*pos]>='0' && s->str[*pos]<='9') { i=(i*10)+s->str[*pos]-'0'; getnext(s,pos); } return i; } static char* img_frompnm(struct pike_string *s) { struct image new; INT32 type,c=0,maxval=255; INT32 pos=0,x,y,i; skipwhite(s,&pos); if (getnext(s,&pos)!='P') return "not pnm"; /* not pnm */ type=getnext(s,&pos); if (type<'1'||type>'6') return "unknown type"; /* unknown type */ new.xsize=getnextnum(s,&pos); new.ysize=getnextnum(s,&pos); if (new.xsize<=0||new.ysize<=0) return "illegal size"; /* illegal size */ if (type=='3'||type=='2'||type=='6'||type=='5') maxval=getnextnum(s,&pos); new.img=malloc(new.xsize*new.ysize*sizeof(rgb_group)+1); if (!new.img) error("Out of memory.\n"); if (type=='1'||type=='2'||type=='3') { skipwhite(s,&pos); } else { skip_to_eol(s,&pos); pos++; } for (y=0; y<new.ysize; y++) { for (i=0,x=0; x<new.xsize; x++) { switch (type) { case '1': c=getnextnum(s,&pos); pixel(&new,x,y).r=pixel(&new,x,y).g=pixel(&new,x,y).b= (unsigned char)~(c*255); break; case '2': c=getnextnum(s,&pos); pixel(&new,x,y).r=pixel(&new,x,y).g=pixel(&new,x,y).b= (unsigned char)((c*255L)/maxval); break; case '3': pixel(&new,x,y).r=(unsigned char)((getnextnum(s,&pos)*255L)/maxval); pixel(&new,x,y).g=(unsigned char)((getnextnum(s,&pos)*255L)/maxval); pixel(&new,x,y).b=(unsigned char)((getnextnum(s,&pos)*255L)/maxval); break; case '4': if (!i) c=getnext(s,&pos),i=8; pixel(&new,x,y).r=pixel(&new,x,y).g=pixel(&new,x,y).b= (unsigned char)~(((c>>7)&1)*255); c<<=1; i--; break; case '5': c=getnext(s,&pos); pixel(&new,x,y).r=pixel(&new,x,y).g=pixel(&new,x,y).b= (unsigned char)((c*255L)/maxval); break; case '6': pixel(&new,x,y).r=(unsigned char)((getnext(s,&pos)*255L)/maxval); pixel(&new,x,y).g=(unsigned char)((getnext(s,&pos)*255L)/maxval); pixel(&new,x,y).b=(unsigned char)((getnext(s,&pos)*255L)/maxval); break; } } } if (THIS->img) free(THIS->img); THIS->xsize=new.xsize; THIS->ysize=new.ysize; THIS->img=new.img; return NULL; } void image_toppm(INT32 args) { char buf[80]; struct pike_string *a,*b; pop_n_elems(args); if (!THIS->img) { error("no image\n"); return; } sprintf(buf,"P6\n%d %d\n255\n",THIS->xsize,THIS->ysize); a=make_shared_string(buf); b=make_shared_binary_string((char*)THIS->img, THIS->xsize*THIS->ysize*3); push_string(add_shared_strings(a,b)); free_string(a); free_string(b); } void image_frompnm(INT32 args) { char *s; if (args<1|| sp[-args].type!=T_STRING) error("Illegal argument to image->frompnm()\n"); s=img_frompnm(sp[-args].u.string); pop_n_elems(args); if (!s) { push_object(THISOBJ); THISOBJ->refs++; } else push_string(make_shared_string(s)); }