28 #ifndef DOXYGEN_SHOULD_SKIP_THIS
31 #define DEFAULT_PSF_SIGMA 0.35
32 #define DEFAULT_RHO_SIGMA_TANGENT 1.2
33 #define DEFAULT_RHO_SIGMA_NORMAL 0.6
34 #define DEFAULT_REFINEMENT_PASSES 2
41 const float ColorLine[3] = {0.35f, 0.60f, 0.86f};
42 const float ColorCurve1[3] = {0.54f, 0.88f, 0.20f};
43 const float ColorCurve2[3] = {0.98f, 0.91f, 0.22f};
44 const float ColorCorner[3] = {1.00f, 0.17f, 0.16f};
69 double (*Psf)(double, double,
const void *Param);
91 printf(
"Contour stencil interpolation demo, P. Getreuer 2011\n\n");
92 printf(
"Usage: sinterp [options] <input file> <output file>\n\n"
95 printf(
" -x <number> the scale factor\n");
96 printf(
" -p <number> sigma_h, the blur size of the point spread function\n");
97 printf(
" -g <grid> grid to use for resampling, choices for <grid> are\n"
98 " centered grid with centered alignment (default)\n"
99 " topleft the top-left anchored grid\n\n");
100 printf(
" -s show the estimated contours instead of interpolating\n\n");
101 printf(
" -t <number> sigma_tau, spread of rho in the tagential direction\n");
102 printf(
" -n <number> sigma_nu, spread of rho in the normal direction\n");
103 printf(
" -r <number> the number of refinement passes\n\n");
105 printf(
" -q <number> quality for saving JPEG images (0 to 100)\n\n");
107 printf(
"When the -s option is given, the output file may be EPS, SVG, or a\n");
108 printf(
"supported raster format. Only for SVG, the background image must be\n");
109 printf(
"written as a separate (raster) image, with the syntax\n");
110 printf(
" sinterp [options] -s <input file> <output.svg> <bg image file>\n\n");
111 printf(
"Example: 4x scaling, sigma_h = 0.5, 2 refinement passes\n"
112 " sinterp -x 4 -p 0.5 -r 2 frog.bmp frog-4x.bmp\n");
117 static double GaussianPsf(
double x,
double y,
const void *Param)
119 const double Sigma = *((
double *)Param);
120 const double SigmaSqr = Sigma*Sigma;
121 return exp(-(x*x + y*y)/(2.0*SigmaSqr))/(
M_2PI*SigmaSqr);
142 return (x < y) ? x : y;
156 return (fabs(x) < y) ? fabs(x) : y;
163 const double a = *((
const double *)Param);
164 const double a2 = a*a;
165 const double xa = fabs(x)/a2;
166 const double z = (1 - a*y)*(2/(3*a2));
169 if((Temp = xa*xa + z*z*z) >= 0)
172 x0 = pow(xa + Temp, 1.0/3.0)
173 + ((a*y < 1) ? -1:1)*pow(fabs(-xa + Temp), 1.0/3.0);
178 x0 = 2*Temp*cos(acos(xa/(-z*Temp))/3);
182 return sqrt(a2*Temp + 1)*((a/2)*Temp - y);
188 const double a = *((
const double *)Param);
189 const double x = 0.985;
191 return PenDrawQBezier(Pen, -x, 0.5*a*x*x, 0, -0.5*a*x*x, x, 0.5*a*x*x);
203 const int FilterScaleFactor = 2;
205 float *Input = NULL, *Filtered = NULL, *Output = NULL;
206 float *FilterRhoSamples = NULL, *RhoSamples = NULL;
207 int *BestStencil = NULL;
208 unsigned long StartTime0, StartTime;
209 int IntegerScaleFactor = (int)(Param.
ScaleFactor + 0.5);
210 int InputWidth, InputHeight, OutputWidth, OutputHeight, OutputNumEl;
214 printf(
"Interp stencils... \t");
221 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
225 printf(
"Precomputing rho... \t");
238 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
241 if(!(Input = (
float *)
ReadImage(&InputWidth, &InputHeight,
242 Param.
InputFile, IMAGEIO_FLOAT | IMAGEIO_RGB)))
245 OutputWidth = (int)ceil(Param.
ScaleFactor*InputWidth);
246 OutputHeight = (int)ceil(Param.
ScaleFactor*InputHeight);
247 OutputNumEl = 3*OutputWidth*OutputHeight;
248 printf(
"\n%gx interpolation, %dx%d -> %dx%d\n", Param.
ScaleFactor,
249 InputWidth, InputHeight, OutputWidth, OutputHeight);
252 printf(
"centered grid, ");
254 printf(
"top-left grid, ");
257 printf(
"1 refinement pass");
261 printf(
"\nsigma_h = %g, sigma_tau = %g, sigma_nu = %g\n",
265 if(!(Output = (
float *)
Malloc(
sizeof(
float)*3*OutputWidth*OutputHeight))
266 || !(Filtered = (
float *)
Malloc(
sizeof(
float)*3*InputWidth*InputHeight))
267 || !(BestStencil = (
int *)
Malloc(
sizeof(
int)*InputWidth*InputHeight)))
270 StartTime0 =
Clock();
272 printf(
"Fitting stencils... \t");
274 FitStencils(BestStencil, StencilSet, Input, InputWidth, InputHeight);
275 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
279 printf(
"Prefiltering... \t");
282 if(!(
Prefilter(Filtered, BestStencil, FilterRhoSamples,
283 Input, InputWidth, InputHeight, FilterScaleFactor,
288 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
293 printf(
"Interpolating int... \t");
296 for(i = 0; i < OutputNumEl; i++)
305 printf(
"Interpolating arb... \t");
314 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
316 printf(
"Total %7.3f s\n", (
Clock() - StartTime0)*0.001f);
330 Free(FilterRhoSamples);
336 static int StringEndsWith(
const char *String,
const char *Suffix)
338 unsigned i, StringLength = strlen(String), SuffixLength = strlen(Suffix);
340 if(StringLength < SuffixLength)
343 String += StringLength - SuffixLength;
345 for(i = 0; i < SuffixLength; i++)
346 if(tolower(String[i]) != tolower(Suffix[i]))
361 float *Input = NULL, *Output = NULL;
362 int *BestStencil = NULL;
363 unsigned long StartTime;
364 int InputWidth, InputHeight, OutputWidth, OutputHeight;
368 if(!(Input = (
float *)
ReadImage(&InputWidth, &InputHeight,
369 Param.
InputFile, IMAGEIO_FLOAT | IMAGEIO_RGB)))
372 OutputWidth = (int)ceil(Param.
ScaleFactor*InputWidth);
373 OutputHeight = (int)ceil(Param.
ScaleFactor*InputHeight);
375 if(!(BestStencil = (
int *)
Malloc(
sizeof(
int)*InputWidth*InputHeight)))
378 printf(
"Fitting stencils... \t");
380 FitStencils(BestStencil, StencilSet, Input, InputWidth, InputHeight);
381 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
383 if(!(Output = (
float *)
Malloc(
sizeof(
float)*3*OutputWidth*OutputHeight)))
386 printf(
"Drawing contours... \t");
393 BestStencil, StencilSet, Input, InputWidth, InputHeight))
396 else if(StringEndsWith(Param.
OutputFile,
".svg"))
400 BestStencil, StencilSet,
401 Input, InputWidth, InputHeight))
408 Input, InputWidth, InputHeight))
412 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
422 int main(
int argc,
char *argv[])
426 static const double a2 = 1;
428 unsigned long StartTime;
436 printf(
"Building stencils... \t");
443 for(S = 0; S < 32; S++)
447 for(S = 0; S < 8; S++)
451 for(S = 0; S < 8; S++)
455 for(S = 0; S < 8; S++)
459 printf(
"%7.3f s\n", (
Clock() - StartTime)*0.001f);
489 static const char *DefaultOutputFile = (
const char *)
"out.bmp";
511 Param->
Psf = GaussianPsf;
512 Param->
PsfParam = DEFAULT_PSF_SIGMA;
518 for(i = 1; i < argc;)
520 if(argv[i] && argv[i][0] ==
'-')
522 if((OptionChar = argv[i][1]) == 0)
529 OptionString = &argv[i][2];
531 OptionString = argv[i];
545 ErrorMessage(
"Scale factor cannot be less than 1.0.\n");
550 if(!strcmp(OptionString,
"centered")
551 || !strcmp(OptionString,
"center"))
553 else if(!strcmp(OptionString,
"topleft")
554 || !strcmp(OptionString,
"top-left"))
558 ErrorMessage(
"Grid must be either \"centered\" or \"topleft\".\n");
572 Param->
PsfParam = atof(OptionString);
576 ErrorMessage(
"Point spread blur size must be nonnegative.\n");
614 ErrorMessage(
"JPEG quality must be between 0 and 100.\n");
623 if(isprint(OptionChar))