Image Interpolation with Contour Stencils
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
cwinterpcli.c
Go to the documentation of this file.
1 
21 #include <math.h>
22 #include <string.h>
23 #include <ctype.h>
24 
25 #include "imageio.h"
26 #include "cwinterp.h"
27 
29 #define VERBOSE 0
30 
32 typedef struct
33 {
35  uint32_t *Data;
37  int Width;
39  int Height;
40 } image;
41 
43 typedef struct
44 {
46  char *InputFile;
48  char *OutputFile;
55 
56  int TestFlag;
58 
59 
60 static int ParseParams(programparams *Param, int argc, char *argv[]);
61 
62 
63 static void PrintHelpMessage()
64 {
65  puts("Image Interpolation with Contour Stencils, P. Getreuer 2010-2011\n");
66  puts("Usage: cwinterp [options] <input file> <output file>\n\n"
67  "Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n");
68  puts("Options:");
69  puts(" -x <number> the scale factor (may be non-integer)");
70  puts(" -p <number> sigma_h, the blur size of the point spread function");
71  puts(" -g <grid> grid to use for resampling, choices for <grid> are\n"
72  " centered grid with centered alignment (default)\n"
73  " topleft the top-left anchored grid\n");
74  puts(" -s "
75  "show the estimated orientations instead of interpolating\n");
76  puts(" -t <number> sigma_tau, spread of phi in the tagential direction");
77  puts(" -n <number> sigma_nu, spread of phi in the normal direction");
78  puts(" -r <number> the number of refinement passes\n");
79 #ifdef USE_LIBJPEG
80  puts(" -q <number> quality for saving JPEG images (0 to 100)\n");
81 #endif
82  puts("Example: 4x scaling, sigma_h = 0.35, 2 refinement passes\n"
83  " cwinterp -x 4 -p 0.35 -r 2 frog.bmp frog-4x.bmp");
84 }
85 
86 int main(int argc, char *argv[])
87 {
88  programparams Param;
89  image v = {NULL, 0, 0}, u = {NULL, 0, 0};
90  int32_t *Psi = NULL;
91  int Status = 1;
92 
93 
94  /* Parse command line parameters */
95  if(!ParseParams(&Param, argc, argv))
96  return 0;
97 
98  /* Perform precomputations (but not when only showing contours) */
99  if(!Param.OnlyShowContours)
100  if(!(Psi = PreCWInterp(Param.Cw)))
101  goto Catch;
102 
103  /* Read the input image */
104  if(!(v.Data = (uint32_t *)ReadImage(&v.Width, &v.Height, Param.InputFile,
106  goto Catch;
107 
108  /* Allocate the output image */
109  u.Width = (int)ceil(Param.Cw.ScaleFactor * v.Width);
110  u.Height = (int)ceil(Param.Cw.ScaleFactor * v.Height);
111 
112  if(!(u.Data = (uint32_t *)Malloc(sizeof(uint32_t)*
113  ((long int)u.Width)*((long int)u.Height))))
114  goto Catch;
115 
116  if(!Param.OnlyShowContours)
117  {
118  if(!Param.TestFlag && Param.Cw.ScaleFactor == ceil(Param.Cw.ScaleFactor))
119  {
120  printf("Integer scale factor %dx%d input -> %dx%d output\n",
121  v.Width, v.Height, u.Width, u.Height);
122 
123  /* Perform interpolation by an integer scale factor. */
124  if(!CWInterp(u.Data, v.Data, v.Width, v.Height, Psi, Param.Cw))
125  goto Catch;
126  }
127  else
128  {
129  printf("Arbitrary scale factor %dx%d input -> %dx%d output\n",
130  v.Width, v.Height, u.Width, u.Height);
131 
132  /* Perform interpolation by an arbitrary scale factor. */
133  if(!CWInterpEx(u.Data, u.Width, u.Height,
134  v.Data, v.Width, v.Height, Psi, Param.Cw))
135  goto Catch;
136  }
137  }
138  else
139  {
140  /* Program has been called with the -s flag. Show the contour
141  orientation estimates using on the best-fitting contour stencils. */
142  if(!(DisplayContours(u.Data, u.Width, u.Height,
143  v.Data, v.Width, v.Height, Param.Cw)))
144  goto Catch;
145  }
146 
147  /* Write the output image */
148  if(!WriteImage(u.Data, u.Width, u.Height, Param.OutputFile,
150  goto Catch;
151 #if VERBOSE > 0
152  else
153  printf("Output written to \"%s\".\n", Param.OutputFile);
154 #endif
155 
156  Status = 0; /* Finished successfully, set exit status to zero. */
157 
158 Catch: /* This label is used for error handling. If something went wrong
159  above (which may be out of memory, file not found, or a computation
160  error), then execution jumps to this point to clean up and exit. */
161  Free(u.Data);
162  Free(v.Data);
163  Free(Psi);
164  return Status;
165 }
166 
167 
168 static int ParseParams(programparams *Param, int argc, char *argv[])
169 {
170  static char *DefaultOutputFile = (char *)"out.bmp";
171  char *OptionString;
172  char OptionChar;
173  int i;
174 
175 
176  if(argc < 2)
177  {
178  PrintHelpMessage();
179  return 0;
180  }
181 
182  /* Set parameter defaults */
183  Param->InputFile = 0;
184  Param->OutputFile = DefaultOutputFile;
185  Param->OnlyShowContours = 0;
186  Param->JpegQuality = 70;
187 
188  Param->Cw.ScaleFactor = 4;
189  Param->Cw.CenteredGrid = 1;
190  Param->Cw.RefinementSteps = 2;
191  Param->Cw.PsfSigma = 0.35;
192  Param->Cw.PhiSigmaTangent = 1.2;
193  Param->Cw.PhiSigmaNormal = 0.6;
194 
195  Param->TestFlag = 0;
196 
197  for(i = 1; i < argc;)
198  {
199  if(argv[i] && argv[i][0] == '-')
200  {
201  if((OptionChar = argv[i][1]) == 0)
202  {
203  ErrorMessage("Invalid parameter format.\n");
204  return 0;
205  }
206 
207  if(argv[i][2])
208  OptionString = &argv[i][2];
209  else if(++i < argc)
210  OptionString = argv[i];
211  else
212  {
213  ErrorMessage("Invalid parameter format.\n");
214  return 0;
215  }
216 
217  switch(OptionChar)
218  {
219  case 'x':
220  Param->Cw.ScaleFactor = atof(OptionString);
221 
222  if(Param->Cw.ScaleFactor < 1)
223  {
224  ErrorMessage("Scale factor cannot be less than 1.0.\n");
225  return 0;
226  }
227  break;
228  case 'g':
229  if(!strcmp(OptionString, "centered")
230  || !strcmp(OptionString, "center"))
231  Param->Cw.CenteredGrid = 1;
232  else if(!strcmp(OptionString, "topleft")
233  || !strcmp(OptionString, "top-left"))
234  Param->Cw.CenteredGrid = 0;
235  else
236  {
237  ErrorMessage("Grid must be either \"centered\" or \"topleft\".\n");
238  return 0;
239  }
240  break;
241  case 'r':
242  Param->Cw.RefinementSteps = atoi(OptionString);
243 
244  if(Param->Cw.RefinementSteps < 0)
245  {
246  ErrorMessage("Invalid number of refinement passes.\n");
247  return 0;
248  }
249  break;
250  case 'p':
251  Param->Cw.PsfSigma = atof(OptionString);
252 
253  if(Param->Cw.PsfSigma < 0.0)
254  {
255  ErrorMessage("Point spread blur size must be nonnegative.\n");
256  return 0;
257  }
258  else if(Param->Cw.PsfSigma > 2.0)
259  {
260  ErrorMessage("Point spread blur size is too large.\n");
261  return 0;
262  }
263  break;
264  case 't':
265  Param->Cw.PhiSigmaTangent = atof(OptionString);
266 
267  if(Param->Cw.PhiSigmaTangent <= 0.0)
268  {
269  ErrorMessage("sigma_tau must be positive.\n");
270  return 0;
271  }
272  break;
273  case 'n':
274  Param->Cw.PhiSigmaNormal = atof(OptionString);
275 
276  if(Param->Cw.PhiSigmaNormal <= 0.0)
277  {
278  ErrorMessage("sigma_nu must be positive.\n");
279  return 0;
280  }
281  break;
282  case 's':
283  Param->OnlyShowContours = 1;
284  i--;
285  break;
286 
287  case 'T':
288  Param->TestFlag = atoi(OptionString);
289  break;
290 
291 #ifdef USE_LIBJPEG
292  case 'q':
293  Param->JpegQuality = atoi(OptionString);
294 
295  if(Param->JpegQuality <= 0 || Param->JpegQuality > 100)
296  {
297  ErrorMessage("JPEG quality must be between 0 and 100.\n");
298  return 0;
299  }
300  break;
301 #endif
302  case '-':
303  PrintHelpMessage();
304  return 0;
305  default:
306  if(isprint(OptionChar))
307  ErrorMessage("Unknown option \"-%c\".\n", OptionChar);
308  else
309  ErrorMessage("Unknown option.\n");
310 
311  return 0;
312  }
313 
314  i++;
315  }
316  else
317  {
318  if(!Param->InputFile)
319  Param->InputFile = argv[i];
320  else
321  Param->OutputFile = argv[i];
322 
323  i++;
324  }
325  }
326 
327  if(!Param->InputFile)
328  {
329  PrintHelpMessage();
330  return 0;
331  }
332 
333  if(Param->Cw.PsfSigma == 0)
334  Param->Cw.RefinementSteps = 0;
335 
336  if(!Param->OnlyShowContours)
337  {
338  /* Display the chosen parameters */
339  printf("Factor-%g interpolation, ", Param->Cw.ScaleFactor);
340 
341  if(Param->Cw.CenteredGrid)
342  printf("centered grid, ");
343  else
344  printf("top-left grid, ");
345 
346  if(Param->Cw.RefinementSteps == 1)
347  printf("1 refinement pass,");
348  else if(Param->Cw.RefinementSteps > 1)
349  printf("%d refinement passes,", Param->Cw.RefinementSteps);
350 
351  printf("\nsigma_h = %g, sigma_tau = %g, sigma_nu = %g\n",
352  Param->Cw.PsfSigma, Param->Cw.PhiSigmaTangent,
353  Param->Cw.PhiSigmaNormal);
354  }
355 
356  return 1;
357 }