/* * textimage.c * * Version 0.1 * first working public version. * * hacked in a rainy April night 2001 by * Robin Gareus * * redistribute in terms of the GPL. * */ #include #include #include #include #include #include #include #include #include #include /* * struct definition */ /* * assume fontsize 1 * how many char(s) or line(s) could we get into a mm? */ #define _CHARS_PER_MM_ 4.725 #define _LINES_PER_MM_ 2.835 struct ImageSize { unsigned long x; unsigned long y; }; struct PaperSize { unsigned long x; unsigned long y; unsigned long w; unsigned long h; }; struct Color { int r; int g; int b; }; enum { IMAGE_RAWRGB, IMAGE_TEST }; /* * Static Variables */ static FILE *IN_COL, *IN_TXT, *OUT; static int filecounter,filecounterfilez; char **t_filename; char *program_name; int wrapped_around; static struct PaperSize papers[] = { /* left_border, offset in y , width, height */ { 0,0,0,0} /* custom - paper */ , { 10,10,841,1189} /* a0 paper */ , { 10,10,594, 841} /* a1 paper */ , { 10,10,420, 594} /* a2 paper */ , { 10,10,297, 420} /* a3 paper */ , { 10,10,210, 297} /* a4 paper */ , { 10,10,148, 210} /* a5 paper */ , }; static const char *postscript_header = ( "%%!\n" "\n" "/inch {72 mul} def\n" "/mm {2.834640089 mul} def\n" "/cm {28.34640089 mul} def\n" "\n" "%%\n" "%% Define Font and Fontsize here\n" "%%\n" "%%/FontName (Palatino-Italic) def \n" "/FontName (Courier-Bold) def \n" "/bfs %i def\n" "/bfsi %i def\n" "\n" "%%\n" "%% Define Paper here\n" "%%\n" "/x0 %i mm def\n" "/y0 %i mm def\n" "\n" "/m {moveto} bind def\n" "\n" "%% Function n: move to the next line\n" "/n {\n" " /y0 y0 bfsi sub store\n" " x0 y0 moveto\n" "} bind def\n" "\n" "%% Function N: show and move to the next line\n" "/N {\n" " show\n" " /y0 y0 bfsi sub store\n" " x0 y0 moveto\n" "} bind def\n" "\n" "/p {\n" " FontName findfont bfs scalefont setfont\n" " show\n" "} bind def\n" "\n" "/c {\n" " setrgbcolor\n" "} bind def\n" "\n" "\n" "%%\n" "%% Here the document Starts\n" "%%\n" "FontName findfont bfs scalefont setfont\n" "x0 y0 m \n" "\n" "%%\n" "%% DATA\n" "%%\n" ); /* * functions */ void usage (int status) { fprintf(stderr," Usage: %s pictue.rgb height width [OPTIONS] TEXTFILE [TEXTFILE]*\n",program_name); fprintf(stderr," Options:\n"); fprintf(stderr," [-o FILENAME ] write output to file \"FILENAME\" instead of STDOUT\n"); fprintf(stderr," [-c [-u] ] calculate Fontsize automatically.\n"); fprintf(stderr," -u Option gives extra space to not overlap underlength chars.\n"); fprintf(stderr," [-s FF LL ] Set Fontsize and Linesize manually to Integer Values FF, LL.\n"); fprintf(stderr," Units are Pixels. Fontsize scales in X, Line in Y direction.\n"); fprintf(stderr," Default fontsize is 8, linsize 6 pixels.\n"); fprintf(stderr," [-f PP ] darken Image (fade) (since white chars on white paper are.\n"); fprintf(stderr," usually invisible. Give Percent Value of what 100%% white\n"); fprintf(stderr," should be faded to (default 85%%)\n"); fprintf(stderr," [-p P ] set Page Size. Value in Din A (default A4).\n"); fprintf(stderr," [-P x y W H ] set custom Page Format in [mm].\n"); fprintf(stderr," x,y specify a border-offset (default 10 mm).\n"); fprintf(stderr," W,H the width and the height of the Paper.\n"); fprintf(stderr," (eg. A4 default is 10,10,210,297)\n"); fprintf(stderr,"\n Creates a Postscript Image from an Input-Raw-RGB Image (picture.rgb),\n"); fprintf(stderr," substituting every Input-Image Pixel by a character read from TEXTFILE\n"); fprintf(stderr," You may specify mutiple Textfiles. If the End of the Textfile is reached\n"); fprintf(stderr," the next file is used, and finally we wrap around...\n"); fprintf(stderr," currently I only support RGP Input-Images. But you may use convert(1)...\n"); fprintf(stderr,"\n Suggestions, bug reports,... contact me \n"); exit (status); } void get_size(struct ImageSize **size, int image){ if (image== IMAGE_RAWRGB ) { // do nothing; } else if (image==IMAGE_TEST) { (*size)->x=110; (*size)->y=155; } } void next_file() { if (IN_TXT > 0) { fclose(IN_TXT); } if ((IN_TXT = fopen(t_filename[filecounter], "r")) == NULL) { fprintf(stderr, "Could not open File %s\nAborting.\n", t_filename[filecounter]); if (IN_COL > 0) fclose(IN_COL); exit(1); } filecounter++; filecounter%=filecounterfilez; if ( filecounter ==0) wrapped_around++; } void next_char(char *a) { int legal_char=0; int rewind_c=0; while (legal_char==0 && rewind_c < filecounterfilez+1) { if (feof(IN_TXT)) { next_file(); // rewind(IN_TXT); rewind_c++; } (*a)=fgetc(IN_TXT); if ( isalnum( *a ) || *a == '!' || *a == '.' || *a == ',' || *a == '>' || *a == '<' || *a == ';' || *a == ':' || *a == '"' || *a == ':' || *a == '|' || *a == '@' || *a == '#' || *a == '$' || *a == '&' || *a == '*' || *a == '-' || *a == '_' || *a == '=' || *a == '+' ) legal_char=1; } if (rewind_c>filecounterfilez) { fclose(IN_COL); fclose(IN_TXT); fclose(OUT); fprintf(stderr, "Read error in Textfile\nAborting.\n"); exit(1); } } void check_feof() { if (feof(IN_COL)) { fclose(IN_COL); fclose(IN_TXT); fclose(OUT); fprintf(stderr, "Read error in Imagefile\nAborting.\n"); exit(1); } } void next_col(struct Color **col , int image){ if (image== IMAGE_RAWRGB ) { (*col)->r=fgetc(IN_COL); (*col)->g=fgetc(IN_COL); (*col)->b=fgetc(IN_COL); check_feof(); } else if (image==IMAGE_TEST) { (*col)->r=100; (*col)->g=100; (*col)->b=100; } } char *col2str(int i, int fade){ char *str; str=(char *) malloc(10*sizeof(char)); sprintf(str,"%.2f",((float)i/255/100*fade)>1 ? 1: (float)i/255/100*fade ); return(str); } static long c2l (const char *s) { long value; register const char *p = s; register char c; value = 0; while ((c = *p++) >= '0' && c <= '9') value = value * 10 + c - '0'; return value; } #define _AC_ if(args == argc) usage(1); int main (int argc,char ** argv) { char *c_filename; char *o_filename=""; int i,args,calc_fonts; struct ImageSize *size; struct Color *color; int x,y,fontsize,linesize,fade,paper; char c; int border_x,border_y; /* * initiate structs */ color=(struct Color *) malloc(sizeof(struct Color)); size =(struct ImageSize *)malloc(sizeof(struct ImageSize)); t_filename= (char ** )malloc (sizeof(char *)); wrapped_around=0; /* * defaults */ fade=85; fontsize=5; linesize=7; paper=5; calc_fonts=0; border_x=0; border_y=0; /* * parse args */ program_name = argv[0]; if (argc < 3) usage(1); c_filename=argv[1]; size->x=c2l(argv[2]); size->y=c2l(argv[3]); args=4; i=0; while (i == 0) { if (strcmp (argv[args], "-o") == 0) { args++; _AC_ o_filename=argv[args++]; } else if (strcmp (argv[args], "-f") == 0) { args++; _AC_ fade=c2l(argv[args++]); fprintf(stderr, "fade set to %i%%.\n",fade); } else if (strcmp (argv[args], "-p") == 0) { args++; _AC_ paper=c2l(argv[args++])+1; paper=paper > (int)(sizeof(papers)/sizeof(struct PaperSize)) ? (int)(sizeof(papers)/sizeof(struct PaperSize)): paper; } else if (strcmp (argv[args], "-P") == 0) { args++; paper=0; _AC_ papers[paper].x=(int)c2l(argv[args++]); _AC_ papers[paper].y=(int)c2l(argv[args++]); _AC_ papers[paper].w=(int)c2l(argv[args++]); _AC_ papers[paper].h=(int)c2l(argv[args++]); } else if (strcmp (argv[args], "-s") == 0) { args++; _AC_ fontsize=c2l(argv[args++]); _AC_ linesize=c2l(argv[args++]); calc_fonts=0; } else if (strcmp (argv[args], "-c") == 0) { calc_fonts=calc_fonts|1; args++; } else if (strcmp (argv[args], "-u") == 0) { if ((calc_fonts&1) == 1 ) calc_fonts=calc_fonts|2; else usage(1); args++; } else { i=1; } } filecounterfilez=argc-args; if (filecounterfilez ==0) usage(1); /* * filenames */ filecounter=0; while (filecounter< filecounterfilez) { t_filename=(char ** ) realloc(t_filename,(filecounter+1)*sizeof(char *)); t_filename[filecounter]= (char * )malloc ((strlen(argv[args+filecounter])+1)*sizeof(char)); strcpy(t_filename[filecounter],argv[args+filecounter]); filecounter++; } /* * initiate Reading Textfile */ filecounter=0; next_file(); /* * open picture */ if ((IN_COL = fopen(c_filename, "r")) == NULL) { fprintf(stderr, "Could not open File %s\nAborting.\n", c_filename); fclose(IN_TXT); exit(1); } /* * init Output */ if (strlen(o_filename)>0) { if ((OUT = fopen(o_filename, "w+")) == NULL) { fprintf(stderr, "Could not open File %s\nAborting.\n", o_filename); fclose(IN_TXT); fclose(IN_COL); exit(1); } } else OUT=stdout; /* * get the picture size from picture (if possoble) */ get_size(&size,IMAGE_RAWRGB); /* * calculate Fontsize * * first try to get max fontsize from width */ if ((calc_fonts&1)==1) { fontsize=(papers[paper].w - 2 * papers[paper].x) * _CHARS_PER_MM_ /size->x ; if ((calc_fonts&2)==2) linesize=fontsize-1; else linesize=ceil((float)fontsize*(float)(_LINES_PER_MM_/_CHARS_PER_MM_))+1; if (fontsize < 1) fontsize=1; if (linesize < 1) linesize=1; if (linesize > fontsize) linesize=fontsize; /* * check height */ while ( ( (papers[paper].h - 2 * papers[paper].y) - size->y * linesize / _LINES_PER_MM_ ) / 2 < 1 && fontsize > 1 ) { fontsize--; if ((calc_fonts&2)==2) linesize=fontsize-1; else linesize=ceil((float)fontsize*(float)(_LINES_PER_MM_/_CHARS_PER_MM_))+1; } if (fontsize < 1) fontsize=1; if (linesize < 1) linesize=1; if (linesize > fontsize) linesize=fontsize; border_x=(int)(((float) (papers[paper].w - 2 * papers[paper].x) - ((float)size->x * (float)fontsize / (float)_CHARS_PER_MM_ ))/2); border_y=( (papers[paper].h - 2 * papers[paper].y) - size->y * linesize / _LINES_PER_MM_ ) /2; border_y+= (linesize / _LINES_PER_MM_ ); fprintf(stderr, "fontsize/linesize was calculated to : %i/%i\n",fontsize,linesize); fprintf(stderr, "border : x=%i[mm] y=%i[mm]\n",border_x,border_y); } /* * print header */ fprintf(OUT,postscript_header, fontsize, linesize, papers[paper].x+border_x, papers[paper].h-(papers[paper].y+border_y) ); /* * create the Image */ for (y=0;yy;y++) { for (x=0;xx;x++) { next_char(&c); next_col(&color,IMAGE_RAWRGB); fprintf(OUT,"%s %s %s c(%c)p ",col2str(color->r,fade), col2str(color->g,fade), col2str(color->b,fade),c); } fprintf(OUT,"n\n"); } fprintf(OUT," () show\nshowpage\n"); /* * clean up */ fclose (IN_TXT); fclose (IN_COL); fclose (OUT); if (wrapped_around >0) fprintf(stderr,"Warning! Wrapped %i time(s) around the input textfile(s).\n",wrapped_around); return(0); }