1 /* pgmoil.c - read a portable pixmap and turn into an oil painting
2 **
3 ** Copyright (C) 1990 by Wilson Bent (whb@hoh-2.att.com)
4 ** Shamelessly butchered into a color version by Chris Sheppard
5 ** 2001
6 **
7 ** Permission to use, copy, modify, and distribute this software and its
8 ** documentation for any purpose and without fee is hereby granted, provided
9 ** that the above copyright notice appear in all copies and that both that
10 ** copyright notice and this permission notice appear in supporting
11 ** documentation.  This software is provided "as is" without express or
12 ** implied warranty.
13 */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include "pam.h"
19 #include "mallocvar.h"
20 
21 static void
convertRow(struct pam const inpam,tuple ** const tuples,tuple * const tuplerow,int const row,int const smearFactor,int * const hist)22 convertRow(struct pam const inpam, tuple ** const tuples,
23            tuple * const tuplerow, int const row, int const smearFactor,
24            int * const hist) {
25 
26     int sample;
27     for (sample = 0; sample < inpam.depth; sample++) {
28         int col;
29         for (col = 0; col < inpam.width; ++col)  {
30             int i;
31             int drow;
32             int modalval;
33                 /* The sample value that occurs most often in the neighborhood
34                    of the pixel being examined
35                 */
36 
37             /* Compute hist[] - frequencies, in the neighborhood, of each
38                sample value
39             */
40             for (i = 0; i <= inpam.maxval; ++i) hist[i] = 0;
41 
42             for (drow = row - smearFactor; drow <= row + smearFactor; ++drow) {
43                 if (drow >= 0 && drow < inpam.height) {
44                     int dcol;
45                     for (dcol = col - smearFactor;
46                          dcol <= col + smearFactor;
47                          ++dcol) {
48                         if ( dcol >= 0 && dcol < inpam.width )
49                             ++hist[tuples[drow][dcol][sample]];
50                     }
51                 }
52             }
53             {
54                 /* Compute modalval */
55                 int sampleval;
56                 int maxfreq;
57 
58                 maxfreq = 0;
59                 modalval = 0;
60 
61                 for (sampleval = 0; sampleval <= inpam.maxval; ++sampleval) {
62                     if (hist[sampleval] > maxfreq) {
63                         maxfreq = hist[sampleval];
64                         modalval = sampleval;
65                     }
66                 }
67             }
68             tuplerow[col][sample] = modalval;
69         }
70     }
71 }
72 
73 
74 
75 int
main(int argc,char * argv[])76 main(int argc, char *argv[] ) {
77     struct pam inpam, outpam;
78     FILE* ifp;
79     tuple ** tuples;
80     tuple * tuplerow;
81     int * hist;
82         /* A buffer for the convertRow subroutine to use */
83     int argn;
84     int row;
85     int smearFactor;
86     const char* const usage = "[-n <n>] [ppmfile]";
87 
88     ppm_init( &argc, argv );
89 
90     argn = 1;
91     smearFactor = 3;       /* DEFAULT VALUE */
92 
93     /* Check for options. */
94     if ( argn < argc && argv[argn][0] == '-' ) {
95         if ( argv[argn][1] == 'n' ) {
96             ++argn;
97             if ( argn == argc || sscanf(argv[argn], "%d", &smearFactor) != 1 )
98                 pm_usage( usage );
99         } else
100             pm_usage( usage );
101         ++argn;
102     }
103     if ( argn < argc ) {
104         ifp = pm_openr( argv[argn] );
105         ++argn;
106     } else
107         ifp = stdin;
108 
109     if ( argn != argc )
110         pm_usage( usage );
111 
112     tuples = pnm_readpam(ifp, &inpam, PAM_STRUCT_SIZE(tuple_type));
113     pm_close(ifp);
114 
115     MALLOCARRAY(hist, inpam.maxval + 1);
116     if (hist == NULL)
117         pm_error("Unable to allocate memory for histogram.");
118 
119     outpam = inpam; outpam.file = stdout;
120 
121     pnm_writepaminit(&outpam);
122 
123     tuplerow = pnm_allocpamrow(&inpam);
124 
125     for (row = 0; row < inpam.height; ++row) {
126         convertRow(inpam, tuples, tuplerow, row, smearFactor, hist);
127         pnm_writepamrow(&outpam, tuplerow);
128     }
129 
130     pnm_freepamrow(tuplerow);
131     free(hist);
132     pnm_freepamarray(tuples, &inpam);
133 
134     pm_close(stdout);
135     exit(0);
136 }
137 
138