const char * UsageLines [] = {
       "Usage: p6addcolor",
       "\t(input P4 PBM mask image file)",
       "\t(added r g b color components)",
       "Reads P6 PPM image, which must have the same dimensions as",
       "the specified mask image, from standard input.",
       "Writes P6 PPM image, of the same dimensions, to standard",
       "output.  Everywhere the mask image has a '1' pixel, the",
       "output pixel will have the specified r g b value.  All other",
       "output pixels will be the same as the input.",
       "March 1, 2023.  Newest is at gopher -p users/julianbr sdf.org",
       };
const int NumUsageLines = sizeof (UsageLines)/sizeof (UsageLines [0] );

#include <stdio.h>


void AddColor (
               FILE * MaskHdl,
               int width, int height,
               int AddedR, int AddedG, int AddedB)
       {
       int across, down;
       int InputR, InputG, InputB, MaskWeight, MaskValue;

       MaskValue = 0; /* Just to make it != EOF */
       InputR = getchar ();
       for (down = 0; down < height; down++) {
               MaskWeight = 128;
               for (across = 0; across < width; across++) {
                       if (MaskValue != EOF && MaskWeight == 128)
                               MaskValue = fgetc (MaskHdl);
                       if (InputR == EOF)
                               InputG = EOF;
                       else
                               InputG = getchar ();
                       if (InputG == EOF)
                               InputB = EOF;
                       else
                               InputB = getchar ();
                       if ((MaskValue != EOF
                                       && MaskValue >= MaskWeight)
                                       || InputB == EOF) {
                               putchar (AddedR);
                               putchar (AddedG);
                               putchar (AddedB);
                               }
                       else {
                               putchar (InputR);
                               putchar (InputG);
                               putchar (InputB);
                               }
                       if (MaskValue != EOF
                                       && MaskValue >= MaskWeight)
                               MaskValue -= MaskWeight;
                       if (InputB == EOF)
                               InputR = EOF;
                       else
                               InputR = getchar ();
                       MaskWeight /= 2;
                       if (MaskWeight == 0)
                               MaskWeight = 128;
                       }
               }
       if (InputB == EOF) {
               fprintf (stderr, "***p6addcolor: Premature end");
               fprintf (stderr, " of input image data.\n");
               }
       else if (InputR != EOF) {
               fprintf (stderr, "***p6addcolor: Extra");
               fprintf (stderr, " data in input image.\n");
               }
       if (MaskValue == EOF) {
               fprintf (stderr, "***p6addcolor: Premature end");
               fprintf (stderr, " of mask image data.\n");
               }
       else if (fgetc (MaskHdl) != EOF) {
               fprintf (stderr, "***p6addcolor: Extra");
               fprintf (stderr, " data in mask image.\n");
               }
       }


void AddColorFile (FILE * MaskHdl, int AddedR, int AddedG, int AddedB)
       {
       int MaskWidth, MaskHeight, InputWidth, InputHeight, inputDepth;
       int ok;

       ok = 1;
       if (fgetc (MaskHdl) != 'P'
                       || fgetc (MaskHdl) != '4'
                       || fgetc (MaskHdl) != '\n'
                       || fscanf (MaskHdl, "%d", & MaskWidth) != 1
                       || fscanf (MaskHdl, "%d", & MaskHeight) != 1
                       || fgetc (MaskHdl) != '\n') {
               fprintf (stderr, "***p6addcolor: Improper mask,");
               fprintf (stderr, " must be P4 PBM.\n");
               ok = 0;
               }
       if (getchar () != 'P'
                       || getchar () != '6'
                       || getchar () != '\n'
                       || scanf ("%d", & InputWidth) != 1
                       || scanf ("%d", & InputHeight) != 1
                       || scanf ("%d", & inputDepth) != 1
                       || getchar () != '\n') {
               fprintf (stderr, "***p6addcolor: Improper input,");
               fprintf (stderr, " must be P6 PPM.\n");
               ok = 0;
               }
       if (ok && !(MaskWidth == InputWidth
                               && MaskHeight == InputHeight) ) {
               fprintf (stderr, "***p6addcolor:  Mask size");
               fprintf (stderr, " %dx%d", MaskWidth, MaskHeight);
               fprintf (stderr, " doesn't match input size");
               fprintf (stderr, " %dx%d.\n", InputWidth, InputHeight);
               ok = 0;
               }
       if (ok) {
               printf ("P6\n");
               printf ("%d %d\n", InputWidth, InputHeight);
               printf ("255\n");
               AddColor (
                               MaskHdl,
                               InputWidth, InputHeight,
                               AddedR, AddedG, AddedB);
               }
       }


int main (int argc, char * argv [] )
       {
       FILE * MaskHdl;
       int i, ok, AddedR, AddedG, AddedB;
       char c;

       if (argc < 2) {
               for (i = 0; i < NumUsageLines; i++)
                       printf ("%s\n", UsageLines [i] );
               }
       else if (argc == 5) {
               ok = 1;
               if (sscanf (argv [2], "%d%c", & AddedR, & c) != 1) {
                       fprintf (stderr, "***p6addcolor: Expecting r value,");
                       fprintf (stderr, " found \"%s\".\n", argv [2] );
                       ok = 0;
                       }
               if (sscanf (argv [3], "%d%c", & AddedG, & c) != 1) {
                       fprintf (stderr, "***p6addcolor: Expecting g value,");
                       fprintf (stderr, " found \"%s\".\n", argv [3] );
                       ok = 0;
                       }
               if (sscanf (argv [4], "%d%c", & AddedB, & c) != 1) {
                       fprintf (stderr, "***p6addcolor: Expecting b value,");
                       fprintf (stderr, " found \"%s\".\n", argv [4] );
                       ok = 0;
                       }
               if (ok) {
                       MaskHdl = fopen (argv [1], "rb");
                       if (MaskHdl == NULL) {
                               fprintf (stderr, "***p6addcolor:");
                               fprintf (stderr, " \"%s\"", argv [1] );
                               fprintf (stderr, " not found.\n");
                               }
                       else {
                               AddColorFile (MaskHdl,
                                       AddedR, AddedG, AddedB);
                               fclose (MaskHdl);
                               }
                       }
               }
       else {
               fprintf (stderr, "Usage: p6addcolor");
               fprintf (stderr, " (Mask PBM) (r) (g) (b)\n");
               }
       return 0;
       }