Blame analyzer/pamsharpness.c

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
}