Roussos-Maragos Tensor-Driven Diffusion Interpolation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
tdinterpcli.c
Go to the documentation of this file.
1 
18 #include <ctype.h>
19 #include <math.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "imageio.h"
25 #include "tdinterp.h"
26 
27 
28 #define DEFAULT_PSF_SIGMA 0.35
29 #define DEFAULT_K (1.0/255)
30 #define DEFAULT_TOL (3e-4)
31 #define DEFAULT_MAXMETHODITER 50
32 #define DEFAULT_DIFFITER 5
33 
34 #define VERBOSE 0
35 
36 
38 typedef struct
39 {
41  float *Data;
43  int Width;
45  int Height;
46 } image;
47 
48 
50 typedef struct
51 {
53  const char *InputFile;
55  const char *OutputFile;
57  int JpegQuality;
58 
62  double PsfSigma;
63 
65  double K;
67  float Tol;
71  int DiffIter;
73 
74 
75 static int ParseParams(programparams *Param, int argc, char *argv[]);
76 
77 
78 static void PrintHelpMessage()
79 {
80  puts("Tensor-driven diffusion interpolation demo, P. Getreuer 2010-2011\n");
81  puts("Usage: tdinterp [options] <input file> <output file>\n\n"
82  "Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n");
83  puts("Options:");
84  puts(" -x <number> the scale factor (must be integer)");
85  puts(" -p <number> sigma_h, the blur size of the point spread function");
86  puts(" -K <number> K, parameter in constructing the tensor (default 1/255)");
87  puts(" -t <number> tol, convergence tolerance (default 3e-4)");
88  puts(" -N <number> N, maximum number of method iterations (default 50)");
89  puts(" -n <number> n, number of diffusion steps per method iteration (default 5)\n");
90 #ifdef USE_LIBJPEG
91  puts(" -q <number> quality for saving JPEG images (0 to 100)\n");
92 #endif
93  puts("Example: 4x scaling, sigma_h = 0.5\n"
94  " tdinterp -x 4 -p 0.5 frog.bmp frog-4x.bmp");
95 }
96 
97 
98 int main(int argc, char *argv[])
99 {
100  programparams Param;
101  image v = {NULL, 0, 0}, u = {NULL, 0, 0};
102  int Status = 1;
103 
104 
105  if(!ParseParams(&Param, argc, argv))
106  return 0;
107 
108  /* Read the input image */
109  if(!(v.Data = (float *)ReadImage(&v.Width, &v.Height, Param.InputFile,
111  goto Catch;
112 
113  if(v.Width < 3 || v.Height < 3)
114  {
115  ErrorMessage("Image is too small (%dx%d).\n", v.Width, v.Height);
116  goto Catch;
117  }
118 
119  /* Allocate the output image */
120  u.Width = Param.ScaleFactor * v.Width;
121  u.Height = Param.ScaleFactor * v.Height;
122 
123  if(!(u.Data = (float *)Malloc(sizeof(float)*3*
124  ((long int)u.Width)*((long int)u.Height))))
125  goto Catch;
126 
127  /* Call the interpolation routine */
128  if(!(RoussosInterp(u.Data, u.Width, u.Height,
129  v.Data, v.Width, v.Height, Param.PsfSigma, Param.K,
130  Param.Tol, Param.MaxMethodIter, Param.DiffIter)))
131  goto Catch;
132 
133  /* Write the output image */
134  if(!WriteImage(u.Data, u.Width, u.Height, Param.OutputFile,
136  goto Catch;
137 
138  Status = 0; /* Finished successfully, set exit status to zero. */
139 
140 Catch:
141  Free(u.Data);
142  Free(v.Data);
143  return Status;
144 }
145 
146 
147 static int ParseParams(programparams *Param, int argc, char *argv[])
148 {
149  static const char *DefaultOutputFile = (const char *)"out.bmp";
150  char *OptionString;
151  char OptionChar;
152  int i;
153 
154 
155  if(argc < 2)
156  {
158  return 0;
159  }
160 
161  /* Set parameter defaults */
162  Param->InputFile = 0;
163  Param->OutputFile = DefaultOutputFile;
164  Param->JpegQuality = 80;
165 
166  Param->ScaleFactor = 4;
167  Param->PsfSigma = DEFAULT_PSF_SIGMA;
168 
169  Param->K = DEFAULT_K;
170  Param->Tol = (float)DEFAULT_TOL;
172  Param->DiffIter = DEFAULT_DIFFITER;
173 
174  for(i = 1; i < argc;)
175  {
176  if(argv[i] && argv[i][0] == '-')
177  {
178  if((OptionChar = argv[i][1]) == 0)
179  {
180  ErrorMessage("Invalid parameter format.\n");
181  return 0;
182  }
183 
184  if(argv[i][2])
185  OptionString = &argv[i][2];
186  else if(++i < argc)
187  OptionString = argv[i];
188  else
189  {
190  ErrorMessage("Invalid parameter format.\n");
191  return 0;
192  }
193 
194  switch(OptionChar)
195  {
196  case 'x':
197  Param->ScaleFactor = atoi(OptionString);
198 
199  if(Param->ScaleFactor < 1)
200  {
201  ErrorMessage("Scale factor cannot be less than 1.0.\n");
202  return 0;
203  }
204  break;
205  case 'p':
206  Param->PsfSigma = atof(OptionString);
207 
208  if(Param->PsfSigma < 0.0)
209  {
210  ErrorMessage("Point spread blur size must be nonnegative.\n");
211  return 0;
212  }
213  else if(Param->PsfSigma > 1.0)
214  {
215  ErrorMessage("Point spread blur size is too large.\n");
216  return 0;
217  }
218  break;
219  case 'K':
220  Param->K = atof(OptionString);
221 
222  if(Param->K <= 0.0)
223  {
224  ErrorMessage("K must be positive.\n");
225  return 0;
226  }
227  break;
228  case 't':
229  Param->Tol = atof(OptionString);
230 
231  if(Param->Tol <= 0.0)
232  {
233  ErrorMessage("Convergence tolerance must be positive.\n");
234  return 0;
235  }
236  break;
237  case 'N':
238  Param->MaxMethodIter = atoi(OptionString);
239 
240  if(Param->MaxMethodIter < 0)
241  {
242  ErrorMessage("Number of method iterations must be nonnegative.\n");
243  return 0;
244  }
245  break;
246  case 'n':
247  Param->DiffIter = atoi(OptionString);
248 
249  if(Param->DiffIter <= 0)
250  {
251  ErrorMessage("Number of diffusion iterations must be positive.\n");
252  return 0;
253  }
254  break;
255 #ifdef USE_LIBJPEG
256  case 'q':
257  Param->JpegQuality = atoi(OptionString);
258 
259  if(Param->JpegQuality <= 0 || Param->JpegQuality > 100)
260  {
261  ErrorMessage("JPEG quality must be between 0 and 100.\n");
262  return 0;
263  }
264  break;
265 #endif
266  case '-':
268  return 0;
269  default:
270  if(isprint(OptionChar))
271  ErrorMessage("Unknown option \"-%c\".\n", OptionChar);
272  else
273  ErrorMessage("Unknown option.\n");
274 
275  return 0;
276  }
277 
278  i++;
279  }
280  else
281  {
282  if(!Param->InputFile)
283  Param->InputFile = argv[i];
284  else
285  Param->OutputFile = argv[i];
286 
287  i++;
288  }
289  }
290 
291  if(!Param->InputFile)
292  {
294  return 0;
295  }
296 
297  return 1;
298 }