Hi,
Here is a C only version of the matlab/octave code. It only needs edtaa3func.c.
Hope this is useful.
Nicolas
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "edtaa3func.c"
// Define some fixed size types.
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
// TGA Header struct to make it simple to dump a TGA to disc.
#if defined(_MSC_VER) || defined(__GNUC__)
#pragma pack(push, 1)
#pragma pack(1) // Dont pad the following struct.
#endif
typedef struct _TGA_header
{
uint8 idLength, // Length of optional identification sequence.
paletteType, // Is a palette present? (1=yes)
imageType; // Image data type (0=none, 1=indexed, 2=rgb,
// 3=grey, +8=rle packed).
uint16 firstPaletteEntry, // First palette index, if present.
numPaletteEntries; // Number of palette entries, if present.
uint8 paletteBits; // Number of bits per palette entry.
uint16 x, // Horiz. pixel coord. of lower left of image.
y, // Vert. pixel coord. of lower left of image.
width, // Image width in pixels.
height; // Image height in pixels.
uint8 depth, // Image color depth (bits per pixel).
descriptor; // Image attribute flags.
} TGA_header;
#if defined(_MSC_VER) || defined(__GNUC__)
#pragma pack(pop)
#endif
int
TGA_write( char * filename,
unsigned int width,
unsigned int height,
unsigned char *data )
{
TGA_header header;
memset( &header, 0, sizeof(TGA_header) );
header.imageType = 3;
header.width = width;
header.height = height;
header.depth = 8;
header.descriptor = 0x20;
FILE *file;
file = fopen(filename, "wb");
if( !file )
{
fprintf(stderr, "Failed to write file\n");
return 0;
}
fwrite( (const char *) &header, sizeof(TGA_header), 1, file );
fwrite( data, sizeof(unsigned char), width * height, file);
fclose(file);
return 1;
}
unsigned char *TGA_read( char *filename,
unsigned int * width,
unsigned int * height,
unsigned int * depth )
{
FILE *file;
unsigned char type[4];
unsigned char info[6];
file = fopen( filename, "rb" );
if( !file )
{
return 0;
}
fread( &type, sizeof (char), 3, file );
fseek( file, 12, SEEK_SET );
fread( &info, sizeof (char), 6, file );
/* Only image type (color) or 3 (greyscale) */
if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
{
fclose( file );
return 0;
}
*width = info[0] + info[1] * 256;
*height = info[2] + info[3] * 256;
*depth = info[4] / 8;
if( *depth != 1 && *depth != 3 && *depth != 4 )
{
fclose(file);
return 0;
}
// Allocate memory for image data
unsigned long size = *height * *width * *depth;
unsigned char *data = (unsigned char *) malloc( size * sizeof(unsigned char) );
// Read in image data
fread( data, sizeof(unsigned char), size, file );
fclose( file );
return data;
}
unsigned char *
make_distance_map( unsigned char *img, unsigned int width, unsigned int height )
{
short * xdist = (short *) malloc( width * height * sizeof(short) );
short * ydist = (short *) malloc( width * height * sizeof(short) );
double * gx = (double *) calloc( width * height, sizeof(double) );
double * gy = (double *) calloc( width * height, sizeof(double) );
double * data = (double *) calloc( width * height, sizeof(double) );
double * outside = (double *) calloc( width * height, sizeof(double) );
double * inside = (double *) calloc( width * height, sizeof(double) );
int i;
// Convert img into double (data)
double img_min = 255, img_max = -255;
for( i=0; i<width*height; ++i)
{
double v = img[i];
data[i] = v;
if (v > img_max) img_max = v;
if (v < img_min) img_min = v;
}
// Rescale image levels between 0 and 1
for( i=0; i<width*height; ++i)
{
data[i] = (img[i]-img_min)/img_max;
}
// Compute outside = edtaa3(bitmap); % Transform background (0's)
computegradient( data, height, width, gx, gy);
edtaa3(data, gx, gy, height, width, xdist, ydist, outside);
for( i=0; i<width*height; ++i)
if( outside[i] < 0 )
outside[i] = 0.0;
// Compute inside = edtaa3(1-bitmap); % Transform foreground (1's)
memset(gx, 0, sizeof(double)*width*height );
memset(gy, 0, sizeof(double)*width*height );
for( i=0; i<width*height; ++i)
data[i] = 1 - data[i];
computegradient( data, height, width, gx, gy);
edtaa3(data, gx, gy, height, width, xdist, ydist, inside);
for( i=0; i<width*height; ++i)
if( inside[i] < 0 )
inside[i] = 0.0;
// distmap = outside - inside; % Bipolar distance field
unsigned char *out = (unsigned char *) malloc( width * height * sizeof(unsigned char) );
for( i=0; i<width*height; ++i)
{
outside[i] -= inside[i];
outside[i] = 128+outside[i]*16;
if( outside[i] < 0 ) outside[i] = 0;
if( outside[i] > 255 ) outside[i] = 255;
out[i] = 255 - (unsigned char) outside[i];
}
free( xdist );
free( ydist );
free( gx );
free( gy );
free( data );
free( outside );
free( inside );
return out;
}
int main( int argc, char **argv )
{
unsigned int width=0, height=0, depth=0;
unsigned char *img = TGA_read("texture.tga", &width, &height, &depth);
if (!img)
{
fprintf( stderr, "Failed to read image !\n" );
return EXIT_FAILURE;
}
printf("Image dimension: %d x %d x %d\n", width, height, depth);
if (depth != 1)
{
fprintf( stderr, "Image has to be grayscale !\n" );
free(img);
return EXIT_FAILURE;
}
unsigned char *out = make_distance_map(img, width, height);
TGA_write("texture-distance.tga", width, height, out);
free(img);
free(out);
return EXIT_SUCCESS;
}