Annotation of OpenXM_contrib/gnuplot/term/png.trm, Revision 1.1.1.3
1.1 maekawa 1: /*
1.1.1.3 ! ohara 2: * $Id: png.trm,v 1.11.2.12 2002/12/12 12:56:44 lhecking Exp $
1.1 maekawa 3: *
4: */
5:
6: /* GNUPLOT - png.trm */
7:
8: /*[
9: * Copyright 1995, 1998
10: *
11: * Permission to use, copy, and distribute this software and its
12: * documentation for any purpose with or without fee is hereby granted,
13: * provided that the above copyright notice appear in all copies and
14: * that both that copyright notice and this permission notice appear
15: * in supporting documentation.
16: *
17: * Permission to modify the software is granted, but not the right to
18: * distribute the complete modified source code. Modifications are to
19: * be distributed as patches to the released version. Permission to
20: * distribute binaries produced by compiling modified sources is granted,
21: * provided you
22: * 1. distribute the corresponding source modifications from the
23: * released version in the form of a patch file along with the binaries,
24: * 2. add special version identification to distinguish your version
25: * in addition to the base release version number,
26: * 3. provide your name and address as the primary contact for the
27: * support of your modified version, and
28: * 4. retain our contact information in regard to use of the base
29: * software.
30: * Permission to distribute the released version of the source code along
31: * with corresponding source modifications in the form of a patch file is
32: * granted with same provisions 2 through 4 for binary distributions.
33: *
34: * This software is provided "as is" without express or implied warranty
35: * to the extent permitted by applicable law.
36: ]*/
37:
38: /*
39: * This file is included by ../term.c.
40: *
41: * This terminal driver supports:
42: * png
43: *
44: * AUTHORS
1.1.1.3 ! ohara 45: * Alexander Lehmann
! 46: * derived from pbm.trm by Russell Lang
! 47: *
! 48: * Eric S. Raymond update for pnglib-1.0.3; transparency.
! 49: * H.-B. Broeker fixes to Eric's changes
1.1 maekawa 50: *
51: * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
52: *
53: */
54:
55: /* To compile this terminal driver, you need libpng and zlib, both are
56: available at ftp://ftp.uu.net/graphics/png. Remember to add the
57: include dirs and libraries to TERMFLAGS and TERMLIBS. */
58:
59: /* The following png drivers use the generic bit mapped graphics
60: routines from bitmap.c to build up a bit map in memory. The driver
61: interchanges colomns and lines in order to access entire lines
62: easily and returns the lines to get bits in the right order :
63: (x,y) -> (y,XMAX-1-x). */
64: /* This interchange is done by calling b_makebitmap() with reversed
65: xmax and ymax, and then setting b_rastermode to TRUE. b_setpixel()
66: will then perform the interchange before each pixel is plotted */
67:
68: #include "driver.h"
69:
70: #ifdef TERM_REGISTER
71: register_term(png_driver)
72: #endif
73:
74: #ifdef TERM_PROTO
1.1.1.2 maekawa 75: TERM_PUBLIC void PNG_options __PROTO((void));
76: TERM_PUBLIC void PNG_init __PROTO((void));
77: TERM_PUBLIC void PNG_reset __PROTO((void));
78: TERM_PUBLIC void PNG_setfont __PROTO((void));
79: TERM_PUBLIC void PNG_graphics __PROTO((void));
80: TERM_PUBLIC void PNG_text __PROTO((void));
81: TERM_PUBLIC void PNG_linetype __PROTO((int linetype));
82: TERM_PUBLIC void PNG_point __PROTO((unsigned int x, unsigned int y, int point));
1.1 maekawa 83: #endif /* TERM_PROTO */
84:
1.1.1.2 maekawa 85: /* make XMAX and YMAX a multiple of 8 */
86: #define PNG_XMAX (640)
87: #define PNG_YMAX (480)
88: #define PNG_VCHAR (FNT5X9_VCHAR)
89: #define PNG_HCHAR (FNT5X9_VCHAR)
90: #define PNG_VTIC FNT5X9_HBITS
91: #define PNG_HTIC FNT5X9_HBITS
92:
1.1 maekawa 93: #ifdef TERM_BODY
94:
95: #include "png.h"
96:
97: /* I'm not sure exactly which is the first version we work with,
98: * but I know that some older ones don't define all the symbols
99: * we use
100: */
101:
102: /* png version test now in configure */
103:
104: static int png_font = 1; /* small font */
105: static int png_mode = 0; /* 0:monochrome 1:gray 2:color */
1.1.1.3 ! ohara 106: static int png_transparent = 0; /* generate transparent first color */
1.1 maekawa 107:
108: /* 7=black, 0=white */
109: static int png_gray[] = { 7, 1, 6, 5, 4, 3, 2, 1, 7 }; /* grays */
1.1.1.3 ! ohara 110: static png_color png_palette[WEB_N_COLORS];
1.1 maekawa 111:
1.1.1.2 maekawa 112: TERM_PUBLIC void
113: PNG_options()
1.1 maekawa 114: {
1.1.1.3 ! ohara 115: unsigned short rgb_color[3];
! 116: int n_colors = 0;
! 117: char *string;
! 118: int i;
! 119:
! 120: rgb_color[0] = 0;
! 121: rgb_color[1] = 0;
! 122: rgb_color[2] = 0;
! 123:
! 124: png_font = 1; /* small */
! 125: png_mode = 2; /* color */
! 126: png_transparent = 0; /* use opaque image background */
1.1 maekawa 127:
128: term_options[0] = NUL;
129:
130: while (!END_OF_COMMAND) {
1.1.1.3 ! ohara 131: if (almost_equals(c_token, "s$mall"))
! 132: png_font = 1;
! 133: else if (almost_equals(c_token, "me$dium"))
! 134: png_font = 2;
! 135: else if (almost_equals(c_token, "l$arge"))
! 136: png_font = 3;
! 137: else if (almost_equals(c_token, "mo$nochrome"))
! 138: png_mode = 0;
! 139: else if (almost_equals(c_token, "g$ray"))
! 140: png_mode = 1;
! 141: else if (almost_equals(c_token, "c$olor")
! 142: || almost_equals(c_token, "c$olour"))
! 143: png_mode = 2;
! 144: else if (almost_equals(c_token, "t$ransparent"))
! 145: png_transparent = 1;
! 146: else if (almost_equals(c_token, "not$ransparent"))
! 147: png_transparent = 0;
! 148: else {
! 149: /* set color */
! 150: string = input_line + token[c_token].start_index;
! 151:
! 152: if (string[0] == 'x') {
! 153: /* HBB 991123: read in as *shorts*, not ints! */
! 154: if (sscanf(string, "x%2hx%2hx%2hx", &rgb_color[0], &rgb_color[1], &rgb_color[2] ) != 3) {
! 155: int_error("invalid color spec, must be xRRGGBB", c_token);
! 156: }
! 157: } else
! 158: int_error("expecting: {small, medium, large},[no]transparent, or {monochrome, gray, color, [xRRGGBB] }", c_token);
! 159:
! 160: if (n_colors >= WEB_N_COLORS) {
! 161: int_warn("too many colors, ignoring", c_token);
! 162: /* Magic number abuse guards against
! 163: * "> WEB_N_COLORS warning" scroll fests. */
! 164: if (!END_OF_COMMAND) {
! 165: while (!END_OF_COMMAND)
! 166: ++c_token; --c_token;
! 167: }
! 168: } else {
! 169: web_color_rgbs[n_colors].r = rgb_color[0];
! 170: web_color_rgbs[n_colors].g = rgb_color[1];
! 171: web_color_rgbs[n_colors].b = rgb_color[2];
! 172: n_colors++;
! 173: }
! 174: }
! 175: c_token++;
1.1 maekawa 176: }
177:
178: /* setup options string */
179:
1.1.1.3 ! ohara 180: /* HBB 991008: moved this block to here, so 'transparent' gets
! 181: * printed out first. Don't print 'notransparent', for now, to
! 182: * protect older gnuplots. Scripts with 'transparent' in them
! 183: * won't work as wanted, with older versions, so put it here. */
! 184: if (png_transparent)
! 185: strcat(term_options, " transparent");
! 186:
1.1 maekawa 187: switch (png_font) {
1.1.1.2 maekawa 188: case 3:
1.1.1.3 ! ohara 189: strcat(term_options, " large");
1.1 maekawa 190: break;
191: case 2:
1.1.1.3 ! ohara 192: strcat(term_options, " medium");
1.1 maekawa 193: break;
1.1.1.2 maekawa 194: case 1:
195: default:
1.1.1.3 ! ohara 196: strcat(term_options, " small");
1.1 maekawa 197: break;
198: }
199:
200: switch (png_mode) {
1.1.1.2 maekawa 201: case 2:
202: strcat(term_options, " color");
1.1 maekawa 203: break;
204: case 1:
205: strcat(term_options, " gray");
206: break;
1.1.1.2 maekawa 207: case 0:
208: default:
209: strcat(term_options, " monochrome");
1.1 maekawa 210: break;
211: }
1.1.1.2 maekawa 212:
1.1.1.3 ! ohara 213: for (i = 0; strlen(term_options) + 9 < MAX_LINE_LEN &&
! 214: i < n_colors ; i++ ) {
! 215: sprintf(term_options,"%s x%02x%02x%02x",
! 216: term_options,
! 217: web_color_rgbs[i].r,
! 218: web_color_rgbs[i].g,
! 219: web_color_rgbs[i].b);
! 220: }
1.1 maekawa 221: }
222:
223:
1.1.1.2 maekawa 224: TERM_PUBLIC void
225: PNG_init()
1.1 maekawa 226: {
1.1.1.2 maekawa 227: PNG_setfont(); /* HBB 980226: do this here! */
1.1 maekawa 228: }
229:
230:
1.1.1.2 maekawa 231: TERM_PUBLIC void
232: PNG_reset()
1.1 maekawa 233: {
234: #ifdef VMS
235: fflush_binary();
236: #endif /* VMS */
237: }
238:
239:
1.1.1.2 maekawa 240: TERM_PUBLIC void
241: PNG_setfont()
1.1 maekawa 242: {
243: switch (png_font) {
1.1.1.2 maekawa 244: case 3:
245: b_charsize(FNT13X25);
246: term->v_char = FNT13X25_VCHAR;
247: term->h_char = FNT13X25_HCHAR;
248: term->v_tic = FNT13X25_HBITS;
249: term->h_tic = FNT13X25_HBITS;
1.1 maekawa 250: break;
251: case 2:
252: b_charsize(FNT9X17);
253: term->v_char = FNT9X17_VCHAR;
254: term->h_char = FNT9X17_HCHAR;
255: term->v_tic = FNT9X17_HBITS;
256: term->h_tic = FNT9X17_HBITS;
257: break;
1.1.1.2 maekawa 258: case 1:
259: default:
260: b_charsize(FNT5X9);
261: term->v_char = FNT5X9_VCHAR;
262: term->h_char = FNT5X9_HCHAR;
263: term->v_tic = FNT5X9_HBITS;
264: term->h_tic = FNT5X9_HBITS;
1.1 maekawa 265: break;
266: }
267: }
268:
269:
1.1.1.2 maekawa 270: TERM_PUBLIC void
271: PNG_graphics()
1.1 maekawa 272: {
1.1.1.2 maekawa 273: int numplanes = 1;
1.1 maekawa 274:
275: switch (png_mode) {
1.1.1.2 maekawa 276: case 2:
1.1.1.3 ! ohara 277: numplanes = 8;
1.1 maekawa 278: break;
279: case 1:
280: numplanes = 3;
281: break;
1.1.1.2 maekawa 282: case 0:
283: default:
284: numplanes = 1;
1.1 maekawa 285: break;
286: }
287:
288: /* PNGsetfont(); *//* HBB 980226: do this in init() ! */
289:
290: /* rotate plot -90 degrees by reversing XMAX and YMAX and by
291: setting b_rastermode to TRUE */
292: b_makebitmap((unsigned int) (PNG_YMAX * ysize),
293: (unsigned int) (PNG_XMAX * xsize), numplanes);
294: b_rastermode = TRUE;
295:
296: if (png_mode != 0)
297: b_setlinetype(0); /* solid lines */
298: }
299:
1.1.1.2 maekawa 300: TERM_PUBLIC void
301: PNG_text()
1.1 maekawa 302: {
303: png_structp png_ptr;
304: png_infop info_ptr;
305: png_bytep prow;
306: png_text pngtext, *pngtext_copy;
1.1.1.3 ! ohara 307: png_byte pal_trans[1];
1.1 maekawa 308: char text[100];
1.1.1.3 ! ohara 309: register int x, i, j;
! 310: /* register int row, value; */
! 311: /* int mask, plane1, plane2, plane3, plane4; */
1.1 maekawa 312:
313: png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
314: if (!png_ptr) {
315: b_freebitmap();
316: return;
317: }
318: info_ptr = png_create_info_struct(png_ptr);
319: if (!info_ptr) {
320: png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
321: b_freebitmap();
322: return;
323: }
324: prow = malloc(b_ysize);
325: if (!prow) {
326: png_destroy_write_struct(&png_ptr, &info_ptr);
327: b_freebitmap();
328: return;
329: }
1.1.1.3 ! ohara 330: memset(prow,0,sizeof(prow));
1.1 maekawa 331: if (setjmp(png_ptr->jmpbuf)) {
332: png_destroy_write_struct(&png_ptr, &info_ptr);
333: free(prow);
334: b_freebitmap();
335: return;
336: }
1.1.1.2 maekawa 337:
338: #ifdef __OLD_PNGLIB__
1.1.1.3 ! ohara 339: /* deprecated and no longer necessary */
1.1 maekawa 340: png_info_init(info_ptr);
1.1.1.2 maekawa 341: png_write_init(png_ptr); */
342: #endif /* __OLD_PNGLIB__ */
1.1 maekawa 343:
344: png_init_io(png_ptr, gpoutfile);
345:
346: info_ptr->width = b_ysize;
347: info_ptr->height = b_xsize;
348:
1.1.1.3 ! ohara 349: info_ptr->bit_depth = png_mode == 0 ? 1 : 8;
1.1 maekawa 350: info_ptr->color_type = png_mode == 2 ? PNG_COLOR_TYPE_PALETTE :
351: PNG_COLOR_TYPE_GRAY;
352: if (png_mode == 2) {
353: info_ptr->valid |= PNG_INFO_PLTE;
354: info_ptr->palette = png_palette;
1.1.1.3 ! ohara 355: info_ptr->num_palette = sizeof(png_palette)/sizeof(png_palette[0]);
1.1 maekawa 356: }
357: if (png_mode != 0) {
358: info_ptr->valid |= PNG_INFO_sBIT;
359: if (png_mode == 1) {
360: info_ptr->sig_bit.gray = 3;
361: png_set_shift(png_ptr, &(info_ptr->sig_bit));
1.1.1.3 ! ohara 362: }
! 363: else {
! 364: /* HBB 991123: we're now using the full 8 bits per color
! 365: * component... */
! 366: info_ptr->sig_bit.red = 8;
! 367: info_ptr->sig_bit.green = 8;
! 368: info_ptr->sig_bit.blue = 8;
1.1 maekawa 369: }
370: }
1.1.1.3 ! ohara 371:
1.1 maekawa 372: info_ptr->interlace_type = 0;
1.1.1.3 ! ohara 373:
1.1 maekawa 374: if (png_mode == 0)
375: png_set_invert_mono(png_ptr);
376:
1.1.1.3 ! ohara 377: if (png_mode == 2) {
! 378: if (png_transparent) {
! 379: info_ptr->valid |= PNG_INFO_tRNS;
! 380: info_ptr->num_trans = 1;
! 381: pal_trans[0] = 0;
! 382: info_ptr->trans=pal_trans;
1.1 maekawa 383: }
1.1.1.3 ! ohara 384:
! 385: for (i = 0; i < WEB_N_COLORS; i++) {
! 386: png_palette[i].red = web_color_rgbs[i].r;
! 387: png_palette[i].green = web_color_rgbs[i].g;
! 388: png_palette[i].blue = web_color_rgbs[i].b;
! 389: }
! 390: }
! 391: sprintf(text, "gnuplot version %s patchlevel %s on %s %s",
! 392: gnuplot_version, gnuplot_patchlevel, os_name, os_rel);
1.1 maekawa 393:
394: pngtext.compression = -1;
395: pngtext.key = "Software";
396: pngtext.text = text;
397: pngtext.text_length = strlen(text);
398:
399: pngtext_copy = malloc(sizeof(*pngtext_copy));
1.1.1.3 ! ohara 400: if (!pngtext_copy) {
! 401: png_destroy_write_struct(&png_ptr, &info_ptr);
! 402: free(prow);
! 403: b_freebitmap();
! 404: return;
! 405: }
! 406: memset(pngtext_copy,0,sizeof(pngtext_copy));
1.1 maekawa 407: *pngtext_copy = pngtext;
408: info_ptr->num_text = 1;
409: info_ptr->text = pngtext_copy;
410:
411: png_write_info(png_ptr, info_ptr);
412:
413: info_ptr->num_text = 0;
414: if (info_ptr->text) free(info_ptr->text);
415: info_ptr->text = NULL;
416:
417: png_set_packing(png_ptr);
418:
419: /* dump bitmap in raster mode */
420: for (x = b_xsize - 1; x >= 0; x--) {
1.1.1.3 ! ohara 421: #if 0
1.1 maekawa 422: row = (b_ysize / 8) - 1;
423: for (j = row; j >= 0; j--) {
424: mask = 0x80;
425: plane1 = (*((*b_p)[j] + x));
426: if (png_mode != 0) {
427: plane2 = (*((*b_p)[j + b_psize] + x));
428: plane3 = (*((*b_p)[j + b_psize + b_psize] + x));
429: } else {
430: plane2 = 0;
431: plane3 = 0;
432: }
433: if (png_mode == 2)
434: plane4 = (*((*b_p)[j + b_psize + b_psize + b_psize] + x));
435: else
436: plane4 = 0;
437:
438: for (i = 0; i < 8; i++) {
439: value = 0;
440: if (plane1 & mask)
441: value += 1;
442: if (plane2 & mask)
443: value += 2;
444: if (plane3 & mask)
445: value += 4;
446: if (plane4 & mask)
447: value += 8;
448: if (png_mode == 1)
449: value = 7 - value;
450:
1.1.1.3 ! ohara 451: prow[(row - j) * 8 + i] = (png_byte) (value & 0xFF) ;
1.1 maekawa 452: mask >>= 1;
453: }
454: }
1.1.1.3 ! ohara 455: #else
! 456: for (j=b_ysize - 1; j>= 0; j--)
! 457: prow[j] = (png_byte)b_getpixel(j, x);
! 458: #endif
1.1 maekawa 459: png_write_rows(png_ptr, &prow, 1);
460: }
461:
462: png_write_end(png_ptr, info_ptr);
463: png_destroy_write_struct(&png_ptr, &info_ptr);
464: free(prow);
465: b_freebitmap();
466: }
467:
1.1.1.3 ! ohara 468: /* _linetype(lt) Called to set the line type before text is displayed or
! 469: * line(s) plotted. This procedure should select a pen color or line
! 470: * style if the device has these capabilities.
! 471: * lt is an integer from -2 to 0 or greater.
! 472: * An lt of -2 is used for the border of the plot.
! 473: * An lt of -1 is used for the X and Y axes.
! 474: * lt 0 and upwards are used for plots 0 and upwards.
! 475: * If _linetype() is called with lt greater than the available line types,
! 476: * it should map it to one of the available line types.
! 477: * Most drivers provide 9 different linetypes (lt is 0 to 8).
! 478: */
1.1.1.2 maekawa 479: TERM_PUBLIC void
480: PNG_linetype(linetype)
1.1 maekawa 481: int linetype;
482: {
483: switch (png_mode) {
1.1.1.3 ! ohara 484: /* HBB 991008: this once made the grid lines and axes (-1) look the
! 485: * same as the borders (-2). That's ugly, IMHO. GIF uses a
! 486: * dashed line, for this, but libpng doesn't seem able to do
! 487: * that. But a look into the palette turns up that color 2
! 488: * is grey, and is currently unused... Let's see: */
1.1.1.2 maekawa 489: case 2:
1.1.1.3 ! ohara 490:
! 491: if (linetype == -2)
! 492: linetype = 1;
! 493: else if (linetype == -1)
! 494: linetype = 2;
! 495:
! 496: else {
! 497: /* HBB 991008: moved the += 3 down, so colors 0, 1, 2 are
! 498: * _not_ used by the regular plots, as it should be */
! 499: if (linetype >= (WEB_N_COLORS - 3))
! 500: linetype %= (WEB_N_COLORS - 3);
! 501: linetype += 3;
! 502: }
! 503: b_setvalue(linetype);
1.1 maekawa 504: break;
505: case 1:
506: if (linetype >= 7)
507: linetype %= 7;
508: b_setvalue(png_gray[linetype + 2]);
509: break;
1.1.1.2 maekawa 510: case 0:
511: default:
512: b_setlinetype(linetype);
1.1 maekawa 513: break;
514: }
515: }
516:
1.1.1.2 maekawa 517: TERM_PUBLIC void
518: PNG_point(x, y, point)
1.1 maekawa 519: unsigned int x, y;
520: int point;
521: {
522: if (png_mode == 0)
523: line_and_point(x, y, point);
524: else
525: do_point(x, y, point);
526: }
527:
528: #endif /* TERM_BODY */
529:
530: #ifdef TERM_TABLE
531:
532: TERM_TABLE_START(png_driver)
533: "png",
534: "Portable Network Graphics [small medium large] [monochrome gray color]",
535: PNG_XMAX, PNG_YMAX, PNG_VCHAR,
1.1.1.2 maekawa 536: PNG_HCHAR, PNG_VTIC, PNG_HTIC, PNG_options,
537: PNG_init, PNG_reset, PNG_text, null_scale,
538: PNG_graphics, b_move, b_vector, PNG_linetype,
539: b_put_text, b_text_angle, null_justify_text, PNG_point,
1.1 maekawa 540: do_arrow, set_font_null,
541: 0, /* pointsize */
542: TERM_CAN_MULTIPLOT | TERM_BINARY
543: TERM_TABLE_END(png_driver)
544:
545: #undef LAST_TERM
546: #define LAST_TERM png_driver
547:
548: #endif /* TERM_TABLE */
549:
550: #ifdef TERM_HELP
551: START_HELP(png)
552: "1 png",
553: "?commands set terminal png",
554: "?set terminal png",
555: "?set term png",
556: "?terminal png",
557: "?term png",
558: "?png",
559: " The `png` terminal driver supports Portable Network Graphics. To compile it,",
560: " you will need the third-party libraries \"libpng\" and \"zlib\"; both are",
1.1.1.3 ! ohara 561: " available at http://www.cdrom.com/pub/png/. `png` has four options.",
! 562: "",
! 563: " By default, the `png` terminal driver uses a shared Web-friendy palette.",
1.1 maekawa 564: "",
565: " Syntax:",
566: " set terminal png {small | medium | large}",
1.1.1.3 ! ohara 567: " {transparent | notransparent}",
1.1 maekawa 568: " {monochrome | gray | color}",
1.1.1.3 ! ohara 569: " {<color0> <color1> <color2> ...}",
! 570: "",
! 571: " `transparent` instructs the driver to generate transparent PNGs. The first",
! 572: " color will be the transparent one.",
! 573: "",
! 574: " The defaults are small (fontsize) and color. Default size of the output",
! 575: " is 640*480 pixel. ",
1.1 maekawa 576: "",
1.1.1.3 ! ohara 577: " Each color must be of the form 'xrrggbb', where x is the literal character",
! 578: " 'x' and 'rrggbb' are the red, green and blue components in hex. For example,",
! 579: " 'x00ff00' is green. The background color is set first, then the border",
! 580: " colors, then the X & Y axis colors, then the plotting colors. The maximum",
! 581: " number of colors that can be set is currently 99."
1.1 maekawa 582: END_HELP(png)
583: #endif /* TERM_HELP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>