1 /*********************************************************************/
2 /* ppmspread -  randomly displace a PPM's pixels by a certain amount */
3 /* Frank Neumann, October 1993                                       */
4 /* V1.1 16.11.1993                                                   */
5 /*                                                                   */
6 /* version history:                                                  */
7 /* V1.0 12.10.1993    first version                                  */
8 /* V1.1 16.11.1993    Rewritten to be NetPBM.programming conforming  */
9 /*********************************************************************/
10 
11 #include <string.h>
12 
13 #include "ppm.h"
14 
15 
16 
17 int
main(int argc,char * argv[])18 main(int    argc,
19      char * argv[]) {
20 
21     FILE * ifP;
22     int argn, rows, cols;
23     unsigned int row;
24     pixel ** destarray, ** srcarray;
25     pixel * pP;
26     pixel * pP2;
27     pixval maxval;
28     pixval r1, g1, b1;
29     int amount;
30     const char * const usage = "amount [ppmfile]\n        amount: # of pixels to displace a pixel by at most\n";
31 
32     /* parse in 'default' parameters */
33     ppm_init(&argc, argv);
34 
35     argn = 1;
36 
37     /* parse in amount & seed */
38     if (argn == argc)
39         pm_usage(usage);
40     if (sscanf(argv[argn], "%d", &amount) != 1)
41         pm_usage(usage);
42     if (amount < 0)
43         pm_error("amount should be a positive number");
44     ++argn;
45 
46     /* parse in filename (if present, stdin otherwise) */
47     if (argn != argc)
48     {
49         ifP = pm_openr(argv[argn]);
50         ++argn;
51     }
52     else
53         ifP = stdin;
54 
55     if (argn != argc)
56         pm_usage(usage);
57 
58     srcarray = ppm_readppm(ifP, &cols, &rows, &maxval);
59 
60     destarray = ppm_allocarray(cols, rows);
61 
62     /* clear out the buffer */
63     for (row = 0; row < rows; ++row)
64         memset(destarray[row], 0, cols * sizeof(pixel));
65 
66     srand(pm_randseed());
67 
68     /* start displacing pixels */
69     for (row = 0; row < rows; ++row) {
70         unsigned int col;
71         pP = &srcarray[row][0];
72 
73         for (col = 0; col < cols; ++col) {
74             int const xdis = (rand() % (amount+1)) - ((amount+1) / 2);
75             int const ydis = (rand() % (amount+1)) - ((amount+1) / 2);
76 
77             int const xnew = col + xdis;
78             int const ynew = row + ydis;
79 
80             /* only set the displaced pixel if it's within the bounds
81                of the image
82             */
83             if (xnew >= 0 && xnew < cols && ynew >= 0 && ynew < rows) {
84                 /* displacing a pixel is accomplished by swapping it
85                    with another pixel in its vicinity - so, first
86                    store other pixel's RGB
87                 */
88                 pP2 = &srcarray[ynew][xnew];
89                 r1 = PPM_GETR(*pP2);
90                 g1 = PPM_GETG(*pP2);
91                 b1 = PPM_GETB(*pP2);
92                 /* set second pixel to new value */
93                 pP2 = &destarray[ynew][xnew];
94                 PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP));
95 
96                 /* now, set first pixel to (old) value of second */
97                 pP2 = &destarray[row][col];
98                 PPM_ASSIGN(*pP2, r1, g1, b1);
99             } else {
100                 /* displaced pixel is out of bounds; leave the old
101                    pixel there
102                 */
103                 pP2 = &destarray[row][col];
104                 PPM_ASSIGN(*pP2, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP));
105             }
106             ++pP;
107         }
108     }
109 
110     ppm_writeppm(stdout, destarray, cols, rows, maxval, 0);
111 
112     pm_close(ifP);
113     ppm_freearray(srcarray, rows);
114     ppm_freearray(destarray, rows);
115 
116     return 0;
117 }
118