/* Add text labels to a PPM image by John Walker -- kelvin@fourmilab.ch WWW home page: http://www.fourmilab.ch/ June 1995 */ #define _XOPEN_SOURCE 500 /* get M_PI in math.h */ #include #include #include "pm_c_util.h" #include "ppm.h" #include "ppmdraw.h" #define dtr(x) (((x) * M_PI) / 180.0) static int argn, rows, cols, x, y, size, angle, transparent; static pixel **pixels; static pixval maxval; static pixel rgbcolor, backcolor; /* DRAWTEXT -- Draw text at current location and advance to start of next line. */ static void drawtext(const char * const text) { if (!transparent && strlen(text) > 0) { struct fillobj * handle; int left, top, right, bottom; int lx, ly; int p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; double sina, cosa; handle = ppmd_fill_create(); ppmd_text_box(size, 0, text, &left, &top, &right, &bottom); /* Displacement vector */ lx = right; ly = -(top - bottom); /* Sine and cosine */ sina = sin(dtr(angle)); cosa = cos(dtr(angle)); /* Rotated extent box corners */ p1x = (int) ((x + left * cosa + bottom * sina) + 0.5); p1y = (int) ((y + bottom * cosa + -left * sina) + 0.5); #define WERF ppmd_fill_drawproc, handle p2x = (int) (p1x - sina * ly + 0.5); p2y = (int) ((p1y - cosa * ly) + 0.5); p3x = (int) (p1x + cosa * lx + -sina * ly + 0.5); p3y = (int) ((p1y - (cosa * ly + sina * lx)) + 0.5); p4x = (int) (p1x + cosa * lx + 0.5); p4y = (int) ((p1y - sina * lx) + 0.5); ppmd_line(pixels, cols, rows, maxval, p1x, p1y, p2x, p2y, WERF); ppmd_line(pixels, cols, rows, maxval, p2x, p2y, p3x, p3y, WERF); ppmd_line(pixels, cols, rows, maxval, p3x, p3y, p4x, p4y, WERF); ppmd_line(pixels, cols, rows, maxval, p4x, p4y, p1x, p1y, WERF); ppmd_fill(pixels, cols, rows, maxval, handle, PPMD_NULLDRAWPROC, (char *) &backcolor); ppmd_fill_destroy(handle); } ppmd_text(pixels, cols, rows, maxval, x, y, size, angle, text, PPMD_NULLDRAWPROC, (char *) &rgbcolor); /* For convenience, simulate a carriage return to the next line. This allows multiple "-text" specifications or multiple lines in a -file input to write consecutive lines of text in a generally reasonable fashion. */ x += (int) ((cos(dtr(angle + 270)) * size * 1.75) + 0.5); y -= (int) ((sin(dtr(angle + 270)) * size * 1.75) + 0.5); } int main(int argc, char *argv[]) { FILE *ifP; /* Process standard command line arguments */ ppm_init(&argc, argv); argn = 1; /* Check for explicit input file specification, Note that we count on the fact that every command line switch takes a single argument. If this becomes untrue due to a change in the future, you'll have to make this test smarter. */ if ((argn != argc) && (argc == 2 || argv[argc - 2][0] != '-')) { ifP = pm_openr(argv[argc - 1]); argc--; } else ifP = stdin; /* Load input image */ pixels = ppm_readppm(ifP, &cols, &rows, &maxval); pm_close(ifP); /* Set initial defaults */ x = 0; y = rows / 2; size = 12; angle = 0; PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); PPM_ASSIGN(backcolor, 0, 0, 0); transparent = TRUE; while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { if (pm_keymatch(argv[argn], "-angle", 1)) { argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &angle) != 1)) pm_error("-angle doesn't have a value"); } else if (pm_keymatch(argv[argn], "-background", 1)) { argn++; if (strcmp(argv[argn], "transparent") == 0) { transparent = TRUE; } else { transparent = FALSE; backcolor = ppm_parsecolor(argv[argn], maxval); } } else if (pm_keymatch(argv[argn], "-color", 1) || pm_keymatch(argv[argn], "-colour", 1)) { argn++; rgbcolor = ppm_parsecolor(argv[argn], maxval); } else if (pm_keymatch(argv[argn], "-file", 1)) { char s[512]; argn++; ifP = pm_openr(argv[argn]); while (fgets(s, sizeof s, ifP) != NULL) { while (s[0] != 0 && s[strlen(s) - 1] < ' ') { s[strlen(s) - 1] = 0; } drawtext(s); } pm_close(ifP); } else if (pm_keymatch(argv[argn], "-size", 1)) { argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &size) != 1)) pm_error("-size doesn't have a value"); } else if (pm_keymatch(argv[argn], "-text", 1)) { argn++; drawtext(argv[argn]); } else if (pm_keymatch(argv[argn], "-u", 1)) { pm_error("-u doesn't have a value"); } else if (pm_keymatch(argv[argn], "-x", 1)) { argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &x) != 1)) pm_error("-x doesn't have a value"); } else if (pm_keymatch(argv[argn], "-y", 1)) { argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &y) != 1)) pm_error("-y doesn't have a value"); } else pm_error("Unrecognized option: '%s'", argv[argn]); argn++; } if (argn != argc) pm_error("Extraneous arguments"); ppm_writeppm(stdout, pixels, cols, rows, maxval, 0); ppm_freearray(pixels, rows); return 0; }