about summary refs log tree commit diff
path: root/editor/pamshuffle.c
blob: bffb79c55848edfb731b7b71a0b13b5e6a77abf0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*=============================================================================
                               pamshuffle
===============================================================================
  Part of the Netpbm package.

  Relocate pixels in row, randomly, using Fisher-Yates shuffling.

  By Akira F. Urushibata

  Contributed to the public domain by its author.
=============================================================================*/

#include <assert.h>
#include "pm_c_util.h"
#include "pam.h"
#include "rand.h"
#include "shhopt.h"

struct CmdlineInfo {
    /* All the information the user supplied in the command line,
       in a form easy for the program to use.
    */
    const char * inputFileName;
    unsigned int column;
    unsigned int randomseedSpec;
    unsigned int randomseed;
};

static void
parseCommandLine(int argc, const char ** const argv,
                 struct CmdlineInfo * const cmdlineP) {
/*----------------------------------------------------------------------------
   Note that the file spec array we return is stored in the storage that
   was passed to us as the argv array.
-----------------------------------------------------------------------------*/
    optEntry * option_def;
        /* Instructions to OptParseOptions3 on how to parse our options. */
    optStruct3 opt;

    unsigned int option_def_index;

    MALLOCARRAY(option_def, 100);

    opt.opt_table = option_def;
    opt.short_allowed = false;  /* We have no short (old-fashioned) options */
    opt.allowNegNum = true;  /* We have no parms that are negative numbers */

    option_def_index = 0;   /* incremented by OPTENT3 */
    OPTENT3(0,   "column",     OPT_FLAG,   NULL,
                               &cmdlineP->column,                    0);
    OPTENT3(0,   "randomseed", OPT_UINT,   &cmdlineP->randomseed,
                               &cmdlineP->randomseedSpec,            0);

    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
        /* Uses and sets argc, argv, and some of *cmdlineP and others. */

    free(option_def);

    if (argc-1 > 1)
        pm_error("Too many arguments (%u). "
                 "The only possible argument is the input file name.", argc-1);
    else if (argc-1 < 1)
        cmdlineP->inputFileName = "-";
    else
        cmdlineP->inputFileName = argv[1];

}



static void
shuffleRow(tuple *            const tuplerow,
           unsigned int       const cols,
           struct pm_randSt * const randStP) {

    unsigned int col;

    for (col = 0; col + 1 < cols; ++col) {
        tuple        const temp    = tuplerow[col];
        unsigned int const randcol = col + pm_rand(randStP) % (cols - col);

        assert(randcol >= col );
        assert(randcol < cols);

        /* swap */
        tuplerow[col]     = tuplerow[randcol];
        tuplerow[randcol] = temp;
    }
}



int
main(int argc, const char * argv[]) {

    FILE * ifP;
    int    eof;     /* no more images in input stream */

    struct CmdlineInfo cmdline;
    struct pam inpam;   /* Input PAM image */
    struct pam outpam;  /* Output PAM image */
    struct pm_randSt randSt;

    pm_proginit(&argc, argv);

    parseCommandLine(argc, argv, &cmdline);

    ifP = pm_openr(cmdline.inputFileName);

    pm_randinit(&randSt);
    pm_srand2(&randSt, cmdline.randomseedSpec, cmdline.randomseed);

    for (eof = FALSE; !eof;) {
        tuple * inrow;   /* Input row buffer */
        tuple * outrow;  /* Pointers into the input row buffer to reorder it */
        unsigned int row, col;

        pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));

        outpam = inpam;
        outpam.file = stdout;

        pnm_writepaminit(&outpam);

        inrow = pnm_allocpamrow(&inpam);

        MALLOCARRAY(outrow, inpam.width);

        if (!outrow)
            pm_error("Unable to allocate memory for %u-column output buffer",
                     inpam.width);

        for (col = 0; col < inpam.width; ++col)
            outrow[col] = inrow[col];

        for (row = 0; row < inpam.height; ++row) {
            pnm_readpamrow(&inpam, inrow);

            if (cmdline.column && row > 0) {
                /* Use the same shuffle ('outrow') as the previous row */
            } else
                shuffleRow(outrow, inpam.width, &randSt);

            pnm_writepamrow(&outpam, outrow);
        }

        pnm_freepamrow(inrow);
        free(outrow);
        pnm_nextimage(ifP, &eof);
    }

    pm_randterm(&randSt);

    return 0;
}