Files
argyllcms/scanin/scanrd_.h
T
2026-08-20 20:28:40 +01:00

322 lines
10 KiB
C

/*
* Argyll Color Correction System
*
* Scanrd: Scan chart reader
* This is the core chart recognition code.
* Private H file for scanrd.c
*
* Author: Graeme W. Gill
* Date: 28/9/96
*
* Copyright 1995, 1996, 2008, Graeme W. Gill
* All rights reserved.
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
* see the License.txt file for licencing details.
*/
#include "scanrd.h" /* Include public structure */
#include "../h/llist.h" /* Linked list macros */
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif
#ifndef M_PI_2
#define M_PI_2 (0.5 * M_PI)
#endif
#ifndef M_PI_4
#define M_PI_4 (0.25 * M_PI)
#endif
#ifndef M_PI_3_4
#define M_PI_3_4 (0.75 * M_PI)
#endif
#ifndef M_2_PI
#define M_2_PI (2.0/M_PI)
#endif
#ifndef M_SQRT_2
#define M_SQRT_2 1.4142135623730950488016887242096980785696718753769
#endif
#define DEG(aa) ((aa) * 180.0/M_PI)
#define iabs(a) ((a) < 0 ? -(a) : (a))
#define MXDE 4 /* Maximum useful pixel depth */
/* A run of points at a given y, in a group */
typedef struct {
int y,lx,hx; /* Region covers values of lx <= x < hx */
} run;
/* Structure to hold the points that may make up a line */
struct _points {
int no; /* number of coordinates (indexed from ca) */
int mxno; /* Maximum number that can be allocated from ca */
run *r; /* point runs array */
int pn; /* Diagnostic serial no */
LINKSTRUCT(struct _points); /* Linked list structure */
/* Line stats */
int flag;
int nop; /* Number of points */
double mw,len; /* mean width, length */
double mx,my; /* Mean point */
double a; /* Angle */
double ca; /* Constrained Angle (constrained to 90 degrees about 0 */
double x1,y1,x2,y2; /* Start/end point of fitted line */
double pmx, pmy; /* Raster (Perspective affected) mean point */
double px1, py1, px2, py2; /* Raster (Perspective affected) line start/end points */
struct _points *opt; /* Next in improvement list */
}; typedef struct _points points;
#define F_LINESTATS 0x01 /* Line stats valid */
#define F_VALID 0x02 /* Line passes valid criteria */
#define F_LONGENOUGH 0x04 /* Line is long enough to be included in angle calc */
#define F_IMPROVE 0x08 /* Line was used to improve fit */
/* Structure to hold an aggregation region description */
struct _region {
int lx,hx; /* Region covers values of lx <= x < hx */
points *p; /* Head of points linked list associated with region */
}; typedef struct _region region;
/* Structure to hold a 2D real point */
struct _point {
double x,y;
}; typedef struct _point point;
/* Structure to hold one entry in an edge list */
struct _epoint {
double pos; /* Position of entry along edge */
double len; /* (Maximum normalized) Total length */
double p1,p2; /* Start and end of line in orthogonal direction */
double ccount; /* (Maximum normalized) Crossing count */
struct _points *opt; /* Linked list of feature lines to optimize to */
int nopt;
}; typedef struct _epoint epoint;
/* Structure of an edge list */
struct _elist {
epoint *a; /* Array of edge points */
int c; /* Count */
double lennorm; /* Total of max. normalized lengths of edge list */
}; typedef struct _elist elist;
#define INIT_ELIST(e) { \
e.a = NULL; \
e.c = 0; \
e.lennorm = 0.0; \
}
/* An edge correlation return structure */
typedef struct {
double cc,off,scale;
} ematch;
/* An integer point */
struct _ipoint {
int x,y;
}; typedef struct _ipoint ipoint;
/* An edge scan structure */
struct _escan {
int e[4]; /* Indexes of points for left or right sides */
int i; /* Index of current pair */
int ev,k1,k2; /* Bresenham constants */
int y; /* Current y value */
int xi,x; /* X increment, current x value */
}; typedef struct _escan escan;
/* Structure of a sample box */
#define SBOX_NAME_SZ 20
struct _sbox {
int diag; /* Non-zero if diagnostic only */
char name[SBOX_NAME_SZ]; /* Box name (usualy letter number coordinate) */
double xpt[3]; /* Lab expected value. L < 0 if not valid */
double x1,y1,x2,y2; /* Reference box corner points */
ipoint p[4]; /* Transformed sample box coordinates */
int active; /* Flag to indicate box is active in scan */
int ymin,ymax; /* Min and nmax y values */
escan l,r; /* left and right edge scan structures */
unsigned long *ps[MXDE]; /* Pixel value histogram arrays (256 or 65536) */
/* Pixel values just scanned, or from best rotation */
double mP[MXDE]; /* Mean Pixel values (0.0 - 255.0) */
double sdP[MXDE]; /* Standard deviations */
double P[MXDE]; /* Output Pixel values */
unsigned int cnt; /* Total pixels in cell */
LINKSTRUCT(struct _sbox); /* Active edge linked list structure */
/* Pixel values for alternate rotations, created if we have expected values */
struct {
double mP[MXDE]; /* Mean Pixel values (0.0 - 255.0) */
double sdP[MXDE]; /* Standard deviations */
double P[MXDE]; /* Robust mean Output Pixel values (0.0 .. 255.0) */
unsigned int cnt; /* Total pixels in cell */
} rot[4];
}; typedef struct _sbox sbox;
/* The private scanrd object */
struct _scanrd_ {
/* Public part of structure */
scanrd public;
/* Private variables */
int flags; /* Operation/diagnostic flags */
int verb; /* verbosity level */
/* 0 = none */
/* 1 = warnings */
/* 2 = minimum */
/* 3 = per patch */
/* 3 = patch scan details */
/* 5 = per line */
/* 7 = matching attempts */
/* 8 = per pixel */
unsigned int errv; /* Error value */
char errm[200]; /* Error message */
double gammav; /* Approximate gamma encoding of input image */
int width,height; /* With and height of raster in pixels */
int depth; /* Useful pixel plane depth */
int tdepth; /* Total pixel plane depth */
int bpp; /* Bit precision per pixel, 8 or 16 */
int bypp; /* Bytes per pixel, either 1 or 2 */
unsigned char *out; /* Diagnostic output raster array */
int noslines; /* Number of lines with valid stats */
int novlines; /* Number of valid lines */
points *gdone; /* Head of done point linked list groups */
double ppc[4]; /* Partial perspective correction values. */
/* persp() applies perspective distortion, */
/* invpersp() applies perspective correction. */
double irot; /* Base image rotation value in radians (clockwize) */
int norots; /* Number of rotations to explore */
int crot; /* Current or best rotation being scanned */
struct {
double irot; /* Image rotation value in radians (clockwize) for this rotation */
double ixoff,iyoff,ixscale,iyscale; /* Image offset and scale factors */
double cc; /* Edge match correlation */
double xcc; /* Expected value correlation, smaller is better */
} rots[4];
double ptrans[8]; /* Combined transform of partial perspective, */
/* irot, i[xy]off and i[xy]scale. */
/* Use ptrans(ptrans[]) to transform from reference to raster. */
double iptrans[8]; /* Inverse transform of ptrans[] */
/* Use ptrans(iptrans[]) to transform from raster to reference */
elist xelist, yelist; /* X and Y raster edge lists array */
elist ixelist, iyelist; /* Inverted direction X and Y raster edge lists array */
elist rxelist, ryelist; /* X and Y .cht reference edge lists array */
double rbox_shrink; /* Reference box shrink factor */
int xpt; /* NZ if got expected reference values */
double fid[8]; /* Four fiducial locations, typicall clockwise from top left */
double fidsize; /* Fiducial diagnostic cross size */
double havefids; /* NZ if there are fiducials */
int nsbox; /* Number of sample boxes */
sbox *sboxes; /* List of sample boxes */
sbox **sbstart; /* Sorted start list */
sbox **sbend; /* Sorted end list */
int csi,cei; /* Current start/end indexes */
sbox *alist; /* Active list during pixel value sampling */
double adivval; /* Overall average divider value */
int divc; /* Average divide count */
int next_read; /* Next box value to read */
char *refname; /* Path of reference file */
int inited; /* Gamma and regions inited */
unsigned short gamma[256 * 256]; /* Inverse gamma lookup */
region *vrego, *vregn; /* Old and New region for delX or vertical lines */
int no_vo, no_vn; /* Number of regions in array */
region *hrego, *hregn; /* Old and New region for delY or horizontal lines */
int no_ho, no_hn; /* Number of regions in array */
double th; /* Color change threshold */
double divval; /* Current orthogonal divider value */
/* aa line stuff */
int aa_inited; /* Non-zero if anti-aliased line tables are inited */
int *coverage; /* Coverage lookup array */
int covercells;
int covershift;
int Pmax;
int adj_pixinc[4]; /* Pixel address increments for 4 directions */
int diag_pixinc[4];
int orth_pixinc[4];
/*** Callbacks ***/
int (*read_line)(void *fdata, int y, char *dst);
/* Read line of source file, non-zero on error */
void *fdata; /* Opaque data for callback */
int (*write_line)(void *ddata, int y, char *src);
/* Write RGB line of diag file, non-zero on error */
void *ddata; /* Opaque data for callback */
}; typedef struct _scanrd_ scanrd_;
/*************************************************************************/
/* Heapsort macro */
/* HEAP_COMPARE(A,B) returns true if A < B */
#define HEAPSORT(TYPE,ARRAY,NUMBER) \
{ \
TYPE *hs_ncb = ARRAY; \
int hs_l,hs_j,hs_ir,hs_i; \
TYPE hs_rra; \
\
if (NUMBER >= 2) \
{ \
hs_l = NUMBER >> 1; \
hs_ir = NUMBER-1; \
for (;;) \
{ \
if (hs_l > 0) \
hs_rra = hs_ncb[--hs_l]; \
else \
{ \
hs_rra = hs_ncb[hs_ir]; \
hs_ncb[hs_ir] = hs_ncb[0]; \
if (--hs_ir == 0) \
{ \
hs_ncb[0] = hs_rra; \
break; \
} \
} \
hs_i = hs_l; \
hs_j = hs_l+hs_l+1; \
while (hs_j <= hs_ir) \
{ \
if (hs_j < hs_ir && HEAP_COMPARE(hs_ncb[hs_j],hs_ncb[hs_j+1])) \
hs_j++; \
if (HEAP_COMPARE(hs_rra,hs_ncb[hs_j])) \
{ \
hs_ncb[hs_i] = hs_ncb[hs_j]; \
hs_i = hs_j; \
hs_j = hs_j+hs_j+1; \
} \
else \
hs_j = hs_ir + 1; \
} \
hs_ncb[hs_i] = hs_rra; \
} \
} \
}
/*************************************************************************/