⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readxpm.c

📁 一个利用SDL语言来实现svgalib函数的示例程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Zgv v3.1 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux. * Copyright (C) 1993-1998 Russell Marks. See README for license details. * * readxpm.c - XPM loader. * * Since (as far as I can tell) the XPM library seems to be * difficult or impossible to use on a machine without X installed * (which is a possibility with zgv), I reluctantly decided not to * use it. So this is a fairly noddy from-scratch XPM reader. * * XXX one problem with this - >256-col reading is suboptimal for cpp==2. * Could be made quicker by using same sort of speedup used for <=256-col * files when cpp==2, i.e. by using a 65536-entry direct-lookup array * containing ints (well, longs) with rgb values. That would be 256k, * but that wouldn't be too bad to malloc. */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include "zgv.h"#include "readpnm.h"	/* for dithering routines */#include "rcfile.h"#include "rc_config.h"#include "readxpm.h"/* max chars/pixel we allow; * most files use one, some use two, I've seen a couple which used * three (though not for any good reason!), so this sounds ok I think. */#define MAX_CPP		16/* for aborted_file_xpm_cleanup() */static unsigned char *work_bmap,*work_pal;static FILE *work_in;/* for read_next_string, but outside it in case e.g. a read error * happens halfway through, which would (in theory, if not practice) * screw up further XPM reads. */static int in_comment=0;/* for colchars_bsearch_cmp, but outside it as it's called from * bsearch(). */static int bsearch_cmp_cpp;/* RGB DB array (dynamically allocated) */#define MAX_COLNAME_LEN	64	/* not ideal but simplifies matters */struct rgb_db_tag  {  int rgb;  unsigned char name[MAX_COLNAME_LEN+1];  };static struct rgb_db_tag *rgb_db_array=NULL;/* rgb_db_size must be at least 2*sizeof... (see init_rgb_db() for why) */static int rgb_db_size=64*sizeof(struct rgb_db_tag);static int rgb_db_incr=32*sizeof(struct rgb_db_tag);static int rgb_db_num_entries=0;static struct colchars_tag	/* this is used to store colour char codes */  {  int idx;  unsigned char r,g,b;  unsigned char name[MAX_CPP+1];  } *colchars=NULL;/* prototypes */int colchars_cmp(const void *p1,const void *p2);int colchars_bsearch_cmp(const void *p1,const void *p2);unsigned char *read_next_string(FILE *in);unsigned char *next_token(unsigned char *ptr);void get_token(unsigned char *token,int tokenmax,unsigned char *buf);int lookup_named_colour(unsigned char *colname);void init_rgb_db(void);/* output_type returns how many bytes per pixel needed for display */int read_xpm_file(char *filename,hffunc howfarfunc,unsigned char **bmap,                  unsigned char **pal,int *output_type,PICINFO *pp){static unsigned char smallcol2idx[65536];	/* lookup tbl if cpp<3 */static unsigned char buf[128]; /* only used for magic/tokens so can be short */static unsigned char colname[256];	/* temp. used to store colour name */FILE *in;unsigned char *inpline;int w,h,f,x,y,bytepp,ncols,cpp;	/* cpp=chars/pixel */unsigned char *cptr;unsigned char *ptr,*palptr;int incr;*bmap=NULL;*pal=NULL;in_comment=0;bytepp=1;if((in=fopen(filename,"rb"))==NULL)  return(_PICERR_NOFILE);if(fgets(buf,sizeof(buf),in)==NULL || strncmp(buf,"/* XPM",6)!=0)  CLOSE_AND_RET(_PICERR_BADMAGIC);/* get width/height etc. */if((inpline=read_next_string(in))==NULL)  CLOSE_AND_RET(_PICERR_CORRUPT);if(sscanf(inpline,"%d %d %d %d",&w,&h,&ncols,&cpp)!=4)  CLOSE_AND_RET(_PICERR_CORRUPT);if(w==0 || h==0)  CLOSE_AND_RET(_PICERR_CORRUPT);if(cpp>MAX_CPP)  CLOSE_AND_RET(_PICERR_TOOMANYCOLS);if((*pal=palptr=calloc(768,1))==NULL)  CLOSE_AND_RET(_PICERR_NOMEM);/* we zero out the palette to avoid possible problems with vkludge in * vgadisp.c if we don't (i.e. random junk colours being used) as there * may well be fewer than 256 colours. */memset(palptr,0,768);if(ncols>256)  {  bytepp=3;  if(*output_type==1 || cfg.jpeg24bit==0)	/* dither? */    {    int r,g,b;        bytepp=1;    if(ditherinit(w)==0)      CLOSE_AND_RET(_PICERR_NOMEM);        ptr=palptr;    for(r=0;r<8;r++)      for(g=0;g<8;g++)	/* colours are 3:3:2 */        for(b=0;b<4;b++)          {          *ptr=r*255/7; ptr[256]=g*255/7; ptr[512]=b*255/3;          ptr++;          }    }  }/* make an effort to always show them on a grey background * by making colour zero grey if possible. * (XXX will need to be changed if the other one is) */incr=0;if(ncols<256)  {  incr=1;  palptr[0]=palptr[256]=palptr[512]=128;  }/* read rgb.txt if we haven't already */if(rgb_db_array==NULL)  init_rgb_db();/* colchars will usually be NULL at this point, but an error could * well have left it hanging around - nuke it if so. */if(colchars!=NULL) free(colchars);/* alloc colchars array */if(ncols>(1<<24) || (colchars=malloc(ncols*sizeof(struct colchars_tag)))==NULL)  CLOSE_AND_RET(_PICERR_NOMEM);/* read in colours. This is REALLY FUN. :-( */for(f=0;f<ncols;f++)  {  int r,g,b;    if((inpline=read_next_string(in))==NULL)    CLOSE_AND_RET(_PICERR_CORRUPT);    memset(colchars[f].name,0,MAX_CPP+1);  memcpy(colchars[f].name,inpline,cpp);  colchars[f].idx=f+incr;    /* look for "c" token */  cptr=inpline+cpp; *buf=0;  while(*cptr && strcmp(buf,"c")!=0)    {    cptr=next_token(cptr);    get_token(buf,sizeof(buf),cptr);    }  if(strcmp(buf,"c")!=0)    {    /* no colour visual definition found.      * this is pretty rare - in fact, I've not seen *any* cases of it.     * for now (XXX), gives a fatal error.     */    CLOSE_AND_RET(_PICERR_UNSUPPORTED);    }    cptr=next_token(cptr);    /* so now cptr points to a colour name/number. Unfortunately,   * people seem to take amazing liberties with colour names.   * They lowercase them (not allowed by the format spec), they   * use separate words for colours like "light sky blue" (not   * allowed by the format spec)... happy happy joy joy, not.   *   * The least awful solution, I think, is to add to the next token   * (i.e. the one that *should* be the colour) any consecutively   * following ones which are more than 2 chars long. Then in any   * string comparisons, we use strcasecmp rather than strcmp.   * As far as I can see, this scheme should work in all cases.   */  get_token(colname,sizeof(colname),cptr);  cptr=next_token(cptr);  get_token(buf,sizeof(buf),cptr);  while(strlen(buf)>2)    {    /* avoid overruns */    if(strlen(colname)+strlen(buf)+2>sizeof(colname))      break;        strcat(colname," ");    strcat(colname,buf);    cptr=next_token(cptr);    get_token(buf,sizeof(buf),cptr);    }    /* now work out what we've got. if it starts with a `#' it's RGB,   * and if it's "None" it's the transparent `colour', otherwise it's a   * colour name from rgb.txt.   *   * However, we also tolerate the old-style "#Transparent" for "None".   */  if(*colname=='#' && isxdigit(colname[1]))    {    /* RGB - length of rest must be 3, 6, 9, or 12. */    int rgb;        switch(strlen(colname+1))      {      case 3:        rgb=strtol(colname+1,NULL,16);        r=(rgb>>8)*16+(rgb>>8);        g=((rgb>>4)&15)*16+((rgb>>4)&15);        b=(rgb&15)*16+(rgb&15);        break;            case 6:        rgb=strtol(colname+1,NULL,16);        r=(rgb>>16);        g=((rgb>>8)&255);        b=(rgb&255);        break;            case 9:        /* 0123456789         * #rr.gg.bb.         */        colname[3]=colname[6]=colname[9]=0;        r=strtol(colname+1,NULL,16);        g=strtol(colname+4,NULL,16);        b=strtol(colname+7,NULL,16);        break;            case 12:        /* 0123456789012         * #rr..gg..bb..         */        colname[3]=colname[7]=colname[11]=0;        r=strtol(colname+1,NULL,16);        g=strtol(colname+5,NULL,16);        b=strtol(colname+9,NULL,16);        break;            default:        CLOSE_AND_RET(_PICERR_BADXCOL);      }    }  else		/* not RGB number... */    if(strcasecmp(colname,"None")==0 || strcasecmp(colname,"#Transparent")==0)      {      /* transparent `colour' - we use grey.       * This is inconsistent with PNG's current background colour,       * true, but it's likely to be what you'd want.       * (XXX may want to make configurable though)       */      r=g=b=128;      }    else      {      /* lookup the colour name. */      int rgb=lookup_named_colour(colname);            if(rgb==-1)	/* colour not found */        CLOSE_AND_RET(_PICERR_BADXCOL);            r=(rgb>>16);      g=((rgb>>8)&255);      b=(rgb&255);      }    /* write colour to colchars[] in case we're producing 24-bit output */  colchars[f].r=r;  colchars[f].g=g;  colchars[f].b=b;    if(ncols<=256)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -