Image Demosaicking with Contour Stencils
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
dmcswl1cli.c
Go to the documentation of this file.
1 
21 #include <math.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include "imageio.h"
25 #include "dmcswl1.h"
26 #include "displaycontours.h"
27 
28 /* Program defaults */
29 #define DEFAULT_ALPHA 1.8
30 #define DEFAULT_EPSILON 0.15
31 #define DEFAULT_SIGMA 0.6
32 #define DEFAULT_TOL 0.001
33 #define DEFAULT_MAXITER 250
34 
35 /* Print verbose information if nonzero */
36 #define VERBOSE 1
37 
38 
40 typedef struct
41 {
43  char *InputFile;
45  char *OutputFile;
47  int JpegQuality;
49  int RedX;
51  int RedY;
57  float Alpha;
59  float Epsilon;
61  float Sigma;
63  float Tol;
65  int MaxIter;
67 
68 
69 static int ParseParams(programparams *Param, int argc, char *argv[]);
70 
71 
73 static void PrintHelpMessage()
74 {
75  printf("Contour stencils weighted L1 demosaicing demo, P. Getreuer 2010-2011\n\n");
76  printf("Usage: dmcswl1 [options] <input file> <output file>\n\n"
77  "Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n\n");
78  printf("Options:\n");
79  printf(" -p <pattern> CFA pattern, choices for <pattern> are\n");
80  printf(" RGGB upperleftmost red pixel is at (0,0)\n");
81  printf(" GRBG upperleftmost red pixel is at (1,0)\n");
82  printf(" GBRG upperleftmost red pixel is at (0,1)\n");
83  printf(" BGGR upperleftmost red pixel is at (1,1)\n\n");
84  printf(" -s Show estimated contours instead of demosaicing.\n"
85  " The output is written as an EPS file.\n");
86  printf(" -E Display energy value after each iteration.\n\n");
87  printf(" -a <number> alpha, chroma weight (default 1.8)\n");
88  printf(" -e <number> epsilon, graph weight (default 0.15)\n");
89  printf(" -f <number> sigma, graph spatial filtering parameter (default 0.6)\n");
90  printf(" -t <number> convergence tolerance (default 0.001)\n");
91  printf(" -m <number> maximum number of iterations (default 250)\n\n");
92 #ifdef USE_LIBJPEG
93  printf(" -q <number> Quality for saving JPEG images (0 to 100)\n\n");
94 #endif
95  printf("Examples: \n"
96  " dmcswl1 -p RGGB frog.bmp frog-dm.bmp\n"
97  " dmcswl1 -p RGGB -s frog.bmp frog-contours.eps\n");
98 }
99 
100 
101 int main(int argc, char *argv[])
102 {
103  programparams Param;
104  float *Image = NULL;
105  int Width, Height, Status = 1;
106 
107  if(!ParseParams(&Param, argc, argv))
108  return 0;
109 
110  /* Read the input image */
111  if(!(Image = (float *)ReadImage(&Width, &Height,
112  Param.InputFile, IMAGEIO_FLOAT | IMAGEIO_RGB | IMAGEIO_PLANAR)))
113  goto Catch;
114 
115  if(Width < 4 || Height < 4)
116  {
117  ErrorMessage("Image is too small (%dx%d).\n", Width, Height);
118  goto Catch;
119  }
120 
121  if(Param.ShowContours)
122  {
123  if(!(DisplayContours(Image, Width, Height,
124  Param.RedX, Param.RedY, Param.OutputFile)))
125  goto Catch;
126 #if VERBOSE > 0
127  else
128  printf("Output written to \"%s\".\n", Param.OutputFile);
129 #endif
130  }
131  else
132  {
133  /* Perform demosaicing */
134  if(!(CSWL1Demosaic(Image, Width, Height, Param.RedX, Param.RedY,
135  Param.Alpha, Param.Epsilon, Param.Sigma,
136  Param.Tol, Param.MaxIter, Param.ShowEnergy)))
137  {
138  ErrorMessage("Error in computation.\n");
139  goto Catch;
140  }
141 
142  /* Write the output image */
143  if(!WriteImage(Image, Width, Height, Param.OutputFile,
144  IMAGEIO_FLOAT | IMAGEIO_RGB | IMAGEIO_PLANAR, Param.JpegQuality))
145  {
146  ErrorMessage("Error writing \"%s\".\n", Param.OutputFile);
147  goto Catch;
148  }
149 #if VERBOSE > 0
150  else
151  printf("Output written to \"%s\".\n", Param.OutputFile);
152 #endif
153  }
154 
155  Status = 0; /* Finished successfully, set exit status to zero. */
156 Catch:
157  Free(Image);
158  return Status;
159 }
160 
161 
163 static int ParseParams(programparams *Param, int argc, char *argv[])
164 {
165  static char *DefaultOutputFile = (char *)"out.bmp";
166  char *OptionString;
167  char OptionChar;
168  int i;
169 
170  if(argc < 2)
171  {
173  return 0;
174  }
175 
176  /* Set parameter defaults */
177  Param->InputFile = 0;
178  Param->OutputFile = DefaultOutputFile;
179  Param->JpegQuality = 80;
180  Param->RedX = 0;
181  Param->RedY = 0;
182  Param->ShowContours = 0;
183  Param->ShowEnergy = 0;
184  Param->Alpha = (float)DEFAULT_ALPHA;
185  Param->Epsilon = (float)DEFAULT_EPSILON;
186  Param->Sigma = (float)DEFAULT_SIGMA;
187  Param->Tol = (float)DEFAULT_TOL;
188  Param->MaxIter = DEFAULT_MAXITER;
189 
190  for(i = 1; i < argc;)
191  {
192  if(argv[i] && argv[i][0] == '-')
193  {
194  if((OptionChar = argv[i][1]) == 0)
195  {
196  ErrorMessage("Invalid parameter format.\n");
197  return 0;
198  }
199 
200  if(argv[i][2])
201  OptionString = &argv[i][2];
202  else if(++i < argc)
203  OptionString = argv[i];
204  else
205  {
206  ErrorMessage("Invalid parameter format.\n");
207  return 0;
208  }
209 
210  switch(OptionChar) /* Parse option flag */
211  {
212  case 'p':
213  if(!strcmp(OptionString, "RGGB")
214  || !strcmp(OptionString, "rggb"))
215  {
216  Param->RedX = 0;
217  Param->RedY = 0;
218  }
219  else if(!strcmp(OptionString, "GRBG")
220  || !strcmp(OptionString, "grbg"))
221  {
222  Param->RedX = 1;
223  Param->RedY = 0;
224  }
225  else if(!strcmp(OptionString, "GBRG")
226  || !strcmp(OptionString, "gbrg"))
227  {
228  Param->RedX = 0;
229  Param->RedY = 1;
230  }
231  else if(!strcmp(OptionString, "BGGR")
232  || !strcmp(OptionString, "bggr"))
233  {
234  Param->RedX = 1;
235  Param->RedY = 1;
236  }
237  else
238  ErrorMessage("CFA pattern must be RGGB, GRBG, GBRG, or BGGR\n");
239  break;
240  case 's':
241  Param->ShowContours = 1;
242  i--;
243  break;
244  case 'E':
245  Param->ShowEnergy = 1;
246  i--;
247  break;
248  case 'a':
249  Param->Alpha = (float)atof(OptionString);
250 
251  if(Param->Alpha <= 0)
252  {
253  ErrorMessage("Chroma weight must be positive.\n");
254  return 0;
255  }
256  break;
257  case 'e':
258  Param->Epsilon = (float)atof(OptionString);
259 
260  if(Param->Epsilon <= 0)
261  {
262  ErrorMessage("Epsilon must be positive.\n");
263  return 0;
264  }
265  break;
266  case 'f':
267  Param->Sigma = (float)atof(OptionString);
268 
269  if(Param->Sigma < 0)
270  {
271  ErrorMessage("Sigma must be nonnegative.\n");
272  return 0;
273  }
274  break;
275  case 't':
276  Param->Tol = (float)atof(OptionString);
277 
278  if(Param->Tol <= 0)
279  {
280  ErrorMessage("Convergence tolerance must be positive.\n");
281  return 0;
282  }
283  break;
284  case 'm':
285  Param->MaxIter = atoi(OptionString);
286 
287  if(Param->MaxIter < 0)
288  {
289  ErrorMessage("Maximum number of iterations must be nonnegative.\n");
290  return 0;
291  }
292  break;
293 
294 #ifdef USE_LIBJPEG
295  case 'q':
296  Param->JpegQuality = atoi(OptionString);
297 
298  if(Param->JpegQuality <= 0 || Param->JpegQuality > 100)
299  {
300  ErrorMessage("JPEG quality must be between 0 and 100.\n");
301  return 0;
302  }
303  break;
304 #endif
305  case '-':
307  return 0;
308  default:
309  if(isprint(OptionChar))
310  ErrorMessage("Unknown option \"-%c\".\n", OptionChar);
311  else
312  ErrorMessage("Unknown option.\n");
313 
314  return 0;
315  }
316 
317  i++;
318  }
319  else
320  {
321  if(!Param->InputFile)
322  Param->InputFile = argv[i];
323  else
324  Param->OutputFile = argv[i];
325 
326  i++;
327  }
328  }
329 
330  if(!Param->InputFile)
331  {
333  return 0;
334  }
335 
336  return 1;
337 }