Image Interpolation with Contour Stencils

cwinterpcli.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines