#include <stdlib.h>
#include <stdio.h>
#include <gd.h>
#include <string.h>
#include <stdint.h>
#include <wchar.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <locale.h>
#include <iconv.h>
/* to determine codepoint categories */
#include <unicode/uchar.h>
/* to output UTF-32 codepoints in proper encoding for terminal */
#include <unicode/ustdio.h>

#include <sys/types.h>
#include <limits.h>
#include <math.h>

#define SEMICOLON 59

#define __INT48_TYPE__

#ifdef __INT48_TYPE__
typedef signed __INT48_TYPE__ int48_t;
typedef unsigned __INT48_TYPE__ uint48_t;
typedef int48_t int_least48_t;
typedef uint48_t uint_least48_t;
typedef int48_t int_fast48_t;
typedef uint48_t uint_fast48_t;
# define __int_least32_t int48_t
# define __uint_least32_t uint48_t
# define __int_least16_t int48_t
# define __uint_least16_t uint48_t
# define __int_least8_t int48_t
# define __uint_least8_t uint48_t
#endif /* __INT48_TYPE__ */

#ifdef __INT48_TYPE__
# ifdef __INT48_C_SUFFIX__
#  define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__)
#  define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__)
#  define __int32_c_suffix __INT48_C_SUFFIX__
#  define __int16_c_suffix __INT48_C_SUFFIX__
#  define __int8_c_suffix  __INT48_C_SUFFIX__
# else
#  define INT48_C(v) v
#  define UINT48_C(v) v ## U
#  undef __int32_c_suffix
#  undef __int16_c_suffix
#  undef  __int8_c_suffix
# endif /* __INT48_C_SUFFIX__ */
#endif /* __INT48_TYPE__ */

#ifdef __INT48_TYPE__
# define INT48_MAX           INT48_C(140737488355327)
# define INT48_MIN         (-INT48_C(140737488355327)-1)
# define UINT48_MAX         UINT48_C(281474976710655)
# define INT_LEAST48_MIN     INT48_MIN
# define INT_LEAST48_MAX     INT48_MAX
# define UINT_LEAST48_MAX   UINT48_MAX
# define INT_FAST48_MIN      INT48_MIN
# define INT_FAST48_MAX      INT48_MAX
# define UINT_FAST48_MAX    UINT48_MAX
# define __INT_LEAST32_MIN   INT48_MIN
# define __INT_LEAST32_MAX   INT48_MAX
# define __UINT_LEAST32_MAX UINT48_MAX
# define __INT_LEAST16_MIN   INT48_MIN
# define __INT_LEAST16_MAX   INT48_MAX
# define __UINT_LEAST16_MAX UINT48_MAX
# define __INT_LEAST8_MIN    INT48_MIN
# define __INT_LEAST8_MAX    INT48_MAX
# define __UINT_LEAST8_MAX  UINT48_MAX
#endif /* __INT48_TYPE__ */

struct BoundBox {
	int x;
	int y;
	int w;
	int h;
};

void Convert_Brect(int *brect, struct BoundBox *bb){
	int h_x=INT_MIN;
	int l_x=INT_MAX;
	int h_y=INT_MIN;
	int l_y=INT_MAX;

	if(brect[0]>h_x)
		h_x = brect[0];
	if(brect[2]>h_x)
		h_x = brect[2];
	if(brect[4]>h_x)
		h_x = brect[4];
	if(brect[6]>h_x)
		h_x = brect[6];

	if(brect[0]<l_x)
		l_x = brect[0];
	if(brect[2]<l_x)
		l_x = brect[2];
	if(brect[4]<l_x)
		l_x = brect[4];
	if(brect[6]<l_x)
		l_x = brect[6];

	if(brect[1]>h_y)
		h_y = brect[1];
	if(brect[3]>h_y)
		h_y = brect[3];
	if(brect[5]>h_y)
		h_y = brect[5];
	if(brect[7]>h_y)
		h_y = brect[7];

	if(brect[1]<l_y)
		l_y = brect[1];
	if(brect[3]<l_y)
		l_y = brect[3];
	if(brect[5]<l_y)
		l_y = brect[5];
	if(brect[7]<l_y)
		l_y = brect[7];

	bb->w = (h_x - l_x);
	bb->h = (h_y - l_y);

        bb->x = brect[6];
        bb->y = brect[7]-bb->h;

	return;
}

int utf8_encode(char *out, uint64_t utf)
{

	out[0] = 0;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 0;
out[6] = 0;
out[7] = 0;

	//memset ((void*)out, '\0', 8);
  //if (utf <= 0x7F) {
if (utf < 0x0080) {
    // Plain ASCII
    out[0] = (char) utf;
    out[1] = 0;
    return 1;
//  } else if (utf <= 0x07FF) {
} else if (utf < 0x0800) {
    // 2-byte unicode
    out[0] = (char) (((utf >> 6) & 0x1F) | 0xC0);
    out[1] = (char) (((utf >> 0) & 0x3F) | 0x80);
    out[2] = 0;
    return 2;
//  } else if (utf <= 0xFFFF) {
} else if (utf < 0x10000) { //65,536
    // 3-byte unicode
    out[0] = (char) (((utf >> 12) & 0x0F) | 0xE0);
    out[1] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[2] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[3] = 0;
    return 3;
//  } else if (utf <= 0x001FFFFF) {
} else if (utf < 0x200000) { // 2097152
//  } else if (utf <= 0x10FFFF) {
    // 4-byte unicode
    out[0] = (char) (((utf >> 18) & 0x07) | 0xF0);
    out[1] = (char) (((utf >> 12) & 0x3F) | 0x80);
    out[2] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[4] = 0;
    return 4;
//  } else if (utf <= 0x03FFFFFF) {
} else if (utf < 0x4000000 ) { // 67108864
    // 5-byte unicode
    out[0] = (char) (((utf >> 24) & 0x03) | 0xF8);
    out[1] = (char) (((utf >> 18) & 0x3F) | 0x80);
    out[2] = (char) (((utf >> 12) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[4] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[5] = 0;
    return 5;
  } else if (utf < 0x80000000) { // 2147483648
    // 6-byte unicode
    out[0] = (char) (((utf >> 30) & 0x01) | 0xFC);
    out[1] = (char) (((utf >> 24) & 0x3F) | 0x80);
    out[2] = (char) (((utf >> 18) & 0x3F) | 0x80);
    out[3] = (char) (((utf >>  12) & 0x3F) | 0x80);
    out[4] = (char) (((utf >>  6) & 0x3F) | 0x80);
    out[5] = (char) (((utf >>  0) & 0x3F) | 0x80);
    out[6] = 0;
    return 6;
  }  else {
    // error - use replacement character
    out[0] = (char) 0xEF;
    out[1] = (char) 0xBF;
    out[2] = (char) 0xBD;
    out[3] = 0;
    return 0;
  }


}


int Is_4_byte(char *str, uint64_t *utf){
	unsigned char byte;
	uint64_t b0, b1, b2, b3;

	b0=str[0];
	b1=str[1];
	b2=str[2];
	b3=str[3];

	byte = *((unsigned char *) str);

	if (byte < 0xC0) {
		*utf = (uint64_t)byte;
		return 1;
	} else if (byte < 0xE0) {
		if ((str[1] & 0xC0) == 0x80) {
			*utf = (uint64_t) (((byte & 0x1F) << 6) | (str[1] & 0x3F));
			return 2;
		}
                        *utf = (uint64_t) byte;
                        return 1;
	} else if (byte < 0xF0) {
		if (  ((b1 & 0xC0) == 0x80) && ((b2 & 0xC0) == 0x80)) {
			*utf = (uint64_t) (((b0 & 0x0F) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F));
			return 3;
		}

                        *utf = (uint64_t)b0;
                        return 1;


	}else if (byte < 0xF8) {
		if (  ((b1 & 0xC0) == 0x80) && ((b2 & 0xC0) == 0x80) && ((b3 & 0xC0) == 0x80)  ) {
			*utf = (uint64_t) (  ((b0 & 0x7) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F));
			return 4;
		}
		*utf = (uint64_t)b0;
		return 1;
	}else{
		return 0;
	}


	//return 0;
}


int main(int argc, char **argv){
	FILE *image_out;
	FILE *font_fnt_out;
	FILE *input_hex;
	FILE *testout;

	gdImagePtr im;
	int black;
	int white;
	double tmp1, tmp2;
	int brect[8];
	int x, y, i;
	char *err;
	int no_fontconfig;
	int row_cur = 0;
	int row_spacing_pixels = 20;
	int col_spacing_pixels = 20;
	int bounding_box_width_max = 0;
	int bounding_box_height_max = 0;
	int bounding_box_width_cur = 0;
	int bounding_box_height_cur = 0;
	int row_width_max = 0;
	int row_width_cur = 0;
	int columns = 50;
	int column_cur = 0;
	//int row_width_cur = 0;
	int row_width_widest = 0;
	char space[3];
	//char space = ' ';
	wchar_t tab = '\t';
	wchar_t newline = '\n';
	wchar_t null = '\0';

	int image_width = 0;
	int image_height = 0;
	wint_t c;
	uint64_t total_chars_to_print = 0;
	uint32_t total_rows = 0;
	uint32_t total_cols = 0;
	char linestring[1024];
//char outputsring[1024];
char *outputstring;

char *s;

char test[64];
uint64_t hexchar;
iconv_t cd;
char *pIn;
char *pOut;
size_t inbytesleft = 4;
size_t outbytesleft = 4;
char *inbuf;
char *outbuf;
int num1;


int tallest_char = 0;
int widest_char = 0;
char Tallest_char[20];
char Widest_char[20];

char *locale = setlocale(LC_ALL, "en_US.UTF-8");
wchar_t *bla;
struct BoundBox bb;
	double pixel_pt_size = 10;
	char *input_ttf = "/mnt/sdb1/pub/test/gdfont/iosevka-fixed-slab-extended.ttf";
//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/LiberationMono-Regular.ttf";
//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/DejaVuSansMono.ttf";
//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/DejaVuSans.ttf";
//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/iosevka.ttc";
//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/iosevka-regular.ttf";

//char *input_ttf = "/mnt/sdb1/pub/test/gdfont/Iosevka-test.ttf";

	int aa_disable;

        int status;
	gdFTStringExtra Strex = {0,0,0,0,0,NULL,NULL};
	gdFTStringExtraPtr strex = &Strex;

//(void)gdFTUseFontConfig(1);
//printf("size of ulong: %zu\n", sizeof(unsigned long) );
//return 0;
strex->flags |= gdFTEX_LINESPACE;
strex->flags |= gdFTEX_CHARMAP;
strex->flags |= gdFTEX_RESOLUTION;
strex->flags |= gdFTEX_DISABLE_KERNING;
strex->flags |= gdFTEX_XSHOW;
strex->flags |= gdFTEX_RETURNFONTPATHNAME;
//strex->flags |= gdFTEX_FONTPATHNAME;
//strex->flags |= gdFTEX_FONTCONFIG;
//strex->flags |= gdFTEX_FONTPATHNAME;


strex->linespacing = 1.00;
strex->charmap = gdFTEX_Unicode;
//FT_ENCODING_UNICODE
//strex->charmap = gdFTEX_Big5;
//strex->charmap = gdFTEX_Shift_JIS;
//strex->charmap = gdFTEX_Adobe_Custom;

//strex->hdpi=1350;
//strex->vdpi=1950;

strex->hdpi=187;
strex->vdpi=187;

size_t totalchars = 0;
size_t outputwritten = 1;
size_t outputstep = 64;
size_t outputsize = 64;
outputstring = (char *)malloc(outputsize*sizeof(char));
outputstring[0] = '\0';
space[0] = ' ';
space[1] = ' ';
space[2] = '\0';


//do nothing but find the widest char and the tallest char
        if( ( input_hex = fopen("hex.txt", "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "hex.txt" );
                return 1;
        }
	memset ((void*) linestring, '\0', sizeof (linestring));
        x = row_spacing_pixels+row_spacing_pixels;
        y = col_spacing_pixels+col_spacing_pixels;

        while( fgets(linestring, sizeof(linestring), input_hex) != NULL){
                //replace newline with null
                for(num1=0; num1<sizeof(linestring); num1++){
                        if(linestring[num1] == '\n'){
                                linestring[num1] = '\0';
                                break;
                        }
                }

		memset ((void*)test, '\0', sizeof(test));
		hexchar = (uint64_t)strtoul((const char *)linestring, NULL, 16);

//		if(hexchar > 0xFFFF)
//	        	break;

/*
		// skip spacing modifiers 02B0 — 02FF
		if(hexchar > 0x02AF && hexchar < 0x0300)
			continue;
                //skip diacritics between 1DBF — 1E00
                if(hexchar > 0x1DBF && hexchar < 0x1E00)
                        continue;
		//skip diacritics 0300 — 036F
		if(hexchar > 0x02FF && hexchar < 0x0370)
			continue;
		//skip diacritics 20D0 — 20FF
		if(hexchar > 0x20CF && hexchar < 0x2100)
			continue;
                //skip diacritics between 1AAF - 1B00
                if(hexchar > 0x1AAF && hexchar < 0x1B00)
                        continue;
*/

		(void)utf8_encode(test, hexchar);

		outputwritten += strlen(test);
		outputwritten += strlen(space);
		if(outputsize < outputwritten){
			outputsize = outputwritten+outputstep;
			outputstring = (char *) realloc((void *)outputstring, outputsize);
		}
		(void)strcat((char *)outputstring, (const char *)space);
		(void)strcat((char *)outputstring, (const char *)test);
		totalchars+=3;


	}


//printf("%s", outputstring);
fclose(input_hex);


//add some extra space on the end
outputwritten += strlen(space);
if(outputsize < outputwritten){
outputsize = outputwritten+4;
outputstring = (char *) realloc((void *)outputstring, outputsize);
}
(void)strcat((char *)outputstring, (const char *)space);
(void)strcat((char *)outputstring, (const char *)space);
totalchars+=4;



	err = gdImageStringFTEx(NULL,brect,0,input_ttf,pixel_pt_size,0.0,x,y,(const char *)outputstring,strex);
                if (err) {fprintf(stderr,err); return 1;}

                bounding_box_width_cur = brect[4]-brect[0];
                bounding_box_height_cur = brect[3]-brect[7];

	//fprintf(font_fnt_out, "\"%s\"=%d,%d,%d,%d\n", test, brect[6], brect[7], bounding_box_width_cur, bounding_box_height_cur );

printf("bounding box: %d x %d\n", bounding_box_width_cur, bounding_box_height_cur);
gdFree((void *)strex->xshow);

strex->flags |= gdFTEX_LINESPACE;
strex->flags |= gdFTEX_CHARMAP;
strex->flags |= gdFTEX_RESOLUTION;
strex->flags |= gdFTEX_DISABLE_KERNING;
strex->flags |= gdFTEX_XSHOW;
strex->flags |= gdFTEX_RETURNFONTPATHNAME;
//strex->flags |= gdFTEX_FONTPATHNAME;
//strex->flags |= gdFTEX_FONTCONFIG;
//strex->flags |= gdFTEX_FONTPATHNAME;


strex->linespacing = 1.00;
strex->charmap = gdFTEX_Unicode;
//FT_ENCODING_UNICODE
//strex->charmap = gdFTEX_Big5;
//strex->charmap = gdFTEX_Shift_JIS;
//strex->charmap = gdFTEX_Adobe_Custom;

//strex->hdpi=1350;
//strex->vdpi=1950;

strex->hdpi=187;
strex->vdpi=187;


	if( ( font_fnt_out = fopen("font.fnt", "w" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "font.fnt" );
                return 1;
        }

fprintf(font_fnt_out, "%c image file\n", SEMICOLON);
fprintf(font_fnt_out, "image=font.png\n");
fprintf(font_fnt_out, "%c \"character\"=x,y,width,height\n", SEMICOLON);


	image_height = bounding_box_height_cur*3;
        image_width  = bounding_box_width_cur+60+200;

        //create image
        im = gdImageCreateTrueColor(image_width, image_height);
	gdImageSetResolution(im,strex->hdpi,strex->vdpi);
        white = gdImageColorResolve(im, 940, 940, 940);
        black = gdImageColorResolve(im, 0, 255, 0);

	x = 30;
	y = bounding_box_height_cur;

	err = gdImageStringFTEx(im,brect,black,input_ttf,pixel_pt_size,0.0,x,y,(const char *)outputstring,strex);
                if (err) {fprintf(stderr,err); return 1;}


//for(i=0;i<totalchars;i++){

//x = 0;
double origin_x[6];
//double scalex = 72/187;
//double scalex = 0.385026737967914423066;

//double scalex = 0.24;

//187 / (64 * 300)

//tmp1 = (double)pixel_pt_size*300;
//double scalex = (double)strex->hdpi / 1090;

double scalex = 1;


	i = 0;
x = brect[0];
//bounding_box_height_cur /= 2;
//y = bounding_box_height_cur;

y = brect[7];
char *xshow_ptr = strex->xshow;
uint64_t big1 = 0;
uint64_t big2 = 0;
//uint64_t four = 0;
//int isfour = 0;
double Origin_Pos = brect[0];

       if( ( input_hex = fopen("hex.txt", "r" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "hex.txt" );
                return 1;
        }
	memset ((void*) linestring, '\0', sizeof (linestring));

        while( fgets(linestring, sizeof(linestring), input_hex) != NULL){
                //replace newline with null
                for(num1=0; num1<sizeof(linestring); num1++){
                        if(linestring[num1] == '\n'){
                                linestring[num1] = '\0';
                                break;
                        }
                }

                memset ((void*)test, '\0', sizeof(test));
                hexchar = (uint64_t)strtoul((const char *)linestring, NULL, 16);

		//respect 2003 unicode limitation
//                if(hexchar > 0xFFFF)
//                        break;
/*
                // skip spacing modifiers 02B0 — 02FF
                if(hexchar > 0x02AF && hexchar < 0x0300)
                        continue;
                //skip diacritics between 1DBF — 1E00
                if(hexchar > 0x1DBF && hexchar < 0x1E00)
                        continue;
                //skip diacritics 0300 — 036F
                if(hexchar > 0x02FF && hexchar < 0x0370)
                        continue;
                //skip diacritics 20D0 — 20FF
                if(hexchar > 0x20CF && hexchar < 0x2100)
                        continue;
		//skip diacritics between 1AAF - 1B00
		if(hexchar > 0x1AAF && hexchar < 0x1B00)
			continue;
*/
                (void)utf8_encode(test, hexchar);

//four = hexchar;
//isfour = Is_4_byte(test, &four);



		//space space char next
		//for(i=0; i<totalchars; i+=3){
			//x offset from previous char, ie: width of previous char

//hmm spaces not added to xshow?
/*
			box_widths[0] = (strex->xshow[i] * 72/187);   //space
			box_widths[1] = (strex->xshow[i+1] * 72/187); //space
			box_widths[2] = (strex->xshow[i+3] * 72/187); //char
			box_widths[3] = (strex->xshow[i+4] * 72/187); //space
			x += box_widths[0] + box_widths[1] + box_widths[2];
			bounding_box_width_cur = box_widths[3];
*/



//printf("%d\n", strex->xshow[i]);

//if(i%3 == 0){

//for(num1=0; num1<

//while(*(xshow_ptr++) != ' '){



//while(strex->xshow[num1]


//x origin

if(i!=0)
origin_x[0] = atof((const char *)xshow_ptr);
else
origin_x[0] = 0;


//origin_x[0] = tmp1;   //space
//if(i=0)
//origin_x[0] = 0;

while(*(xshow_ptr) != ' ')
xshow_ptr++;

origin_x[1] = atof((const char *)xshow_ptr);
//origin_x[1] = tmp1; //space

while(*(xshow_ptr) != ' ')
xshow_ptr++;
origin_x[2] = atof((const char *)xshow_ptr);
//origin_x[2] = tmp1; //char
while(*(xshow_ptr) != ' ')
xshow_ptr++;
origin_x[3] = atof((const char *)xshow_ptr);
//origin_x[3] = tmp1; //space

i+=3;
//xshow_ptr = &strex->xshow[i];


//if(i!=0)
//box_widths[0] = (strex->xshow[i] * 72/187);
//else

//if(i!=0){
//box_widths[0] = floor((double)strex->xshow[i] * 72/187);
//box_widths[1] = floor((double)strex->xshow[i+1] * 72/187 - 1);
//}else{
//box_widths[0] = 0;
//box_widths[1] = 0;
//}
//box_widths[2] = floor((double)strex->xshow[i+3] * 72/187);
//box_widths[3] = floor((double)strex->xshow[i+4] * 72/187);
//box_widths[4] = 0;
//box_widths[5] = (strex->xshow[i+6] * 72/187);

//needs to be double prec
//x += box_widths[0] + box_widths[1];

//if(i<6)
//printf("%d %d %d %d\n", i, strex->xshow[i], strex->xshow[i+1], strex->xshow[i+2]);

//printf("%d %d %d %d\n", strex->xshow[i], strex->xshow[i+1], strex->xshow[i+2], strex->xshow[i+3]);


//printf("%lf %lf %lf %lf\n", origin_x[0], origin_x[1], origin_x[2], origin_x[3]);


Origin_Pos += (origin_x[0] + origin_x[1] + origin_x[2])*scalex;
//Origin_Pos *= scalex;

//printf("%lf %lu\n", Origin_Pos, big1);
big1 = (uint64_t)floor(Origin_Pos);
//printf("%lf %lu\n", Origin_Pos, big1);

tmp1 = origin_x[2]/2;
tmp2 = origin_x[3]/2;
tmp1 += tmp2;
tmp1 *= scalex;
big2 = (uint64_t)ceil(tmp1);

//x += box_widths[0] + box_widths[1] + box_widths[2]; //+ box_widths[1] + box_widths[2];

//bounding_box_width_cur = box_widths[3]/2;

			//bounding_box_width_next = strex->xshow[i] * 72/187;
			//x += bounding_box_width_cur;
			//printf("%d\n", strex->xshow[i] * 72/187);
			fprintf(font_fnt_out, "\"%s\"=%lu,%d,%lu,%d\n", test, big1, y, big2, bounding_box_height_cur );

//fprintf(font_fnt_out,", %lu, %d, %lu\n", hexchar, isfour, four);


			//x += bounding_box_width_cur;
//x += box_widths[2];
		//Origin_Pos += origin_x[0] + origin_x[1] + origin_x[2];

//}
//		i+=3;

	}

printf("total chars: %ld\n", totalchars);


	gdFree((void *)strex->xshow);


/*
        if( ( font_fnt_out = fopen("font.fnt", "w" ) ) == NULL ) {
                fprintf( stderr, "Error opening %s\n", "font.fnt" );
                return 1;
        }


	memset ((void*) linestring, '\0', sizeof (linestring));


fprintf(font_fnt_out, "%c image file\n", SEMICOLON);
fprintf(font_fnt_out, "image=font.png\n");
fprintf(font_fnt_out, "%c \"character\"=x,y,width,height\n", SEMICOLON);


        x = row_spacing_pixels+row_spacing_pixels;
        y = col_spacing_pixels+col_spacing_pixels;
        row_width_cur = 0;
        row_cur = 0;
        bounding_box_height_max = 0;
        column_cur = 0;


fclose(font_fnt_out);
fclose(input_hex);
fclose(testout);
*/

        image_out = fopen("test01.png", "w");
        gdImageInterlace(im, 1);
        gdImagePng(im, image_out);



        fclose(image_out);
        gdImageDestroy(im);
	printf("image size: %d x %d\n", image_width, image_height);

	free(outputstring);
	fclose(input_hex);
	fclose(font_fnt_out);
	return 0;
}
