1 /******************************************************************************
2 hdifftopam
3 *******************************************************************************
4 This program recovers a PAM image from a horizontal difference images
5 such as created by Pamtohdiff.
6
7 By Bryan Henderson, San Jose, CA 2002.04.15.
8 ******************************************************************************/
9 #include <string.h>
10 #include <stdio.h>
11
12 #include "pm_c_util.h"
13 #include "pam.h"
14 #include "shhopt.h"
15 #include "nstring.h"
16
17 struct cmdlineInfo {
18 /* All the information the user supplied in the command line,
19 in a form easy for the program to use.
20 */
21 const char *inputFilespec; /* Filespecs of input files */
22 unsigned int pnm;
23 unsigned int verbose;
24 };
25
26
27
28 static void
parseCommandLine(int argc,char ** argv,struct cmdlineInfo * const cmdlineP)29 parseCommandLine(int argc, char ** argv,
30 struct cmdlineInfo * const cmdlineP) {
31 /*----------------------------------------------------------------------------
32 Note that the file spec array we return is stored in the storage that
33 was passed to us as the argv array.
34 -----------------------------------------------------------------------------*/
35 optEntry *option_def = malloc( 100*sizeof( optEntry ) );
36 /* Instructions to pm_optParseOptions3 on how to parse our options.
37 */
38 optStruct3 opt;
39
40 unsigned int option_def_index;
41
42 option_def_index = 0; /* incremented by OPTENTRY */
43 OPTENT3(0, "pnm", OPT_FLAG, NULL, &cmdlineP->pnm, 0);
44 OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
45
46 opt.opt_table = option_def;
47 opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
48 opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
49
50 pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
51 /* Uses and sets argc, argv, and some of *cmdlineP and others. */
52
53 if (argc-1 < 1)
54 cmdlineP->inputFilespec = "-";
55 else if (argc-1 == 1)
56 cmdlineP->inputFilespec = argv[1];
57 else
58 pm_error("Too many arguments.");
59 }
60
61
62
63 static void
makePnm(struct pam * const pamP)64 makePnm(struct pam * const pamP) {
65
66 switch (pamP->depth) {
67 case 1:
68 pamP->format = PGM_FORMAT;
69 break;
70 case 3:
71 pamP->format = PPM_FORMAT;
72 break;
73 default:
74 pm_error("Input depth (%d) does not correspond to a PNM format.",
75 pamP->depth);
76 }
77 }
78
79
80
81 static void
describeOutput(struct pam const pam)82 describeOutput(struct pam const pam) {
83
84 pm_message("Output is %d x %d x %d, maxval %u",
85 pam.width, pam.height, pam.depth, (unsigned int) pam.maxval);
86 }
87
88
89
90 int
main(int argc,char * argv[])91 main(int argc, char *argv[]) {
92 FILE *ifP;
93 struct cmdlineInfo cmdline;
94 struct pam diffpam, outpam;
95 unsigned int row;
96 tuple * diffrow;
97 tuple * outrow;
98 tuple * prevrow;
99
100 pnm_init(&argc, argv);
101
102 parseCommandLine(argc, argv, &cmdline);
103
104 ifP = pm_openr(cmdline.inputFilespec);
105
106 pnm_readpaminit(ifP, &diffpam, PAM_STRUCT_SIZE(tuple_type));
107
108 if (diffpam.format != PAM_FORMAT)
109 pm_error("Input must be a PAM file, not PNM");
110 else if (!streq(diffpam.tuple_type, "hdiff"))
111 pm_error("Input tuple type is '%s'. Must be 'hdiff'",
112 diffpam.tuple_type);
113
114 outpam = diffpam;
115 outpam.file = stdout;
116 strcpy(outpam.tuple_type, "unhdiff");
117
118 if (cmdline.verbose)
119 describeOutput(outpam);
120 if (cmdline.pnm)
121 makePnm(&outpam);
122
123 pnm_writepaminit(&outpam);
124
125 diffrow = pnm_allocpamrow(&diffpam);
126 outrow = pnm_allocpamrow(&outpam);
127 prevrow = pnm_allocpamrow(&diffpam);
128
129 pnm_setpamrow(&diffpam, prevrow, 0);
130
131 {
132 unsigned int const bias = diffpam.maxval/2;
133
134 for (row = 0; row < diffpam.height; ++row) {
135 unsigned int col;
136 pnm_readpamrow(&diffpam, diffrow);
137 for (col = 0; col < diffpam.width; ++col) {
138 unsigned int plane;
139 for (plane = 0; plane < diffpam.depth; ++plane) {
140 sample const prevSample = prevrow[col][plane];
141 sample const diffSample = diffrow[col][plane];
142
143 outrow[col][plane] =
144 (-bias + prevSample + diffSample) % (outpam.maxval+1);
145 prevrow[col][plane] = outrow[col][plane];
146 }
147 }
148 pnm_writepamrow(&outpam, outrow);
149 }
150 }
151 pnm_freepamrow(prevrow);
152 pnm_freepamrow(outrow);
153 pnm_freepamrow(diffrow);
154
155 exit(0);
156 }
157
158