const char * UsageLines [] = {
       "NOTICE: p6addpath is deprecated,",
       "use p4paths and pnmcomp instead.",
       "Usage: p6addpath (path r) (path g) (path b) (path width)",
       "\t[(path corner across) (path corner down) ]+",
       "Reads P6 PPM image from standard input and writes to",
       "standard output same size but with specified path.",
       "Each point on the path is specified by an across",
       "and down (left and top edges are zero).  The corners",
       "are connected by straight line segments.",
       "June 8, 2021.  Newest is at gopher -p users/julianbr sdf.org",
       };
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );


#include <stdio.h>


void AddPath (
               int width, int height,
               int pathr, int pathg, int pathb,
               int pathwidth,
               int (* Corners) [2], int NumCorners)
       {
       int across1, down1, across2, down2, across, down;
       int segmentwidth, segmentheight, pathheight;
       int along1, along2, below1, below2, along, below;
       int r, g, b, i, isOnPath;

       printf ("P6\n");
       printf ("%d %d\n", width, height);
       printf ("255\n");
       r = getchar ();
       for (down = 0; down < height; down++) {
               for (across = 0; across < width; across++) {
                       isOnPath = 0;
                       for (i = 0; i < NumCorners; i++) {
                               across1 = Corners [i] [0];
                               down1 = Corners [i] [1];
                               if (4*((across - across1)*(across - across1)
                                       + (down - down1)*(down - down1) )
                                               < pathwidth*pathwidth)
                                       isOnPath = 1;
                               }
                       for (i = 0; i + 1 < NumCorners; i++) {
                               across1 = Corners [i] [0];
                               down1 = Corners [i] [1];
                               across2 = Corners [i + 1] [0];
                               down2 = Corners [i + 1] [1];
                               segmentwidth = across2 - across1;
                               if (segmentwidth < 0)
                                       segmentwidth = - segmentwidth;
                               segmentheight = down2 - down1;
                               if (segmentheight < 0)
                                       segmentheight = - segmentheight;
                               if (segmentwidth == 0 && segmentheight == 0)
                                       pathheight = 0;
                               else if (segmentwidth > segmentheight)
                                       pathheight = pathwidth*segmentwidth
                                               + pathwidth*segmentheight
                                               *segmentheight/(2*segmentwidth);
                               else
                                       pathheight = pathwidth*segmentheight
                                               + pathwidth*segmentwidth
                                               *segmentwidth/(2*segmentheight);
                               along1 = (across2 - across1)*across1
                                       + (down2 - down1)*down1;
                               below1 = across2*down1 - across1*down2;
                               along2 = (across2 - across1)*across2
                                       + (down2 - down1)*down2;
                               along = (across2 - across1)*across
                                       + (down2 - down1)*down;
                               below = - (down2 - down1)*across
                                       + (across2 - across1)*down;
                               if (along > along1 && along < along2) {
                                       below2 = below1 - pathheight/2;
                                       if (below > below2
                                       && below < below2 + pathheight)
                                               isOnPath = 1;
                                       }
                               }
                       if (r != EOF)
                               g = getchar ();
                       if (g != EOF)
                               b = getchar ();
                       if (isOnPath) {
                               putchar (pathr);
                               putchar (pathg);
                               putchar (pathb);
                               }
                       else {
                               putchar (r);
                               putchar (g);
                               putchar (b);
                               }
                       if (b != EOF)
                               r = getchar ();
                       }
               }
       if (b == EOF)
               fprintf (stderr, "***p6addpath: Not enough image data.\n");
       if (r != EOF)
               fprintf (stderr, "***p6addpath: Too much image data.\n");
       }


#include <stdlib.h>


int main (int argc, char * argv [] )
       {
       int (* Corners) [2];
       int i, width, height, r, g, b, pathwidth, NumCorners, ok, depth;
       char c;

       Corners = NULL;
       if (argc < 2) {
               for (i = 0; i < NumUsageLines; i++)
                       printf ("%s\n", UsageLines [i] );
               }
       else if (argc < 5 || (argc - 5) % 2 > 0) {
               fprintf (stderr, "***Usage: %s", argv [0] );
               fprintf (stderr, " (r) (g) (b) (width)");
               fprintf (stderr, " (across down for each corner)\n");
               }
       else {
               ok = 1;
               if (sscanf (argv [1], "%d%c", & r, & c) != 1) {
                       fprintf (stderr, "***p6addpath: Expecting number");
                       fprintf (stderr, " for path r, found");
                       fprintf (stderr, " \"%s\".\n", argv [1] );
                       ok = 0;
                       }
               if (sscanf (argv [2], "%d%c", & g, & c) != 1) {
                       fprintf (stderr, "***p6addpath: Expecting number");
                       fprintf (stderr, " for path g, found");
                       fprintf (stderr, " \"%s\".\n", argv [2] );
                       ok = 0;
                       }
               if (sscanf (argv [3], "%d%c", & b, & c) != 1) {
                       fprintf (stderr, "***p6addpath: Expecting number");
                       fprintf (stderr, " for path b, found");
                       fprintf (stderr, " \"%s\".\n", argv [3] );
                       ok = 0;
                       }
               if (sscanf (argv [4], "%d%c", & pathwidth, & c) != 1) {
                       fprintf (stderr, "***p6addpath: Expecting number");
                       fprintf (stderr, " for path width, found");
                       fprintf (stderr, " \"%s\".\n", argv [3] );
                       ok = 0;
                       }
               if (ok) {
                       NumCorners = (argc - 5)/2;
                       Corners = NULL;
                       if (NumCorners > 0) {
                               Corners = malloc (NumCorners*sizeof (Corners [0] ) );
                               if (Corners == NULL) {
                                       fprintf (stderr, "***p6addpath: Not");
                                       fprintf (stderr, " enough memory.\n");
                                       ok = 0;
                                       }
                               }
                       }
               if (ok) {
                       for (i = 0; i < NumCorners; i++) {
                               if (sscanf (argv [i + i + 5], "%d%c",
                                               Corners [i] + 0, & c) != 1) {
                                       fprintf (stderr, "***p6addpath: Expecting");
                                       fprintf (stderr, " number for across,");
                                       fprintf (stderr, " found \"");
                                       fprintf (stderr, "%s", argv [i + 4] );
                                       fprintf (stderr, "\".\n");
                                       ok = 0;
                                       }
                               if (sscanf (argv [i + i + 6], "%d%c",
                                               Corners [i] + 1, & c) != 1) {
                                       fprintf (stderr, "***p6addpath: Expecting");
                                       fprintf (stderr, " number for down,");
                                       fprintf (stderr, " found \"");
                                       fprintf (stderr, "%s", argv [i + 5] );
                                       fprintf (stderr, "\".\n");
                                       ok = 0;
                                       }
                               }
                       }
               if (ok) {
                       if (getchar () != 'P'
                                       || getchar () != '6'
                                       || scanf ("%d", & width) != 1
                                       || scanf ("%d", & height) != 1
                                       || scanf ("%d", & depth) != 1
                                       || getchar () != '\n') {
                               fprintf (stderr, "***p6addpath: Improper input,");
                               fprintf (stderr, " must be P6 PPM.\n");
                               ok = 0;
                               }
                       }
               if (ok) {
                       AddPath (width, height, r, g, b, pathwidth,
                                       Corners, NumCorners);
                       }
               }
       if (Corners != NULL)
               free (Corners);
       return 0;
       }