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; }