41b25f28a4
mindtct is mostly as-is for now, with just a couple of bits ripped out.
683 lines
26 KiB
C
683 lines
26 KiB
C
/*******************************************************************************
|
|
|
|
License:
|
|
This software was developed at the National Institute of Standards and
|
|
Technology (NIST) by employees of the Federal Government in the course
|
|
of their official duties. Pursuant to title 17 Section 105 of the
|
|
United States Code, this software is not subject to copyright protection
|
|
and is in the public domain. NIST assumes no responsibility whatsoever for
|
|
its use by other parties, and makes no guarantees, expressed or implied,
|
|
about its quality, reliability, or any other characteristic.
|
|
|
|
Disclaimer:
|
|
This software was developed to promote biometric standards and biometric
|
|
technology testing for the Federal Government in accordance with the USA
|
|
PATRIOT Act and the Enhanced Border Security and Visa Entry Reform Act.
|
|
Specific hardware and software products identified in this software were used
|
|
in order to perform the software development. In no case does such
|
|
identification imply recommendation or endorsement by the National Institute
|
|
of Standards and Technology, nor does it imply that the products and equipment
|
|
identified are necessarily the best available for the purpose.
|
|
|
|
*******************************************************************************/
|
|
|
|
/***********************************************************************
|
|
LIBRARY: LFS - NIST Latent Fingerprint System
|
|
|
|
FILE: RESULTS.C
|
|
AUTHOR: Michael D. Garris
|
|
DATE: 03/16/1999
|
|
UPDATED: 10/04/1999 Version 2 by MDG
|
|
09/14/2004
|
|
UPDATED: 03/16/2005 by MDG
|
|
|
|
Contains routines useful in visualizing intermediate and final
|
|
results when exercising the NIST Latent Fingerprint System (LFS).
|
|
|
|
***********************************************************************
|
|
ROUTINES:
|
|
write_text_results()
|
|
write_minutiae_XYTQ()
|
|
dump_map()
|
|
drawmap()
|
|
drawmap2()
|
|
drawblocks()
|
|
drawrotgrid()
|
|
dump_link_table()
|
|
|
|
***********************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/param.h>
|
|
#include <lfs.h>
|
|
#include <sunrast.h>
|
|
#include <defs.h>
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: write_text_results - Takes LFS results including minutiae and image
|
|
#cat: maps and writes them to separate formatted text files.
|
|
|
|
Input:
|
|
oroot - root pathname for output files
|
|
m1flag - if flag set, write (X,Y,T)'s out to "*.xyt" file according
|
|
to M1 (ANSI INCITS 378-2004) minutiae representation
|
|
|
|
M1 Rep:
|
|
1. pixel origin top left
|
|
2. direction pointing up the ridge ending or
|
|
bifurcaiton valley
|
|
NIST Internal Rep:
|
|
1. pixel origin bottom left
|
|
2. direction pointing out and away from the
|
|
ridge ending or bifurcation valley
|
|
|
|
iw - image pixel width
|
|
ih - image pixel height
|
|
minutiae - structure containing the detected minutiae
|
|
quality_map - integrated image quality map
|
|
direction_map - direction map
|
|
low_contrast_map - low contrast map
|
|
low_flow_map - low ridge flow map
|
|
high_curve_map - high curvature map
|
|
map_w - width (in blocks) of image maps
|
|
map_h - height (in blocks) of image maps
|
|
Return Code:
|
|
Zero - successful completion
|
|
Negative - system error
|
|
**************************************************************************/
|
|
int write_text_results(char *oroot, const int m1flag,
|
|
const int iw, const int ih,
|
|
const MINUTIAE *minutiae, int *quality_map,
|
|
int *direction_map, int *low_contrast_map,
|
|
int *low_flow_map, int *high_curve_map,
|
|
const int map_w, const int map_h)
|
|
{
|
|
FILE *fp;
|
|
int ret;
|
|
char ofile[MAXPATHLEN];
|
|
|
|
/* 1. Write Minutiae results to text file "<oroot>.min". */
|
|
/* XYT's written in LFS native representation: */
|
|
/* 1. pixel coordinates with origin top-left */
|
|
/* 2. 11.25 degrees quantized integer orientation */
|
|
/* on range [0..31] */
|
|
/* 3. minutiae reliability on range [0.0 .. 1.0] */
|
|
/* with 0.0 lowest and 1.0 highest reliability */
|
|
sprintf(ofile, "%s.%s", oroot, MIN_TXT_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-2);
|
|
}
|
|
/* Print out Image Dimensions Header */
|
|
/* !!!! Image dimension header added 09-13-04 !!!! */
|
|
fprintf(fp, "Image (w,h) %d %d\n", iw, ih);
|
|
/* Print text report from the structure containing detected minutiae. */
|
|
dump_minutiae(fp, minutiae);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-3);
|
|
}
|
|
|
|
/* 2. Write just minutiae XYT's & Qualities to text */
|
|
/* file "<oroot>.xyt". */
|
|
/* */
|
|
/* A. If M1 flag set: */
|
|
/* XYTQ's written according to M1 (ANSI INCITS */
|
|
/* 378-2004) representation: */
|
|
/* 1. pixel coordinates with origin top-left */
|
|
/* 2. orientation in degrees on range [0..360] */
|
|
/* with 0 pointing east and increasing counter */
|
|
/* clockwise */
|
|
/* 3. direction pointing up the ridge ending or */
|
|
/* bifurcaiton valley */
|
|
/* 4. minutiae qualities on integer range [0..100] */
|
|
/* (non-standard) */
|
|
/* */
|
|
/* B. If M1 flag NOT set: */
|
|
/* XYTQ's written according to NIST internal rep. */
|
|
/* 1. pixel coordinates with origin bottom-left */
|
|
/* 2. orientation in degrees on range [0..360] */
|
|
/* with 0 pointing east and increasing counter */
|
|
/* clockwise (same as M1) */
|
|
/* 3. direction pointing out and away from the */
|
|
/* ridge ending or bifurcation valley */
|
|
/* (opposite direction from M1) */
|
|
/* 4. minutiae qualities on integer range [0..100] */
|
|
/* (non-standard) */
|
|
sprintf(ofile, "%s.%s", oroot, XYT_EXT);
|
|
if(m1flag){
|
|
if((ret = write_minutiae_XYTQ(ofile, M1_XYT_REP, minutiae, iw, ih))){
|
|
return(ret);
|
|
}
|
|
}
|
|
else{
|
|
if((ret = write_minutiae_XYTQ(ofile, NIST_INTERNAL_XYT_REP,
|
|
minutiae, iw, ih))){
|
|
return(ret);
|
|
}
|
|
}
|
|
|
|
/* 3. Write Integrated Quality Map results to text file. */
|
|
sprintf(ofile, "%s.%s", oroot, QUALITY_MAP_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-4);
|
|
}
|
|
/* Print a text report from the map. */
|
|
dump_map(fp, quality_map, map_w, map_h);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-5);
|
|
}
|
|
|
|
/* 4. Write Direction Map results to text file. */
|
|
sprintf(ofile, "%s.%s", oroot, DIRECTION_MAP_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-6);
|
|
}
|
|
/* Print a text report from the map. */
|
|
dump_map(fp, direction_map, map_w, map_h);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-7);
|
|
}
|
|
|
|
/* 5. Write Low Contrast Map results to text file. */
|
|
sprintf(ofile, "%s.%s", oroot, LOW_CONTRAST_MAP_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-8);
|
|
}
|
|
/* Print a text report from the map. */
|
|
dump_map(fp, low_contrast_map, map_w, map_h);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-9);
|
|
}
|
|
|
|
/* 6. Write Low Flow Map results to text file. */
|
|
sprintf(ofile, "%s.%s", oroot, LOW_FLOW_MAP_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-10);
|
|
}
|
|
/* Print a text report from the map. */
|
|
dump_map(fp, low_flow_map, map_w, map_h);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-11);
|
|
}
|
|
|
|
/* 7. Write High Curvature Map results to text file. */
|
|
sprintf(ofile, "%s.%s", oroot, HIGH_CURVE_MAP_EXT);
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_text_results : fopen : %s\n", ofile);
|
|
return(-12);
|
|
}
|
|
/* Print a text report from the map. */
|
|
dump_map(fp, high_curve_map, map_w, map_h);
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_text_results : fclose : %s\n", ofile);
|
|
return(-13);
|
|
}
|
|
|
|
/* Return normally. */
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: write_minutiae_XYTQ - Write just minutiae XYT's & Qualities to text
|
|
#cat: file according to the specified mintuiae represenation
|
|
|
|
Input:
|
|
ofile - output file name
|
|
reptype - specifies XYT output representation
|
|
minutiae - structure containing a list of LFS detected minutiae
|
|
iw - width (in pixels) of the input image
|
|
ih - height (in pixels) of the input image
|
|
Return Code:
|
|
Zero - successful completion
|
|
Negative - system error
|
|
**************************************************************************/
|
|
int write_minutiae_XYTQ(char *ofile, const int reptype,
|
|
const MINUTIAE *minutiae, const int iw, const int ih)
|
|
{
|
|
FILE *fp;
|
|
int i, ox, oy, ot, oq;
|
|
MINUTIA *minutia;
|
|
|
|
/* A. If M1 flag set: */
|
|
/* XYTQ's written according to M1 (ANSI INCITS */
|
|
/* 378-2004) representation: */
|
|
/* 1. pixel coordinates with origin top-left */
|
|
/* 2. orientation in degrees on range [0..360] */
|
|
/* with 0 pointing east and increasing counter */
|
|
/* clockwise */
|
|
/* 3. direction pointing up the ridge ending or */
|
|
/* bifurcaiton valley */
|
|
/* 4. minutiae qualities on integer range [0..100] */
|
|
/* (non-standard) */
|
|
/* */
|
|
/* B. If M1 flag NOT set: */
|
|
/* XYTQ's written according to NIST internal rep. */
|
|
/* 1. pixel coordinates with origin bottom-left */
|
|
/* 2. orientation in degrees on range [0..360] */
|
|
/* with 0 pointing east and increasing counter */
|
|
/* clockwise (same as M1) */
|
|
/* 3. direction pointing out and away from the */
|
|
/* ridge ending or bifurcation valley */
|
|
/* (opposite direction from M1) */
|
|
/* 4. minutiae qualities on integer range [0..100] */
|
|
/* (non-standard) */
|
|
|
|
if((fp = fopen(ofile, "wb")) == (FILE *)NULL){
|
|
fprintf(stderr, "ERROR : write_minutiae_XYTQ : fopen : %s\n", ofile);
|
|
return(-2);
|
|
}
|
|
|
|
for(i = 0; i < minutiae->num; i++){
|
|
minutia = minutiae->list[i];
|
|
|
|
switch(reptype){
|
|
case M1_XYT_REP:
|
|
lfs2m1_minutia_XYT(&ox, &oy, &ot, minutia);
|
|
break;
|
|
case NIST_INTERNAL_XYT_REP:
|
|
lfs2nist_minutia_XYT(&ox, &oy, &ot, minutia, iw, ih);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "ERROR : write_minutiae_XYTQ : ");
|
|
fprintf(stderr, "Invalid XYT representation type = %d\n", reptype);
|
|
fclose(fp);
|
|
return(-4);
|
|
}
|
|
|
|
oq = sround(minutia->reliability * 100.0);
|
|
|
|
fprintf(fp, "%d %d %d %d\n", ox, oy, ot, oq);
|
|
}
|
|
|
|
|
|
if(fclose(fp)){
|
|
fprintf(stderr, "ERROR : write_minutiae_XYTQ : fopen : %s\n", ofile);
|
|
return(-5);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: dump_map - Prints a text report to the specified open file pointer
|
|
#cat: of the integer values in a 2D integer vector.
|
|
|
|
Input:
|
|
fpout - open file pointer
|
|
map - vector of integer directions (-1 ==> invalid direction)
|
|
mw - width (number of blocks) of map vector
|
|
mh - height (number of blocks) of map vector
|
|
**************************************************************************/
|
|
void dump_map(FILE *fpout, int *map, const int mw, const int mh)
|
|
{
|
|
int mx, my;
|
|
int *iptr;
|
|
|
|
/* Simply print the map matrix out to the specified file pointer. */
|
|
iptr = map;
|
|
for(my = 0; my < mh; my++){
|
|
for(mx = 0; mx < mw; mx++){
|
|
fprintf(fpout, "%2d ", *iptr++);
|
|
}
|
|
fprintf(fpout, "\n");
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: drawmap - Draws integer direction vectors over their respective blocks
|
|
#cat: of an input image. Note that the input image is modified
|
|
#cat: upon return form this routine.
|
|
|
|
Input:
|
|
imap - computed vector of integer directions. (-1 ==> invalid)
|
|
mw - width (in blocks) of the map
|
|
mh - height (in blocks) of the map
|
|
idata - input image data to be annotated
|
|
iw - width (in pixels) of the input image
|
|
ih - height (in pixels) of the input image
|
|
rotgrids - structure containing the rotated pixel grid offsets
|
|
draw_pixel - pixel intensity to be used when drawing on the image
|
|
Output:
|
|
idata - input image contains the results of the annoatation
|
|
Return Code:
|
|
Zero - successful completion
|
|
Negative - system error
|
|
**************************************************************************/
|
|
int drawmap(int *imap, const int mw, const int mh,
|
|
unsigned char *idata, const int iw, const int ih,
|
|
const ROTGRIDS *dftgrids, const int draw_pixel)
|
|
{
|
|
int bi, *iptr;
|
|
double dy, dx, xincr, yincr;
|
|
int cbxy;
|
|
int i, xyoffset;
|
|
unsigned char *cptr, *lptr, *rptr, *eptr;
|
|
double theta, pi_incr;
|
|
int *blkoffs, bw, bh;
|
|
int ret; /* return code */
|
|
|
|
/* Compute block offsets into the input image. */
|
|
/* Block_offsets() assumes square block (grid), so ERROR otherwise. */
|
|
if(dftgrids->grid_w != dftgrids->grid_h){
|
|
fprintf(stderr, "ERROR : drawmap : DFT grids must be square\n");
|
|
return(-130);
|
|
}
|
|
if((ret = block_offsets(&blkoffs, &bw, &bh, iw, ih,
|
|
dftgrids->pad, dftgrids->grid_w))){
|
|
return(ret);
|
|
}
|
|
|
|
if((bw != mw) || (bh != mh)){
|
|
/* Free memory allocated to this point. */
|
|
free(blkoffs);
|
|
fprintf(stderr,
|
|
"ERROR : drawmap : block dimensions between map and image do not match\n");
|
|
return(-131);
|
|
}
|
|
|
|
cbxy = dftgrids->grid_w>>1;
|
|
pi_incr = M_PI/(double)dftgrids->ngrids;
|
|
|
|
eptr = idata + (ih*iw);
|
|
iptr = imap;
|
|
/* Foreach block in image ... */
|
|
for(bi = 0; bi < mw*mh; bi++){
|
|
|
|
/* If valid direction for block ... */
|
|
if(*iptr != INVALID_DIR){
|
|
|
|
/* Get slope components of direction angle */
|
|
theta = dftgrids->start_angle + (*iptr * pi_incr);
|
|
dx = cos(theta);
|
|
dy = sin(theta);
|
|
|
|
/* Draw line rotated by the direction angle and centered */
|
|
/* on the block. */
|
|
/* Check if line is perfectly vertical ... */
|
|
if(dx == 0){
|
|
/* Draw vertical line starting at top of block shifted */
|
|
/* over to horizontal center of the block. */
|
|
lptr = idata + blkoffs[bi] + cbxy;
|
|
for(i = 0; i < dftgrids->grid_w; i++){
|
|
if((lptr > idata) && (lptr < eptr)){
|
|
*lptr = draw_pixel;
|
|
}
|
|
lptr += iw;
|
|
}
|
|
}
|
|
else{
|
|
cptr = idata + blkoffs[bi] + (cbxy*iw) + cbxy;
|
|
|
|
/* Draw center pixel */
|
|
*cptr = draw_pixel;
|
|
|
|
/* Draw left and right half of line */
|
|
xincr = dx;
|
|
yincr = dy;
|
|
for(i = 0; i < cbxy; i++){
|
|
xyoffset = (sround(yincr)*iw) + sround(xincr);
|
|
rptr = cptr + xyoffset;
|
|
if((rptr > idata) && (rptr < eptr)){
|
|
*rptr = draw_pixel;
|
|
}
|
|
lptr = cptr - xyoffset;
|
|
if((lptr > idata) && (lptr < eptr)){
|
|
*lptr = draw_pixel;
|
|
}
|
|
xincr += dx;
|
|
yincr += dy;
|
|
}
|
|
}
|
|
}
|
|
iptr++;
|
|
}
|
|
|
|
/* Deallocate working memory */
|
|
free(blkoffs);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: drawmap2 - Draws integer direction vectors over their respective blocks
|
|
#cat: of an input image. Note that the input image is modified
|
|
#cat: upon return form this routine. In this version of the
|
|
#cat: routine, offsets to the origin of each block in the image
|
|
#cat: must be precomputed and passed in.
|
|
|
|
Input:
|
|
imap - computed vector of integer directions. (-1 ==> invalid)
|
|
blkoffs - list of pixel offsets to the origin of each block in the
|
|
image from which the map was computed
|
|
mw - width (in blocks) of the map
|
|
mh - height (in blocks) of the map
|
|
pdata - input image data to be annotated
|
|
pw - width (in pixels) of the input image
|
|
ph - height (in pixels) of the input image
|
|
start_angle - the angle (in radians) that the direction 0 points in
|
|
ndirs - number of directions within a half circle
|
|
blocksize - the dimensions (in pixels) of each block
|
|
Output:
|
|
pdata - input image contains the results of the annoatation
|
|
**************************************************************************/
|
|
void drawmap2(int *imap, const int *blkoffs, const int mw, const int mh,
|
|
unsigned char *pdata, const int pw, const int ph,
|
|
const double start_angle, const int ndirs, const int blocksize)
|
|
{
|
|
int bi, *iptr;
|
|
double dy, dx, xincr, yincr;
|
|
int cbxy;
|
|
int i, xyoffset;
|
|
unsigned char *cptr, *lptr, *rptr, *eptr;
|
|
double theta, pi_incr;
|
|
|
|
cbxy = blocksize>>1;
|
|
pi_incr = M_PI/(double)ndirs;
|
|
|
|
eptr = pdata + (pw*ph);
|
|
iptr = imap;
|
|
/* Foreach block in image ... */
|
|
for(bi = 0; bi < mw*mh; bi++){
|
|
|
|
/* If valid direction for block ... */
|
|
if(*iptr != INVALID_DIR){
|
|
|
|
/* Get slope components of direction angle */
|
|
theta = start_angle + (*iptr * pi_incr);
|
|
dx = cos((double)theta);
|
|
dy = sin((double)theta);
|
|
|
|
/* Draw line rotated by the direction angle and centered */
|
|
/* on the block. */
|
|
/* Check if line is perfectly vertical ... */
|
|
if(dx == 0){
|
|
/* Draw vertical line starting at top of block shifted */
|
|
/* over to horizontal center of the block. */
|
|
lptr = pdata + blkoffs[bi] + cbxy;
|
|
for(i = 0; i < blocksize; i++){
|
|
if((lptr > pdata) && (lptr < eptr))
|
|
*lptr = 255;
|
|
lptr += pw;
|
|
}
|
|
}
|
|
else{
|
|
cptr = pdata + blkoffs[bi] + (cbxy*pw) + cbxy;
|
|
|
|
/* Draw center pixel */
|
|
*cptr = 255;
|
|
|
|
/* Draw left and right half of line */
|
|
xincr = dx;
|
|
yincr = dy;
|
|
for(i = 0; i < cbxy; i++){
|
|
xyoffset = (sround(yincr)*pw) + sround(xincr);
|
|
rptr = cptr + xyoffset;
|
|
if((rptr > pdata) && (rptr < eptr))
|
|
*rptr = 255;
|
|
lptr = cptr - xyoffset;
|
|
if((lptr > pdata) && (lptr < eptr))
|
|
*lptr = 255;
|
|
xincr += dx;
|
|
yincr += dy;
|
|
}
|
|
}
|
|
}
|
|
iptr++;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: drawblocks - Annotates an input image with the location of each block's
|
|
#cat: origin. This routine is useful to see how blocks are
|
|
#cat: assigned to arbitrarily-sized images that are not an even
|
|
#cat: width or height of the block size. In these cases the last
|
|
#cat: column pair and row pair of blocks overlap each other.
|
|
#cat: Note that the input image is modified upon return form
|
|
#cat: this routine.
|
|
|
|
Input:
|
|
blkoffs - offsets to the pixel origin of each block in the image
|
|
mw - number of blocks horizontally in the input image
|
|
mh - number of blocks vertically in the input image
|
|
pdata - input image data to be annotated that has pixel dimensions
|
|
compatible with the offsets in blkoffs
|
|
pw - width (in pixels) of the input image
|
|
ph - height (in pixels) of the input image
|
|
draw_pixel - pixel intensity to be used when drawing on the image
|
|
Output:
|
|
pdata - input image contains the results of the annoatation
|
|
**************************************************************************/
|
|
void drawblocks(const int *blkoffs, const int mw, const int mh,
|
|
unsigned char *pdata, const int pw, const int ph,
|
|
const int draw_pixel)
|
|
{
|
|
int bi;
|
|
unsigned char *bptr;
|
|
|
|
for(bi = 0; bi < mw*mh; bi++){
|
|
bptr = pdata + blkoffs[bi];
|
|
*bptr = draw_pixel;
|
|
}
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: drawrotgrid - Annotates an input image with a specified rotated grid.
|
|
#cat: This routine is useful to see the location and orientation
|
|
#cat: of a specific rotated grid within a specific block in the
|
|
#cat: image. Note that the input image is modified upon return
|
|
#cat: form this routine.
|
|
|
|
Input:
|
|
rotgrids - structure containing the rotated pixel grid offsets
|
|
dir - integer direction of the rotated grid to be annontated
|
|
idata - input image data to be annotated.
|
|
blkoffset - the pixel offset from the origin of the input image to
|
|
the origin of the specific block to be annoted
|
|
iw - width (in pixels) of the input image
|
|
ih - height (in pixels) of the input image
|
|
draw_pixel - pixel intensity to be used when drawing on the image
|
|
Return Code:
|
|
Zero - successful completion
|
|
Negative - system error
|
|
**************************************************************************/
|
|
int drawrotgrid(const ROTGRIDS *rotgrids, const int dir,
|
|
unsigned char *idata, const int blkoffset,
|
|
const int iw, const int ih, const int draw_pixel)
|
|
{
|
|
int i, j, gi;
|
|
|
|
/* Check if specified rotation direction is within range of */
|
|
/* rotated grids. */
|
|
if(dir >= rotgrids->ngrids){
|
|
fprintf(stderr,
|
|
"ERROR : drawrotgrid : input direction exceeds range of rotated grids\n");
|
|
return(-140);
|
|
}
|
|
|
|
/* Intialize grid offset index */
|
|
gi = 0;
|
|
/* Foreach row in rotated grid ... */
|
|
for(i = 0; i < rotgrids->grid_h; i++){
|
|
/* Foreach column in rotated grid ... */
|
|
for(j = 0; j < rotgrids->grid_w; j++){
|
|
/* Draw pixels from every other rotated row to represent direction */
|
|
/* of line sums used in DFT processing. */
|
|
if(i%2)
|
|
*(idata+blkoffset+rotgrids->grids[dir][gi]) = draw_pixel;
|
|
/* Bump grid offset index */
|
|
gi++;
|
|
}
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
**************************************************************************
|
|
#cat: dump_link_table - takes a link table and vectors of minutia IDs
|
|
#cat: assigned to its axes and prints the table's contents out
|
|
#cat: as formatted text to the specified open file pointer.
|
|
|
|
Input:
|
|
fpout - open file pointer
|
|
link_table - sparse 2D table containing scores of potentially linked
|
|
minutia pairs
|
|
x_axis - minutia IDs registered along x-axis
|
|
y_axis - minutia IDs registered along y-axis
|
|
nx_axis - number of minutia registered along x-axis
|
|
ny_axis - number of minutia registered along y-axis
|
|
tbldim - dimension of each axes of the link table
|
|
minutiae - list of minutia points
|
|
**************************************************************************/
|
|
void dump_link_table(FILE *fpout, const int *link_table,
|
|
const int *x_axis, const int *y_axis,
|
|
const int nx_axis, const int ny_axis, const int tbldim,
|
|
const MINUTIAE *minutiae)
|
|
{
|
|
int i, tx, ty, sentry, entry;
|
|
|
|
fprintf(fpout, "DUMP LINK TABLE:\n");
|
|
|
|
fprintf(fpout, "X-AXIS:\n");
|
|
for(i = 0; i < nx_axis; i++){
|
|
fprintf(fpout, "%d: %d,%d\n", i, minutiae->list[x_axis[i]]->x,
|
|
minutiae->list[x_axis[i]]->y);
|
|
}
|
|
|
|
fprintf(fpout, "Y-AXIS:\n");
|
|
for(i = 0; i < ny_axis; i++){
|
|
fprintf(fpout, "%d: %d,%d\n", i, minutiae->list[y_axis[i]]->x,
|
|
minutiae->list[y_axis[i]]->y);
|
|
}
|
|
|
|
fprintf(fpout, "TABLE:\n");
|
|
sentry = 0;
|
|
for(ty = 0; ty < ny_axis; ty++){
|
|
entry = sentry;
|
|
for(tx = 0; tx < nx_axis; tx++){
|
|
fprintf(fpout, "%7d ", link_table[entry++]);
|
|
}
|
|
fprintf(fpout, "\n");
|
|
sentry += tbldim;
|
|
}
|
|
}
|
|
|