const char * UsageLines [] = {
"Usage: p6fadetrim (background r) (background g) (background b)",
"\t(retention factor between 0 and 9)",
"\t[(vertical edge across) (horizontal edge down) ]+",
"Reads P6 PPM image from standard input and writes to",
"standard output same size but trimmed. Everything outside",
"the specified edges is replaced with background color.",
" Boundaries alternate",
"between vertical edges specified by across (left edge = 0)",
"and horizontal edges specified by down (top edge = 0).",
"The edge path is always closed. p6fadetrim will use the",
"first across again if needed to close path.",
"If no path is apecified, will operate on whole image.",
"Need a minimum of 4 numbers for any effect (4 will be a rectangle).",
"",
"Retention of 0 will replace what's outside the edge",
"with the specified background color. Retention of 10",
"will have no effect (output image will be same as input).",
"Numbers from 1 through 9 will fade proportionally.",
"",
"April 21, 2021. Newest is at gopher -p users/julianbr sdf.org",
};
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );
#include <stdio.h>
void FadeTrim (
int width, int height,
int backgroundr, int backgroundg, int backgroundb,
int retention,
int * Edges, int NumEdges)
{
int across1, down1, across2, across, down;
int r, g, b, i, j, k;
int NumCrossings;
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++) {
NumCrossings = 0;
i = 0;
j = 1;
k = 2;
while (j < NumEdges) {
across1 = Edges [i];
down1 = Edges [j];
if (k < NumEdges)
across2 = Edges [k];
else
across2 = Edges [0];
if (down >= down1) {
if (across2 > across
&& across >= across1)
NumCrossings++;
else if (across1 > across
&& across >= across2)
NumCrossings--;
}
i += 2;
j += 2;
k += 2;
}
if (r != EOF)
g = getchar ();
if (g != EOF)
b = getchar ();
if (NumCrossings == 0) {
putchar (((10 - retention)*backgroundr
+ retention*r + 5)/10);
putchar (((10 - retention)*backgroundg
+ retention*g + 5)/10);
putchar (((10 - retention)*backgroundb
+ retention*b + 5)/10);
}
else {
putchar (r);
putchar (g);
putchar (b);
}
if (b != EOF)
r = getchar ();
}
}
if (b == EOF)
fprintf (stderr, "***p6fadetrim: Not enough image data.\n");
if (r != EOF)
fprintf (stderr, "***p6fadetrim: Too much image data.\n");
}
#include <stdlib.h>
int main (int argc, char * argv [] )
{
int * Edges;
int i, width, height, r, g, b, NumEdges, ok, depth, retention;
char c;
Edges = NULL;
if (argc < 2) {
for (i = 0; i < NumUsageLines; i++)
printf ("%s\n", UsageLines [i] );
}
else if (argc < 5) {
fprintf (stderr, "***Usage: %s", argv [0] );
fprintf (stderr, " (r) (g) (b)");
fprintf (stderr, " (retention) (edges)\n");
}
else {
ok = 1;
if (sscanf (argv [1], "%d%c", & r, & c) != 1) {
fprintf (stderr, "***p6fadetrim: Expecting number");
fprintf (stderr, " for background r, found");
fprintf (stderr, " \"%s\".\n", argv [1] );
ok = 0;
}
if (sscanf (argv [2], "%d%c", & g, & c) != 1) {
fprintf (stderr, "***p6fadetrim: Expecting number");
fprintf (stderr, " for background g, found");
fprintf (stderr, " \"%s\".\n", argv [2] );
ok = 0;
}
if (sscanf (argv [3], "%d%c", & b, & c) != 1) {
fprintf (stderr, "***p6fadetrim: Expecting number");
fprintf (stderr, " for background b, found");
fprintf (stderr, " \"%s\".\n", argv [3] );
ok = 0;
}
if (sscanf (argv [4], "%d%c", & retention, & c) != 1
|| retention < 0 || retention > 10) {
fprintf (stderr, "***p6fadetrim: Expecting number");
fprintf (stderr, " between 0 and 9 for");
fprintf (stderr, " retention, found");
fprintf (stderr, " \"%s\".\n", argv [4] );
ok = 0;
}
if (ok) {
NumEdges = argc - 5;
Edges = NULL;
if (NumEdges > 0) {
Edges = malloc (NumEdges*sizeof (Edges [0] ) );
if (Edges == NULL) {
fprintf (stderr, "***p6fadetrim: Not");
fprintf (stderr, " enough memory.\n");
ok = 0;
}
}
}
if (ok) {
for (i = 0; i < NumEdges; i++) {
if (sscanf (argv [i + 5], "%d%c",
Edges + i, & c) != 1) {
fprintf (stderr, "***p6fadetrim:");
fprintf (stderr, " Expecting");
fprintf (stderr, " number for edge,");
fprintf (stderr, " found \"");
fprintf (stderr, "%s", argv [i + 4] );
fprintf (stderr, "\".\n");
ok = 0;
}
}
}
if (ok) {
if (NumEdges > 2 && NumEdges%2 == 1
&& Edges [0] != Edges [NumEdges - 1] ) {
fprintf (stderr, "***p6fadetrim:");
fprintf (stderr, " First across must be same");
fprintf (stderr, " as last across but found");
fprintf (stderr, " %d and", Edges [0] );
fprintf (stderr, " %d", Edges [NumEdges - 1] );
fprintf (stderr, ".\nCan omit last across.\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, "***p6fadetrim: Improper");
fprintf (stderr, " input,");
fprintf (stderr, " must be P6 PPM.\n");
ok = 0;
}
}
if (ok)
FadeTrim (width, height, r, g, b, retention,
Edges, NumEdges);
}
if (Edges != NULL)
free (Edges);
return 0;
}