From 151b2a752e6c09e1a43c5cd855694332b9e154af Mon Sep 17 00:00:00 2001 From: giraffedata Date: Thu, 3 Mar 2011 03:16:21 +0000 Subject: cleanup git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1415 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pamrubber.c | 823 +++++++++++++++++++++++++++++------------------------ 1 file changed, 446 insertions(+), 377 deletions(-) diff --git a/editor/pamrubber.c b/editor/pamrubber.c index 83d75613..02ada801 100644 --- a/editor/pamrubber.c +++ b/editor/pamrubber.c @@ -29,21 +29,8 @@ #include "pam.h" #include "pamdraw.h" -/*----------------------------------------------------------------------------*/ - - -struct cmdlineInfo { - const char * filename; - unsigned int quad; - unsigned int tri; - unsigned int frame; - unsigned int linear; - unsigned int verbose; -}; -/*----------------------------------------------------------------------------*/ - typedef struct point { double x; double y; @@ -61,11 +48,101 @@ typedef struct triangle { } triangle; +struct cmdlineInfo { + unsigned int nCP; + point oldCP[4]; + point newCP[4]; + const char * filename; + unsigned int quad; + unsigned int tri; + unsigned int frame; + unsigned int linear; + unsigned int verbose; + unsigned int randseedSpec; + unsigned int randseed; +}; + + +static void +parseCmdline(int argc, const char ** argv, + struct cmdlineInfo * const cmdlineP) { + +/* parse all parameters from the command line */ + + unsigned int option_def_index; + char * endptr; + unsigned int i; + unsigned int nCP; + + /* instructions to optParseOptions3 on how to parse our options. */ + optEntry * option_def; + optStruct3 opt; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENT3 */ + OPTENT3(0, "quad", OPT_FLAG, NULL, &cmdlineP->quad, 0); + OPTENT3(0, "tri", OPT_FLAG, NULL, &cmdlineP->tri, 0); + OPTENT3(0, "frame", OPT_FLAG, NULL, &cmdlineP->frame, 0); + OPTENT3(0, "linear", OPT_FLAG, NULL, &cmdlineP->linear, 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); + OPTENT3(0, "randseed", OPT_UINT, &cmdlineP->randseed, + &cmdlineP->randseedSpec, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* we have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* we have no parms that are negative numbers */ + + /* uses and sets argc, argv, and some of *cmdlineP and others. */ + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + + if (!cmdlineP->tri && !cmdlineP->quad) + pm_error("You must specify either -tri or -quad"); + + if (cmdlineP->tri && cmdlineP->quad) + pm_error("You may not specify both -tri and -quad"); + + /* Parameters are the control points (in qty of 4) and possibly a filename + */ + nCP = (argc-1) / 4; + + if (nCP > 4) + pm_error("Too many arguments: %u. Arguments are " + "control point coordinates and an optional file name, " + "with a maximum of 4 control points", argc-1); + + cmdlineP->nCP = nCP; + + assert(nCP <= ARRAY_SIZE(cmdlineP->oldCP)); + assert(nCP <= ARRAY_SIZE(cmdlineP->newCP)); + + for (i = 0; i < nCP; ++i) { + cmdlineP->oldCP[i].x = strtol(argv[i * 2 + 1], &endptr, 10); + cmdlineP->oldCP[i].y = strtol(argv[i * 2 + 2], &endptr, 10); + cmdlineP->newCP[i].x = strtol(argv[4 * nCP / 2 + i * 2 + 1], + &endptr, 10); + cmdlineP->newCP[i].y = strtol(argv[4 * nCP / 2 + i * 2 + 2], + &endptr, 10); + } + + if (argc - 1 == 4 * nCP) + cmdlineP->filename = "-"; + else if (argc - 2 == 4 * nCP) + cmdlineP->filename = argv[nCP * 4 + 1]; + else + pm_error("Invalid number of arguments. Arguments are " + "control point coordinates and an optional file name, " + "so there must be a multiple of 4 or a multiple of 4 " + "plus 1."); +} + + + /* global variables */ static int nCP; -static point oldCP[4] = {{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0}}; -static point newCP[4] = {{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0},{-1.0,-1.0}}; +static point oldCP[4]; +static point newCP[4]; static int nTri; static triangle tri1s[10]; static triangle tri2s[10]; @@ -75,13 +152,16 @@ static tuple black; /*----------------------------------------------------------------------------*/ -static void -makepoint(point * const p1P, - double const x, - double const y) { +static point +makepoint(double const x, + double const y) { + + point retval; + + retval.x = x; + retval.y = y; - p1P->x = x; - p1P->y = y; + return retval; } @@ -100,38 +180,38 @@ static double distance(point * const p1P, point * const p2P) { - return sqrt((p1P->x - p2P->x) * (p1P->x - p2P->x) + - (p1P->y - p2P->y) * (p1P->y - p2P->y)); + return sqrt(SQR(p1P->x - p2P->x) + SQR(p1P->y - p2P->y)); } -static void -makeline(line * const lP, - point * const p1P, - point * const p2P) { +static line +makeline(point const p1, + point const p2) { + + line retval; - lP->p1.x = p1P->x; - lP->p1.y = p1P->y; - lP->p2.x = p2P->x; - lP->p2.y = p2P->y; + retval.p1 = p1; + retval.p2 = p2; + + return retval; } -static int +static bool intersect(line * const l1P, line * const l2P, point * const pP) { - int cross; - double ua, ub; - - cross = 0; /* initial value */ + bool cross; 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; + 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; @@ -155,12 +235,14 @@ intersect(line * const l1P, } } else { /* intersecting lines */ - ua = ((l2P->p2.x - l2P->p1.x) * (l1P->p1.y - l2P->p1.y) + double const ua = + ((l2P->p2.x - l2P->p1.x) * (l1P->p1.y - l2P->p1.y) - (l2P->p2.y - l2P->p1.y) * (l1P->p1.x - l2P->p1.x)) / ((l2P->p2.y - l2P->p1.y) * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x) * (l1P->p2.y - l1P->p1.y)); - ub = ((l1P->p2.x - l1P->p1.x) * (l1P->p1.y - l2P->p1.y) + double const ub = + ((l1P->p2.x - l1P->p1.x) * (l1P->p1.y - l2P->p1.y) - (l1P->p2.y - l1P->p1.y) * (l1P->p1.x - l2P->p1.x)) / ((l2P->p2.y - l2P->p1.y) * (l1P->p2.x - l1P->p1.x) - (l2P->p2.x - l2P->p1.x) @@ -170,7 +252,9 @@ intersect(line * const l1P, pP->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 = 1; + cross = true; + else + cross = false; } return cross; @@ -228,30 +312,30 @@ insidetri(triangle * const triP, -static int +static bool windtriangle(triangle * const tP, point * const p1P, point * const p2P, point * const p3P) { point f, c; line le, lv; - int cw; + bool cw; /* find cross of vertical through p3 and the edge p1-p2 */ f.x = p3P->x; f.y = -1.0; - makeline (&lv, p3P, &f); - makeline (&le, p1P, p2P); - intersect (&le, &lv, &c); + lv = makeline(*p3P, f); + le = makeline(*p1P, *p2P); + intersect(&le, &lv, &c); /* check for clockwise winding triangle */ if (((p1P->x > p2P->x) && (p3P->y < c.y)) || ((p1P->x < p2P->x) && (p3P->y > c.y))) { maketriangle(tP, p1P, p2P, p3P); - cw = 1; + cw = true; } else { /* p1/2/3 were counter clockwise */ maketriangle (tP, p1P, p3P, p2P); - cw = 0; + cw = false; } return cw; @@ -284,16 +368,12 @@ angle(point * const p1P, -/*----------------------------------------------------------------------------*/ - - - #define TL 0 #define TR 1 #define BL 2 #define BR 3 -/*----------------------------------------------------------------------------*/ + #define SIDETRIANGLE(N,TRIG1,P11,P12,P13,P14,R11,R12,TRIG2,P21,P22,P23,P24,R21,R22) { \ if (fabs (R11.x - R12.x) < 1.0) { /* vertical edge */ \ @@ -359,13 +439,21 @@ angle(point * const p1P, } \ } -#define QUAD_RECT(QUAD,LFT,RGT,TOP,BOT) { \ - makepoint (&QUAD[0], LFT, TOP); \ - makepoint (&QUAD[1], RGT, TOP); \ - makepoint (&QUAD[2], LFT, BOT); \ - makepoint (&QUAD[3], RGT, BOT); \ +static void +quadRect(point * const quad, + double const lft, + double const rgt, + double const top, + double const bot) { + + quad[0] = makepoint(lft, top); + quad[1] = makepoint(rgt, top); + quad[2] = makepoint(lft, bot); + quad[3] = makepoint(rgt, bot); } + + #define QUAD_CORNER(QUAD,P0,P1,P2,P3,MID,TRI) { \ /* P0-P1 and P2-P3 are the diagonals */ \ if (fabs(P0.x - P1.x) + fabs(P0.y - P1.y) >= fabs(P2.x - P3.x) + fabs(P2.y - P3.y)) { \ @@ -529,65 +617,6 @@ static void drawClippedTriangle(const struct pam * const pamP, -/*----------------------------------------------------------------------------*/ - -static void -parseCmdline(int argc, const char ** argv, - struct cmdlineInfo * const pCmdline) { - -/* parse all parameters from the command line */ - - unsigned int option_def_index; - char * endptr; - int i; - - /* instructions to optParseOptions3 on how to parse our options. */ - optEntry * option_def; - optStruct3 opt; - - MALLOCARRAY_NOFAIL(option_def, 100); - - option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "quad", OPT_FLAG, NULL, &pCmdline->quad, 0); - OPTENT3(0, "tri", OPT_FLAG, NULL, &pCmdline->tri, 0); - OPTENT3(0, "frame", OPT_FLAG, NULL, &pCmdline->frame, 0); - OPTENT3(0, "linear", OPT_FLAG, NULL, &pCmdline->linear, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, &pCmdline->verbose, 0); - - opt.opt_table = option_def; - opt.short_allowed = FALSE; /* we have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* we have no parms that are negative numbers */ - - /* uses and sets argc, argv, and some of *pCmdline and others. */ - pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); - - /* check if one of -tri and -quad are given */ - if (pCmdline->tri == pCmdline->quad) { - pm_error ("Either '-tri' or '-quad' are required."); - } - - /* remaining are the control points (in qty of 4) and possibly a filename */ - nCP = (argc - 1) / 4; - for (i = 0; i < nCP; i++) { - oldCP[i].x = strtol(argv[i * 2 + 1], &endptr, 10); - oldCP[i].y = strtol(argv[i * 2 + 2], &endptr, 10); - newCP[i].x = strtol(argv[4 * nCP / 2 + i * 2 + 1], &endptr, 10); - newCP[i].y = strtol(argv[4 * nCP / 2 + i * 2 + 2], &endptr, 10); - } - - /* only parameter allowed is optional filespec */ - if (argc - 1 == 4 * nCP) { - pCmdline->filename = "-"; - } else - if (argc - 2 == 4 * nCP) { - pCmdline->filename = argv[nCP * 4 + 1]; - } else { - pm_error ("Incorrect number of coordinates."); - } -} - - - static void prepTrig(int const wd, int const ht) { @@ -601,19 +630,19 @@ prepTrig(int const wd, line l1, l2; point p0; - makepoint (&rtl1, 0.0 + tiny(), 0.0 + tiny()); - makepoint (&rtr1, (double) wd - 1.0 + tiny(), 0.0 + tiny()); - makepoint (&rbl1, 0.0 + tiny(), (double) ht - 1.0 + tiny()); - makepoint (&rbr1, (double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny()); + rtl1 = makepoint(0.0 + tiny(), 0.0 + tiny()); + rtr1 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny()); + rbl1 = makepoint(0.0 + tiny(), (double) ht - 1.0 + tiny()); + rbr1 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny()); - makepoint (&rtl2, 0.0 + tiny(), 0.0 + tiny()); - makepoint (&rtr2, (double) wd - 1.0 + tiny(), 0.0 + tiny()); - makepoint (&rbl2, 0.0 + tiny(), (double) ht - 1.0 + tiny()); - makepoint (&rbr2, (double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny()); + rtl2 = makepoint(0.0 + tiny(), 0.0 + tiny()); + rtr2 = makepoint((double) wd - 1.0 + tiny(), 0.0 + tiny()); + rbl2 = makepoint(0.0 + tiny(), (double) ht - 1.0 + tiny()); + rbr2 = makepoint((double) wd - 1.0 + tiny(), (double) ht - 1.0 + tiny()); if (nCP == 1) { - copypoint (&c1p1, &oldCP[0]); - copypoint (&c2p1, &newCP[0]); + c1p1 = oldCP[0]; + c2p1 = newCP[0]; /* connect control point to all corners to get 4 triangles */ SIDETRIANGLE(nCP,tri1s[0],c1p1,p0,p0,p0,rbl1,rtl1,tri2s[0],c2p1,p0,p0,p0,rbl2,rtl2); /* left side triangle */ @@ -625,10 +654,10 @@ prepTrig(int const wd, } else if (nCP == 2) { - copypoint (&c1p1, &oldCP[0]); - copypoint (&c1p2, &oldCP[1]); - copypoint (&c2p1, &newCP[0]); - copypoint (&c2p2, &newCP[1]); + c1p1 = oldCP[0]; + c1p2 = oldCP[1]; + c2p1 = newCP[0]; + c2p2 = newCP[1]; /* check for hor/ver edges */ angle (&c1p1, &c1p2); @@ -648,13 +677,13 @@ prepTrig(int const wd, } else if (nCP == 3) { - copypoint (&c1p1, &oldCP[0]); - copypoint (&c1p2, &oldCP[1]); - copypoint (&c1p3, &oldCP[2]); - - copypoint (&c2p1, &newCP[0]); - copypoint (&c2p2, &newCP[1]); - copypoint (&c2p3, &newCP[2]); + c1p1 = oldCP[0]; + c1p2 = oldCP[1]; + c1p3 = oldCP[2]; + + c2p1 = newCP[0]; + c2p2 = newCP[1]; + c2p3 = newCP[2]; /* check for hor/ver edges */ angle (&c1p1, &c1p2); @@ -671,13 +700,13 @@ prepTrig(int const wd, maketriangle (&tri2s[0], &c2p1, &c2p3, &c2p2); } - copypoint (&c1p1, &tri1s[0].p1); - copypoint (&c1p2, &tri1s[0].p2); - copypoint (&c1p3, &tri1s[0].p3); - - copypoint (&c2p1, &tri2s[0].p1); - copypoint (&c2p2, &tri2s[0].p2); - copypoint (&c2p3, &tri2s[0].p3); + c1p1 = tri1s[0].p1; + c1p2 = tri1s[0].p2; + c1p3 = tri1s[0].p3; + + c2p1 = tri2s[0].p1; + c2p2 = tri2s[0].p2; + c2p3 = tri2s[0].p3; /* point to side triangles */ SIDETRIANGLE(nCP,tri1s[1],c1p1,c1p2,c1p3,p0,rbl1,rtl1,tri2s[1],c2p1,c2p2,c2p3,p0,rbl2,rtl2); /* left side */ @@ -694,15 +723,15 @@ prepTrig(int const wd, } else if (nCP == 4) { - copypoint (&c1p1, &oldCP[0]); - copypoint (&c1p2, &oldCP[1]); - copypoint (&c1p3, &oldCP[2]); - copypoint (&c1p4, &oldCP[3]); - - copypoint (&c2p1, &newCP[0]); - copypoint (&c2p2, &newCP[1]); - copypoint (&c2p3, &newCP[2]); - copypoint (&c2p4, &newCP[3]); + c1p1 = oldCP[0]; + c1p2 = oldCP[1]; + c1p3 = oldCP[2]; + c1p4 = oldCP[3]; + + c2p1 = newCP[0]; + c2p2 = newCP[1]; + c2p3 = newCP[2]; + c2p4 = newCP[3]; /* check for hor/ver edges */ angle (&c1p1, &c1p2); @@ -727,8 +756,8 @@ prepTrig(int const wd, /*--------------------------------------------------------------------*/ /* center two triangles */ - makeline (&l1, &c1p1, &c1p4); - makeline (&l2, &c1p2, &c1p3); + l1 = makeline(c1p1, c1p4); + l2 = makeline(c1p2, c1p3); if (intersect(&l1, &l2, &p0)) { if (windtriangle (&tri1s[0], &c1p1, &c1p2, &c1p3)) { maketriangle (&tri1s[1], &c1p4, &c1p3, &c1p2); @@ -740,8 +769,8 @@ prepTrig(int const wd, maketriangle (&tri2s[1], &c2p4, &c2p2, &c2p3); } } - makeline (&l1, &c1p1, &c1p3); - makeline (&l2, &c1p2, &c1p4); + l1 = makeline(c1p1, c1p3); + l2 = makeline(c1p2, c1p4); if (intersect(&l1, &l2, &p0)) { if (windtriangle (&tri1s[0], &c1p1, &c1p2, &c1p4)) { maketriangle (&tri1s[1], &c1p3, &c1p4, &c1p2); @@ -753,8 +782,8 @@ prepTrig(int const wd, maketriangle (&tri2s[1], &c2p3, &c2p2, &c2p4); } } - makeline (&l1, &c1p1, &c1p2); - makeline (&l2, &c1p3, &c1p4); + l1 = makeline(c1p1, c1p2); + l2 = makeline(c1p3, c1p4); if (intersect(&l1, &l2, &p0)) { if (windtriangle (&tri1s[0], &c1p1, &c1p3, &c1p4)) { maketriangle (&tri1s[1], &c1p2, &c1p4, &c1p3); @@ -768,14 +797,14 @@ prepTrig(int const wd, } /* control points in correct orientation */ - copypoint (&c1p1, &tri1s[0].p1); - copypoint (&c1p2, &tri1s[0].p2); - copypoint (&c1p3, &tri1s[0].p3); - copypoint (&c1p4, &tri1s[1].p1); - copypoint (&c2p1, &tri2s[0].p1); - copypoint (&c2p2, &tri2s[0].p2); - copypoint (&c2p3, &tri2s[0].p3); - copypoint (&c2p4, &tri2s[1].p1); + c1p1 = tri1s[0].p1; + c1p2 = tri1s[0].p2; + c1p3 = tri1s[0].p3; + c1p4 = tri1s[1].p1; + c2p1 = tri2s[0].p1; + c2p2 = tri2s[0].p2; + c2p3 = tri2s[0].p3; + c2p4 = tri2s[1].p1; /* triangle from triangle point to side of image */ SIDETRIANGLE(nCP,tri1s[2],c1p1,c1p2,c1p3,c1p4,rbl1,rtl1,tri2s[2],c2p1,c2p2,c2p3,c2p4,rbl2,rtl2); /* left side triangle */ @@ -815,40 +844,35 @@ prepQuad(void) { triangle tri; if (nCP == 1) { - /* create a rectangle from top-left corner of image and control point */ - QUAD_RECT(quad1,0.0,oldCP[0].x,0.0,oldCP[0].y); - QUAD_RECT(quad2,0.0,newCP[0].x,0.0,newCP[0].y); - - } else - - if (nCP == 2) { - + quadRect(quad1, 0.0, oldCP[0].x, 0.0, oldCP[0].y); + quadRect(quad2, 0.0, newCP[0].x, 0.0, newCP[0].y); + } else if (nCP == 2) { /* create a rectangle with the two points as opposite corners */ if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* top-left and bottom-right */ - QUAD_RECT(quad1,oldCP[0].x,oldCP[1].x,oldCP[0].y,oldCP[1].y); + quadRect(quad1,oldCP[0].x,oldCP[1].x,oldCP[0].y,oldCP[1].y); } else if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* top-right and bottom-left */ - QUAD_RECT(quad1,oldCP[1].x,oldCP[0].x,oldCP[0].y,oldCP[1].y); + quadRect(quad1,oldCP[1].x,oldCP[0].x,oldCP[0].y,oldCP[1].y); } else if ((oldCP[0].x < oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* bottom-left and top-right */ - QUAD_RECT(quad1,oldCP[0].x,oldCP[1].x,oldCP[1].y,oldCP[0].y); + quadRect(quad1,oldCP[0].x,oldCP[1].x,oldCP[1].y,oldCP[0].y); } else if ((oldCP[0].x > oldCP[1].x) && (oldCP[0].y < oldCP[1].y)) { /* bottom-right and top-left */ - QUAD_RECT(quad1,oldCP[1].x,oldCP[0].x,oldCP[1].y,oldCP[0].y); + quadRect(quad1,oldCP[1].x,oldCP[0].x,oldCP[1].y,oldCP[0].y); } if ((newCP[0].x < newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* top-left and bottom-right */ - QUAD_RECT(quad2,newCP[0].x,newCP[1].x,newCP[0].y,newCP[1].y); + quadRect(quad2,newCP[0].x,newCP[1].x,newCP[0].y,newCP[1].y); } else if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* top-right and bottom-left */ - QUAD_RECT(quad2,newCP[1].x,newCP[0].x,newCP[0].y,newCP[1].y); + quadRect(quad2,newCP[1].x,newCP[0].x,newCP[0].y,newCP[1].y); } else if ((newCP[0].x < newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* bottom-left and top-right */ - QUAD_RECT(quad2,newCP[0].x,newCP[1].x,newCP[1].y,newCP[0].y); + quadRect(quad2,newCP[0].x,newCP[1].x,newCP[1].y,newCP[0].y); } else if ((newCP[0].x > newCP[1].x) && (newCP[0].y < newCP[1].y)) { /* bottom-right and top-left */ - QUAD_RECT(quad2,newCP[1].x,newCP[0].x,newCP[1].y,newCP[0].y); + quadRect(quad2,newCP[1].x,newCP[0].x,newCP[1].y,newCP[0].y); } } else { @@ -891,50 +915,47 @@ prepQuad(void) { /* nCP = 3 or 4 */ /* find the intersection of the diagonals */ - makeline (&l1, &oldCP[0], &oldCP[1]); - makeline (&l2, &oldCP[2], &oldCP[3]); + l1 = makeline(oldCP[0], oldCP[1]); + l2 = makeline(oldCP[2], oldCP[3]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad1,oldCP[0],oldCP[1],oldCP[2],oldCP[3],mid,tri); - } - else { - makeline (&l1, &oldCP[0], &oldCP[2]); - makeline (&l2, &oldCP[1], &oldCP[3]); + } else { + l1 = makeline(oldCP[0], oldCP[2]); + l2 = makeline(oldCP[1], oldCP[3]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad1,oldCP[0],oldCP[2],oldCP[1],oldCP[3],mid,tri); } else { - makeline (&l1, &oldCP[0], &oldCP[3]); - makeline (&l2, &oldCP[1], &oldCP[2]); + l1 = makeline(oldCP[0], oldCP[3]); + l2 = makeline(oldCP[1], oldCP[2]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad1,oldCP[0],oldCP[3],oldCP[1],oldCP[2],mid,tri); } - else { - pm_error ("pamrubber: The four old control points don't seem to be corners."); - } + else + pm_error("The four old control points don't seem to be corners."); } } /* repeat for the "to-be" control points */ - makeline (&l1, &newCP[0], &newCP[1]); - makeline (&l2, &newCP[2], &newCP[3]); + l1 = makeline(newCP[0], newCP[1]); + l2 = makeline(newCP[2], newCP[3]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad2,newCP[0],newCP[1],newCP[2],newCP[3],mid,tri); } else { - makeline (&l1, &newCP[0], &newCP[2]); - makeline (&l2, &newCP[1], &newCP[3]); + l1 = makeline(newCP[0], newCP[2]); + l2 = makeline(newCP[1], newCP[3]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad2,newCP[0],newCP[2],newCP[1],newCP[3],mid,tri); } else { - makeline (&l1, &newCP[0], &newCP[3]); - makeline (&l2, &newCP[1], &newCP[2]); + l1 = makeline(newCP[0], newCP[3]); + l2 = makeline(newCP[1], newCP[2]); if (intersect(&l1, &l2, &mid)) { QUAD_CORNER(quad2,newCP[0],newCP[3],newCP[1],newCP[2],mid,tri); } - else { - pm_error ("pamrubber: The four new control points don't seem to be corners."); - } + else + pm_error("The four new control points don't seem to be corners."); } } } @@ -943,78 +964,86 @@ prepQuad(void) { static void -warpTrig(point * const p2, - point * const p1) { +warpTrig(point * const p2P, + point * const p1P) { /* map target to source by triangulation */ - point e1p1, e1p2, e1p3; - point e2p1, e2p2, e2p3; - line lp, le; - line l1, l2, l3; - double d1, d2, d3; - int i; - - /* find in which triangle p2 lies */ - for (i = 0; i < nTri; i++) { - if (insidetri (&tri2s[i], p2)) - break; - } - - if (i == nTri) { - p1->x = 0.0; - p1->y = 0.0; - return; - } - - /* 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 */ - makeline (&lp, &tri2s[i].p1, p2); - makeline (&le, &tri2s[i].p2, &tri2s[i].p3); - intersect (&lp, &le, &e2p1); - - /* line through p2 and p intersecting with edge p3-p1 */ - makeline (&lp, &tri2s[i].p2, p2); - makeline (&le, &tri2s[i].p3, &tri2s[i].p1); - intersect (&lp, &le, &e2p2); - - /* line through p3 and p intersecting with edge p1-p2 */ - makeline (&lp, &tri2s[i].p3, p2); - makeline (&le, &tri2s[i].p1, &tri2s[i].p2); - intersect (&lp, &le, &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) * (tri1s[i].p3.x - tri1s[i].p2.x); - e1p1.y = tri1s[i].p2.y + (e2p1.y - tri2s[i].p2.y)/(tri2s[i].p3.y - tri2s[i].p2.y) * (tri1s[i].p3.y - tri1s[i].p2.y); - e1p2.x = tri1s[i].p3.x + (e2p2.x - tri2s[i].p3.x)/(tri2s[i].p1.x - tri2s[i].p3.x) * (tri1s[i].p1.x - tri1s[i].p3.x); - e1p2.y = tri1s[i].p3.y + (e2p2.y - tri2s[i].p3.y)/(tri2s[i].p1.y - tri2s[i].p3.y) * (tri1s[i].p1.y - tri1s[i].p3.y); - e1p3.x = tri1s[i].p1.x + (e2p3.x - tri2s[i].p1.x)/(tri2s[i].p2.x - tri2s[i].p1.x) * (tri1s[i].p2.x - tri1s[i].p1.x); - e1p3.y = tri1s[i].p1.y + (e2p3.y - tri2s[i].p1.y)/(tri2s[i].p2.y - tri2s[i].p1.y) * (tri1s[i].p2.y - tri1s[i].p1.y); + point e1p1, e1p2, e1p3; + point e2p1, e2p2, e2p3; + line lp, le; + line l1, l2, l3; + double d1, d2, d3; + int i; - /* intersect grid lines in source */ - makeline (&l1, &tri1s[i].p1, &e1p1); - makeline (&l2, &tri1s[i].p2, &e1p2); - makeline (&l3, &tri1s[i].p3, &e1p3); + /* find in which triangle p2 lies */ + for (i = 0; i < nTri; i++) { + if (insidetri (&tri2s[i], p2P)) + break; + } - if ((d1 < d2) && (d1 < d3)) { - intersect (&l2, &l3, p1); - } else - if (d2 < d3) { - intersect (&l1, &l3, p1); - } else { - intersect (&l1, &l2, p1); - } + if (i == nTri) + *p1P = makepoint(0.0, 0.0); + else { + /* where in triangle is point */ + d1 = fabs (p2P->x - tri2s[i].p1.x) + fabs (p2P->y - tri2s[i].p1.y); + d2 = fabs (p2P->x - tri2s[i].p2.x) + fabs (p2P->y - tri2s[i].p2.y); + d3 = fabs (p2P->x - tri2s[i].p3.x) + fabs (p2P->y - tri2s[i].p3.y); + + /* line through p1 and p intersecting with edge p2-p3 */ + lp = makeline(tri2s[i].p1, *p2P); + 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, *p2P); + le = makeline(tri2s[i].p3, tri2s[i].p1); + intersect (&lp, &le, &e2p2); + + /* line through p3 and p intersecting with edge p1-p2 */ + lp = makeline(tri2s[i].p3, *p2P); + le = makeline(tri2s[i].p1, tri2s[i].p2); + intersect (&lp, &le, &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) + * (tri1s[i].p3.x - tri1s[i].p2.x); + e1p1.y = tri1s[i].p2.y + + (e2p1.y - tri2s[i].p2.y)/(tri2s[i].p3.y - tri2s[i].p2.y) + * (tri1s[i].p3.y - tri1s[i].p2.y); + e1p2.x = tri1s[i].p3.x + + (e2p2.x - tri2s[i].p3.x)/(tri2s[i].p1.x - tri2s[i].p3.x) + * (tri1s[i].p1.x - tri1s[i].p3.x); + e1p2.y = tri1s[i].p3.y + + (e2p2.y - tri2s[i].p3.y)/(tri2s[i].p1.y - tri2s[i].p3.y) + * (tri1s[i].p1.y - tri1s[i].p3.y); + e1p3.x = tri1s[i].p1.x + + (e2p3.x - tri2s[i].p1.x)/(tri2s[i].p2.x - tri2s[i].p1.x) + * (tri1s[i].p2.x - tri1s[i].p1.x); + e1p3.y = tri1s[i].p1.y + + (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); + } } static void -warpQuad(point * const p2, - point * const p1) { +warpQuad(point * const p2P, + point * const p1P) { /* map target to source for quad control points */ @@ -1026,31 +1055,31 @@ warpQuad(point * const p2, line l2t, l2b, l2l, l2r; line lh, lv; - copypoint (&c1tl, &quad1[TL]); - copypoint (&c1tr, &quad1[TR]); - copypoint (&c1bl, &quad1[BL]); - copypoint (&c1br, &quad1[BR]); - - copypoint (&c2tl, &quad2[TL]); - copypoint (&c2tr, &quad2[TR]); - copypoint (&c2bl, &quad2[BL]); - copypoint (&c2br, &quad2[BR]); - - makeline (&l2t, &c2tl, &c2tr); - makeline (&l2b, &c2bl, &c2br); - makeline (&l2l, &c2tl, &c2bl); - makeline (&l2r, &c2tr, &c2br); + c1tl = quad1[TL]; + c1tr = quad1[TR]; + c1bl = quad1[BL]; + c1br = quad1[BR]; + + c2tl = quad2[TL]; + c2tr = quad2[TR]; + 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 */ - makeline (&lv, p2, &v2); + lv = makeline(*p2P, v2); intersect (&l2t, &lv, &e2t); intersect (&l2b, &lv, &e2b); - makeline (&lh, p2, &h2); + lh = makeline(*p2P, h2); intersect (&l2l, &lh, &e2l); intersect (&l2r, &lh, &e2r); @@ -1080,9 +1109,44 @@ warpQuad(point * const p2, e1r.y = c1tr.y + (e2r.y - c2tr.y)/(c2br.y - c2tr.y) * (c1br.y - c1tr.y); /* intersect grid lines in source */ - makeline (&lv, &e1t, &e1b); - makeline (&lh, &e1l, &e1r); - intersect (&lh, &lv, p1); + lv = makeline(e1t, e1b); + lh = makeline(e1l, e1r); + intersect (&lh, &lv, p1P); +} + + + +static void +setGlobalCP(struct cmdlineInfo const cmdline) { + + unsigned int i; + + for (i = 0; i < cmdline.nCP; ++i) { + oldCP[i] = cmdline.oldCP[i]; + newCP[i] = cmdline.newCP[i]; + } + nCP = cmdline.nCP; + for (i = nCP; i < ARRAY_SIZE(oldCP); ++i) + oldCP[i] = makepoint(-1.0, -1.0); + for (i = nCP; i < ARRAY_SIZE(newCP); ++i) + newCP[i] = makepoint(-1.0, -1.0); +} + + + +static void +createWhiteTuple(const struct pam * const pamP, + tuple * const tupleP) { + + tuple white; + unsigned int plane; + + white = pnm_allocpamtuple(pamP); + + for (plane = 0; plane < pamP->depth; ++plane) + white[plane] = pamP->maxval; + + *tupleP = white; } @@ -1090,116 +1154,121 @@ warpQuad(point * const p2, int main(int argc, const char ** const argv) { - struct cmdlineInfo cmdline; - FILE * rdFile; - struct pam inpam, outpam; - tuple ** rdTuples; - tuple ** wrTuples; - tuple white; - int row, col; + struct cmdlineInfo cmdline; + FILE * rdFileP; + struct pam inpam, outpam; + tuple ** rdTuples; + tuple ** wrTuples; + tuple white; + unsigned int row; - point p1, p2; - int p2x, p2y; - double rx, ry; - double pix; - int i; + point p1, p2; + int p2x, p2y; + double rx, ry; + double pix; + + pm_proginit(&argc, argv); - /* initialize random generator */ - srand ( time(NULL) ); + parseCmdline(argc, argv, &cmdline); - /* get parameters, open input file, read header */ - pm_proginit(&argc, argv); - parseCmdline(argc, argv, &cmdline); + setGlobalCP(cmdline); - rdFile = pm_openr(cmdline.filename); + srand(cmdline.randseedSpec ? cmdline.randseed : time(NULL)); - rdTuples = pnm_readpam (rdFile, &inpam, PAM_STRUCT_SIZE(tuple_type)); - if (rdTuples == NULL) { - pm_error ("Out of memory."); - } - outpam = inpam; /* initial value */ - outpam.file = stdout; - - if (cmdline.verbose) { - fprintf (stderr, "type = %s\n", inpam.tuple_type); - fprintf (stderr, "width = %d\n", inpam.width); - fprintf (stderr, "height = %d\n", inpam.height); - fprintf (stderr, "depth = %d\n", inpam.depth); - fprintf (stderr, "maxval = %d\n", (int) inpam.maxval); - } + rdFileP = pm_openr(cmdline.filename); - wrTuples = pnm_allocpamarray(&outpam); + rdTuples = pnm_readpam (rdFileP, &inpam, PAM_STRUCT_SIZE(tuple_type)); - white = pnm_allocpamtuple(&outpam); - for (i = 0; i < inpam.depth; i++) - white[i] = outpam.maxval; - for (row = 0; row < inpam.height; row++) { - for (col = 0; col < inpam.width; col++) { - pnm_assigntuple(&outpam, wrTuples[row][col], white); - } - } + outpam = inpam; /* initial value */ + outpam.file = stdout; - if (cmdline.tri) - prepTrig(inpam.width, inpam.height); - if (cmdline.quad) - prepQuad(); + wrTuples = pnm_allocpamarray(&outpam); - for (p2y = 0; p2y < inpam.height; p2y++) - { - for (p2x = 0; p2x < inpam.width; p2x++) - { - makepoint (&p2, (double) p2x, (double) p2y); - if (cmdline.quad) - warpQuad (&p2, &p1); - if (cmdline.tri) - warpTrig (&p2, &p1); - - p1.x += 1E-3; - p1.y += 1E-3; - if ((p1.x >= 0.0) && (p1.x < (double) inpam.width - 0.5) && - (p1.y >= 0.0) && (p1.y < (double) inpam.height - 0.5)) - { - for (i = 0; i < inpam.depth; i++) { - if (!cmdline.linear) { - pix = rdTuples[(int) floor(p1.y + 0.5)][(int) floor(p1.x + 0.5)][i]; - } else { - rx = p1.x - floor(p1.x); - ry = p1.y - floor(p1.y); - pix = 0.0; - pix += (1.0 - rx) * (1.0 - ry) * rdTuples[(int) floor(p1.y)][(int) floor(p1.x)][i]; - pix += rx * (1.0 - ry) * rdTuples[(int) floor(p1.y)][(int) floor(p1.x) + 1][i]; - pix += (1.0 - rx) * ry * rdTuples[(int) floor(p1.y) + 1][(int) floor(p1.x)][i]; - pix += rx * ry * rdTuples[(int) floor(p1.y) + 1][(int) floor(p1.x) + 1][i]; - } - wrTuples[p2y][p2x][i] = (int) floor(pix); - } /* end for */ - } + pnm_createBlackTuple(&outpam, &black); + createWhiteTuple(&outpam, &white); + + for (row = 0; row < inpam.height; ++row) { + unsigned int col; + for (col = 0; col < inpam.width; ++col) + pnm_assigntuple(&outpam, wrTuples[row][col], white); } - } - pnm_createBlackTuple(&outpam, &black); + if (cmdline.tri) + prepTrig(inpam.width, inpam.height); + if (cmdline.quad) + prepQuad(); - if (cmdline.frame) { - if (cmdline.quad) { - drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[1]); - drawExtendedLine(&outpam, wrTuples, quad2[2], quad2[3]); - drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[2]); - drawExtendedLine(&outpam, wrTuples, quad2[1], quad2[3]); + for (p2y = 0; p2y < inpam.height; p2y++) + { + for (p2x = 0; p2x < inpam.width; p2x++) + { + p2 = makepoint(p2x, p2y); + if (cmdline.quad) + warpQuad (&p2, &p1); + if (cmdline.tri) + warpTrig (&p2, &p1); + + p1.x += 1E-3; + p1.y += 1E-3; + if ((p1.x >= 0.0) && (p1.x < (double) inpam.width - 0.5) && + (p1.y >= 0.0) && (p1.y < (double) inpam.height - 0.5)) { + unsigned int i; + for (i = 0; i < inpam.depth; ++i) { + if (!cmdline.linear) { + pix = rdTuples + [(int) floor(p1.y + 0.5)] + [(int) floor(p1.x + 0.5)][i]; + } else { + rx = p1.x - floor(p1.x); + ry = p1.y - floor(p1.y); + pix = 0.0; + pix += (1.0 - rx) * (1.0 - ry) + * rdTuples + [(int) floor(p1.y)] + [(int) floor(p1.x)][i]; + pix += rx * (1.0 - ry) + * rdTuples + [(int) floor(p1.y)] + [(int) floor(p1.x) + 1][i]; + pix += (1.0 - rx) * ry + * rdTuples + [(int) floor(p1.y) + 1] + [(int) floor(p1.x)][i]; + pix += rx * ry + * rdTuples + [(int) floor(p1.y) + 1] + [(int) floor(p1.x) + 1][i]; + } + wrTuples[p2y][p2x][i] = (int) floor(pix); + } /* end for */ + } + } } - if (cmdline.tri) { - unsigned int i; - for (i = 0; i < nTri; ++i) { - drawClippedTriangle(&outpam, wrTuples, tri2s[i]); + + if (cmdline.frame) { + if (cmdline.quad) { + drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[1]); + drawExtendedLine(&outpam, wrTuples, quad2[2], quad2[3]); + drawExtendedLine(&outpam, wrTuples, quad2[0], quad2[2]); + drawExtendedLine(&outpam, wrTuples, quad2[1], quad2[3]); + } + if (cmdline.tri) { + unsigned int i; + for (i = 0; i < nTri; ++i) { + drawClippedTriangle(&outpam, wrTuples, tri2s[i]); + } } } - } - pnm_writepam( &outpam, wrTuples ); - pnm_freepamarray(wrTuples, &outpam); - pnm_freepamarray(rdTuples, &inpam); + pnm_writepam(&outpam, wrTuples); + + pnm_freepamtuple(white); + pnm_freepamtuple(black); + pnm_freepamarray(wrTuples, &outpam); + pnm_freepamarray(rdTuples, &inpam); - pm_close( inpam.file ); - pm_close( outpam.file ); + pm_close(rdFileP); + pm_close(stdout); - return 0; + return 0; } -- cgit 1.4.1