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