/* AlphaTone * * Converts a small PPM file to a PostScript file. * All pixels are replaced with a character of * varying weights. Replacement string should * be specified on the command line. * * Output is to STDOUT. * * bkg2 * 10/11/00 */ #include #include "Image.h" #define MAX_JITTER 8 enum METHOD { GREYVAL, COLORVAL, JITTER }; METHOD method_; char *filename_; char *phrase_; int plength_; Image image_; FILE *ps_; int char_height_; int font_scale_; void print_help(void) { printf(" param 1: PPM filename\n"); printf(" param 2: phrase\n"); printf("[param 3]: method: {greyval, colorval, jitter}\n"); printf("[param 4]: output filename\n"); } void parse_commandline(int argc, char *argv[]) { if (argc < 3) { print_help(); exit(-1); } if (argc >= 3) { filename_ = argv[1]; phrase_ = argv[2]; plength_ = strlen(phrase_); ps_ = stdout; } if (argc >= 4) { if (strcasecmp(argv[3], "greyval") == 0) { method_ = GREYVAL; } else if (strcasecmp(argv[3], "colorval") == 0) { method_ = COLORVAL; } else if (strcasecmp(argv[3], "jitter") == 0) { method_ = JITTER; } else { print_help(); exit(-1); } } if (argc >= 5) { ps_ = fopen(argv[4], "w"); if (ps_ == NULL) { perror("fopen (using stdout)"); ps_ = stdout; } } fprintf(stderr, "Using method %d\n", method_); } void print_ps_header(void) { font_scale_ = (int)((double)(72 * 11) / (double)image_.rows_); font_scale_ *= 3; char_height_ = font_scale_; fprintf(ps_, "\%%!PS-Adobe-2.0\n"); fprintf(ps_, "%%%%BoundingBox: 0 0 2592 2592\n"); fprintf(ps_, "%%<> setpagedevice %% 36in x 36in\n"); fprintf(ps_, "%%0.2361 dup scale %% for 8.5 x 11\n"); fprintf(ps_, "<> setpagedevice %% 8.5in x 11in\n"); fprintf(ps_, "1.33 1.0 scale %% correct aspect ratio\n"); fprintf(ps_, "0 0 moveto\n"); fprintf(ps_, "/Courier findfont %d scalefont setfont\n", font_scale_); fprintf(ps_, "/charwidth (W) stringwidth pop def\n"); fprintf(ps_, "/charheight %d def\n", char_height_); fprintf(ps_, "%%% ===== END HEADER ===== %%%\n\n"); } void print_ps_footer(void) { fprintf(ps_, "%%% ===== BEGIN FOOTER ===== %%%\n\n"); fprintf(ps_, "showpage\n"); } void alpha_tone(void) { /* Need to get code for HSV conversion */ int j; int c; // the character pixel p; float value; float r, g, b; int phrase_idx = 0; int invy; /* * Output pre-PS stuff */ //fprintf(ps_, "\n/%s {\n", "alpha"); // define a function for (int y = 0; y < image_.rows_; y++) { invy = image_.rows_ - y - 1; //for (int y = image_.rows_ - 1; y >= 0; y--) { fprintf(ps_, "\n0 %d moveto\n", (int)(y * char_height_)); for (int x = 0; x < image_.cols_; x++) { /* Get colors and grey value */ p = image_.pixels_[invy][x]; r = PPM_GETR(p) / 255.0; g = PPM_GETG(p) / 255.0; b = PPM_GETB(p) / 255.0; value = (r + g + b) / 3.0; /* Get smear quantization */ int smear = (int)((1 - value) * (float)MAX_JITTER); //fprintf(stderr, "smear=%d\n", smear); /* Get character */ c = (int)((char)phrase_[phrase_idx++ % plength_]); switch (method_) { case GREYVAL: fprintf(ps_, "%f setgray (%c) show ", value, c); break; case COLORVAL: fprintf(ps_, "%f %f %f setrgbcolor (%c) show ", r, g, b, c); break; case JITTER: if (smear > 0) { fprintf(ps_, "currentpoint (%c) show moveto currentpoint\n", c); // main character for (j = 0; j < smear; j++) { fprintf(ps_, " rand 3 mod 1 sub rand 3 mod 1 sub rmoveto (%c) show charwidth neg 0 rmoveto\n", c); } fprintf(ps_, " exch charwidth add exch moveto\n"); } else { fprintf(ps_, "(%c) show\n", c); } break; } /* switch */ } /* for x */ } /* for y */ /* * Output post-PS stuff */ //fprintf(ps_, "\n} def\n"); // close function } int main(int argc, char *argv[]) { /* * Get command line stuff */ parse_commandline(argc, argv); /* * Load image */ if (!image_.read_ppm(filename_)) { fprintf(stderr, "Error reading %s.\n", filename_); exit(-1); } /* * Create beginning of PostScript document */ print_ps_header(); /* * Do it! */ alpha_tone(); /* * Create end of PostScript document */ print_ps_footer(); /* * Close output file if opened */ if (ps_ != stdout) { fclose(ps_); } }