diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2010-03-27 19:22:22 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2010-03-27 19:22:22 +0000 |
commit | 4c233fcfb54b386fcd96f71deb1e88e10d635825 (patch) | |
tree | 8cd7f623d29368a59905ccc108e5151bc28d2e62 /lib | |
parent | 3a54a339a59e83834ea18d88cab7104fd9d8b9ca (diff) | |
download | netpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.tar.gz netpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.tar.xz netpbm-mirror-4c233fcfb54b386fcd96f71deb1e88e10d635825.zip |
Release 10.50.00 - copied from trunk
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@1162 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libpam.c | 61 | ||||
-rw-r--r-- | lib/libpbmfont.c | 80 | ||||
-rw-r--r-- | lib/libpgm1.c | 2 | ||||
-rw-r--r-- | lib/libpnm3.c | 2 | ||||
-rw-r--r-- | lib/libppmd.c | 214 | ||||
-rw-r--r-- | lib/pam.h | 4 | ||||
-rw-r--r-- | lib/pnm.h | 3 | ||||
-rw-r--r-- | lib/ppm.h | 6 | ||||
-rw-r--r-- | lib/util/shhopt.h | 12 |
9 files changed, 270 insertions, 114 deletions
diff --git a/lib/libpam.c b/lib/libpam.c index b890434e..9384e178 100644 --- a/lib/libpam.c +++ b/lib/libpam.c @@ -1066,6 +1066,67 @@ pnm_getopacity(const struct pam * const pamP, +tuple +pnm_backgroundtuple(struct pam * const pamP, + tuple ** const tuples) { +/*-------------------------------------------------------------------- + This function was copied from libpnm3.c's pnm_backgroundxel() and + modified to use tuples instead of xels. +----------------------------------------------------------------------*/ + tuple tuplePtr, bgtuple, ul, ur, ll, lr; + + /* Guess a good background value. */ + ul = tuples[0][0]; + ur = tuples[0][pamP->width-1]; + ll = tuples[pamP->height-1][0]; + lr = tuples[pamP->height-1][pamP->width-1]; + bgtuple = NULL; + + /* We first recognize three corners equal. If not, we look for any + two. If not, we just average all four. + */ + if (pnm_tupleequal(pamP, ul, ur) && pnm_tupleequal(pamP, ur, ll)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ul, ur) && + pnm_tupleequal(pamP, ur, lr)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ul, ll) && + pnm_tupleequal(pamP, ll, lr)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ur, ll) && + pnm_tupleequal(pamP, ll, lr)) + tuplePtr = ur; + else if (pnm_tupleequal(pamP, ul, ur)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ul, ll)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ul, lr)) + tuplePtr = ul; + else if (pnm_tupleequal(pamP, ur, ll)) + tuplePtr = ur; + else if (pnm_tupleequal(pamP, ur, lr)) + tuplePtr = ur; + else if (pnm_tupleequal(pamP, ll, lr)) + tuplePtr = ll; + else { + /* Reimplement libpnm3.c's mean4() but for tuples. */ + unsigned int plane; + bgtuple = pnm_allocpamtuple(pamP); + for (plane = 0; plane < pamP->depth; ++plane) + bgtuple[plane] = (ul[plane] + ur[plane] + ll[plane] + lr[plane]) / 4; + } + if (!bgtuple) { + unsigned int plane; + bgtuple = pnm_allocpamtuple(pamP); + for (plane = 0; plane < pamP->depth; ++plane) + bgtuple[plane] = tuplePtr[plane]; + } + + return bgtuple; +} + + + /*============================================================================= pm_system() Standard Input feeder and Standard Output accepter functions. =============================================================================*/ diff --git a/lib/libpbmfont.c b/lib/libpbmfont.c index ff75d0a1..793de6c5 100644 --- a/lib/libpbmfont.c +++ b/lib/libpbmfont.c @@ -1275,9 +1275,9 @@ skipCharacter(FILE * const fp) { static void -validateEncoding(const char ** const arg, - unsigned int * const codepointP, - bool * const badCodepointP) { +interpEncoding(const char ** const arg, + unsigned int * const codepointP, + bool * const badCodepointP) { /*---------------------------------------------------------------------------- With arg[] being the ENCODING statement from the font, return as *codepointP the codepoint that it indicates (code point is the character @@ -1315,12 +1315,29 @@ validateEncoding(const char ** const arg, - static void -processCharsLine(FILE * const fp, - const char ** const arg, - struct font * const fontP) { +readEncoding(FILE * const ifP, + unsigned int * const codepointP, + bool * const badCodepointP) { + + const char * arg[32]; + + expect(ifP, "ENCODING", arg); + + interpEncoding(arg, codepointP, badCodepointP); +} + + +static void +processChars(FILE * const fp, + const char ** const arg, + struct font * const fontP) { +/*---------------------------------------------------------------------------- + Process the CHARS block in a BDF font file, assuming the file is positioned + just after the CHARS line and 'arg' is the contents of that CHARS line. + Read the rest of the block and apply its contents to *fontP. +-----------------------------------------------------------------------------*/ unsigned int const nCharacters = atoi(arg[1]); unsigned int nCharsDone; @@ -1354,12 +1371,8 @@ processCharsLine(FILE * const fp, pm_error("no memory for font glyph for '%s' character", charName); - { - const char * arg[32]; - expect(fp, "ENCODING", arg); + readEncoding(fp, &codepoint, &badCodepoint); - validateEncoding(arg, &codepoint, &badCodepoint); - } if (badCodepoint) skipCharacter(fp); else { @@ -1389,7 +1402,7 @@ processCharsLine(FILE * const fp, const char * arg[32]; expect(fp, "ENDCHAR", arg); } - assert(codepoint < 256); /* Ensured by validateEncoding() */ + assert(codepoint < 256); /* Ensured by readEncoding() */ fontP->glyph[codepoint] = glyphP; } @@ -1401,19 +1414,26 @@ processCharsLine(FILE * const fp, static void -processFontLine(FILE * const fp, - const char * const line, - const char ** const arg, - struct font * const fontP, - bool * const endOfFontP) { +processBdfFontLine(FILE * const fp, + const char * const line, + const char ** const arg, + struct font * const fontP, + bool * const endOfFontP) { +/*---------------------------------------------------------------------------- + Process a nonblank line just read from a BDF font file. + This processing may involve reading more lines. +-----------------------------------------------------------------------------*/ *endOfFontP = FALSE; /* initial assumption */ + assert(arg[0] != NULL); /* Entry condition */ + if (streq(arg[0], "COMMENT")) { /* ignore */ } else if (streq(arg[0], "SIZE")) { /* ignore */ } else if (streq(arg[0], "STARTPROPERTIES")) { + /* Read off the properties and ignore them all */ unsigned int const propCount = atoi(arg[1]); unsigned int i; for (i = 0; i < propCount; ++i) { @@ -1431,8 +1451,11 @@ processFontLine(FILE * const fp, fontP->y = atoi(arg[4]); } else if (streq(arg[0], "ENDFONT")) { *endOfFontP = true; - } else if (!strcmp(arg[0], "CHARS")) - processCharsLine(fp, arg, fontP); + } else if (streq(arg[0], "CHARS")) { + processChars(fp, arg, fontP); + } else { + /* ignore */ + } } @@ -1440,18 +1463,17 @@ processFontLine(FILE * const fp, struct font * pbm_loadbdffont(const char * const name) { - FILE * fp; - char line[1024]; - const char * arg[32]; + FILE * ifP; struct font * fontP; + const char * wordList[32]; bool endOfFont; - fp = fopen(name, "rb"); - if (!fp) + ifP = fopen(name, "rb"); + if (!ifP) pm_error("Unable to open BDF font file name '%s'. errno=%d (%s)", name, errno, strerror(errno)); - expect(fp, "STARTFONT", arg); + expect(ifP, "STARTFONT", wordList); MALLOCVAR(fontP); if (fontP == NULL) @@ -1471,12 +1493,14 @@ pbm_loadbdffont(const char * const name) { endOfFont = FALSE; while (!endOfFont) { + char line[1024]; + const char * wordList[32]; int rc; - rc = readline(fp, line, arg); + rc = readline(ifP, line, wordList); if (rc < 0) pm_error("End of file before ENDFONT statement in BDF font file"); - processFontLine(fp, line, arg, fontP, &endOfFont); + processBdfFontLine(ifP, line, wordList, fontP, &endOfFont); } return fontP; } diff --git a/lib/libpgm1.c b/lib/libpgm1.c index 4d93e4be..64a43534 100644 --- a/lib/libpgm1.c +++ b/lib/libpgm1.c @@ -189,7 +189,7 @@ readRpgmRow(FILE * const fileP, asprintfN(&error, "Unable to allocate memory for row buffer " "for %u columns", cols); else { - ssize_t rc; + size_t rc; rc = fread(rowBuffer, 1, bytesPerRow, fileP); if (rc == 0) asprintfN(&error, "Error reading row. fread() errno=%d (%s)", diff --git a/lib/libpnm3.c b/lib/libpnm3.c index c41a2108..0426ebcb 100644 --- a/lib/libpnm3.c +++ b/lib/libpnm3.c @@ -45,7 +45,7 @@ mean4(int const format, break; default: - pm_error( "Invalid format passed to pnm_backgroundxel()"); + pm_error("Invalid format passed to pnm_backgroundxel()"); } return retval; } diff --git a/lib/libppmd.c b/lib/libppmd.c index 3f824302..deb47c0f 100644 --- a/lib/libppmd.c +++ b/lib/libppmd.c @@ -966,14 +966,25 @@ typedef struct int edge; } coord; -typedef struct fillobj { +typedef struct fillState { int n; + /* Number of elements in 'coords' */ int size; int curedge; int segstart; int ydir; int startydir; coord * coords; +} fillState; + +typedef struct fillobj { + + /* The only reason we have a struct fillState separate from + struct fillobj is that the drawproc interface is defined to + have drawing not modify the fillobj, i.e. it passed + const fillobj * to the drawing program. + */ + struct fillState * stateP; } fillobj; #define SOME 1000 @@ -984,16 +995,24 @@ struct fillobj * ppmd_fill_create(void) { fillobj * fillObjP; + struct fillState * stateP; MALLOCVAR(fillObjP); if (fillObjP == NULL) pm_error("out of memory allocating a fillhandle"); - fillObjP->n = 0; - fillObjP->size = SOME; - MALLOCARRAY(fillObjP->coords, fillObjP->size); - if (fillObjP->coords == NULL) + + MALLOCVAR(stateP); + if (stateP == NULL) + pm_error("out of memory allocating a fillhandle"); + + stateP->n = 0; + stateP->size = SOME; + MALLOCARRAY(stateP->coords, stateP->size); + if (stateP->coords == NULL) pm_error("out of memory allocating a fillhandle"); - fillObjP->curedge = 0; + stateP->curedge = 0; + + fillObjP->stateP = stateP; /* Turn off line clipping. */ /* UGGH! We must eliminate this global variable */ @@ -1021,14 +1040,95 @@ ppmd_fill_init(void) { void -ppmd_fill_destroy(struct fillobj * fillObjP) { +ppmd_fill_destroy(struct fillobj * const fillObjP) { - free(fillObjP->coords); + free(fillObjP->stateP->coords); + free(fillObjP->stateP); free(fillObjP); } +static void +addCoord(struct fillState * const stateP, + ppmd_point const point) { + + stateP->coords[stateP->n].point = point; + stateP->coords[stateP->n].edge = stateP->curedge; + + ++stateP->n; +} + + + +static void +startNewSegment(struct fillState * const stateP) { +/*---------------------------------------------------------------------------- + Close off the segment we're currently building and start a new one. +-----------------------------------------------------------------------------*/ + if (stateP->startydir != 0 && stateP->ydir != 0) { + /* There's stuff in the current segment. */ + if (stateP->startydir == stateP->ydir) { + /* Oops, first edge and last edge of current segment are the same. + Change all points in the first edge to be in the last. + */ + int const firstEdge = stateP->coords[stateP->segstart].edge; + int const lastEdge = stateP->coords[stateP->n - 1].edge; + coord * const segStartCoordP = &stateP->coords[stateP->segstart]; + coord * const segEndCoordP = &stateP->coords[stateP->n]; + + coord * fcP; + + for (fcP = segStartCoordP; + fcP < segEndCoordP && fcP->edge == firstEdge; + ++fcP) + fcP->edge = lastEdge; + } + } + /* And start new segment. */ + ++stateP->curedge; + stateP->segstart = stateP->n; + stateP->ydir = 0; + stateP->startydir = 0; +} + + + +static void +continueSegment(struct fillState * const stateP, + int const dy) { +/*---------------------------------------------------------------------------- + 'dy' is how much the current point is above the previous one. +-----------------------------------------------------------------------------*/ + if (dy != 0) { + if (stateP->ydir != 0 && stateP->ydir != dy) { + /* Direction changed. Insert a fake coord, old + position but new edge number. + */ + ++stateP->curedge; + addCoord(stateP, stateP->coords[stateP->n - 1].point); + } + stateP->ydir = dy; + if (stateP->startydir == 0) + stateP->startydir = dy; + } +} + + + + +/* ppmd_fill_drawprocp() is a drawproc that turns an outline drawing function + into a filled shape function. This is a somewhat off-label application of + a drawproc: A drawproc is intended just to draw a point. So e.g. you + might draw a circle with a fat brush by calling ppmd_circle with a drawproc + that draws a point as a 10-pixel disk. + + But ppmd_fill_drawproc() just draws a point the trivial way: as one pixel. + However, it tracks every point that is drawn in a form that a subsequent + ppmd_fill() call can use to to fill in the shape drawn, assuming it turns + out to be a closed shape. +*/ + void ppmd_fill_drawprocp(pixel ** const pixels, unsigned int const cols, @@ -1037,85 +1137,39 @@ ppmd_fill_drawprocp(pixel ** const pixels, ppmd_point const p, const void * const clientdata) { - fillobj * fh; - coord * cp; - - fh = (fillobj*) clientdata; + const fillobj * const fillObjP = clientdata; + struct fillState * const stateP = fillObjP->stateP; - /* If these are the same coords we saved last time, don't bother. */ - if (fh->n > 0) { - ppmd_point const lastPoint = fh->coords[fh->n - 1].point; - if (pointsEqual(p, lastPoint)) - return; - } - - /* Ok, these are new; make room for two more coords. */ - if (fh->n + 1 >= fh->size) { - fh->size += SOME; - REALLOCARRAY(fh->coords, fh->size); - if (fh->coords == NULL) + /* Make room for two more coords, the max we might add. */ + if (stateP->n + 2 > stateP->size) { + stateP->size += SOME; + REALLOCARRAY(stateP->coords, stateP->size); + if (stateP->coords == NULL) pm_error("out of memory enlarging a fillhandle"); } - /* Check for extremum and set the edge number. */ - if (fh->n == 0) { + if (stateP->n == 0) { /* Start first segment. */ - fh->segstart = fh->n; - fh->ydir = 0; - fh->startydir = 0; + stateP->segstart = stateP->n; + stateP->ydir = 0; + stateP->startydir = 0; + addCoord(stateP, p); } else { - coord * const ocp = &(fh->coords[fh->n - 1]); - int dx, dy; - - dx = p.x - ocp->point.x; - dy = p.y - ocp->point.y; - if (dx < -1 || dx > 1 || dy < -1 || dy > 1) { - /* Segment break. Close off old one. */ - if (fh->startydir != 0 && fh->ydir != 0) - if (fh->startydir == fh->ydir) { - /* Oops, first edge and last edge are the same. - Renumber the first edge in the old segment. - */ - const coord * const fcpLast= &(fh->coords[fh->n -1]); - coord * fcp; - - int oldedge; - - fcp = &(fh->coords[fh->segstart]); - oldedge = fcp->edge; - for (; fcp <= fcpLast && fcp->edge == oldedge ; ++fcp) - fcp->edge = ocp->edge; - } - /* And start new segment. */ - ++fh->curedge; - fh->segstart = fh->n; - fh->ydir = 0; - fh->startydir = 0; + ppmd_point const prevPoint = stateP->coords[stateP->n - 1].point; + int const dx = p.x - prevPoint.x; + int const dy = p.y - prevPoint.y; + + if (dx == 0 && dy == 0) { + /* These are the same coords we had last time; don't bother */ } else { - /* Segment continues. */ - if (dy != 0) { - if (fh->ydir != 0 && fh->ydir != dy) { - /* Direction changed. Insert a fake coord, old - position but new edge number. - */ - ++fh->curedge; - cp = &fh->coords[fh->n]; - cp->point = ocp->point; - cp->edge = fh->curedge; - ++fh->n; - } - fh->ydir = dy; - if (fh->startydir == 0) - fh->startydir = dy; - } + if (abs(dx) > 1 || abs(dy) > 1) + startNewSegment(stateP); + else + continueSegment(stateP, dy); + + addCoord(stateP, p); } } - - /* Save this coord. */ - cp = &fh->coords[fh->n]; - cp->point = p; - cp->edge = fh->curedge; - ++fh->n; } @@ -1173,10 +1227,12 @@ ppmd_fill(pixel ** const pixels, int const cols, int const rows, pixval const maxval, - struct fillobj * const fh, + struct fillobj * const fillObjP, ppmd_drawproc drawProc, const void * const clientdata) { + struct fillState * const fh = fillObjP->stateP; + int pedge; int i, edge, lx, rx, py; coord * cp; diff --git a/lib/pam.h b/lib/pam.h index c28c5c2c..3d1f8532 100644 --- a/lib/pam.h +++ b/lib/pam.h @@ -483,6 +483,10 @@ pnm_YCbCr_to_rgbtuple(const struct pam * const pamP, ((tuple)[PAM_RED_PLANE] == (tuple)[PAM_GRN_PLANE] && \ (tuple)[PAM_RED_PLANE] == (tuple)[PAM_BLU_PLANE]) +tuple +pnm_backgroundtuple(struct pam * const pamP, + tuple ** const tuples); + /*---------------------------------------------------------------------------- These are meant for passing to pm_system() as Standard Input feeder and Standard Output accepter. diff --git a/lib/pnm.h b/lib/pnm.h index e4bd34a8..de5f1d91 100644 --- a/lib/pnm.h +++ b/lib/pnm.h @@ -20,6 +20,9 @@ typedef pixval xelval; #define PNM_OVERALLMAXVAL PPM_OVERALLMAXVAL #define PNM_MAXMAXVAL PPM_MAXMAXVAL #define PNM_GET1(x) PPM_GETB(x) +#define PNM_GETR(x) PPM_GETR(x) +#define PNM_GETG(x) PPM_GETG(x) +#define PNM_GETB(x) PPM_GETB(x) #define PNM_ASSIGN1(x,v) PPM_ASSIGN(x,0,0,v) #define PNM_ASSIGN(x,r,g,b) PPM_ASSIGN(x,r,g,b) #define PNM_EQUAL(x,y) PPM_EQUAL(x,y) diff --git a/lib/ppm.h b/lib/ppm.h index 0695295f..57b6c04a 100644 --- a/lib/ppm.h +++ b/lib/ppm.h @@ -250,6 +250,12 @@ ppm_hsv_from_color(pixel const color, pixval const maxval); static __inline pixval +ppm_luminosity(pixel const p) { + + return (pixval)(PPM_LUMIN(p) + 0.5); +} + +static __inline pixval ppm_colorvalue(pixel const p) { /*---------------------------------------------------------------------------- The color value (V is HSV) as a pixval diff --git a/lib/util/shhopt.h b/lib/util/shhopt.h index 2175fc5d..e5e138e1 100644 --- a/lib/util/shhopt.h +++ b/lib/util/shhopt.h @@ -1,4 +1,5 @@ -/*============================================================================= +#if 0 +============================================================================= HERE IS AN EXAMPLE OF THE USE OF SHHOPT: @@ -6,8 +7,9 @@ HERE IS AN EXAMPLE OF THE USE OF SHHOPT: int main ( int argc, char **argv ) { - // initial values here are just to demonstrate what gets set and - // what doesn't by the code below. + /* initial values here are just to demonstrate what gets set and + what doesn't by the code below. + */ int help_flag = 7; unsigned int help_spec =7; unsigned int height_spec =7; @@ -67,8 +69,8 @@ Now run this program with something like myprog -v /etc/passwd -name=Bryan --hei=4 -========================================================================*/ - +======================================================================== +#endif /* 0 */ #ifndef SHHOPT_H #define SHHOPT_H |