/* pgmoil.c - read a portable pixmap and turn into an oil painting
**
** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
** Shamelessly butchered into a color version by Chris Sheppard
** 2001
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "pam.h"
#include "mallocvar.h"

static void 
convertRow(struct pam const inpam, tuple ** const tuples,
           tuple * const tuplerow, int const row, int const smearFactor,
           int * const hist) {

    int sample;
    for (sample = 0; sample < inpam.depth; sample++) {
        int col;
        for (col = 0; col < inpam.width; ++col)  {
            int i;
            int drow;
            int modalval;
                /* The sample value that occurs most often in the neighborhood
                   of the pixel being examined
                */

            /* Compute hist[] - frequencies, in the neighborhood, of each 
               sample value
            */
            for (i = 0; i <= inpam.maxval; ++i) hist[i] = 0;

            for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) {
                if (drow >= 0 && drow < inpam.height) {
                    int dcol;
                    for (dcol = col - smearFactor; 
                         dcol <= col + smearFactor; 
                         ++dcol) {
                        if ( dcol >= 0 && dcol < inpam.width )
                            ++hist[tuples[drow][dcol][sample]];
                    }
                }
            }
            {
                /* Compute modalval */
                int sampleval;
                int maxfreq;

                maxfreq = 0;
                modalval = 0;

                for (sampleval = 0; sampleval <= inpam.maxval; ++sampleval) {
                    if (hist[sampleval] > maxfreq) {
                        maxfreq = hist[sampleval];
                        modalval = sampleval;
                    }
                }
            }
            tuplerow[col][sample] = modalval;
        }
    }
}



int
main(int argc, char *argv[] ) {
    struct pam inpam, outpam;
    FILE* ifp;
    tuple ** tuples;
    tuple * tuplerow;
    int * hist;
        /* A buffer for the convertRow subroutine to use */
    int argn;
    int row;
    int smearFactor;
    const char* const usage = "[-n <n>] [ppmfile]";

    ppm_init( &argc, argv );

    argn = 1;
    smearFactor = 3;       /* DEFAULT VALUE */

    /* Check for options. */
    if ( argn < argc && argv[argn][0] == '-' ) {
        if ( argv[argn][1] == 'n' ) {
            ++argn;
            if ( argn == argc || sscanf(argv[argn], "%d", &smearFactor) != 1 )
                pm_usage( usage );
        } else
            pm_usage( usage );
        ++argn;
    }
    if ( argn < argc ) {
        ifp = pm_openr( argv[argn] );
        ++argn;
    } else
        ifp = stdin;

    if ( argn != argc )
        pm_usage( usage );

    tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type));
    pm_close(ifp);

    overflow_add(inpam.maxval, 1);
    MALLOCARRAY(hist, inpam.maxval + 1);
    if (hist == NULL)
        pm_error("Unable to allocate memory for histogram.");

    outpam = inpam; outpam.file = stdout;

    pnm_writepaminit(&outpam);

    tuplerow = pnm_allocpamrow(&inpam);

    for (row = 0; row < inpam.height; ++row) {
        convertRow(inpam, tuples, tuplerow, row, smearFactor, hist);
        pnm_writepamrow(&outpam, tuplerow);
    }

    pnm_freepamrow(tuplerow);
    free(hist);
    pnm_freepamarray(tuples, &inpam);

    pm_close(stdout);
    exit(0);
}

