119#if defined ( PLD_png ) || defined ( PLD_jpeg ) || defined ( PLD_gif )
134#if defined ( PLD_png )
135 "png:PNG file:0:gd:39:png\n"
137#if defined ( PLD_jpeg )
138 "jpeg:JPEG file:0:gd:40:jpeg\n"
140#if defined ( PLD_gif )
141 "gif:GIF file:0:gd:47:gif\n"
146#ifdef PL_HAVE_FREETYPE
147#define SMOOTH_LINES_OK
151#ifdef PL_HAVE_FREETYPE
186#ifdef PL_HAVE_FREETYPE
188static void plD_pixel_gd(
PLStream *
pls,
short x,
short y );
190static void plD_set_pixel_gd(
PLStream *
pls,
short x,
short y,
PLINT colour );
198static int NCOLOURS = gdMaxColors;
208#define use_experimental_hidden_line_hack
221#ifndef max_number_of_grey_levels_used_in_text_smoothing
222#define max_number_of_grey_levels_used_in_text_smoothing 64
227#ifndef gdImagePalettePixel
228#define gdImagePalettePixel( im, x, y ) ( im )->pixels[( y )][( x )]
232int plToGdAlpha(
PLFLT a )
234 int tmp = (int) ( ( 1.0 - a ) * gdAlphaMax );
258 unsigned char TRY_BLENDED_ANTIALIASING;
263 unsigned char smooth;
268void plD_line_png(
PLStream *,
short,
short,
short,
short );
285#ifndef ENABLE_DYNDRIVERS
286 pdt->pl_MenuStr =
"PNG file";
287 pdt->pl_DevName =
"png";
307#ifndef ENABLE_DYNDRIVERS
308 pdt->pl_MenuStr =
"JPEG File";
309 pdt->pl_DevName =
"jpeg";
329#ifndef ENABLE_DYNDRIVERS
330 pdt->pl_MenuStr =
"GIF File";
331 pdt->pl_DevName =
"gif";
361 static int optimise = 0;
362 static int black15 = 0;
363 static int red15 = 0;
365 static int truecolour = 0;
366 static int palette = 0;
367 static int smooth_line = 0;
369#ifdef PL_HAVE_FREETYPE
370 static int freetype = 1;
371 static int smooth_text = 1;
375 DrvOpt gd_options[] = { {
"optimise",
DRV_INT, &optimise,
"Optimise PNG palette when possible" },
376 {
"def_black15",
DRV_INT, &black15,
"Define idx 15 as black. If the background is \"whiteish\" (from \"-bg\" option), force index 15 (traditionally white) to be \"black\"" },
377 {
"swp_red15",
DRV_INT, &red15,
"Swap index 1 (usually red) and 1 (usually white); always done after \"black15\"; quite useful for quick changes to web pages" },
379 {
"8bit",
DRV_INT, &palette,
"Palette (8 bit) mode" },
380 {
"24bit",
DRV_INT, &truecolour,
"Truecolor (24 bit) mode" },
381 {
"smoothlines",
DRV_INT, &smooth_line,
"Turn line Anti Aliasing on (1) or off (0)" },
383#ifdef PL_HAVE_FREETYPE
384 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
385 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
387 { NULL,
DRV_INT, NULL, NULL } };
392 if (
pls->dev != NULL )
393 free( (
void *)
pls->dev );
395 pls->dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
396 if (
pls->dev == NULL )
397 plexit(
"plD_init_png_Dev: Out of memory." );
399 dev = (png_Dev *)
pls->dev;
408 dev->black15 = black15;
410 dev->optimise = optimise;
414 dev->palette = palette;
415 dev->truecolour = truecolour;
419 if ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) )
420 plwarn(
"Selecting both \"truecolor\" AND \"palette\" driver options is contradictory, so\nI will just use my best judgment.\n" );
421 else if ( dev->truecolour > 0 )
423 else if ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) && ( (
pls->ncol1 +
pls->ncol0 ) > NCOLOURS ) )
428 if ( ( dev->palette == 0 ) && ( dev->optimise == 0 ) && ( smooth_line == 1 ) )
433#ifdef PL_HAVE_FREETYPE
437 pls->dev_unicode = 1;
445 init_freetype_lv1(
pls );
446 FT = (FT_Data *)
pls->FT;
447 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
448 if ( ( dev->optimise == 0 ) && ( dev->palette == 0 ) && ( smooth_text != 0 ) )
450 FT->BLENDED_ANTIALIASING = 1;
474 if ( !
pls->colorset )
484 plD_init_png_Dev(
pls );
485 dev = (png_Dev *)
pls->dev;
491 if (
pls->xdpi <= 0. ||
pls->ydpi <= 0. )
497 if (
pls->xlength == 0 ||
pls->ylength == 0 )
505 dev->pngx =
pls->xlength - 1;
506 dev->pngy =
pls->ylength - 1;
508#ifdef use_experimental_hidden_line_hack
510 if ( dev->pngx > dev->pngy )
527 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
529#ifdef PL_HAVE_FREETYPE
532 init_freetype_lv2(
pls );
556 static int black15 = 0;
557 static int red15 = 0;
558#ifdef PL_HAVE_FREETYPE
559 static int freetype = 1;
560 static int smooth_text = 0;
564 DrvOpt gd_options[] = { {
"def_black15",
DRV_INT, &black15,
"Define idx 15 as black. If the background is \"whiteish\" (from \"-bg\" option), force index 15 (traditionally white) to be \"black\"" },
565 {
"swp_red15",
DRV_INT, &red15,
"Swap index 1 (usually red) and 1 (usually white); always done after \"black15\"; quite useful for quick changes to web pages" },
566#ifdef PL_HAVE_FREETYPE
567 {
"text",
DRV_INT, &freetype,
"Use driver text (FreeType)" },
568 {
"smooth",
DRV_INT, &smooth_text,
"Turn text smoothing on (1) or off (0)" },
570 { NULL,
DRV_INT, NULL, NULL } };
575 if (
pls->dev != NULL )
576 free( (
void *)
pls->dev );
578 pls->dev = calloc( 1, (
size_t)
sizeof ( png_Dev ) );
579 if (
pls->dev == NULL )
580 plexit(
"plD_init_gif_Dev: Out of memory." );
582 dev = (png_Dev *)
pls->dev;
590 dev->black15 = black15;
597#ifdef PL_HAVE_FREETYPE
601 pls->dev_unicode = 1;
603 init_freetype_lv1(
pls );
604 FT = (FT_Data *)
pls->FT;
606 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
628 if ( !
pls->colorset )
638 plD_init_gif_Dev(
pls );
639 dev = (png_Dev *)
pls->dev;
645 if (
pls->xdpi <= 0. ||
pls->ydpi <= 0. )
651 if (
pls->xlength == 0 ||
pls->ylength == 0 )
659 dev->pngx =
pls->xlength - 1;
660 dev->pngy =
pls->ylength - 1;
662#ifdef use_experimental_hidden_line_hack
664 if ( dev->pngx > dev->pngy )
682 plP_setphy( 0, dev->scale * dev->pngx, 0, dev->scale * dev->pngy );
684#ifdef PL_HAVE_FREETYPE
687 init_freetype_lv2(
pls );
702plD_line_png(
PLStream *
pls,
short x1a,
short y1a,
short x2a,
short y2a )
704 png_Dev *dev = (png_Dev *)
pls->dev;
705 int x1 = x1a / dev->scale, y1 = y1a / dev->scale, x2 = x2a / dev->scale, y2 = y2a / dev->scale;
709 #ifdef SMOOTH_LINES_OK
710 if ( dev->smooth == 1 )
712 gdImageSetAntiAliased( dev->im_out, dev->colour );
713 gdImageLine( dev->im_out, x1, y1, x2, y2, gdAntiAliased );
717 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
720 gdImageLine( dev->im_out, x1, y1, x2, y2, dev->colour );
735 for ( i = 0; i < npts - 1; i++ )
736 plD_line_png(
pls, xa[i], ya[i], xa[i + 1], ya[i + 1] );
749 png_Dev *dev = (png_Dev *)
pls->dev;
752 gdPoint *points = NULL;
754 if (
pls->dev_npts < 1 )
757 points = malloc( (
size_t)
pls->dev_npts * sizeof ( gdPoint ) );
759 for ( i = 0; i <
pls->dev_npts; i++ )
761 points[i].x =
pls->dev_x[i] / dev->scale;
762 points[i].y = dev->pngy - (
pls->dev_y[i] / dev->scale );
765 #ifdef SMOOTH_LINES_OK
766 if ( dev->smooth == 1 )
768 gdImageSetAntiAliased( dev->im_out, dev->colour );
769 gdImageFilledPolygon( dev->im_out, points,
pls->dev_npts, gdAntiAliased );
773 gdImageFilledPolygon( dev->im_out, points,
pls->dev_npts, dev->colour );
776 gdImageFilledPolygon( dev->im_out, points,
pls->dev_npts, dev->colour );
791 int i, ncol1 =
pls->ncol1;
792 int ncol0 =
pls->ncol0, total_colours;
794 png_Dev *dev = (png_Dev *)
pls->dev;
795 PLFLT tmp_colour_pos;
802 if ( dev->im_out != NULL )
804 for ( i = 0; i < 256; i++ )
806 gdImageColorDeallocate( dev->im_out, i );
810 if ( ncol0 > NCOLOURS / 2 )
812 plwarn(
"Too many colours in cmap0." );
813 ncol0 = NCOLOURS / 2;
819 total_colours = ncol0 + ncol1;
821 if ( total_colours > NCOLOURS )
823 total_colours = NCOLOURS;
824 ncol1 = total_colours - ncol0;
828 plexit(
"Problem setting colourmap in PNG or JPEG driver." );
839 if ( ( ncol0 > 0 ) && ( dev->im_out != NULL ) )
841 for ( i = 0; i < ncol0; i++ )
844 gdImageColorAllocateAlpha( dev->im_out,
845 pls->cmap0[i].r,
pls->cmap0[i].g,
pls->cmap0[i].b,
846 plToGdAlpha(
pls->cmap0[i].a ) );
848 gdImageColorAllocate( dev->im_out,
849 pls->cmap0[i].r,
pls->cmap0[i].g,
pls->cmap0[i].b );
858 if ( ( ncol1 > 0 ) && ( dev->im_out != NULL ) )
860 for ( i = 0; i < ncol1; i++ )
862 if ( ncol1 < pls->ncol1 )
872 tmp_colour_pos = i > 0 ?
pls->ncol1 * ( (
PLFLT) i / ncol1 ) : 0;
882 gdImageColorAllocateAlpha( dev->im_out,
883 cmap1col.r, cmap1col.g, cmap1col.b,
884 plToGdAlpha( cmap1col.a ) );
886 gdImageColorAllocate( dev->im_out,
887 cmap1col.r, cmap1col.g, cmap1col.b );
905 png_Dev *dev = (png_Dev *)
pls->dev;
906 PLFLT tmp_colour_pos;
916 gdImageSetThickness( dev->im_out,
pls->width );
924 ( gdImageTrueColor( dev->im_out ) ) )
926 if ( ( dev->totcol < NCOLOURS ) ||
927 ( gdImageTrueColor( dev->im_out ) ) )
931 temp_col = gdImageColorAllocateAlpha( dev->im_out,
pls->curcolor.r,
932 pls->curcolor.g,
pls->curcolor.b,
933 plToGdAlpha(
pls->curcolor.a ) );
935 temp_col = gdImageColorAllocate( dev->im_out,
pls->curcolor.r,
936 pls->curcolor.g,
pls->curcolor.b );
939 if ( gdImageTrueColor( dev->im_out ) )
940 dev->colour = temp_col;
943 dev->colour = dev->totcol;
950 dev->colour =
pls->icol0;
954 dev->colour =
pls->icol0;
957 if ( dev->totcol < NCOLOURS )
960 gdImageColorAllocateAlpha( dev->im_out,
pls->curcolor.r,
961 pls->curcolor.g,
pls->curcolor.b,
962 plToGdAlpha(
pls->curcolor.a ) );
964 gdImageColorAllocate( dev->im_out,
pls->curcolor.r,
965 pls->curcolor.g,
pls->curcolor.b );
967 dev->colour = dev->totcol;
976 if ( !gdImageTrueColor( dev->im_out ) )
983 if ( dev->ncol1 <
pls->ncol1 )
985 tmp_colour_pos = dev->ncol1 * ( (
PLFLT)
pls->icol1 / (
pls->ncol1 > 0 ?
pls->ncol1 : 1 ) );
986 dev->colour =
pls->ncol0 + (int) tmp_colour_pos;
989 dev->colour =
pls->ncol0 +
pls->icol1;
995 dev->colour = gdTrueColorAlpha(
pls->curcolor.r,
pls->curcolor.g,
997 plToGdAlpha(
pls->curcolor.a ) );
999 dev->colour = gdTrueColor(
pls->curcolor.r,
pls->curcolor.g,
1011 if ( ( dev->im_out != NULL ) && !gdImageTrueColor( dev->im_out ) )
1046#ifdef PL_HAVE_FREETYPE
1048 plD_render_freetype_text(
pls, (
EscText *) ptr );
1075 dev = (png_Dev *)
pls->dev;
1082 plD_black15_gd(
pls );
1084 plD_red15_gd(
pls );
1087 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1088 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1089 ( (
pls->ncol1 +
pls->ncol0 ) <= 256 ) ) ||
1090 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1094 dev->im_out = gdImageCreate(
pls->xlength,
pls->ylength );
1102 dev->im_out = gdImageCreateTrueColor(
pls->xlength,
pls->ylength );
1118 if ( (
pls->cmap0[0].r != 0 ) || (
pls->cmap0[0].g != 0 ) ||
1119 (
pls->cmap0[0].b != 0 ) || (
pls->cmap0[0].a != 0.0 ) )
1121 gdImageFilledRectangle( dev->im_out, 0, 0,
pls->xlength - 1,
pls->ylength - 1,
1122 gdTrueColorAlpha(
pls->cmap0[0].r,
pls->cmap0[0].g,
1124 plToGdAlpha(
pls->cmap0[0].a ) ) );
1145#ifdef PL_HAVE_FREETYPE
1146 if (
pls->dev_text )
1148 plD_FreeType_Destroy(
pls );
1167 if (
pls->ncol0 > 15 )
1169 if ( (
pls->cmap0[0].r > 227 ) && (
pls->cmap0[0].g > 227 ) && (
pls->cmap0[0].b > 227 ) )
1171 pls->cmap0[15].r = 0;
1172 pls->cmap0[15].g = 0;
1173 pls->cmap0[15].b = 0;
1207 char r =
pls->cmap0[1].r;
1208 char g =
pls->cmap0[1].g;
1209 char b =
pls->cmap0[1].b;
1211 if (
pls->ncol0 > 15 )
1213 pls->cmap0[1].r =
pls->cmap0[15].r;
1214 pls->cmap0[1].g =
pls->cmap0[15].r;
1215 pls->cmap0[1].b =
pls->cmap0[15].r;
1217 pls->cmap0[15].r = r;
1218 pls->cmap0[15].g = g;
1219 pls->cmap0[15].b = b;
1254 png_Dev *dev = (png_Dev *)
pls->dev;
1258 bbuf = calloc( 256, (
size_t) 1 );
1260 plexit(
"plD_gd_optimise: Out of memory." );
1262 for ( i = 0; i < (
pls->xlength - 1 ); i++ )
1264 for ( j = 0; j < (
pls->ylength - 1 ); j++ )
1266 bbuf[gdImagePalettePixel( dev->im_out, i, j )] = 1;
1270 for ( i = 0; i < 256; i++ )
1273 gdImageColorDeallocate( dev->im_out, i );
1290 png_Dev *dev = (png_Dev *)
pls->dev;
1292 int png_compression;
1293 void *im_ptr = NULL;
1296 if (
pls->family ||
pls->page == 1 )
1298 if ( dev->optimise )
1301 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1302 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1303 ( (
pls->ncol1 +
pls->ncol0 ) <= 256 ) ) ||
1304 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1307 plD_gd_optimise(
pls );
1331 png_compression = ( (
pls->dev_compression <= 0 ) || (
pls->dev_compression > 99 ) ) ? 90 :
pls->dev_compression;
1332 png_compression = ( png_compression > 9 ) ? ( png_compression / 10 ) : png_compression;
1333 im_ptr = gdImagePngPtrEx( dev->im_out, &im_size, png_compression );
1335 im_ptr = gdImagePngPtr( dev->im_out, &im_size );
1339 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size,
pls->OutFile );
1340 if ( nwrite != im_size )
1341 plabort(
"gd driver: Error writing png file" );
1345 gdImageDestroy( dev->im_out );
1352#ifdef PL_HAVE_FREETYPE
1361void plD_pixel_gd(
PLStream *
pls,
short x,
short y )
1363 png_Dev *dev = (png_Dev *)
pls->dev;
1365 gdImageSetPixel( dev->im_out, x, y, dev->colour );
1377 png_Dev *dev = (png_Dev *)
pls->dev;
1381 G = GetGValue( colour );
1382 R = GetRValue( colour );
1383 B = GetBValue( colour );
1385 Colour = gdImageColorResolve( dev->im_out, R, G, B );
1386 gdImageSetPixel( dev->im_out, x, y, Colour );
1399 png_Dev *dev = (png_Dev *)
pls->dev;
1401 unsigned char R, G, B;
1403 colour = gdImageGetTrueColorPixel( dev->im_out, x, y );
1405 R = gdTrueColorGetRed( colour );
1406 G = gdTrueColorGetGreen( colour );
1407 B = gdTrueColorGetBlue( colour );
1409 colour = RGB( R, G, B );
1427 plD_FreeType_init(
pls );
1429 FT = (FT_Data *)
pls->FT;
1430 FT->pixel = (plD_pixel_fp) plD_pixel_gd;
1431 FT->read_pixel = (plD_read_pixel_fp) plD_read_pixel_gd;
1432 FT->set_pixel = (plD_set_pixel_fp) plD_set_pixel_gd;
1462 png_Dev *dev = (png_Dev *)
pls->dev;
1463 FT_Data *FT = (FT_Data *)
pls->FT;
1465 FT->scale = dev->scale;
1466 FT->ymax = dev->pngy;
1468 FT->smooth_text = 0;
1470 if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 0 ) )
1472 FT->ncol0_org =
pls->ncol0;
1473 FT->ncol0_xtra = NCOLOURS - (
pls->ncol1 +
pls->ncol0 );
1474 FT->ncol0_width = FT->ncol0_xtra / (
pls->ncol0 - 1 );
1475 if ( FT->ncol0_width > 4 )
1477 if ( FT->ncol0_width > max_number_of_grey_levels_used_in_text_smoothing )
1478 FT->ncol0_width = max_number_of_grey_levels_used_in_text_smoothing;
1479 plscmap0n( FT->ncol0_org + ( FT->ncol0_width *
pls->ncol0 ) );
1487 level_save =
pls->level;
1489 pl_set_extended_cmap0(
pls, FT->ncol0_width, FT->ncol0_org );
1490 pls->level = level_save;
1492 FT->smooth_text = 1;
1495 plwarn(
"Insufficient colour slots available in CMAP0 to do text smoothing." );
1497 else if ( ( FT->want_smooth_text == 1 ) && ( FT->BLENDED_ANTIALIASING == 1 ) )
1499 FT->smooth_text = 1;
1516 png_Dev *dev = (png_Dev *)
pls->dev;
1518 void *im_ptr = NULL;
1520 int jpeg_compression;
1522 if (
pls->family ||
pls->page == 1 )
1527 if ( (
pls->dev_compression <= 0 ) || (
pls->dev_compression > 99 ) )
1528 jpeg_compression = 90;
1530 jpeg_compression =
pls->dev_compression;
1536 im_ptr = gdImageJpegPtr( dev->im_out, &im_size, jpeg_compression );
1539 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size,
pls->OutFile );
1540 if ( nwrite != im_size )
1541 plabort(
"gd driver: Error writing png file" );
1545 gdImageDestroy( dev->im_out );
1562 png_Dev *dev = (png_Dev *)
pls->dev;
1564 void *im_ptr = NULL;
1567 if (
pls->family ||
pls->page == 1 )
1573 im_ptr = gdImageGifPtr( dev->im_out, &im_size );
1576 nwrite = fwrite( im_ptr,
sizeof (
char ), im_size,
pls->OutFile );
1577 if ( nwrite != im_size )
1578 plabort(
"gd driver: Error writing png file" );
1582 gdImageDestroy( dev->im_out );
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
void(* plD_tidy_fp)(struct PLStream_struct *)
void(* plD_bop_fp)(struct PLStream_struct *)
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
void(* plD_eop_fp)(struct PLStream_struct *)
void(* plD_init_fp)(struct PLStream_struct *)
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_gif(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_jpeg(PLDispatchTable *pdt)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_png(PLDispatchTable *pdt)
int plParseDrvOpts(DrvOpt *acc_opt)
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
static PLStream * pls[PL_NSTREAMS]
void plFamInit(PLStream *pls)
void plwarn(PLCHAR_VECTOR errormsg)
void plcol_interp(PLStream *pls, PLColor *newcolor, int i, int ncol)
void plCloseFile(PLStream *pls)
void plOpenFile(PLStream *pls)
void plexit(PLCHAR_VECTOR errormsg)
void plGetFam(PLStream *pls)
void plabort(PLCHAR_VECTOR errormsg)
#define PLDLLIMPEXP_DRIVER
#define PLPLOT_MM_PER_INCH
#define PLPLOT_DEFAULT_WIDTH_PIXELS
#define PLPLOT_DEFAULT_HEIGHT_PIXELS
#define PLPLOT_DEFAULT_PIXELS_PER_INCH
static void fill_polygon(PLStream *pls)