📄 readxpm.c
字号:
{ /* also write palette entries */ palptr[f+incr ]=r; palptr[f+incr+256]=g; palptr[f+incr+512]=b; } }switch(cpp) { /* for cpp<=2, make code -> index lookup table. the disadvantage of * this is that we don't spot invalid colour codes, but it's so * much quicker this is probably worth it. The memsets do at least * ensure we give a consistent result (invalid codes give the * background colour (i.e. colour index 0)). */ case 1: memset(smallcol2idx,0,256); for(f=0;f<ncols;f++) smallcol2idx[colchars[f].name[0]]=f+incr; break; case 2: /* even for 2 cpp, use faster method if <=256 colours... */ if(ncols<=256) { memset(smallcol2idx,0,65536); for(f=0;f<ncols;f++) smallcol2idx[(colchars[f].name[0])|(colchars[f].name[1]<<8)]=f+incr; break; } /* else FALLS THROUGH */ default: /* i.e. if cpp>=3 (or cpp==2 and ncols>256) */ /* sort colchars[] so binary search will work. */ qsort(colchars,ncols,sizeof(struct colchars_tag),colchars_cmp); }/* phew. finally dealt with the colours, let's try (gasp) reading the * bloody *picture*! :-) *//* extra lines are in case we're dithering. */if(WH_BAD(w,h) || (*bmap=malloc(w*(h+2)*bytepp))==NULL) CLOSE_AND_RET(_PICERR_NOMEM);ptr=*bmap;/* save stuff in case of abort */work_in=in; work_bmap=ptr; work_pal=*pal;bsearch_cmp_cpp=cpp; /* needed if we get cols with bsearch() */for(y=0;y<h;y++) { cptr=read_next_string(in); switch(cpp) { case 1: /* loop over line directly indexing in smallcol2idx */ for(x=0;x<w;x++) *ptr++=smallcol2idx[*cptr++]; break; case 2: if(ncols<=256) { /* loop over line directly indexing in smallcol2idx again, but a * little more work needed to convert code to an int... */ for(x=0;x<w;x++,cptr+=2) *ptr++=smallcol2idx[(*cptr)|(cptr[1]<<8)]; break; } /* else FALLS THROUGH */ default: /* cpp>=3 */ /* loop over line doing binary search to get colour index. */ for(x=0;x<w;x++,cptr+=cpp) { static struct colchars_tag *match; match=bsearch(cptr,colchars,ncols, sizeof(struct colchars_tag),colchars_bsearch_cmp); if(match==NULL) CLOSE_AND_RET(_PICERR_CORRUPT); /* colour code not found */ if(ncols<=256) *ptr++=match->idx; else { *ptr++=match->b; *ptr++=match->g; *ptr++=match->r; } } break; } /* do dithering if needed */ if(ncols>256 && bytepp==1) { ptr-=w*3; ditherline(ptr,y,w); ptr+=w; } if(howfarfunc!=NULL) howfarfunc(y,h); }pp->width=w;pp->height=h;pp->numcols=256;*output_type=bytepp;if(ncols>256 && bytepp==1) ditherfinish();free(colchars);colchars=NULL; fclose(in);return(_PIC_OK); }/* I don't normally bother with const, but using it here saves * a complaint from gcc -Wall. */int colchars_cmp(const void *p1,const void *p2){struct colchars_tag *cc1=(struct colchars_tag *)p1;struct colchars_tag *cc2=(struct colchars_tag *)p2;return(strcmp(cc1->name,cc2->name));}/* need a different cmp for bsearch(). */int colchars_bsearch_cmp(const void *p1,const void *p2){unsigned char *cc1=(unsigned char *)p1;struct colchars_tag *cc2=(struct colchars_tag *)p2;return(memcmp(cc1,cc2->name,bsearch_cmp_cpp));}/* reads a string from the XPM. * returns string, or NULL if EOF found first. */unsigned char *read_next_string(FILE *in){static unsigned char buf[16384];static int in_string=0;int c,c2,buflen,gotstring;in_string=gotstring=0;buflen=0;do { if((c=fgetc(in))==EOF) return(NULL); if(in_comment) { if(c=='*') /* check for end of comment */ { if((c2=fgetc(in))=='/') in_comment=0; else ungetc(c2,in); /* since this could (in theory) be a `*' */ } } else /* not in comment */ { if(!in_string) { if(c=='/') /* check for start of comment */ { if((c2=fgetc(in))=='*') in_comment=1; else ungetc(c2,in); /* equally, this could be `"' to start string */ } else if(c=='"') /* check for start of string */ in_string=1; } else /* already in string */ { if(c=='"') /* check for end of string */ { in_string=0; gotstring=1; } else { buf[buflen++]=c; /* this is probably unlikely, but just in case... */ if(buflen>=sizeof(buf)-1) gotstring=1; } } } }while(!gotstring); buf[buflen]=0;return(buf);}void aborted_file_xpm_cleanup(){free(work_bmap);free(work_pal);fclose(work_in);}unsigned char *next_token(unsigned char *ptr){while(*ptr!=0 && *ptr!=' ' && *ptr!='\t') ptr++;while(*ptr==' ' || *ptr=='\t') ptr++;return(ptr);}void get_token(unsigned char *token,int tokenmax,unsigned char *buf){int n=0;while(*buf!=0 && *buf!=' ' && *buf!='\t' && n<tokenmax-1) *token++=*buf++,n++;*token=0;}/* return 24-bit colour value if found, else -1. */int lookup_named_colour(unsigned char *colname){int f;for(f=0;f<rgb_db_num_entries;f++) if(strcasecmp(colname,rgb_db_array[f].name)==0) return(rgb_db_array[f].rgb);return(-1);}/* parse X rgb db (rgb.txt) into rgb_db_array. */void init_rgb_db(){static char buf[256];FILE *db;char *ptr;int r,g,b;if((rgb_db_array=malloc(rgb_db_size))==NULL) return; /* no big deal, it was NULL before anyway :-) */if((db=fopen(RGB_DB_FILE,"r"))==NULL) { /* knock up entries for black and white at least! * we know rgb_db_array is at least two entries big already. */ rgb_db_array[rgb_db_num_entries].rgb=0; strcpy(rgb_db_array[rgb_db_num_entries].name,"black"); rgb_db_num_entries++; rgb_db_array[rgb_db_num_entries].rgb=0xffffff; strcpy(rgb_db_array[rgb_db_num_entries].name,"white"); rgb_db_num_entries++; return; }/* ok, we've opened the file, read it in. */while(fgets(buf,sizeof(buf),db)!=NULL) { if(*buf=='#' || *buf=='!') continue; /* chop LF */ if(*buf && buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1]=0; if(*buf==0) continue; /* make array bigger if needed */ if(rgb_db_num_entries*sizeof(struct rgb_db_tag)>=rgb_db_size) { rgb_db_size+=rgb_db_incr; if((rgb_db_array=realloc(rgb_db_array,rgb_db_size))==NULL) { /* give up if out of memory */ fclose(db); return; } } ptr=buf; r=strtol(ptr,&ptr,10); if(r<0) r=0; if(r>255) r=255; g=strtol(ptr,&ptr,10); if(g<0) g=0; if(g>255) g=255; b=strtol(ptr,&ptr,10); if(b<0) b=0; if(b>255) b=255; rgb_db_array[rgb_db_num_entries].rgb=((r<<16)|(g<<8)|b); ptr=next_token(ptr); if(strlen(ptr)>MAX_COLNAME_LEN) ptr[MAX_COLNAME_LEN]=0; strcpy(rgb_db_array[rgb_db_num_entries].name,ptr); rgb_db_num_entries++; }fclose(db);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -