diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-12-27 17:33:56 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-12-27 17:33:56 +0000 |
commit | 6e629f983aa205c3eaa5f339f1c71bb5e7938049 (patch) | |
tree | a89f594443ac2330138f0bd0f19ee59135c2213f /editor | |
parent | ec52f41aabc9de9aac203c2f462252e403c7374a (diff) | |
download | netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.tar.gz netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.tar.xz netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.zip |
Promote Development to Advanced to make Release 10.97.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@4222 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r-- | editor/pambackground.c | 52 | ||||
-rw-r--r-- | editor/pamenlarge.c | 1 | ||||
-rw-r--r-- | editor/pamrubber.c | 390 | ||||
-rw-r--r-- | editor/pbmclean.c | 8 | ||||
-rw-r--r-- | editor/pbmpscale.c | 30 | ||||
-rw-r--r-- | editor/pnmcat.c | 5 | ||||
-rw-r--r-- | editor/pnmpad.c | 22 | ||||
-rw-r--r-- | editor/specialty/pampaintspill.c | 136 |
8 files changed, 390 insertions, 254 deletions
diff --git a/editor/pambackground.c b/editor/pambackground.c index b4941042..218f5b7e 100644 --- a/editor/pambackground.c +++ b/editor/pambackground.c @@ -4,19 +4,19 @@ #include "shhopt.h" #include "pam.h" -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - const char * inputFileName; + const char * inputFileName; unsigned int verbose; }; static void -parseCommandLine(int argc, char ** const argv, - struct cmdlineInfo * const cmdlineP) { +parseCommandLine(int argc, const char ** const argv, + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. @@ -37,7 +37,7 @@ parseCommandLine(int argc, char ** const argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc-1 < 1) @@ -48,7 +48,7 @@ parseCommandLine(int argc, char ** const argv, pm_error("There is at most one argument: input file name. " "You specified %d", argc-1); } -} +} @@ -83,7 +83,7 @@ allocateOutputPointerRow(unsigned int const width, static void -createWhiteTuple(const struct pam * const pamP, +createWhiteTuple(const struct pam * const pamP, tuple * const whiteTupleP) { /*---------------------------------------------------------------------------- Create a "white" tuple. By that we mean a tuple all of whose elements @@ -134,7 +134,7 @@ selectBackground(struct pam * const pamP, bg = ul; } } - + *bgColorP = pnm_allocpamtuple(pamP); pnm_assigntuple(pamP, *bgColorP, bg); } @@ -301,8 +301,8 @@ expandBackgroundHoriz(unsigned char ** const pi, unsigned int const height, bool * const expandedP) { /*---------------------------------------------------------------------------- - In every row, expand the background rightward from any known background - pixel through all consecutive unknown pixels. + In every row except top and bottom, expand the background rightward from + any known background pixel through all consecutive unknown pixels. Then do the same thing leftward. @@ -343,8 +343,9 @@ expandBackgroundVert(unsigned char ** const pi, unsigned int const height, bool * const expandedP) { /*---------------------------------------------------------------------------- - In every column, expand the background downward from any known background - pixel through all consecutive unknown pixels. + In every column except leftmost and rightmost, expand the background + downward from any known background pixel through all consecutive unknown + pixels. Then do the same thing upward. @@ -400,7 +401,7 @@ findBackgroundPixels(struct pam * const inpamP, -----------------------------------------------------------------------------*/ unsigned char ** pi; bool backgroundComplete; - unsigned int passes; + unsigned int passCt; pi = newPi(inpamP->width, inpamP->height); @@ -409,29 +410,29 @@ findBackgroundPixels(struct pam * const inpamP, setEdges(pi, inpamP->width, inpamP->height); backgroundComplete = FALSE; - passes = 0; - + passCt = 0; + while (!backgroundComplete) { bool expandedHoriz, expandedVert; expandBackgroundHoriz(pi, inpamP->width, inpamP->height, &expandedHoriz); - + expandBackgroundVert(pi, inpamP->width, inpamP->height, &expandedVert); backgroundComplete = !expandedHoriz && !expandedVert; - ++passes; + ++passCt; } if (verbose) - pm_message("Background found in %u passes", passes); + pm_message("Background found in %u passes", passCt); *piP = (const unsigned char * const *)pi; } - + static void writeOutput(const struct pam * const inpamP, @@ -468,16 +469,16 @@ writeOutput(const struct pam * const inpamP, int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; struct pam inpam; FILE * ifP; pm_filepos rasterpos; tuple backgroundColor; const unsigned char * const * pi; - - pnm_init(&argc, argv); + + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -500,6 +501,9 @@ main(int argc, char *argv[]) { pm_close(ifP); pnm_freepamtuple(backgroundColor); - + return 0; } + + + diff --git a/editor/pamenlarge.c b/editor/pamenlarge.c index 56a8c6f7..eb3b6ba2 100644 --- a/editor/pamenlarge.c +++ b/editor/pamenlarge.c @@ -690,6 +690,7 @@ enlargePbm(struct pam * const inpamP, unsigned int const rightPadding = scaleMethod == METHOD_GENERAL ? 0 : (xScaleFactor - 1) * 8; + assert (outcols < UINT_MAX - rightPadding); outrow = pbm_allocrow_packed(outcols + rightPadding); if (scaleMethod == METHOD_GENERAL) diff --git a/editor/pamrubber.c b/editor/pamrubber.c index 802d8c20..f68e36fe 100644 --- a/editor/pamrubber.c +++ b/editor/pamrubber.c @@ -193,38 +193,39 @@ makeline(point const p1, -static bool -intersect(line * const l1P, - line * const l2P, - point * const pP) { +static void +findIntersection(const line * const l1P, + const line * const l2P, + bool * const theyIntersectP, + point * const intersectionP) { - bool cross; + bool theyIntersect; if (((l2P->p2.y - l2P->p1.y) * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x) * (l1P->p2.y - l1P->p1.y)) == 0) { /* parallel lines */ - cross = false; + theyIntersect = false; if ((l1P->p1.x == l1P->p2.x) && (l2P->p1.x == l2P->p2.x)) { /* two vertical lines */ - pP->x = (l1P->p1.x + l2P->p1.x) / 2.0; - pP->y = 1e10; + intersectionP->x = (l1P->p1.x + l2P->p1.x) / 2.0; + intersectionP->y = 1e10; } else if ((l1P->p1.y == l1P->p2.y) && (l2P->p1.y == l2P->p2.y)) { /* two horizontal lines */ - pP->x = 1e10; - pP->y = (l1P->p1.y + l2P->p1.y) / 2.0; + intersectionP->x = 1e10; + intersectionP->y = (l1P->p1.y + l2P->p1.y) / 2.0; } else { if (fabs(l1P->p2.y - l1P->p1.y) > fabs(l1P->p2.x - l1P->p1.x)) { /* steep slope */ - pP->y = 1e10; - pP->x = (l1P->p2.x - l1P->p1.x) / (l1P->p2.y - l1P->p1.y) - * 1e10; + intersectionP->y = 1e10; + intersectionP->x = + (l1P->p2.x - l1P->p1.x) / (l1P->p2.y - l1P->p1.y) * 1e10; } else { /* even slope */ - pP->x = 1e10; - pP->y = (l1P->p2.y - l1P->p1.y) / (l1P->p2.x - l1P->p1.x) - * 1e10; + intersectionP->x = 1e10; + intersectionP->y = + (l1P->p2.y - l1P->p1.y) / (l1P->p2.x - l1P->p1.x) * 1e10; } } } else { @@ -242,16 +243,16 @@ intersect(line * const l1P, * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x) * (l1P->p2.y - l1P->p1.y)); - pP->x = l1P->p1.x + ua * (l1P->p2.x - l1P->p1.x); - pP->y = l1P->p1.y + ua * (l1P->p2.y - l1P->p1.y); + intersectionP->x = l1P->p1.x + ua * (l1P->p2.x - l1P->p1.x); + intersectionP->y = l1P->p1.y + ua * (l1P->p2.y - l1P->p1.y); if ((ua >= 0.0) && (ua <= 1.0) && (ub >= 0.0) && (ub <= 1.0)) - cross = true; + theyIntersect = true; else - cross = false; + theyIntersect = false; } - - return cross; + if (theyIntersectP) + *theyIntersectP = theyIntersect; } @@ -307,28 +308,29 @@ insidetri(triangle * const triP, static bool -windtriangle(triangle * const tP, +windtriangle(triangle * const triP, point const p1, point const p2, point const p3) { point f, c; - line le, lv; bool cw; /* find cross of vertical through p3 and the edge p1-p2 */ f.x = p3.x; f.y = -1.0; - lv = makeline(p3, f); - le = makeline(p1, p2); - intersect(&le, &lv, &c); + { + line const lv = makeline(p3, f); + line const le = makeline(p1, p2); + findIntersection(&le, &lv, NULL, &c); + } /* check for clockwise winding triangle */ if (((p1.x > p2.x) && (p3.y < c.y)) || ((p1.x < p2.x) && (p3.y > c.y))) { - *tP = maketriangle(p1, p2, p3); + *triP = maketriangle(p1, p2, p3); cw = true; } else { /* p1/2/3 were counter clockwise */ - *tP = maketriangle(p1, p3, p2); + *triP = maketriangle(p1, p3, p2); cw = false; } return cw; @@ -612,12 +614,16 @@ quadCorner(point const p0, /* p0-p1 and p2-p3 are the diagonals */ + triangle tri; + if (fabs(p0.x - p1.x) + fabs(p0.y - p1.y) >= fabs(p2.x - p3.x) + fabs(p2.y - p3.y)) { - quadCornerSized(p0, p1, p2, p3, mid, quadP, triP); + quadCornerSized(p0, p1, p2, p3, mid, quadP, &tri); } else { - quadCornerSized(p2, p3, p0, p1, mid, quadP, triP); + quadCornerSized(p2, p3, p0, p1, mid, quadP, &tri); } + if (triP) + *triP = tri; } @@ -730,7 +736,6 @@ prepTrig(int const wd, point rtl2, rtr2, rbl2, rbr2; point c1p1, c1p2, c1p3, c1p4; point c2p1, c2p2, c2p3, c2p4; - line l1, l2; point p0; struct pm_randSt randSt; @@ -897,47 +902,58 @@ prepTrig(int const wd, /* 3 4 2 4 4 3 2 3 4 2 3 2 */ /*-------------------------------------------------------------------*/ - /* center two triangles */ - l1 = makeline(c1p1, c1p4); - l2 = makeline(c1p2, c1p3); - if (intersect(&l1, &l2, &p0)) { - if (windtriangle(&tri1s[0], c1p1, c1p2, c1p3)) { - tri1s[1] = maketriangle(c1p4, c1p3, c1p2); - tri2s[0] = maketriangle(c2p1, c2p2, c2p3); - tri2s[1] = maketriangle(c2p4, c2p3, c2p2); - } else { - tri1s[1] = maketriangle(c1p4, c1p2, c1p3); - tri2s[0] = maketriangle(c2p1, c2p3, c2p2); - tri2s[1] = maketriangle(c2p4, c2p2, c2p3); + { + /* center two triangles */ + line const l1 = makeline(c1p1, c1p4); + line const l2 = makeline(c1p2, c1p3); + bool theyIntersect; + findIntersection(&l1, &l2, &theyIntersect, &p0); + if (theyIntersect) { + if (windtriangle(&tri1s[0], c1p1, c1p2, c1p3)) { + tri1s[1] = maketriangle(c1p4, c1p3, c1p2); + tri2s[0] = maketriangle(c2p1, c2p2, c2p3); + tri2s[1] = maketriangle(c2p4, c2p3, c2p2); + } else { + tri1s[1] = maketriangle(c1p4, c1p2, c1p3); + tri2s[0] = maketriangle(c2p1, c2p3, c2p2); + tri2s[1] = maketriangle(c2p4, c2p2, c2p3); + } } } - l1 = makeline(c1p1, c1p3); - l2 = makeline(c1p2, c1p4); - if (intersect(&l1, &l2, &p0)) { - if (windtriangle(&tri1s[0], c1p1, c1p2, c1p4)) { - tri1s[1] = maketriangle(c1p3, c1p4, c1p2); - tri2s[0] = maketriangle(c2p1, c2p2, c2p4); - tri2s[1] = maketriangle(c2p3, c2p4, c2p2); - } else { - tri1s[1] = maketriangle(c1p3, c1p2, c1p4); - tri2s[0] = maketriangle(c2p1, c2p4, c2p2); - tri2s[1] = maketriangle(c2p3, c2p2, c2p4); + { + line const l1 = makeline(c1p1, c1p3); + line const l2 = makeline(c1p2, c1p4); + bool theyIntersect; + findIntersection(&l1, &l2, &theyIntersect, &p0); + if (theyIntersect) { + if (windtriangle(&tri1s[0], c1p1, c1p2, c1p4)) { + tri1s[1] = maketriangle(c1p3, c1p4, c1p2); + tri2s[0] = maketriangle(c2p1, c2p2, c2p4); + tri2s[1] = maketriangle(c2p3, c2p4, c2p2); + } else { + tri1s[1] = maketriangle(c1p3, c1p2, c1p4); + tri2s[0] = maketriangle(c2p1, c2p4, c2p2); + tri2s[1] = maketriangle(c2p3, c2p2, c2p4); + } } } - l1 = makeline(c1p1, c1p2); - l2 = makeline(c1p3, c1p4); - if (intersect(&l1, &l2, &p0)) { - if (windtriangle(&tri1s[0], c1p1, c1p3, c1p4)) { - tri1s[1] = maketriangle(c1p2, c1p4, c1p3); - tri2s[0] = maketriangle(c2p1, c2p3, c2p4); - tri2s[1] = maketriangle(c2p2, c2p4, c2p3); - } else { - tri1s[1] = maketriangle(c1p2, c1p3, c1p4); - tri2s[0] = maketriangle(c2p1, c2p4, c2p3); - tri2s[1] = maketriangle(c2p2, c2p3, c2p4); + { + line const l1 = makeline(c1p1, c1p2); + line const l2 = makeline(c1p3, c1p4); + bool theyIntersect; + findIntersection(&l1, &l2, &theyIntersect, &p0); + if (theyIntersect) { + if (windtriangle(&tri1s[0], c1p1, c1p3, c1p4)) { + tri1s[1] = maketriangle(c1p2, c1p4, c1p3); + tri2s[0] = maketriangle(c2p1, c2p3, c2p4); + tri2s[1] = maketriangle(c2p2, c2p4, c2p3); + } else { + tri1s[1] = maketriangle(c1p2, c1p3, c1p4); + tri2s[0] = maketriangle(c2p1, c2p4, c2p3); + tri2s[1] = maketriangle(c2p2, c2p3, c2p4); + } } } - /* control points in correct orientation */ c1p1 = tri1s[0].p1; c1p2 = tri1s[0].p2; @@ -995,11 +1011,6 @@ prepQuad(void) { /* order quad control points */ - double d01, d12, d20; - line l1, l2; - point mid; - triangle tri; - if (nCP == 1) { /* create a rectangle from top-left corner of image and control point @@ -1042,9 +1053,9 @@ prepQuad(void) { furthest apart */ - d01 = distance(newCP[0], newCP[1]); - d12 = distance(newCP[1], newCP[2]); - d20 = distance(newCP[2], newCP[0]); + double const d01 = distance(newCP[0], newCP[1]); + double const d12 = distance(newCP[1], newCP[2]); + double const d20 = distance(newCP[2], newCP[0]); if ((d01 > d12) && (d01 > d20)) { oldCP[3].x = oldCP[0].x + oldCP[1].x - oldCP[2].x; @@ -1074,51 +1085,72 @@ prepQuad(void) { /* nCP = 3 or 4 */ - /* find the intersection of the diagonals */ - l1 = makeline(oldCP[0], oldCP[1]); - l2 = makeline(oldCP[2], oldCP[3]); - if (intersect(&l1, &l2, &mid)) { - quadCorner(oldCP[0], oldCP[1], oldCP[2], oldCP[3], - mid, &quad1, &tri); - } else { - l1 = makeline(oldCP[0], oldCP[2]); - l2 = makeline(oldCP[1], oldCP[3]); - if (intersect(&l1, &l2, &mid)) - quadCorner(oldCP[0], oldCP[2], oldCP[1], oldCP[3], - mid, &quad1, &tri); + { + /* find the intersection of the diagonals */ + line const l1 = makeline(oldCP[0], oldCP[1]); + line const l2 = makeline(oldCP[2], oldCP[3]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(oldCP[0], oldCP[1], oldCP[2], oldCP[3], + mid, &quad1, NULL); else { - l1 = makeline(oldCP[0], oldCP[3]); - l2 = makeline(oldCP[1], oldCP[2]); - if (intersect(&l1, &l2, &mid)) - quadCorner(oldCP[0], oldCP[3], - oldCP[1], oldCP[2], mid, &quad1, &tri); - else - pm_error("The four old control points don't seem " - "to be corners."); + line const l1 = makeline(oldCP[0], oldCP[2]); + line const l2 = makeline(oldCP[1], oldCP[3]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(oldCP[0], oldCP[2], oldCP[1], oldCP[3], + mid, &quad1, NULL); + else { + line const l1 = makeline(oldCP[0], oldCP[3]); + line const l2 = makeline(oldCP[1], oldCP[2]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(oldCP[0], oldCP[3], + oldCP[1], oldCP[2], mid, &quad1, NULL); + else + pm_error("The four old control points don't seem " + "to be corners."); + } } } - - /* repeat for the "to-be" control points */ - l1 = makeline(newCP[0], newCP[1]); - l2 = makeline(newCP[2], newCP[3]); - if (intersect(&l1, &l2, &mid)) - quadCorner(newCP[0], newCP[1], newCP[2], newCP[3], - mid, &quad2, &tri); - else { - l1 = makeline(newCP[0], newCP[2]); - l2 = makeline(newCP[1], newCP[3]); - if (intersect(&l1, &l2, &mid)) - quadCorner(newCP[0], newCP[2], newCP[1], newCP[3], - mid, &quad2, &tri); + { + /* repeat for the "to-be" control points */ + line const l1 = makeline(newCP[0], newCP[1]); + line const l2 = makeline(newCP[2], newCP[3]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(newCP[0], newCP[1], newCP[2], newCP[3], + mid, &quad2, NULL); else { - l1 = makeline(newCP[0], newCP[3]); - l2 = makeline(newCP[1], newCP[2]); - if (intersect(&l1, &l2, &mid)) - quadCorner(newCP[0], newCP[3], - newCP[1], newCP[2], mid, &quad2, &tri); - else - pm_error("The four new control points don't seem " - "to be corners."); + line const l1 = makeline(newCP[0], newCP[2]); + line const l2 = makeline(newCP[1], newCP[3]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(newCP[0], newCP[2], newCP[1], newCP[3], + mid, &quad2, NULL); + else { + line const l1 = makeline(newCP[0], newCP[3]); + line const l2 = makeline(newCP[1], newCP[2]); + bool theyIntersect; + point mid; + findIntersection(&l1, &l2, &theyIntersect, &mid); + if (theyIntersect) + quadCorner(newCP[0], newCP[3], + newCP[1], newCP[2], mid, &quad2, NULL); + else + pm_error("The four new control points don't seem " + "to be corners."); + } } } } @@ -1134,14 +1166,11 @@ warpTrig(point const p2, point e1p1, e1p2, e1p3; point e2p1, e2p2, e2p3; - line lp, le; - line l1, l2, l3; - double d1, d2, d3; - int i; + unsigned int i; /* find in which triangle p2 lies */ - for (i = 0; i < nTri; i++) { - if (insidetri (&tri2s[i], p2)) + for (i = 0; i < nTri; ++i) { + if (insidetri(&tri2s[i], p2)) break; } @@ -1149,25 +1178,33 @@ warpTrig(point const p2, *p1P = makepoint(0.0, 0.0); else { /* where in triangle is point */ - d1 = fabs (p2.x - tri2s[i].p1.x) + fabs (p2.y - tri2s[i].p1.y); - d2 = fabs (p2.x - tri2s[i].p2.x) + fabs (p2.y - tri2s[i].p2.y); - d3 = fabs (p2.x - tri2s[i].p3.x) + fabs (p2.y - tri2s[i].p3.y); - - /* line through p1 and p intersecting with edge p2-p3 */ - lp = makeline(tri2s[i].p1, p2); - le = makeline(tri2s[i].p2, tri2s[i].p3); - intersect (&lp, &le, &e2p1); - - /* line through p2 and p intersecting with edge p3-p1 */ - lp = makeline(tri2s[i].p2, p2); - le = makeline(tri2s[i].p3, tri2s[i].p1); - intersect (&lp, &le, &e2p2); + double const d1 = + fabs (p2.x - tri2s[i].p1.x) + fabs (p2.y - tri2s[i].p1.y); + double const d2 = + fabs (p2.x - tri2s[i].p2.x) + fabs (p2.y - tri2s[i].p2.y); + double const d3 = + fabs (p2.x - tri2s[i].p3.x) + fabs (p2.y - tri2s[i].p3.y); + + { + /* line through p1 and p intersecting with edge p2-p3 */ + line const lp = makeline(tri2s[i].p1, p2); + line const le = makeline(tri2s[i].p2, tri2s[i].p3); + findIntersection(&lp, &le, NULL, &e2p1); + } - /* line through p3 and p intersecting with edge p1-p2 */ - lp = makeline(tri2s[i].p3, p2); - le = makeline(tri2s[i].p1, tri2s[i].p2); - intersect (&lp, &le, &e2p3); + { + /* line through p2 and p intersecting with edge p3-p1 */ + line const lp = makeline(tri2s[i].p2, p2); + line const le = makeline(tri2s[i].p3, tri2s[i].p1); + findIntersection(&lp, &le, NULL, &e2p2); + } + { + /* line through p3 and p intersecting with edge p1-p2 */ + line const lp = makeline(tri2s[i].p3, p2); + line const le = makeline(tri2s[i].p1, tri2s[i].p2); + findIntersection(&lp, &le, NULL, &e2p3); + } /* map target control points to source control points */ e1p1.x = tri1s[i].p2.x + (e2p1.x - tri2s[i].p2.x)/(tri2s[i].p3.x - tri2s[i].p2.x) @@ -1188,17 +1225,19 @@ warpTrig(point const p2, + (e2p3.y - tri2s[i].p1.y)/(tri2s[i].p2.y - tri2s[i].p1.y) * (tri1s[i].p2.y - tri1s[i].p1.y); - /* intersect grid lines in source */ - l1 = makeline(tri1s[i].p1, e1p1); - l2 = makeline(tri1s[i].p2, e1p2); - l3 = makeline(tri1s[i].p3, e1p3); - - if ((d1 < d2) && (d1 < d3)) - intersect (&l2, &l3, p1P); - else if (d2 < d3) - intersect (&l1, &l3, p1P); - else - intersect (&l1, &l2, p1P); + { + /* intersect grid lines in source */ + line const l1 = makeline(tri1s[i].p1, e1p1); + line const l2 = makeline(tri1s[i].p2, e1p2); + line const l3 = makeline(tri1s[i].p3, e1p3); + + if ((d1 < d2) && (d1 < d3)) + findIntersection(&l2, &l3, NULL, p1P); + else if (d2 < d3) + findIntersection(&l1, &l3, NULL, p1P); + else + findIntersection(&l1, &l2, NULL, p1P); + } } } @@ -1215,8 +1254,6 @@ warpQuad(point const p2, point c2tl, c2tr, c2bl, c2br; point e1t, e1b, e1l, e1r; point e2t, e2b, e2l, e2r; - line l2t, l2b, l2l, l2r; - line lh, lv; c1tl = quad1.tl; c1tr = quad1.tr; @@ -1228,24 +1265,27 @@ warpQuad(point const p2, c2bl = quad2.bl; c2br = quad2.br; - l2t = makeline(c2tl, c2tr); - l2b = makeline(c2bl, c2br); - l2l = makeline(c2tl, c2bl); - l2r = makeline(c2tr, c2br); - - /* find intersections of lines through control points */ - intersect (&l2t, &l2b, &h2); - intersect (&l2l, &l2r, &v2); - - /* find intersections of axes through P with control point box */ - lv = makeline(p2, v2); - intersect (&l2t, &lv, &e2t); - intersect (&l2b, &lv, &e2b); - - lh = makeline(p2, h2); - intersect (&l2l, &lh, &e2l); - intersect (&l2r, &lh, &e2r); - + { + line const l2t = makeline(c2tl, c2tr); + line const l2b = makeline(c2bl, c2br); + line const l2l = makeline(c2tl, c2bl); + line const l2r = makeline(c2tr, c2br); + + /* find intersections of lines through control points */ + findIntersection(&l2t, &l2b, NULL, &h2); + findIntersection(&l2l, &l2r, NULL, &v2); + + { + /* find intersections of axes through P with control point box */ + line const lv = makeline(p2, v2); + line const lh = makeline(p2, h2); + + findIntersection(&l2t, &lv, NULL, &e2t); + findIntersection(&l2b, &lv, NULL, &e2b); + findIntersection(&l2l, &lh, NULL, &e2l); + findIntersection(&l2r, &lh, NULL, &e2r); + } + } /* map target control points to source control points */ e1t.x = c1tl.x + (e2t.x - c2tl.x)/(c2tr.x - c2tl.x) * (c1tr.x - c1tl.x); if (c1tl.y == c1tr.y) @@ -1275,10 +1315,12 @@ warpQuad(point const p2, = c1tr.x + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.x - c1tr.x); e1r.y = c1tr.y + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.y - c1tr.y); - /* intersect grid lines in source */ - lv = makeline(e1t, e1b); - lh = makeline(e1l, e1r); - intersect (&lh, &lv, p1P); + { + /* intersect grid lines in source */ + line const lv = makeline(e1t, e1b); + line const lh = makeline(e1l, e1r); + findIntersection(&lh, &lv, NULL, p1P); + } } diff --git a/editor/pbmclean.c b/editor/pbmclean.c index 08f410c0..47c775e5 100644 --- a/editor/pbmclean.c +++ b/editor/pbmclean.c @@ -381,7 +381,7 @@ cleanSimple(FILE * const ifP, Do the traditional clean where you look only at the immediate neighboring pixels of a subject pixel to determine whether to erase that pixel. -----------------------------------------------------------------------------*/ - bit ** buffer; + bit ** buffer; /* one bit per pixel */ /* The rows of the input relevant to our current processing: the current row and the one above and below it. */ @@ -399,7 +399,7 @@ cleanSimple(FILE * const ifP, setupInputBuffers(ifP, cols, format, &buffer, &edgeRow, &thisRow, &nextRow); - outRow = pbm_allocrow(cols); + outRow = pbm_allocrow_packed(cols); pbm_writepbminit(ofP, cols, rows, 0) ; @@ -756,12 +756,12 @@ cleanExtended(FILE * const ifP, We erase (flip) every pixel in every trivial blob. A trivial blob is one with 'trivialSize' pixels or fewer. -----------------------------------------------------------------------------*/ - bit ** pixels; + bit ** pixels; /* one byte per pixel */ int cols, rows; pixels = pbm_readpbm(ifP, &cols, &rows); - cleanPixels(pixels, cols, rows, foregroundColor, trivialSize, nFlippedP); + cleanPixels(pixels, cols, rows, foregroundColor, trivialSize, nFlippedP); pbm_writepbm(ofP, pixels, cols, rows, 0); diff --git a/editor/pbmpscale.c b/editor/pbmpscale.c index 3b6935b2..434c7965 100644 --- a/editor/pbmpscale.c +++ b/editor/pbmpscale.c @@ -12,7 +12,7 @@ #define LEFTBITS pm_byteLeftBits #define RIGHTBITS pm_byteRightBits -/* Table for translating bit pattern into "corners" flag element */ +/* Table for translating bit pattern into "corners" flag element */ unsigned char const transTable[512] = { @@ -191,8 +191,8 @@ setFlags(const bit * const prevrow, unsigned char * const flags, unsigned int const cols ) { /*---------------------------------------------------------------------------- - Scan one row, examining the row above and row below, and determine - whether there are "corners" for each pixel. Feed a 9 bit sample into + Scan one row, examining the row above and row below, and determine + whether there are "corners" for each pixel. Feed a 9 bit sample into pre-calculated array transTable[512] to calculate all four corner statuses at once. @@ -220,7 +220,7 @@ setFlags(const bit * const prevrow, The high byte of the patterns is a mask, which determines which bits are not ignored. */ - uint16_t const patterns[] + uint16_t const patterns[] = { 0x0000, 0xd555, /* no corner */ 0x0001, 0xffc1, 0xd514, /* normal corner */ 0x0002, 0xd554, 0xd515, 0xbea2, 0xdfc0, 0xfd81, 0xfd80, 0xdf80, @@ -230,7 +230,7 @@ setFlags(const bit * const prevrow, /* For example, the NE corner is examined with the following 8 bit sample: Current : W : NW : N : NE : E : SE : S - (SW is the "square behind") + (SW is the "square behind") */ #endif @@ -257,7 +257,7 @@ setFlags(const bit * const prevrow, sample = ( ( prevrow24 >> ( 8 -offset) ) & 0x01c0 ) | ( ( thisrow24 >> (11 -offset) ) & 0x0038 ) | ( ( nextrow24 >> (14 -offset) ) & 0x0007 ); - + flags[col] = transTable[sample]; } } @@ -275,14 +275,14 @@ expandRow(const bit * const thisrow, int const ucutoff) { /*---------------------------------------------------------------------------- Process one row, using flags array as reference. If pixel has no corners - output a NxN square of the given color, otherwise output with the + output a NxN square of the given color, otherwise output with the specified corner area(s) clipped off. -----------------------------------------------------------------------------*/ unsigned int const outcols = cols * scale; unsigned int i; unsigned int col; - + for (i = 0; i < scale; ++i) { int const zone = (i > ucutoff) - (i < cutoff); int const cut1 = @@ -297,7 +297,7 @@ expandRow(const bit * const thisrow, cut[1] = cut1; cut[2] = cut1 ? cut1 - 1 : 0; cut[3] = (cut1 && cutoff > 1) ? cut1 - 1 : cut1; - + for (col = 0; col < cols; ++col) { unsigned int const col8 = col / 8; unsigned int const offset = col % 8; @@ -309,11 +309,11 @@ expandRow(const bit * const thisrow, if (flag == 0x00) { /* There are no corners, no color change */ outcol += scale; - } else { + } else { switch (zone) { case -1: if (i==0 && flag == 0xff) { - /* No corners, color changed */ + /* No corners, color changed */ cutl = cutr = 0; flags[col] = 0x00; /* Use above skip procedure next cycle */ @@ -330,7 +330,7 @@ expandRow(const bit * const thisrow, cutr = cut[SE(flag)]; break; } - + if (cutl > 0) { writeBitSpan(outrow, cutl, outcol, !pix); outcol += cutl; @@ -384,10 +384,10 @@ main(int argc, const char ** argv) { pbm_readpbminit(ifP, &cols, &rows, &format) ; - validateComputableDimensions(cols, rows, cmdline.scale); + validateComputableDimensions(cols, rows, cmdline.scale); outcols = cols * cmdline.scale; - outrows = rows * cmdline.scale; + outrows = rows * cmdline.scale; /* Initialize input buffers. We add a margin of 8 bits on the right of the three rows. @@ -402,7 +402,7 @@ main(int argc, const char ** argv) { for (i = 0; i < pbm_packed_bytes(cols + 8); ++i) edgerow[i] = 0x00; - /* Add blank bytes at right edges */ + /* Add blank bytes at right edges */ for (i = 0; i < 3; ++i) buffer[i][pbm_packed_bytes(cols + 8) - 1] = 0x00; diff --git a/editor/pnmcat.c b/editor/pnmcat.c index 9097dc99..fea80181 100644 --- a/editor/pnmcat.c +++ b/editor/pnmcat.c @@ -115,7 +115,7 @@ parseCommandLine(int argc, const char ** const argv, cmdlineP->backcolor = BACK_AUTO; if (jtop + jbottom + jleft + jright + jcenter > 1) - pm_error("You may specify onlyone of -jtop, -jbottom, " + pm_error("You may specify only one of -jtop, -jbottom, " "-jleft, and -jright"); else { switch (cmdlineP->orientation) { @@ -703,6 +703,9 @@ concatenateLeftRightGen(FILE * const ofP, */ } } + /* Note that img2[N].inrow{] is an alias to part of outrow[], so + outrow[] has been set. + */ pnm_writepnmrow(ofP, outrow, newcols, newmaxval, newformat, 0); } pnm_freerow(outrow); diff --git a/editor/pnmpad.c b/editor/pnmpad.c index 5cef21af..9fa9f9e6 100644 --- a/editor/pnmpad.c +++ b/editor/pnmpad.c @@ -129,16 +129,16 @@ parseCommandLine(int argc, const char ** argv, pm_error("You can specify -height only once"); if (xalignSpec && (cmdlineP->leftSpec || cmdlineP->rightSpec)) - pm_error("You cannot specify both -xalign and -left or -right"); + pm_error("You cannot specify both -halign and -left or -right"); if (yalignSpec && (cmdlineP->topSpec || cmdlineP->bottomSpec)) - pm_error("You cannot specify both -yalign and -top or -bottom"); + pm_error("You cannot specify both -valign and -top or -bottom"); - if (xalignSpec && !cmdlineP->xsizeSpec) - pm_error("-xalign is meaningless without -width"); + if (xalignSpec && (!cmdlineP->xsizeSpec && !mwidthSpec) ) + pm_error("-halign is meaningless without -width or -mwidth"); - if (yalignSpec && !cmdlineP->ysizeSpec) - pm_error("-yalign is meaningless without -height"); + if (yalignSpec && (!cmdlineP->ysizeSpec && !mheightSpec) ) + pm_error("-valign is meaningless without -height or -mheight"); if (xalignSpec) { if (cmdlineP->xalign < 0) @@ -268,7 +268,7 @@ validateHorizontalSize(struct cmdlineInfo const cmdline, pm_error("The right padding value you specified is too large."); if ((double) cols + - (double) lpad + + (double) lpad + (double) rpad + (double) mwidthMaxPad > MAX_WIDTHHEIGHT) pm_error("Given padding parameters make output width too large " @@ -378,9 +378,9 @@ computePadSizesOneDim(unsigned int const unpaddedSize, unsigned int const totalPadBeforeMult = begPadBeforeMult + endPadBeforeMult; double const begFrac = - totalPadBeforeMult > 0 ? + totalPadBeforeMult > 0 ? (double)begPadBeforeMult / totalPadBeforeMult : - 0.0; + align; unsigned int const addlMsizeBegPad = ROUNDU(morePadNeeded * begFrac); /* # of pixels we have to add to the beginning to satisfy user's desire for the final size to be a multiple of something @@ -501,7 +501,7 @@ reportPadSizes(int const inCols, unsigned int const outCols = inCols + lpad + rpad; unsigned int const outRows = inRows + tpad + bpad; - + printf("%u %u %u %u %u %u\n", lpad, rpad, tpad, bpad, outCols, outRows); } @@ -547,7 +547,7 @@ padPbm(FILE * const ifP, /* Write top margin */ for (row = 0; row < tpad; ++row) pbm_writepbmrow_packed(stdout, bgrow, newcols, 0); - + /* Read rows, shift and write with left and right margins added */ for (row = 0; row < rows; ++row) { pbm_readpbmrow_bitoffset(ifP, newrow, cols, format, lpad); diff --git a/editor/specialty/pampaintspill.c b/editor/specialty/pampaintspill.c index 5cd482d5..7490fcef 100644 --- a/editor/specialty/pampaintspill.c +++ b/editor/specialty/pampaintspill.c @@ -6,7 +6,7 @@ * * ---------------------------------------------------------------------- * - * Copyright (C) 2010 Scott Pakin <scott+pbm@pakin.org> + * Copyright (C) 2010-2021 Scott Pakin <scott+pbm@pakin.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,6 +69,8 @@ struct cmdlineInfo { unsigned int downsample; unsigned int randomseedSpec; unsigned int randomseed; + unsigned int nearSpec; + unsigned int near; }; struct coords { @@ -112,6 +114,8 @@ parseCommandLine(int argc, const char ** const argv, &downsampleSpec, 0); OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomseed, &cmdlineP->randomseedSpec, 0); + OPTENT3(0, "near", OPT_UINT, &cmdlineP->near, + &cmdlineP->nearSpec, 0); opt.opt_table = option_def; opt.short_allowed = 0; @@ -128,6 +132,11 @@ parseCommandLine(int argc, const char ** const argv, if (!downsampleSpec) cmdlineP->downsample = 0; + if (cmdlineP->nearSpec) { + if (cmdlineP->near == 0) + pm_error("The -near option requires a positive argument"); + } + if (argc-1 < 1) cmdlineP->inputFilename = "-"; else { @@ -365,6 +374,70 @@ reportProgress(unsigned int const rowsComplete, +struct distanceList { + struct coords * sources; /* malloc'ed */ + /* The list of places in the image from which paint comes */ + double * distSqrs; /* malloc'ed */ + /* The list of squared distances from the current point */ + unsigned int size; + /* Number of entries in sources[] */ +}; + + + +static void +computeDistances(struct pam * const pamP, + struct coords const target, + struct paintSourceSet const paintSources, + distFunc_t * const distFunc, + bool const nearOnly, + unsigned int const numNear, + struct distanceList * const distancesP) { + + unsigned int ps; + + /* Acquire a list of all distances. */ + distancesP->size = 0; + for (ps = 0; ps < paintSources.size; ++ps) { + struct coords const source = paintSources.list[ps]; + double const distSqr = + (*distFunc)(&target, &source, + pamP->width, pamP->height); + distancesP->sources[distancesP->size] = source; + distancesP->distSqrs[distancesP->size] = distSqr; + ++distancesP->size; + } + + /* If requested, truncate the list to the smallest numNear distances. */ + if (nearOnly && numNear < distancesP->size) { + unsigned int i; + + /* Perform a partial sort -- just enough to identify the numNear + smallest distances. For performance reasons we assume that + numNear is much less than paintSources.size (say, less than + log2(paintSources.size)). + */ + for (i = 0; i < numNear; ++i) { + unsigned int j; + for (j = i + 1; j < distancesP->size; ++j) { + if (distancesP->distSqrs[i] > distancesP->distSqrs[j]) { + /* Swap elements i and j. */ + struct coords const src = distancesP->sources[i];; + double const dist2 = distancesP->distSqrs[i]; + + distancesP->sources[i] = distancesP->sources[j]; + distancesP->distSqrs[i] = distancesP->distSqrs[j]; + distancesP->sources[j] = src; + distancesP->distSqrs[j] = dist2; + } + } + } + distancesP->size = numNear; + } +} + + + static void spillOnePixel(struct pam * const pamP, struct coords const target, @@ -372,37 +445,38 @@ spillOnePixel(struct pam * const pamP, distFunc_t * const distFunc, double const distPower, tuple const outTuple, - double * const newColor) { + double * const newColor, + bool const nearOnly, + unsigned int const numNear, + struct distanceList * const distancesP) { unsigned int plane; - unsigned int ps; + unsigned int d; double totalWeight; for (plane = 0; plane < pamP->depth; ++plane) newColor[plane] = 0.0; + computeDistances(pamP, target, paintSources, distFunc, + nearOnly, numNear, distancesP); totalWeight = 0.0; - for (ps = 0; ps < paintSources.size; ++ps) { - struct coords const source = paintSources.list[ps]; - double const distSqr = - (*distFunc)(&target, &source, - pamP->width, pamP->height); + for (d = 0; d < distancesP->size; ++d) { + double const distSqr = distancesP->distSqrs[d]; + struct coords const source = distancesP->sources[d]; - if (distSqr > 0.0) { - /* We do special cases for some common cases with code - that is much faster than pow(). - */ - double const weight = - distPower == -2.0 ? 1.0 / distSqr : - distPower == -1.0 ? 1.0 / sqrt(distSqr): - pow(distSqr, distPower/2); + /* We do special cases for some common cases with code + that is much faster than pow(). + */ + double const weight = + distPower == -2.0 ? 1.0 / distSqr : + distPower == -1.0 ? 1.0 / sqrt(distSqr): + pow(distSqr, distPower/2); - unsigned int plane; + unsigned int plane; - for (plane = 0; plane < pamP->depth; ++plane) - newColor[plane] += weight * source.color[plane]; + for (plane = 0; plane < pamP->depth; ++plane) + newColor[plane] += weight * source.color[plane]; - totalWeight += weight; - } + totalWeight += weight; } for (plane = 0; plane < pamP->depth; ++plane) outTuple[plane] = (sample) (newColor[plane] / totalWeight); @@ -418,6 +492,8 @@ produceOutputImage(struct pam * const pamP, distFunc_t * const distFunc, double const distPower, bool const all, + bool const nearOnly, + unsigned int const numNear, tuple *** const outtuplesP) { /*-------------------------------------------------------------------- Color each background pixel (or, if allPixels is 1, all pixels) @@ -433,10 +509,14 @@ produceOutputImage(struct pam * const pamP, rowsComplete = 0; #pragma omp parallel for for (row = 0; row < pamP->height; ++row) { - struct coords target; - double * newColor; + struct coords target; + double * newColor; /* malloc'ed */ + struct distanceList * distancesP; /* malloc'ed */ MALLOCARRAY(newColor, pamP->depth); + MALLOCVAR_NOFAIL(distancesP); + MALLOCARRAY_NOFAIL(distancesP->sources, paintSources.size); + MALLOCARRAY_NOFAIL(distancesP->distSqrs, paintSources.size); target.y = row; for (target.x = 0; target.x < pamP->width; ++target.x) { @@ -445,13 +525,17 @@ produceOutputImage(struct pam * const pamP, if (all || tupleEqualColor(pamP, targetTuple, bgColor)) spillOnePixel(pamP, target, paintSources, distFunc, distPower, - outputTuple, newColor); + outputTuple, newColor, nearOnly, numNear, + distancesP); else pnm_assigntuple(pamP, outputTuple, targetTuple); } #pragma omp critical (rowTally) reportProgress(++rowsComplete, pamP->height); + free(distancesP->distSqrs); + free(distancesP->sources); + free(distancesP); free(newColor); } *outtuplesP = outtuples; @@ -497,7 +581,8 @@ main(int argc, const char *argv[]) { cmdline.randomseedSpec, cmdline.randomseed); produceOutputImage(&inPam, inTuples, bgColor, paintSources, distFunc, - cmdline.power, cmdline.all, &outTuples); + cmdline.power, cmdline.all, + cmdline.nearSpec, cmdline.near, &outTuples); outPam = inPam; outPam.file = stdout; @@ -510,3 +595,4 @@ main(int argc, const char *argv[]) { } + |