Image Interpolation with Contour Stencils
|
00001 00021 #include <math.h> 00022 #include <string.h> 00023 #include <ctype.h> 00024 00025 #include "imageio.h" 00026 #include "cwinterp.h" 00027 00029 #define VERBOSE 0 00030 00032 typedef struct 00033 { 00035 uint32_t *Data; 00037 int Width; 00039 int Height; 00040 } image; 00041 00043 typedef struct 00044 { 00046 char *InputFile; 00048 char *OutputFile; 00050 int OnlyShowContours; 00052 int JpegQuality; 00054 cwparams Cw; 00055 00056 int TestFlag; 00057 } programparams; 00058 00059 00060 static int ParseParams(programparams *Param, int argc, char *argv[]); 00061 00062 00063 static void PrintHelpMessage() 00064 { 00065 printf("Image Interpolation with Contour Stencils, P. Getreuer 2010-2011\n\n"); 00066 printf("Usage: cwinterp [options] <input file> <output file>\n\n" 00067 "Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n\n"); 00068 printf("Options:\n"); 00069 printf(" -x <number> the scale factor (may be non-integer)\n"); 00070 printf(" -p <number> sigma_h, the blur size of the point spread function\n"); 00071 printf(" -g <grid> grid to use for resampling, choices for <grid> are\n" 00072 " centered grid with centered alignment (default)\n" 00073 " topleft the top-left anchored grid\n\n"); 00074 printf(" -s show the estimated orientations instead of interpolating\n\n"); 00075 printf(" -t <number> sigma_tau, spread of phi in the tagential direction\n"); 00076 printf(" -n <number> sigma_nu, spread of phi in the normal direction\n"); 00077 printf(" -r <number> the number of refinement passes\n"); 00078 #ifdef LIBJPEG_SUPPORT 00079 printf(" -q <number> quality for saving JPEG images (0 to 100)\n\n"); 00080 #endif 00081 printf("Example: 4x scaling, sigma_h = 0.35, 2 refinement passes\n" 00082 " cwinterp -x 4 -p 0.35 -r 2 frog.bmp frog-4x.bmp\n"); 00083 } 00084 00085 int main(int argc, char *argv[]) 00086 { 00087 programparams Param; 00088 image v = {NULL, 0, 0}, u = {NULL, 0, 0}; 00089 int32_t *Psi = NULL; 00090 int Status = 1; 00091 00092 00093 /* Parse command line parameters */ 00094 if(!ParseParams(&Param, argc, argv)) 00095 return 0; 00096 00097 /* Perform precomputations (but not when only showing contours) */ 00098 if(!Param.OnlyShowContours) 00099 if(!(Psi = PreCWInterp(Param.Cw))) 00100 goto Catch; 00101 00102 /* Read the input image */ 00103 if(!(v.Data = (uint32_t *)ReadImage(&v.Width, &v.Height, Param.InputFile, 00104 IMAGEIO_U8 | IMAGEIO_RGBA))) 00105 goto Catch; 00106 00107 /* Allocate the output image */ 00108 u.Width = (int)ceil(Param.Cw.ScaleFactor * v.Width); 00109 u.Height = (int)ceil(Param.Cw.ScaleFactor * v.Height); 00110 00111 if(!(u.Data = (uint32_t *)Malloc(sizeof(uint32_t)* 00112 ((long int)u.Width)*((long int)u.Height)))) 00113 goto Catch; 00114 00115 if(!Param.OnlyShowContours) 00116 { 00117 if(!Param.TestFlag && Param.Cw.ScaleFactor == ceil(Param.Cw.ScaleFactor)) 00118 { 00119 printf("Integer scale factor %dx%d input -> %dx%d output\n", 00120 v.Width, v.Height, u.Width, u.Height); 00121 00122 /* Perform interpolation by an integer scale factor. */ 00123 if(!CWInterp(u.Data, v.Data, v.Width, v.Height, Psi, Param.Cw)) 00124 goto Catch; 00125 } 00126 else 00127 { 00128 printf("Arbitrary scale factor %dx%d input -> %dx%d output\n", 00129 v.Width, v.Height, u.Width, u.Height); 00130 00131 /* Perform interpolation by an arbitrary scale factor. */ 00132 if(!CWInterpEx(u.Data, u.Width, u.Height, 00133 v.Data, v.Width, v.Height, Psi, Param.Cw)) 00134 goto Catch; 00135 } 00136 } 00137 else 00138 { 00139 /* Program has been called with the -s flag. Show the contour 00140 orientation estimates using on the best-fitting contour stencils. */ 00141 if(!(DisplayContours(u.Data, u.Width, u.Height, 00142 v.Data, v.Width, v.Height, Param.Cw))) 00143 goto Catch; 00144 } 00145 00146 /* Write the output image */ 00147 if(!WriteImage(u.Data, u.Width, u.Height, Param.OutputFile, 00148 IMAGEIO_U8 | IMAGEIO_RGBA, Param.JpegQuality)) 00149 goto Catch; 00150 #if VERBOSE > 0 00151 else 00152 printf("Output written to \"%s\".\n", Param.OutputFile); 00153 #endif 00154 00155 Status = 0; /* Finished successfully, set exit status to zero. */ 00156 00157 Catch: /* This label is used for error handling. If something went wrong 00158 above (which may be out of memory, file not found, or a computation 00159 error), then execution jumps to this point to clean up and exit. */ 00160 Free(u.Data); 00161 Free(v.Data); 00162 Free(Psi); 00163 return Status; 00164 } 00165 00166 00167 static int ParseParams(programparams *Param, int argc, char *argv[]) 00168 { 00169 static char *DefaultOutputFile = (char *)"out.bmp"; 00170 char *OptionString; 00171 char OptionChar; 00172 int i; 00173 00174 00175 if(argc < 2) 00176 { 00177 PrintHelpMessage(); 00178 return 0; 00179 } 00180 00181 /* Set parameter defaults */ 00182 Param->InputFile = 0; 00183 Param->OutputFile = DefaultOutputFile; 00184 Param->OnlyShowContours = 0; 00185 Param->JpegQuality = 70; 00186 00187 Param->Cw.ScaleFactor = 4; 00188 Param->Cw.CenteredGrid = 1; 00189 Param->Cw.RefinementSteps = 2; 00190 Param->Cw.PsfSigma = 0.35; 00191 Param->Cw.PhiSigmaTangent = 1.2; 00192 Param->Cw.PhiSigmaNormal = 0.6; 00193 00194 Param->TestFlag = 0; 00195 00196 for(i = 1; i < argc;) 00197 { 00198 if(argv[i] && argv[i][0] == '-') 00199 { 00200 if((OptionChar = argv[i][1]) == 0) 00201 { 00202 ErrorMessage("Invalid parameter format.\n"); 00203 return 0; 00204 } 00205 00206 if(argv[i][2]) 00207 OptionString = &argv[i][2]; 00208 else if(++i < argc) 00209 OptionString = argv[i]; 00210 else 00211 { 00212 ErrorMessage("Invalid parameter format.\n"); 00213 return 0; 00214 } 00215 00216 switch(OptionChar) 00217 { 00218 case 'x': 00219 Param->Cw.ScaleFactor = atof(OptionString); 00220 00221 if(Param->Cw.ScaleFactor < 1) 00222 { 00223 ErrorMessage("Scale factor cannot be less than 1.0.\n"); 00224 return 0; 00225 } 00226 break; 00227 case 'g': 00228 if(!strcmp(OptionString, "centered") 00229 || !strcmp(OptionString, "center")) 00230 Param->Cw.CenteredGrid = 1; 00231 else if(!strcmp(OptionString, "topleft") 00232 || !strcmp(OptionString, "top-left")) 00233 Param->Cw.CenteredGrid = 0; 00234 else 00235 { 00236 ErrorMessage("Grid must be either \"centered\" or \"topleft\".\n"); 00237 return 0; 00238 } 00239 break; 00240 case 'r': 00241 Param->Cw.RefinementSteps = atoi(OptionString); 00242 00243 if(Param->Cw.RefinementSteps < 0) 00244 { 00245 ErrorMessage("Invalid number of refinement passes.\n"); 00246 return 0; 00247 } 00248 break; 00249 case 'p': 00250 Param->Cw.PsfSigma = atof(OptionString); 00251 00252 if(Param->Cw.PsfSigma < 0.0) 00253 { 00254 ErrorMessage("Point spread blur size must be nonnegative.\n"); 00255 return 0; 00256 } 00257 else if(Param->Cw.PsfSigma > 2.0) 00258 { 00259 ErrorMessage("Point spread blur size is too large.\n"); 00260 return 0; 00261 } 00262 break; 00263 case 't': 00264 Param->Cw.PhiSigmaTangent = atof(OptionString); 00265 00266 if(Param->Cw.PhiSigmaTangent <= 0.0) 00267 { 00268 ErrorMessage("sigma_tau must be positive.\n"); 00269 return 0; 00270 } 00271 break; 00272 case 'n': 00273 Param->Cw.PhiSigmaNormal = atof(OptionString); 00274 00275 if(Param->Cw.PhiSigmaNormal <= 0.0) 00276 { 00277 ErrorMessage("sigma_nu must be positive.\n"); 00278 return 0; 00279 } 00280 break; 00281 case 's': 00282 Param->OnlyShowContours = 1; 00283 i--; 00284 break; 00285 00286 case 'T': 00287 Param->TestFlag = atoi(OptionString); 00288 break; 00289 00290 #ifdef LIBJPEG_SUPPORT 00291 case 'q': 00292 Param->JpegQuality = atoi(OptionString); 00293 00294 if(Param->JpegQuality <= 0 || Param->JpegQuality > 100) 00295 { 00296 ErrorMessage("JPEG quality must be between 0 and 100.\n"); 00297 return 0; 00298 } 00299 break; 00300 #endif 00301 case '-': 00302 PrintHelpMessage(); 00303 return 0; 00304 default: 00305 if(isprint(OptionChar)) 00306 ErrorMessage("Unknown option \"-%c\".\n", OptionChar); 00307 else 00308 ErrorMessage("Unknown option.\n"); 00309 00310 return 0; 00311 } 00312 00313 i++; 00314 } 00315 else 00316 { 00317 if(!Param->InputFile) 00318 Param->InputFile = argv[i]; 00319 else 00320 Param->OutputFile = argv[i]; 00321 00322 i++; 00323 } 00324 } 00325 00326 if(!Param->InputFile) 00327 { 00328 PrintHelpMessage(); 00329 return 0; 00330 } 00331 00332 if(Param->Cw.PsfSigma == 0) 00333 Param->Cw.RefinementSteps = 0; 00334 00335 if(!Param->OnlyShowContours) 00336 { 00337 /* Display the chosen parameters */ 00338 printf("Factor-%g interpolation, ", Param->Cw.ScaleFactor); 00339 00340 if(Param->Cw.CenteredGrid) 00341 printf("centered grid, "); 00342 else 00343 printf("top-left grid, "); 00344 00345 if(Param->Cw.RefinementSteps == 1) 00346 printf("1 refinement pass,"); 00347 else if(Param->Cw.RefinementSteps > 1) 00348 printf("%d refinement passes,", Param->Cw.RefinementSteps); 00349 00350 printf("\nsigma_h = %g, sigma_tau = %g, sigma_nu = %g\n", 00351 Param->Cw.PsfSigma, Param->Cw.PhiSigmaTangent, 00352 Param->Cw.PhiSigmaNormal); 00353 } 00354 00355 return 1; 00356 }