/****** Brian Shucker Created Dec 18, 2000 initial revision Modified Aug 30 2001 Converted to new version of gd library with JPEG and PNG support, no GIF support Modified Sep 2 2001 Added text-wrap feature test2pic.c This program converts a JPEG image and a text file into an HTML or JPEG file of the text, colored to resemble the image This version tested with RedHat Linux 7.1 only Requires gd and math libraries Build with gcc flags -lm, -lgd ******/ #include #include #include #include #include #include #include #define EAT_SPACE 1 #define COLLAPSE_SPACE 2 #define NORMAL_SPACE 3 #define JPEG_MODE 1 #define HTML_MODE 2 #define PNG_MODE 3 #define WRAP_TEXT 1 #define NO_WRAP_TEXT 2 #define line(x) printf("%s\n", x); FILE *imageFile, *textFile, *outFile; char *imageFileName; int spaceMode = NORMAL_SPACE; int outMode = HTML_MODE; int wrapMode = WRAP_TEXT; int jpegQuality = -1; gdFontPtr font; int backGroundSet = 0; int bgR, bgG, bgB; void displayHelp(void) { line(""); line("Text2Pic converter by Brian Shucker"); line(""); line("This program converts a text file and a jpeg image into"); line("a formatted text colorized to match the image."); line(""); line("Arguments are as follows:"); line(""); line("-help\tdisplays this message"); line(""); line("-text \tspecifies source text file"); line(""); line("-image \tspecifies source image file"); line(""); line("-out \tspecifies output file"); line(""); line("-eatSpace\tremoves all white space from output"); line(""); line("-collapseSpace\tcollapses multiple white space characters into"); line("\t\ta single space in output"); line(""); line("-normSpace\tconverts all white space characters into single"); line("\t\tspaces in output"); line("\t\tThis is the default setting, so specifying the option"); line("\t\thas no effect"); line(""); line("-exact\trescales the image to match the size of the text file, so"); line("\tthe text in the produced picture matches the input text exactly."); line("\tIf this option is not selected, the text will be truncated or"); line("\twrapped to match the size of the image."); line(""); line("-jpeg\tspecifies output in JPEG format"); line(""); line("-quality \tspecifies a JPEG quality level. It should be followed"); line("\t\t\tby a value 0-95, with 0 lowest and 95 highest quality."); line("\t\t\tThis setting has no effect if not in JPEG mode."); line(""); line("-png\tspecifies output in PNG format. This is advised if"); line("\tyou intend to print the output."); line(""); line("-html\tspecifies output in HTML format. This is advised if"); line("\tyou want to post the output on a web page. The HTML is"); line("\tgenerally much more compact than the JPEG or PNG format."); line("\tThis is the default setting, so specifying the option"); line("\thas no effect"); line(""); line("-bg \tspecifies background color"); line("\t\tr, g, and b must be integer values between 0 and 255"); line("\t\trepresenting red, green, and blue values for background."); line("\t\tIf -bg is not used, background will be transparent."); line("\t\tOn systems that do not support transparency, the default"); line("\t\tbackground color is dark grey (r=g=b=50)."); line(""); line("-bigFont\t specifies large font (useful for printing)"); line(""); line("The -text, -image, and -out arguments are required."); line(""); } /*processArgs() processes the command-line arguments*/ void processArgs(int numArgs, char *args[]) { int i; if(numArgs == 1) { displayHelp(); exit(0); } font = gdFontMediumBold; /*set default font*/ /*loop through and process each arg in sequence*/ for(i=1; i 95) { jpegQuality = -1; fprintf(stderr, "text2pic: Invalid quality setting; using default instead\n"); } } else if(!strcmp(args[i], "-html")) outMode = HTML_MODE; else if(!strcmp(args[i], "-bigFont")) font = gdFontLarge; else if(!strcmp(args[i], "-bg")) { if(numArgs < i+4) { fprintf(stderr, "text2pic: Must specify r, g, b values after \"-bg\"\n"); exit(1); } bgR = atoi(args[++i]); bgG = atoi(args[++i]); bgB = atoi(args[++i]); backGroundSet = 1; } else if(!strcmp(args[i], "-text")) { if(numArgs < ++i + 1) { fprintf(stderr, "text2pic: Must specify file name after \"-text\"\n"); exit(1); } if((textFile = fopen(args[i], "r")) == NULL) { fprintf(stderr, "text2pic: Cannot open source text file %s\n", args[i]); exit(1); } } else if(!strcmp(args[i], "-image")) { if(numArgs < ++i + 1) { fprintf(stderr, "text2pic: Must specify file name after \"-image\"\n"); exit(1); } //put a copy of the image file name in buffer for parsing later if((imageFileName = (char *)malloc(strlen(args[i])+1)) == NULL) { fprintf(stderr, "text2pic: Out of memory!\n"); exit(1); } strcpy(imageFileName, args[i]); if((imageFile = fopen(args[i], "rb")) == NULL) { fprintf(stderr, "text2pic: Cannot open source image file %s\n", args[i]); exit(1); } } else if(!strcmp(args[i], "-out")) { if(numArgs < ++i + 1) { fprintf(stderr, "text2pic: Must specify file name after \"-out\"\n"); exit(1); } if((outFile = fopen(args[i], "wb")) == NULL) { fprintf(stderr, "text2pic: Cannot open output file %s\n", args[i]); exit(1); } } else { fprintf(stderr, "text2pic: Unrecognized argument: %s\n", args[i]); exit(1); } } /*finished processing command line args*/ /*check that all required files are open*/ if (textFile == NULL) { fprintf(stderr, "text2pic: Error: must specify source text file (with \"-text\")\n"); exit(1); } if (imageFile == NULL) { fprintf(stderr, "text2pic: Error: must specify source image file (with \"-image\")\n"); exit(1); } if (outFile == NULL) { fprintf(stderr, "text2pic: Error: must specify output file (with \"-out\")\n"); exit(1); } } /*readImage parses the file name to find the file type, then opens the appropriate file type*/ gdImagePtr readImage(void) { char *extension; extension = imageFileName + strlen(imageFileName); while(*extension != '.' && extension > imageFileName) extension--; if (extension == imageFileName) { fprintf(stderr, "text2pic: Could not find file extension, exiting\n"); exit(1); } if(!strcmp(extension, ".jpg") || !strcmp(extension, ".jpeg") || !strcmp(extension, ".JPG") || !strcmp(extension, ".JPEG")) return gdImageCreateFromJpeg(imageFile); else if(!strcmp(extension, ".png") || !strcmp(extension, ".PNG")) return gdImageCreateFromPng(imageFile); else { fprintf(stderr, "text2pic: Unsupported file format: %s\n", extension); exit(1); } return NULL; /*never reached*/ } /*getNextChar() finds the next character in the input file that should be printed into the output file*/ char getNextChar(void) { char ch; switch(spaceMode) { case EAT_SPACE: ch = getc(textFile); while (ch == '\t' || ch == '\n' || ch == ' ') ch = getc(textFile); break; case NORMAL_SPACE: ch = getc(textFile); if (ch == '\t' || ch == '\n' || ch == ' ') ch = ' '; break; case COLLAPSE_SPACE: { static int inSpace = 0; ch = getc(textFile); while (ch == '\t' || ch == '\n' || ch == ' ') { if (!inSpace) { inSpace = 1; ch = ' '; break; } ch = getc(textFile); } if (ch != ' ') inSpace = 0; break; } } return ch; } /*outputGraphicalChar() prints a given character into a graphical (non-html) output file*/ void outputGraphicalChar(gdImagePtr im, int x, int y, char ch, int r, int g, int b) { int color; if (ch == EOF) return; color = gdImageColorExact(im, r, g, b); if(color == -1) color = gdImageColorAllocate(im, r, g, b); if(color == -1) color = gdImageColorClosest(im, r, g, b); gdImageChar(im, font, x*font->w, y*font->h, ch, color); } /*outputHtmlChar() prints a given character into an html output file. It is optimized to collapse color tags if adjacent characters have the same color. However, it is necessary for the '<' and '>' characters to have their own color tags to prevent any text from being interpreted as html tags*/ void outputHtmlChar(int x, int y, char ch, int r, int g, int b) { static int prevR = 0; static int prevG = 0; static int prevB = 0; static char pch = EOF; if (ch == EOF) return; if(x == 0 && y != 0) fprintf(outFile, "\n
\n"); if (r == prevR && g == prevG && b == prevB && ch != '<' && ch != '>' && pch != '<' && pch != '>') fprintf(outFile, "%c", ch); else fprintf(outFile, "%c", r, g, b, ch); prevR = r; prevG = g; prevB = b; pch = ch; } int main(int argc, char *argv[]) { gdImagePtr sourceIm, im, out; int sourceW, sourceH, w, h; int i,j; int charCount = 0; float aspectFactor; /*set default background color*/ bgR = bgG = bgB = 50; /*process input args*/ processArgs(argc, argv); /*create image from input file*/ sourceIm = readImage(); fclose(imageFile); /*find size of image*/ sourceW = gdImageSX(sourceIm); sourceH = gdImageSY(sourceIm); aspectFactor = (float)font->h/font->w; if(wrapMode == NO_WRAP_TEXT) { /*find size of input text*/ while(getNextChar() != EOF) charCount++; rewind(textFile); /*compute new image size so #pixels is equal or slightly greater than number of characters in input text*/ w = ceil(sqrt(aspectFactor*charCount*((double)sourceW/sourceH))); h = ceil((double)charCount / w); } else /*wrapping text*/ { w = sourceW; h = sourceH / aspectFactor; } /*create resized image*/ im = gdImageCreate(w, h); gdImageCopyResized(im, sourceIm, 0, 0, 0, 0, w, h, sourceW, sourceH); /*set up output image for JPEG/PNG*/ if (outMode == JPEG_MODE || outMode == PNG_MODE) { int bgColor; out = gdImageCreate(w*font->w, h*font->h); bgColor = gdImageColorAllocate(out, bgR, bgG, bgB); if(!backGroundSet) gdImageColorTransparent(out, bgColor); gdImageFilledRectangle(out, 0, 0, w*font->w, h*font->h, bgColor); } /*set up output file for HTML*/ if (outMode == HTML_MODE) { fprintf(outFile, "\n"); if (backGroundSet) fprintf(outFile, "\n", bgR, bgG, bgB); else fprintf(outFile, "\n"); fprintf(outFile, "
\n"); fprintf(outFile, "\n"); fprintf(outFile, "\n"); /*fencepost*/ } /*loop through new image and print appropriately colored char*/ for(j=0; jred[c], im->green[c], im->blue[c]); if (outMode == HTML_MODE) outputHtmlChar(i, j, ch, im->red[c], im->green[c], im->blue[c]); } } /*ending stuff*/ if (outMode == JPEG_MODE) gdImageJpeg(out, outFile, jpegQuality); //-1 indicated default quality if (outMode == PNG_MODE) gdImagePng(out, outFile); if (outMode == HTML_MODE) fprintf(outFile, "\n\n"); /*clean up*/ fclose(textFile); fclose(outFile); gdImageDestroy(sourceIm); gdImageDestroy(im); if (outMode == JPEG_MODE || outMode == PNG_MODE) gdImageDestroy(out); printf("\nDone!\n"); return 0; }