https://doi.org/10.5201/ipol.2011.g_iics
Tip revision: 2f369309d6656c6bbbe0c0533385c5838cd165bc authored by Software Heritage on 01 January 2010, 00:00:00 UTC
ipol: Deposit 692 in collection ipol
ipol: Deposit 692 in collection ipol
Tip revision: 2f36930
cwinterpcli.c
/**
* @file cwinterpcli.c
* @brief Image Interpolation with Contour Stencils command line program
* @author Pascal Getreuer <getreuer@gmail.com>
*
*
* Copyright (c) 2010-2011, Pascal Getreuer
* All rights reserved.
*
* This program is free software: you can use, modify and/or
* redistribute it under the terms of the simplified BSD License. You
* should have received a copy of this license along this program. If
* not, see <http://www.opensource.org/licenses/bsd-license.html>.
*/
/**
* @mainpage
* @htmlinclude readme.html
*/
#include <math.h>
#include <string.h>
#include <ctype.h>
#include "imageio.h"
#include "cwinterp.h"
/** @brief Set to 1 for informative program output, 0 for quiet */
#define VERBOSE 0
/** @brief struct representing an image */
typedef struct
{
/** @brief 32-bit RGBA image data */
uint32_t *Data;
/** @brief Image width */
int Width;
/** @brief Image height */
int Height;
} image;
/** @brief struct of program parameters */
typedef struct
{
/** @brief Input file name */
char *InputFile;
/** @brief Output file name */
char *OutputFile;
/** @brief If true, only show the estimated contour orientations */
int OnlyShowContours;
/** @brief Quality for saving JPEG images (0 to 100) */
int JpegQuality;
/** @brief interpolation parameters */
cwparams Cw;
int TestFlag;
} programparams;
static int ParseParams(programparams *Param, int argc, char *argv[]);
static void PrintHelpMessage()
{
printf("Image Interpolation with Contour Stencils, P. Getreuer 2010-2011\n\n");
printf("Usage: cwinterp [options] <input file> <output file>\n\n"
"Only " READIMAGE_FORMATS_SUPPORTED " images are supported.\n\n");
printf("Options:\n");
printf(" -x <number> the scale factor (may be non-integer)\n");
printf(" -p <number> sigma_h, the blur size of the point spread function\n");
printf(" -g <grid> grid to use for resampling, choices for <grid> are\n"
" centered grid with centered alignment (default)\n"
" topleft the top-left anchored grid\n\n");
printf(" -s show the estimated orientations instead of interpolating\n\n");
printf(" -t <number> sigma_tau, spread of phi in the tagential direction\n");
printf(" -n <number> sigma_nu, spread of phi in the normal direction\n");
printf(" -r <number> the number of refinement passes\n");
#ifdef LIBJPEG_SUPPORT
printf(" -q <number> quality for saving JPEG images (0 to 100)\n\n");
#endif
printf("Example: 4x scaling, sigma_h = 0.35, 2 refinement passes\n"
" cwinterp -x 4 -p 0.35 -r 2 frog.bmp frog-4x.bmp\n");
}
int main(int argc, char *argv[])
{
programparams Param;
image v = {NULL, 0, 0}, u = {NULL, 0, 0};
int32_t *Psi = NULL;
int Status = 1;
/* Parse command line parameters */
if(!ParseParams(&Param, argc, argv))
return 0;
/* Perform precomputations (but not when only showing contours) */
if(!Param.OnlyShowContours)
if(!(Psi = PreCWInterp(Param.Cw)))
goto Catch;
/* Read the input image */
if(!(v.Data = (uint32_t *)ReadImage(&v.Width, &v.Height, Param.InputFile,
IMAGEIO_U8 | IMAGEIO_RGBA)))
goto Catch;
/* Allocate the output image */
u.Width = (int)ceil(Param.Cw.ScaleFactor * v.Width);
u.Height = (int)ceil(Param.Cw.ScaleFactor * v.Height);
if(!(u.Data = (uint32_t *)Malloc(sizeof(uint32_t)*
((long int)u.Width)*((long int)u.Height))))
goto Catch;
if(!Param.OnlyShowContours)
{
if(!Param.TestFlag && Param.Cw.ScaleFactor == ceil(Param.Cw.ScaleFactor))
{
printf("Integer scale factor %dx%d input -> %dx%d output\n",
v.Width, v.Height, u.Width, u.Height);
/* Perform interpolation by an integer scale factor. */
if(!CWInterp(u.Data, v.Data, v.Width, v.Height, Psi, Param.Cw))
goto Catch;
}
else
{
printf("Arbitrary scale factor %dx%d input -> %dx%d output\n",
v.Width, v.Height, u.Width, u.Height);
/* Perform interpolation by an arbitrary scale factor. */
if(!CWInterpEx(u.Data, u.Width, u.Height,
v.Data, v.Width, v.Height, Psi, Param.Cw))
goto Catch;
}
}
else
{
/* Program has been called with the -s flag. Show the contour
orientation estimates using on the best-fitting contour stencils. */
if(!(DisplayContours(u.Data, u.Width, u.Height,
v.Data, v.Width, v.Height, Param.Cw)))
goto Catch;
}
/* Write the output image */
if(!WriteImage(u.Data, u.Width, u.Height, Param.OutputFile,
IMAGEIO_U8 | IMAGEIO_RGBA, Param.JpegQuality))
goto Catch;
#if VERBOSE > 0
else
printf("Output written to \"%s\".\n", Param.OutputFile);
#endif
Status = 0; /* Finished successfully, set exit status to zero. */
Catch: /* This label is used for error handling. If something went wrong
above (which may be out of memory, file not found, or a computation
error), then execution jumps to this point to clean up and exit. */
Free(u.Data);
Free(v.Data);
Free(Psi);
return Status;
}
static int ParseParams(programparams *Param, int argc, char *argv[])
{
static char *DefaultOutputFile = (char *)"out.bmp";
char *OptionString;
char OptionChar;
int i;
if(argc < 2)
{
PrintHelpMessage();
return 0;
}
/* Set parameter defaults */
Param->InputFile = 0;
Param->OutputFile = DefaultOutputFile;
Param->OnlyShowContours = 0;
Param->JpegQuality = 70;
Param->Cw.ScaleFactor = 4;
Param->Cw.CenteredGrid = 1;
Param->Cw.RefinementSteps = 2;
Param->Cw.PsfSigma = 0.35;
Param->Cw.PhiSigmaTangent = 1.2;
Param->Cw.PhiSigmaNormal = 0.6;
Param->TestFlag = 0;
for(i = 1; i < argc;)
{
if(argv[i] && argv[i][0] == '-')
{
if((OptionChar = argv[i][1]) == 0)
{
ErrorMessage("Invalid parameter format.\n");
return 0;
}
if(argv[i][2])
OptionString = &argv[i][2];
else if(++i < argc)
OptionString = argv[i];
else
{
ErrorMessage("Invalid parameter format.\n");
return 0;
}
switch(OptionChar)
{
case 'x':
Param->Cw.ScaleFactor = atof(OptionString);
if(Param->Cw.ScaleFactor < 1)
{
ErrorMessage("Scale factor cannot be less than 1.0.\n");
return 0;
}
break;
case 'g':
if(!strcmp(OptionString, "centered")
|| !strcmp(OptionString, "center"))
Param->Cw.CenteredGrid = 1;
else if(!strcmp(OptionString, "topleft")
|| !strcmp(OptionString, "top-left"))
Param->Cw.CenteredGrid = 0;
else
{
ErrorMessage("Grid must be either \"centered\" or \"topleft\".\n");
return 0;
}
break;
case 'r':
Param->Cw.RefinementSteps = atoi(OptionString);
if(Param->Cw.RefinementSteps < 0)
{
ErrorMessage("Invalid number of refinement passes.\n");
return 0;
}
break;
case 'p':
Param->Cw.PsfSigma = atof(OptionString);
if(Param->Cw.PsfSigma < 0.0)
{
ErrorMessage("Point spread blur size must be nonnegative.\n");
return 0;
}
else if(Param->Cw.PsfSigma > 2.0)
{
ErrorMessage("Point spread blur size is too large.\n");
return 0;
}
break;
case 't':
Param->Cw.PhiSigmaTangent = atof(OptionString);
if(Param->Cw.PhiSigmaTangent <= 0.0)
{
ErrorMessage("sigma_tau must be positive.\n");
return 0;
}
break;
case 'n':
Param->Cw.PhiSigmaNormal = atof(OptionString);
if(Param->Cw.PhiSigmaNormal <= 0.0)
{
ErrorMessage("sigma_nu must be positive.\n");
return 0;
}
break;
case 's':
Param->OnlyShowContours = 1;
i--;
break;
case 'T':
Param->TestFlag = atoi(OptionString);
break;
#ifdef LIBJPEG_SUPPORT
case 'q':
Param->JpegQuality = atoi(OptionString);
if(Param->JpegQuality <= 0 || Param->JpegQuality > 100)
{
ErrorMessage("JPEG quality must be between 0 and 100.\n");
return 0;
}
break;
#endif
case '-':
PrintHelpMessage();
return 0;
default:
if(isprint(OptionChar))
ErrorMessage("Unknown option \"-%c\".\n", OptionChar);
else
ErrorMessage("Unknown option.\n");
return 0;
}
i++;
}
else
{
if(!Param->InputFile)
Param->InputFile = argv[i];
else
Param->OutputFile = argv[i];
i++;
}
}
if(!Param->InputFile)
{
PrintHelpMessage();
return 0;
}
if(Param->Cw.PsfSigma == 0)
Param->Cw.RefinementSteps = 0;
if(!Param->OnlyShowContours)
{
/* Display the chosen parameters */
printf("Factor-%g interpolation, ", Param->Cw.ScaleFactor);
if(Param->Cw.CenteredGrid)
printf("centered grid, ");
else
printf("top-left grid, ");
if(Param->Cw.RefinementSteps == 1)
printf("1 refinement pass,");
else if(Param->Cw.RefinementSteps > 1)
printf("%d refinement passes,", Param->Cw.RefinementSteps);
printf("\nsigma_h = %g, sigma_tau = %g, sigma_nu = %g\n",
Param->Cw.PsfSigma, Param->Cw.PhiSigmaTangent,
Param->Cw.PhiSigmaNormal);
}
return 1;
}