[BACK]Return to png.trm CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot / term

File: [local] / OpenXM_contrib / gnuplot / term / Attic / png.trm (download)

Revision 1.1, Sun Jan 9 17:01:15 2000 UTC (24 years, 4 months ago) by maekawa
Branch: MAIN

Initial revision

/*
 * $Id: png.trm,v 1.13 1998/06/18 14:59:23 ddenholm Exp $
 *
 */

/* GNUPLOT - png.trm */

/*[
 * Copyright 1995, 1998
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the complete modified source code.  Modifications are to
 * be distributed as patches to the released version.  Permission to
 * distribute binaries produced by compiling modified sources is granted,
 * provided you
 *   1. distribute the corresponding source modifications from the
 *    released version in the form of a patch file along with the binaries,
 *   2. add special version identification to distinguish your version
 *    in addition to the base release version number,
 *   3. provide your name and address as the primary contact for the
 *    support of your modified version, and
 *   4. retain our contact information in regard to use of the base
 *    software.
 * Permission to distribute the released version of the source code along
 * with corresponding source modifications in the form of a patch file is
 * granted with same provisions 2 through 4 for binary distributions.
 *
 * This software is provided "as is" without express or implied warranty
 * to the extent permitted by applicable law.
]*/

/*
 * This file is included by ../term.c.
 *
 * This terminal driver supports:
 *  png
 *
 * AUTHORS
 *  Alexander Lehmann
 *                      derived from pbm.trm by Russell Lang
 *
 * send your comments or suggestions to (info-gnuplot@dartmouth.edu).
 *
 */

/* To compile this terminal driver, you need libpng and zlib, both are
   available at ftp://ftp.uu.net/graphics/png. Remember to add the
   include dirs and libraries to TERMFLAGS and TERMLIBS. */

/* The following png drivers use the generic bit mapped graphics
   routines from bitmap.c to build up a bit map in memory.  The driver
   interchanges colomns and lines in order to access entire lines
   easily and returns the lines to get bits in the right order :
   (x,y) -> (y,XMAX-1-x). */
/* This interchange is done by calling b_makebitmap() with reversed
   xmax and ymax, and then setting b_rastermode to TRUE.  b_setpixel()
   will then perform the interchange before each pixel is plotted */

#include "driver.h"

#ifdef TERM_REGISTER
register_term(png_driver)
#endif

#ifdef TERM_PROTO
TERM_PUBLIC void PNGoptions __PROTO((void));
TERM_PUBLIC void PNGinit __PROTO((void));
TERM_PUBLIC void PNGreset __PROTO((void));
TERM_PUBLIC void PNGsetfont __PROTO((void));
TERM_PUBLIC void PNGgraphics __PROTO((void));
TERM_PUBLIC void PNGtext __PROTO((void));
TERM_PUBLIC void PNGlinetype __PROTO((int linetype));
TERM_PUBLIC void PNGpoint __PROTO((unsigned int x, unsigned int y, int point));
#endif /* TERM_PROTO */

#ifdef TERM_BODY

#include "png.h"

/* I'm not sure exactly which is the first version we work with,
 * but I know that some older ones don't define all the symbols
 * we use
 */

/* png version test now in configure */

/* From version.c */
extern char version[];
extern char patchlevel[];

/* make XMAX and YMAX a multiple of 8 */
#define PNG_XMAX (640)
#define PNG_YMAX (480)
#define PNG_VCHAR (FNT5X9_VCHAR)
#define PNG_HCHAR (FNT5X9_VCHAR)
#define PNG_VTIC FNT5X9_HBITS
#define PNG_HTIC FNT5X9_HBITS

static int png_font = 1;	/* small font */
static int png_mode = 0;	/* 0:monochrome 1:gray 2:color */

/* 7=black, 0=white */
static int png_gray[] = { 7, 1, 6, 5, 4, 3, 2, 1, 7 };	/* grays  */
/* bit3=!intensify, bit2=!red, bit1=!green, bit0=!blue */
static int png_color_table[] ={ 15, 8, 3, 5, 6, 4, 2, 1, 11, 13, 14 };	/* colors */
static png_color png_palette[16];

void PNGoptions()
{
    png_font = 1;
    png_mode = 0;

    term_options[0] = NUL;

    while (!END_OF_COMMAND) {
	if (almost_equals(c_token, "s$mall"))
	    png_font = 1;
	else if (almost_equals(c_token, "me$dium"))
	    png_font = 2;
	else if (almost_equals(c_token, "l$arge"))
	    png_font = 3;
	else if (almost_equals(c_token, "mo$nochrome"))
	    png_mode = 0;
	else if (almost_equals(c_token, "g$ray"))
	    png_mode = 1;
	else if (almost_equals(c_token, "c$olor")
		 || almost_equals(c_token, "c$olour"))
	    png_mode = 2;
	else {
	    /* reset to default, since term is already set */
	    png_font = 1;
	    png_mode = 0;
	    int_error("expecting: {small, medium, large} and {monochrome, gray, color}", c_token);
	}
	c_token++;
    }

    /* setup options string */

    switch (png_font) {
    case 1:
	strcat(term_options, "small");
	break;
    case 2:
	strcat(term_options, "medium");
	break;
    case 3:
	strcat(term_options, "large");
	break;
    }

    switch (png_mode) {
    case 0:
	strcat(term_options, " monochrome");
	break;
    case 1:
	strcat(term_options, " gray");
	break;
    case 2:
	strcat(term_options, " color");
	break;
    }
}


void PNGinit()
{
    PNGsetfont();		/* HBB 980226: do this here! */
}


void PNGreset()
{
#ifdef VMS
    fflush_binary();
#endif /* VMS */
}


void PNGsetfont()
{
    switch (png_font) {
    case 1:
	b_charsize(FNT5X9);
	term->v_char = FNT5X9_VCHAR;
	term->h_char = FNT5X9_HCHAR;
	term->v_tic = FNT5X9_HBITS;
	term->h_tic = FNT5X9_HBITS;
	break;
    case 2:
	b_charsize(FNT9X17);
	term->v_char = FNT9X17_VCHAR;
	term->h_char = FNT9X17_HCHAR;
	term->v_tic = FNT9X17_HBITS;
	term->h_tic = FNT9X17_HBITS;
	break;
    case 3:
	b_charsize(FNT13X25);
	term->v_char = FNT13X25_VCHAR;
	term->h_char = FNT13X25_HCHAR;
	term->v_tic = FNT13X25_HBITS;
	term->h_tic = FNT13X25_HBITS;
	break;
    }
}


void PNGgraphics()
{
    int numplanes;

    switch (png_mode) {
    case 0:
	numplanes = 1;
	break;
    case 1:
	numplanes = 3;
	break;
    case 2:
	numplanes = 4;
	break;
    }

    /* PNGsetfont(); *//* HBB 980226: do this in init() ! */

    /* rotate plot -90 degrees by reversing XMAX and YMAX and by
       setting b_rastermode to TRUE */
    b_makebitmap((unsigned int) (PNG_YMAX * ysize),
		 (unsigned int) (PNG_XMAX * xsize), numplanes);
    b_rastermode = TRUE;

    if (png_mode != 0)
	b_setlinetype(0);	/* solid lines */
}

void PNGtext()
{
    register int x, j, row;
    png_structp png_ptr;
    png_infop info_ptr;
    register int i, value;
    png_bytep prow;
    int mask, plane1, plane2, plane3, plane4;
    int red, green, blue;
    png_text pngtext, *pngtext_copy;
    char text[100];

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
	b_freebitmap();
	return;
    }
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
	png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
	b_freebitmap();
	return;
    }
    prow = malloc(b_ysize);
    if (!prow) {
	png_destroy_write_struct(&png_ptr, &info_ptr);
	b_freebitmap();
	return;
    }
    if (setjmp(png_ptr->jmpbuf)) {
	png_destroy_write_struct(&png_ptr, &info_ptr);
	free(prow);
	b_freebitmap();
	return;
    }
    png_info_init(info_ptr);
    png_write_init(png_ptr);

    png_init_io(png_ptr, gpoutfile);

    info_ptr->width = b_ysize;
    info_ptr->height = b_xsize;

    info_ptr->bit_depth = png_mode == 0 ? 1 : 4;
    info_ptr->color_type = png_mode == 2 ? PNG_COLOR_TYPE_PALETTE :
	PNG_COLOR_TYPE_GRAY;
    if (png_mode == 2) {
	info_ptr->valid |= PNG_INFO_PLTE;
	info_ptr->palette = png_palette;
	info_ptr->num_palette = 16;
    }
    if (png_mode != 0) {
	info_ptr->valid |= PNG_INFO_sBIT;
	if (png_mode == 1) {
	    info_ptr->sig_bit.gray = 3;
	    png_set_shift(png_ptr, &(info_ptr->sig_bit));
	} else {
	    info_ptr->sig_bit.red = 2;
	    info_ptr->sig_bit.green = 2;
	    info_ptr->sig_bit.blue = 2;
	}
    }
    info_ptr->interlace_type = 0;
    if (png_mode == 0)
	png_set_invert_mono(png_ptr);

    if (png_mode == 2)
	for (i = 0; i < 16; i++) {
	    red = (i & 4) ? 1 : 3;
	    green = (i & 2) ? 1 : 3;
	    blue = (i & 1) ? 1 : 3;
	    if (i & 8) {
		red--;
		green--;
		blue--;
	    }
	    png_palette[i].red = red * 85;
	    png_palette[i].green = green * 85;
	    png_palette[i].blue = blue * 85;
	}
    sprintf(text, "gnuplot %sversion %s patchlevel %s", OS, version, patchlevel);

    pngtext.compression = -1;
    pngtext.key = "Software";
    pngtext.text = text;
    pngtext.text_length = strlen(text);

    pngtext_copy = malloc(sizeof(*pngtext_copy));
    *pngtext_copy = pngtext;
    info_ptr->num_text = 1;
    info_ptr->text = pngtext_copy;

    png_write_info(png_ptr, info_ptr);

    info_ptr->num_text = 0;
    if (info_ptr->text) free(info_ptr->text);
    info_ptr->text = NULL;

    png_set_packing(png_ptr);

    /* dump bitmap in raster mode */
    for (x = b_xsize - 1; x >= 0; x--) {
	row = (b_ysize / 8) - 1;
	for (j = row; j >= 0; j--) {
	    mask = 0x80;
	    plane1 = (*((*b_p)[j] + x));
	    if (png_mode != 0) {
		plane2 = (*((*b_p)[j + b_psize] + x));
		plane3 = (*((*b_p)[j + b_psize + b_psize] + x));
	    } else {
		plane2 = 0;
		plane3 = 0;
	    }
	    if (png_mode == 2)
		plane4 = (*((*b_p)[j + b_psize + b_psize + b_psize] + x));
	    else
		plane4 = 0;

	    for (i = 0; i < 8; i++) {
		value = 0;
		if (plane1 & mask)
		    value += 1;
		if (plane2 & mask)
		    value += 2;
		if (plane3 & mask)
		    value += 4;
		if (plane4 & mask)
		    value += 8;
		if (png_mode == 1)
		    value = 7 - value;

		prow[(row - j) * 8 + i] = (png_byte) value;
		mask >>= 1;
	    }
	}
	png_write_rows(png_ptr, &prow, 1);
    }

    png_write_end(png_ptr, info_ptr);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    free(prow);
    b_freebitmap();
}

void PNGlinetype(linetype)
int linetype;
{
    switch (png_mode) {
    case 0:
	b_setlinetype(linetype);
	break;
    case 1:
	if (linetype >= 7)
	    linetype %= 7;
	b_setvalue(png_gray[linetype + 2]);
	break;
    case 2:
	if (linetype >= 9)
	    linetype %= 9;
	b_setvalue(png_color_table[linetype + 2]);
	break;
    }
}

void PNGpoint(x, y, point)
unsigned int x, y;
int point;
{
    if (png_mode == 0)
	line_and_point(x, y, point);
    else
	do_point(x, y, point);
}

#endif /* TERM_BODY */

#ifdef TERM_TABLE

TERM_TABLE_START(png_driver)
    "png",
    "Portable Network Graphics [small medium large] [monochrome gray color]",
    PNG_XMAX, PNG_YMAX, PNG_VCHAR,
    PNG_HCHAR, PNG_VTIC, PNG_HTIC, PNGoptions,
    PNGinit, PNGreset, PNGtext, null_scale,
    PNGgraphics, b_move, b_vector, PNGlinetype,
    b_put_text, b_text_angle, null_justify_text, PNGpoint,
    do_arrow, set_font_null,
    0,				/* pointsize */
    TERM_CAN_MULTIPLOT | TERM_BINARY
TERM_TABLE_END(png_driver)

#undef LAST_TERM
#define LAST_TERM png_driver

#endif /* TERM_TABLE */

#ifdef TERM_HELP
START_HELP(png)
"1 png",
"?commands set terminal png",
"?set terminal png",
"?set term png",
"?terminal png",
"?term png",
"?png",
" The `png` terminal driver supports Portable Network Graphics.  To compile it,",
" you will need  the third-party libraries \"libpng\" and \"zlib\"; both are",
" available at ftp://ftp.uu.net/graphics/png.  `png` has two options.",
"",
" Syntax:",
"       set terminal png {small | medium | large}",
"                        {monochrome | gray | color}",
"",
" The defaults are small (fontsize) and monochrome."
END_HELP(png)
#endif /* TERM_HELP */