|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Pnmsharpness
|
|
Packit |
78deda |
------------------------------------------------------------------------------
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Bryan Henderson derived this (January 2004) from the program of the
|
|
Packit |
78deda |
same name by B.W. van Schooten and distributed to Bryan under the Perl
|
|
Packit |
78deda |
Artistic License, as part of the Photopnmtools package. Bryan placed
|
|
Packit |
78deda |
his modifications in the public domain.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
This is the copyright/license notice from the original:
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Copyright (c) 2002, 2003 by B.W. van Schooten. All rights reserved.
|
|
Packit |
78deda |
This software is distributed under the Perl Artistic License.
|
|
Packit |
78deda |
No warranty. See file 'artistic.license' for more details.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
boris@13thmonkey.org
|
|
Packit |
78deda |
www.13thmonkey.org/~boris/photopnmtools/
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <stdio.h>
|
|
Packit |
78deda |
#include <math.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
#include "shhopt.h"
|
|
Packit |
78deda |
#include "pam.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo {
|
|
Packit |
78deda |
/* All the information the user supplied in the command line,
|
|
Packit |
78deda |
in a form easy for the program to use.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
const char *inputFilespec; /* '-' if stdin */
|
|
Packit |
78deda |
unsigned int context;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int argc, char ** argv,
|
|
Packit |
78deda |
struct cmdlineInfo *cmdlineP) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
parse program command line described in Unix standard form by argc
|
|
Packit |
78deda |
and argv. Return the information in the options as *cmdlineP.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
If command line is internally inconsistent (invalid options, etc.),
|
|
Packit |
78deda |
issue error message to stderr and abort program.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Note that the strings we return are stored in the storage that
|
|
Packit |
78deda |
was passed to us as the argv array. We also trash *argv.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
optEntry * option_def;
|
|
Packit |
78deda |
/* Instructions to pm_optParseOptions3 on how to parse our options.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
optStruct3 opt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int option_def_index;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int contextSpec;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(option_def, 100);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
option_def_index = 0; /* incremented by OPTENT3 */
|
|
Packit |
78deda |
OPTENT3(0, "context", OPT_UINT, &cmdlineP->context,
|
|
Packit |
78deda |
&contextSpec, 0 );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
opt.opt_table = option_def;
|
|
Packit |
78deda |
opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
|
|
Packit |
78deda |
opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_optParseOptions3( &argc, argv, opt, sizeof(opt), 0);
|
|
Packit |
78deda |
/* Uses and sets argc, argv, and some of *cmdlineP and others. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!contextSpec)
|
|
Packit |
78deda |
cmdlineP->context = 1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (cmdlineP->context < 1)
|
|
Packit |
78deda |
pm_error("-context must be at least 1");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 > 1)
|
|
Packit |
78deda |
pm_error("The only argument is the input file name");
|
|
Packit |
78deda |
else if (argc-1 < 1)
|
|
Packit |
78deda |
cmdlineP->inputFilespec = "-";
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
cmdlineP->inputFilespec = argv[1];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(option_def);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
computeSharpness(struct pam * const inpamP,
|
|
Packit |
78deda |
tuplen ** const tuplenarray,
|
|
Packit |
78deda |
double * const sharpnessP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int row;
|
|
Packit |
78deda |
double totsharp;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
totsharp = 0.0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 1; row < inpamP->height-1; ++row) {
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
for (col = 1; col < inpamP->width-1; ++col) {
|
|
Packit |
78deda |
int dy;
|
|
Packit |
78deda |
for (dy = -1; dy <= 1; ++dy) {
|
|
Packit |
78deda |
int dx;
|
|
Packit |
78deda |
for (dx = -1; dx <= 1; ++dx) {
|
|
Packit |
78deda |
if (dx != 0 || dy != 0) {
|
|
Packit |
78deda |
unsigned int plane;
|
|
Packit |
78deda |
for (plane = 0; plane < inpamP->depth; ++plane) {
|
|
Packit |
78deda |
samplen const sampleval =
|
|
Packit |
78deda |
tuplenarray[row][col][plane];
|
|
Packit |
78deda |
samplen const sampleval2 =
|
|
Packit |
78deda |
tuplenarray[row+dy][col+dx][plane];
|
|
Packit |
78deda |
totsharp += fabs(sampleval - sampleval2);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*sharpnessP =
|
|
Packit |
78deda |
totsharp / (inpamP->width * inpamP->height * inpamP->depth * 8);
|
|
Packit |
78deda |
/* The 8 above is for the 8 neighbors to which we compare each pixel */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, char **argv) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo cmdline;
|
|
Packit |
78deda |
FILE * ifP;
|
|
Packit |
78deda |
tuplen ** tuplenarray;
|
|
Packit |
78deda |
struct pam inpam;
|
|
Packit |
78deda |
double sharpness;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_init(&argc, argv);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ifP = pm_openr(cmdline.inputFilespec);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
tuplenarray = pnm_readpamn(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (inpam.height < 3 || inpam.width < 3)
|
|
Packit |
78deda |
pm_error("sharpness is undefined for an image less than 3 pixels "
|
|
Packit |
78deda |
"in all directions. This image is %d x %d",
|
|
Packit |
78deda |
inpam.width, inpam.height);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
computeSharpness(&inpam, tuplenarray, &sharpness);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
printf("Sharpness = %f\n", sharpness);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_freepamarrayn(tuplenarray, &inpam);
|
|
Packit |
78deda |
pm_close(ifP);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|