📄 gfuntype.c
字号:
/* --- try both 8-bits/count and 4-bits/count for best compression --- */
int maxbitcount[2] = {254,14}; /* don't count too much in one byte */
int repeatcmds[2] = {255,15}; /* opcode for repeat/duplicate count */
int minbytes = 0; /* #bytes needed for smallest format */
for ( iformat=2; iformat<=3; iformat++ ) { /* 2=8-bit packing, 3=4-bit */
int gfbitcount = 0, /* count of consecutive gfbitval's */
gfbitval = 0, /* begin with count of leading 0's */
pixcount = 0; /* #packed bytes (#black/white flips) */
unsigned char *gfcount = gfpixcount[iformat-2]; /*counts for this format*/
if ( gformat!=0 && gformat!=iformat ) /* this format not allowed */
continue; /* so just skip it */
for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */
{
int bitval = 0; /* current actual pixel value */
int nrepeats=0, nextreps=0; /* #duplicate lines below current,next line*/
/* --- check for repeated/duplicate scan lines --- */
if ( isrepeat /* we're storing scan line repeat counts */
&& iscan < height-1 ) { /* current scan line isn't the last line */
/* --- count repeats --- */
int jscan = iscan; /* compare current scan with lines below it*/
while ( ++jscan < height ) { /* until last scan line */
if (nrepeats == jscan-iscan-1) /*no intervening non-identical lines*/
if ( bitcmp(bitvec[iscan],bitvec[jscan],width) == 0 ) /* identical */
nrepeats++; /* so bump repeat count */
if ( jscan > iscan+1 ) /* we're below next line */
if (nextreps == jscan-iscan-2) /*no intervening non-identical lines*/
if ( bitcmp(bitvec[iscan+1],bitvec[jscan],width) == 0 )/*identical*/
nextreps++; } /* so bump next lline repeat count */
/* --- set repeat command and count --- */
if ( nrepeats > 0 ) { /* found repeated lines below current */
int maxrepeats = maxbitcount[iformat-2]; /*max count/repeats per byte*/
if ( nrepeats > maxrepeats ) nrepeats=maxrepeats; /* don't exceed max */
{setbyfmt(iformat,gfcount,pixcount,repeatcmds[iformat-2]);} /*set cmd*/
{setbyfmt(iformat,gfcount,pixcount+1,nrepeats);} /* set #repeats */
pixcount += 2; } /* don't bump pixcount within macros */
} /* --- end-of-if(isrepeat) --- */
/* --- set bit counts for current scan line --- */
for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */
{
bitval = getlongbit(bitvec[iscan],ibit); /* check actual pixel value */
if ( bitval != gfbitval ) { /* black-to-white edge (or vice versa) */
{setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
pixcount++; /* don't bump pixcount within macro */
gfbitcount = 0; /* reset consecutive bit count */
gfbitval = 1-gfbitval; } /* flip bit to be counted */
else /* check count if continuing with same val */
if ( gfbitcount >= maxbitcount[iformat-2] ) { /* max count per byte */
{setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
clearbyfmt(iformat,gfcount,pixcount+1); /*followed by dummy 0 count*/
pixcount += 2; /* don't bump pixcount within macros */
gfbitcount = 0; } /* reset consecutive bit count */
if ( bitval == gfbitval ) /* same bit val as preceding, or first new */
gfbitcount++; /* so just count another pixel */
} /* --- end-of-for(ibit) --- */
/* --- adjust for repeated scan lines --- */
iscan += nrepeats; /* skip repeated/duplicate scan lines */
if ( nrepeats>0 || nextreps>0 ) /* emit count to align on full scan */
if ( iscan < height-1 ) /* have another scan line below this one */
if ( gfbitcount > 0 ) { /* should always have some final count */
{setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
pixcount++; /* don't bump pixcount within macro */
gfbitcount = 0; /* reset consecutive bit count */
if ( bitval == getlongbit(bitvec[iscan+1],0) ) { /* same bit value */
clearbyfmt(iformat,gfcount,pixcount); /*so we need a dummy 0 count*/
pixcount++; } /* don't bump pixcount within macros */
else /* bitval flips at start of next line */
gfbitval = 1-gfbitval; /* so flip bit to be counted */
} /* --- end-of-if(nrepeats...gfbitcount>0) --- */
} /* --- end-of-for(iscan) --- */
/* --- store final count --- */
if ( gfbitcount > 0 ) { /* have a final count */
{setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
pixcount++; } /* don't bump pixcount within macro */
else /* ended exactly after maxbitcount? */
if ( getbyfmt(iformat,gfcount,pixcount-1) == 0 )/*have dummy 0 trailer?*/
pixcount--; /* remove unneeded dummy trailer */
/* --- save count to choose smallest --- */
npixcounts[iformat-2] = pixcount; /* save count */
} /* --- end-of-for(iformat) --- */
/* --- check for optimal/smallest format --- */
nbytes2=npixcounts[0]; nbytes3=(1+npixcounts[1])/2; /* #bytes for count */
iformat = (nbytes2<nbytes3? 2:3); /* choose smallest format */
minbytes = (iformat==2?nbytes2:nbytes3); /* #bytes for smallest format */
if ( gformat == 0 ) /* bitmap representation also permitted */
if ( nbytes1 <= minbytes ) /* and it's the optimal/smallest format */
iformat = 1; /* so flip format */
/* --- move results to returned image --- */
if ( iformat != 1 ) { /* using a .gf format */
if ( (image->pixmap = (unsigned char *)malloc(minbytes)) /* alloc pixmap */
== NULL ) goto end_of_job; /* quit if failed to allocate pixmap */
memcpy(image->pixmap,gfpixcount[iformat-2],minbytes); /*copy local counts*/
image->format = iformat; /* signal byte counts or nibble counts */
image->pixsz = npixcounts[iformat-2]; /*#counts in pixmap for gformat=2,3*/
} /* --- end-of-if(iformat!=1) --- */
} /* --- end-of-if(gformat==2) --- */
/* --------------------------------------------------------------------------
copy each integer in bitvec[] to raster pixmap, bit by bit
-------------------------------------------------------------------------- */
if ( iformat == 1 ) /* bit-by-bit representation of image */
{
int ipixel = 0; /* pixmap index */
/* --- first allocate image raster pixmap for character --- */
if ( (image->pixmap = (unsigned char *)malloc(pixmapsz(image)))
== NULL ) goto end_of_job; /* quit if failed to allocate pixmap */
image->format = iformat; /* reset format */
/* --- now store bit image in allocated raster --- */
for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */
for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */
{
if ( getlongbit(bitvec[iscan],ibit) != 0 ) /* check current scan pixel */
{ setlongbit(image->pixmap,ipixel); }
else /*turn off corresponding raster bit*/
{ unsetlongbit(image->pixmap,ipixel); }
ipixel++; /* bump image raster pixel */
} /* --- end-of-for(iscan,ibit) --- */
} /* --- end-of-if(gformat==1) --- */
/* --------------------------------------------------------------------------
done
-------------------------------------------------------------------------- */
isokay = 1; /* reset flag for success */
end_of_job:
return ( isokay ); /* back with 1=success, 0=failure */
} /* --- end-of-function rasterizechar() --- */
/* ==========================================================================
* Function: parsecorner ( line, row, col )
* Purpose: Parses a "pixel corner" line (upper left or lower left)
* and returns the (col,row) information on it as integers.
* --------------------------------------------------------------------------
* Arguments: line (I) char * to input line containing
* ".<--This pixel's..." to be parsed
* row (O) int * returning the (,row)
* col (O) int * returning the (col,)
* Returns: ( int ) 1 if successful, or 0 for any error
* --------------------------------------------------------------------------
* Notes: o
* ======================================================================= */
/* --- entry point --- */
int parsecorner ( char *line, int *row, int *col )
{
/* --------------------------------------------------------------------------
Allocations and Declarations
-------------------------------------------------------------------------- */
int isokay = 0; /* success/fail flag, init for failure */
char field[99], *delim; /*(col,row) field and ptr to various delims*/
/* --------------------------------------------------------------------------
extract (col,row) field from line, and interpret col and row as integers
-------------------------------------------------------------------------- */
/* --- first, check beginning of line --- */
if ( line == (char *)NULL ) goto end_of_job; /* no line supplied by caller */
/* --- check for blank line --- */
if ( strstr(line,BLANKCHAR_STUB) != NULL ) /* got entirely blank character */
return ( -999 ); /* so return special -999 signal */
/* --- check for corner --- */
if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) != 0 ) /*not valid corner*/
goto end_of_job; /* so quit */
/* --- extract col,row field from line --- */
if ( (delim=strchr(line,'(')) == NULL ) goto end_of_job; /*find open paren*/
strncpy(field,delim+1,10); /* extract next 10 chars */
field[10] = '\000'; /* and null-terminate field */
if ( (delim=strchr(field,')')) == NULL ) goto end_of_job; /*find close paren*/
*delim = '\000'; /* terminate field at close paren */
/* --- interpret col,row as integers --- */
if ( (delim=strchr(field,',')) == NULL ) goto end_of_job; /* find comma */
*delim = '\000'; /* break field into col and row */
if ( col != (int *)NULL ) /* caller gave us ptr for col */
*col = atoi(field); /* so return it to him */
if ( row != (int *)NULL ) /* caller gave us ptr for row */
*row = atoi(delim+1); /* so return it to him */
/* --------------------------------------------------------------------------
done
-------------------------------------------------------------------------- */
isokay = 1; /* reset flag for success */
end_of_job:
return ( isokay ); /* back with success/fail flag */
} /* --- end-of-function parsecorner() --- */
/* ==========================================================================
* Function: readaline ( fp )
* Purpose: Reads a line from fp, strips terminating newline,
* and returns ptr to internal buffer
* --------------------------------------------------------------------------
* Arguments: fp (I) FILE * to input file to be read.
* If null, returns line previously read.
* Returns: ( char * ) internal buffer containing line read,
* or NULL for eof or error.
* --------------------------------------------------------------------------
* Notes: o fp is left on the line following the returned line
* ======================================================================= */
/* --- entry point --- */
char *readaline ( FILE *fp )
{
/* --------------------------------------------------------------------------
Allocations and Declarations
-------------------------------------------------------------------------- */
static char buffer[2048]; /* static buffer returned to caller */
char *fgets(), *bufptr=buffer; /* read line from fp */
char *strchr(), *delim; /* remove terminating newline */
/* --------------------------------------------------------------------------
Read line and strip trailing newline
-------------------------------------------------------------------------- */
if ( fp != NULL ) /*if null, return previous line read*/
if ( (bufptr=fgets(buffer,2047,fp)) /* read next line from fp */
!= NULL ) /* and check that we succeeded */
{
if ( (delim=strchr(bufptr,'\n')) /* look for terminating newline */
!= NULL ) /* and check that we found it */
*delim = '\000'; /* truncate line at newline */
} /* --- end-of-if(fgets()!=NULL) --- */
return ( bufptr ); /*back to caller with buffer or null*/
} /* --- end-of-function readaline() --- */
/* ==========================================================================
* Function: bitcmp ( bs1, bs2, n )
* Purpose: compares the first n bits of two strings
* --------------------------------------------------------------------------
* Arguments: bs1 (I) unsigned char * to first bit string
* bs2 (I) unsigned char * to second bit string
* n (I) int containing #bits to compare
* Returns: ( int ) 0 if first n bits are identical
* -1 if first unmatching bit of bs1 is 0
* +1 if first unmatching bit of bs2 id 0
* --------------------------------------------------------------------------
* Notes: o
* ======================================================================= */
/* --- entry point --- */
int bitcmp ( unsigned char *bs1, unsigned char *bs2, int n )
{
/* --------------------------------------------------------------------------
Allocations and Declarations
-------------------------------------------------------------------------- */
int icmp = 0; /* returned to caller */
int nbytes = n/8, /* #full bytes we can compare with memcmp()*/
nbits = n%8, ibit=0; /* #trailing bits in last byte, index */
/* --------------------------------------------------------------------------
compare leading bytes, then trailing bits
-------------------------------------------------------------------------- */
if ( nbytes > 0 ) icmp = memcmp(bs1,bs2,nbytes); /* compare leading bytes */
if ( icmp == 0 ) /* leading bytes identical */
if ( nbits > 0 ) /* and we have trailing bits */
for ( ibit=0; ibit<nbits; ibit++ ) /* check each bit */
{ icmp = (int)get1bit(bs1[nbytes],ibit) - (int)get1bit(bs2[nbytes],ibit);
if ( icmp != 0 ) break; } /* done at first unmatched bit */
return ( icmp ); /* back to caller with -1,0,+1 */
} /* --- end-of-function bitcmp() --- */
/* --- end-of-file gfuntype.c --- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -