⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.c

📁 Hausdorff Distance for Image Recognition
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	to which the pointer refers; imPtrDown increments it. imPtrLeft and *	imPtrRight decrement and increment respectively the x component. * * imPtrEq compares two pointers for equality, returning TRUE if they are, *	FALSE if they are not. The pointers must refer to pixels in the *	same Image. The use of this allows more efficient image operations. * * Some of these are implemented partially as macros for strange reasons. * As a result, they may not be entirely safety-checked. If you want to * have safety-checking in place, at a cost in speed and code size, put * -DIMAGE_CHECKALL on your gcc line, or add * #define IMAGE_CHECKALL * to your code somewhere before you include image.h. * This only works if you're compiling with gcc. * */#include "misc.h"#include "image.h"#include <ctype.h>#include <stdio.h>/* File tags *//* Standard pbmplus tags */#define	TAG_BINARY_COOKED	"P1"#define	TAG_GRAY_COOKED		"P2"#define	TAG_RGB_COOKED		"P3"#define	TAG_BINARY		"P4"#define	TAG_GRAY		"P5"#define	TAG_RGB			"P6"/* Nonstandard wjr tags */#define	TAG_FLOAT	"Q1"#define	TAG_DOUBLE	"Q2"#define	TAG_LONG	"Q3"#define	TAG_SHORT	"Q4"/* Maximum line length in a non-raw P?M file */#define	PBM_MAX_LINELEN	70/* How big a comment buffer we'll have for reading files */#define	LOAD_COMMENT_MAX	8192static char incomment[LOAD_COMMENT_MAX];static int incommentsize;static void *readBinaryCooked(FILE *inFile, ImageHeader **readimHeader);static void *readGrayCooked(FILE *inFile, ImageHeader **readimHeader);static void *readRGBCooked(FILE *inFile, ImageHeader **readimHeader);static void *readBinary(FILE *inFile, ImageHeader **readimHeader);static void *readGray(FILE *inFile, ImageHeader **readimHeader);static void *readRGB(FILE *inFile, ImageHeader **readimHeader);static void *readFloat(FILE *inFile, ImageHeader **readimHeader);static void *readDouble(FILE *inFile, ImageHeader **readimHeader);static void *readLong(FILE *inFile, ImageHeader **readimHeader);static void *readShort(FILE *inFile, ImageHeader **readimHeader);/* * Here begins file magic: list of tags with associated file types and * reading functions. */static struct {    char *filetag;    ImageType filetype;    void * (*readfunc)(FILE *inFile, ImageHeader **readimHeader);    } fileReaders[] = {	{ TAG_BINARY_COOKED, IMAGE_BINARY, readBinaryCooked },	{ TAG_GRAY_COOKED, IMAGE_GRAY, readGrayCooked },	{ TAG_RGB_COOKED, IMAGE_RGB, readRGBCooked },	{ TAG_BINARY, IMAGE_BINARY, readBinary },	{ TAG_GRAY, IMAGE_GRAY, readGray },	{ TAG_RGB, IMAGE_RGB, readRGB },	{ TAG_FLOAT, IMAGE_FLOAT, readFloat },	{ TAG_DOUBLE, IMAGE_DOUBLE, readDouble },	{ TAG_LONG, IMAGE_LONG, readLong },	{ TAG_SHORT, IMAGE_SHORT, readShort }	};#define	NREADERS	(sizeof(fileReaders) / sizeof(fileReaders[0]))/* Here are all the conversion routines */static void                  *pG2F(void *im), *pG2R(void *im), *pG2D(void *im);static void *dG2B(void *im), *pG2L(void *im), *pG2S(void *im);static void *dF2G(void *im),                  *dF2R(void *im), *pF2D(void *im);static void *dF2B(void *im), *dF2L(void *im), *dF2S(void *im);static void *dR2G(void *im), *dR2F(void *im),                  *dR2D(void *im);static void *dR2B(void *im), *dR2L(void *im), *dR2S(void *im);static void *dD2G(void *im), *dD2F(void *im), *dD2R(void *im)                 ;static void *dD2B(void *im), *dD2L(void *im), *dD2S(void *im);static void *pB2G(void *im), *pB2F(void *im), *pB2R(void *im), *pB2D(void *im);static void                  *pB2L(void *im), *pB2S(void *im);static void *dL2G(void *im), *dL2F(void *im), *dL2R(void *im), *pL2D(void *im);static void *dL2B(void *im),                  *dL2S(void *im);static void *dS2G(void *im), *pS2F(void *im), *dS2R(void *im), *pS2D(void *im);static void *dS2B(void *im), *pS2L(void *im)                 ;/* * Here's the table of conversions. * convertTable[type1][type2] tells how we convert from an image of type1 * to an image of type2. */static struct {    boolean isPromotion;    double slope;    double offset;    void * (*convertFunc)(void *im);    } convertTable[IMAGE_SHORT + 1][IMAGE_SHORT + 1] = {	{	/* Invalid image type */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL} },	{	/* GrayImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { TRUE , 1, 0, pG2F},	{ TRUE , 1, 0, pG2R}, { TRUE , 1, 0, pG2D}, { FALSE, 0, 0, dG2B},	{ TRUE , 1, 0, pG2L}, { FALSE, 0, 0, NULL}, { TRUE , 1, 0, pG2S} },	{	/* FloatImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dF2G}, { FALSE, 0, 0, NULL},	{ FALSE, 0, 0, dF2R}, { TRUE , 1, 0, pF2D}, { FALSE, 0, 0, dF2B},	{ FALSE, 0, 0, dF2L}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, dF2S} },	{	/* RGBImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dR2G}, { FALSE, 0, 0, dR2F},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dR2D}, { FALSE, 0, 0, dR2B},	{ FALSE, 0, 0, dR2L}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, dR2S} },	{	/* DoubleImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dD2G}, { FALSE, 0, 0, dD2F},	{ FALSE, 0, 0, dD2R}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, dD2B},	{ FALSE, 0, 0, dD2L}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, dD2S} },	{	/* BinaryImage */	{ FALSE, 0, 0, NULL}, { TRUE , 1-COLRNG, COLRNG-1, pB2G}, { TRUE , 1, 0, pB2F},	{ TRUE , 1-COLRNG, COLRNG-1, pB2R}, { TRUE , 1, 0, pB2D}, { FALSE, 0, 0, NULL},	{ TRUE , 1-COLRNG, COLRNG-1, pB2L}, { FALSE, 0, 0, NULL}, { TRUE , 1-COLRNG, COLRNG-1, pB2S} },		{	/* LongImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dL2G}, { FALSE, 0, 0, dL2F},	{ FALSE, 0, 0, dL2R}, { TRUE , 1, 0, pL2D}, { FALSE, 0, 0, dL2B},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, dL2S} },	{	/* PtrImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL},	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL} },	{	/* ShortImage */	{ FALSE, 0, 0, NULL}, { FALSE, 0, 0, dS2G}, { TRUE , 1, 0, pS2F},	{ FALSE, 0, 0, dS2R}, { TRUE , 1, 0, pS2D}, { FALSE, 0, 0, dS2B},	{ TRUE , 1, 0, pS2L}, { FALSE, 0, 0, NULL}, { FALSE, 0, 0, NULL} }	};/* * This routine allocates a rectangular area of width*height*el_size bytes * (suitable for holding width*height elements of el_size size), and * initialises it to zero. It then allocates and sets up an array of * height pointers into this, each one pointing to a row (width*el_size bytes). * * Each pointer is offset by xbase elements, and the returned pointer is * offset by ybase rows; this means that the first element in this array * is accessed by array[ybase][xbase]. Note that xbase and ybase may be * negative. * * Note that this isn't really type-safe: it takes this (void **) pointer * which will get cast, for example, into a (float **) pointer, which isn't * really legit. On machines where all pointers have the same format, * it will work. The problem is also that dereferencing a (float **) * should get you a (float *), but will actually point to the bit-pattern * of a (void *), which could be cast into that (float *) with no problems, * but which might not work if it is simply *treated* as a (float *) * without the cast. Bah. Doing it right would be too horrendous for words. * C just can't handle generics very well... */static void **allocImage(unsigned width, unsigned height, int xbase, int ybase,	   unsigned el_size){    register int i;    register void *mainArea;    register void **ptrArea;    register char *p;    register void **q;    /* Allocate the actual image data area */    mainArea = calloc(height, width*el_size);    if (mainArea == (void *)NULL) {	return((void **)NULL);	}    /* Allocate a pointer for each row */    ptrArea = (void **)malloc(height * sizeof(void *));    if (ptrArea == (void **)NULL) {	free(mainArea);	return((void **)NULL);	}    /* Set up the row pointers to point to the (offset) rows */    for (i = 0, q = ptrArea, p = (char *)mainArea;	 i < height;	 i++, q++, p += width*el_size) {	*q = (void *)(p - xbase * (int)el_size);	}    /* and return the (offset) row pointer area */    return(ptrArea - ybase);    }/* * This routine gets rid of a memory block allocated by allocImage above. */static voidfreeImage(void **ptr, int xbase, int ybase, unsigned el_size){    /* Free the memory block. This should give the first element. */    free((void *)((char *)(*(ptr + ybase)) + xbase * (int)el_size));    /* and the pointer block */    free((void *)(ptr + ybase));    }/* * Root through the image's header to find its type, and get the appropriate * base pointer of the data area, and the element size. */static voidgetAreaAndSize(void *im, ImageHeader *header,	       void ***areaPtr, unsigned *el_size){    assert(im != (void *)NULL);    assert(header != (ImageHeader *)NULL);    assert(areaPtr != (void ***)NULL);    assert(el_size != (unsigned *)NULL);    switch(header->tag) {      case IMAGE_GRAY: {	*areaPtr = (void **)(((GrayImage)im)->data);	*el_size = sizeof(unsigned char);	break;	}	      case IMAGE_FLOAT: {	*areaPtr = (void **)(((FloatImage)im)->data);	*el_size = sizeof(float);	break;	}	      case IMAGE_RGB: {	*areaPtr = (void **)(((RGBImage)im)->data);	*el_size = sizeof(RGB);	break;	}      case IMAGE_DOUBLE: {	*areaPtr = (void **)(((DoubleImage)im)->data);	*el_size = sizeof(double);	break;	}      case IMAGE_BINARY: {	*areaPtr = (void **)(((BinaryImage)im)->data);	*el_size = sizeof(char);	break;	}      case IMAGE_LONG: {	*areaPtr = (void **)(((LongImage)im)->data);	*el_size = sizeof(long);	break;	}      case IMAGE_PTR: {	*areaPtr = (void **)(((PtrImage)im)->data);	*el_size = sizeof(void *);	break;	}      case IMAGE_SHORT: {	*areaPtr = (void **)(((ShortImage)im)->data);	*el_size = sizeof(short);	break;	}      default: {	panic("bad image tag");	}      }    }/* * Given an Image's type, find its header */ImageHeader *getHeader(void *im, ImageType type){    ImageHeader *header;    assert(im != (void *)NULL);    switch(type) {	case IMAGE_GRAY: {	    header = ((GrayImage)im)->header;	    break;	    }		case IMAGE_FLOAT: {	    header = ((FloatImage)im)->header;	    break;	    }		case IMAGE_RGB: {	    header = ((RGBImage)im)->header;	    break;	    }		case IMAGE_DOUBLE: {	    header = ((DoubleImage)im)->header;	    break;	    }		case IMAGE_BINARY: {	    header = ((DoubleImage)im)->header;	    break;	    }		case IMAGE_LONG: {	    header = ((LongImage)im)->header;	    break;	    }		case IMAGE_PTR: {	    header = ((PtrImage)im)->header;	    break;	    }		case IMAGE_SHORT: {	    header = ((ShortImage)im)->header;	    break;	    }		default: {	    panic("bad image tag");	    }	}    return(header);    }    /* * Get a single positive integer from f. Eat a single character of whitespace * following the integer. The integer must be terminated by whitespace or * EOF. Nothing else (except for a comment) is allowed. Accumulate comments * in incomment. */static intgettoken(FILE *f, boolean *failed){    int val;    int c;    assert(failed != (boolean *)NULL);    /* Skip over whitespace and comments */    while (TRUE) {	do {	    c = getc(f);	    if (c == EOF) {		*failed = TRUE;		return(0);		}	    } while (isspace(c));	if (c == '#') {	    /* A comment - skip to the newline */	    do {		c = getc(f);		if (c == EOF) {		    *failed = TRUE;		    return(0);		    }		if (incommentsize < LOAD_COMMENT_MAX - 1) {		    incomment[incommentsize++] = c;		    }		} while (c != '\n');	    }	else {	    break;	    }	}    assert(!isspace(c));    /* Accumulate the digits */    val = 0;    while (isdigit(c)) {	val = 10 * val + c - '0';	c = getc(f);	if (c == EOF) {	    /* Number terminated by EOF */	    *failed = FALSE;	    return(val);	    }	}    if (!isspace(c)) {	/* Number terminated by something which isn't whitespace */	*failed = TRUE;	return(0);	}    /* Number terminated by whitespace */    *failed = FALSE;    return(val);    }/* * Get a 1 or 0 from f. Eat whitespace before the character, if any. * Nothing else (except for a comment) is allowed. Accumulate comments * in incomment. */static intgetpbmtoken(FILE *f, boolean *failed){    int c;    assert(failed != (boolean *)NULL);    /* Skip over whitespace and comments */    while (TRUE) {	do {	    c = getc(f);	    if (c == EOF) {		*failed = TRUE;		return(0);		}	    } while (isspace(c));	if (c == '#') {	    /* A comment - skip to the newline */	    do {		c = getc(f);		if (c == EOF) {		    *failed = TRUE;		    return(0);		    }		if (incommentsize < LOAD_COMMENT_MAX - 1) {		    incomment[incommentsize++] = c;		    }		} while (c != '\n');	    }	else {	    break;	    }	}    assert(!isspace(c));    *failed = FALSE;    if (c == '0') {	return(0);	}    else if (c == '1') {	return(1);	}    else {	*failed = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -