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
188 static void plD_pixel_gd(
PLStream *
pls,
short x,
short y );
190 static void plD_set_pixel_gd(
PLStream *
pls,
short x,
short y,
PLINT colour );
198 static 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 )]
232 int plToGdAlpha(
PLFLT a )
234 int tmp = (int) ( ( 1.0 - a ) * gdAlphaMax );
258 unsigned char TRY_BLENDED_ANTIALIASING;
263 unsigned char smooth;
268 void plD_line_png(
PLStream *,
short,
short,
short,
short );
269 void plD_polyline_png(
PLStream *,
short *,
short *,
PLINT );
285 #ifndef ENABLE_DYNDRIVERS
307 #ifndef ENABLE_DYNDRIVERS
329 #ifndef ENABLE_DYNDRIVERS
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
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;
484 plD_init_png_Dev( pls );
485 dev = (png_Dev *) pls->
dev;
491 if ( pls->
xdpi <= 0. || pls->
ydpi <= 0. )
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
603 init_freetype_lv1( pls );
604 FT = (FT_Data *) pls->
FT;
606 FT->want_smooth_text = smooth_text > 0 ? 1 : 0;
638 plD_init_gif_Dev( pls );
639 dev = (png_Dev *) pls->
dev;
645 if ( pls->
xdpi <= 0. || pls->
ydpi <= 0. )
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 );
702 plD_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 );
731 plD_polyline_png(
PLStream *pls,
short *xa,
short *ya,
PLINT npts )
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;
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,
846 plToGdAlpha( pls->
cmap0[i].
a ) );
848 gdImageColorAllocate( dev->im_out,
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,
935 temp_col = gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
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,
964 gdImageColorAllocate( dev->im_out, pls->
curcolor.
r,
967 dev->colour = dev->totcol;
976 if ( !gdImageTrueColor( dev->im_out ) )
983 if ( dev->ncol1 < pls->
ncol1 )
986 dev->colour = pls->
ncol0 + (int) tmp_colour_pos;
1011 if ( ( dev->im_out != NULL ) && !gdImageTrueColor( dev->im_out ) )
1043 fill_polygon( pls );
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 ) ) ) &&
1090 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
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,
1124 plToGdAlpha( pls->
cmap0[0].
a ) ) );
1145 #ifdef PL_HAVE_FREETYPE
1148 plD_FreeType_Destroy( pls );
1165 void plD_black15_gd(
PLStream *pls )
1167 if ( pls->
ncol0 > 15 )
1169 if ( ( pls->
cmap0[0].
r > 227 ) && ( pls->
cmap0[0].
g > 227 ) && ( pls->
cmap0[0].
b > 227 ) )
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 )
1252 void plD_gd_optimise(
PLStream *pls )
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;
1298 if ( dev->optimise )
1301 if ( ( ( ( ( dev->truecolour > 0 ) && ( dev->palette > 0 ) ) ||
1302 ( ( dev->truecolour == 0 ) && ( dev->palette == 0 ) ) ) &&
1304 ( ( ( dev->palette > 0 ) && ( dev->truecolour == 0 ) ) ) )
1307 plD_gd_optimise( pls );
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
1361 void 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 );
1375 void plD_set_pixel_gd(
PLStream *pls,
short x,
short y,
PLINT 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 );
1423 static void init_freetype_lv1(
PLStream *pls )
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;
1460 static void init_freetype_lv2(
PLStream *pls )
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;
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;
1528 jpeg_compression = 90;
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;
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 );
int plParseDrvOpts(DrvOpt *acc_opt)
void(* plD_line_fp)(struct PLStream_struct *, short, short, short, short)
void plexit(PLCHAR_VECTOR errormsg)
void(* plD_eop_fp)(struct PLStream_struct *)
void(* plD_state_fp)(struct PLStream_struct *, PLINT)
void(* plD_tidy_fp)(struct PLStream_struct *)
void plOpenFile(PLStream *pls)
void plCloseFile(PLStream *pls)
void plGetFam(PLStream *pls)
#define PLPLOT_MM_PER_INCH
void plcol_interp(PLStream *pls, PLColor *newcolor, int i, int ncol)
void plabort(PLCHAR_VECTOR errormsg)
void plFamInit(PLStream *pls)
void(* plD_polyline_fp)(struct PLStream_struct *, short *, short *, PLINT)
void(* plD_esc_fp)(struct PLStream_struct *, PLINT, void *)
void(* plD_bop_fp)(struct PLStream_struct *)
PLDLLIMPEXP_DRIVER void plD_dispatch_init_gif(PLDispatchTable *pdt)
#define PLPLOT_DEFAULT_WIDTH_PIXELS
PLDLLIMPEXP_DRIVER void plD_dispatch_init_png(PLDispatchTable *pdt)
#define PLPLOT_DEFAULT_PIXELS_PER_INCH
void plP_setpxl(PLFLT xpmm, PLFLT ypmm)
#define PLDLLIMPEXP_DRIVER
static PLStream * pls[PL_NSTREAMS]
void plP_setphy(PLINT xmin, PLINT xmax, PLINT ymin, PLINT ymax)
void plwarn(PLCHAR_VECTOR errormsg)
#define PLPLOT_DEFAULT_HEIGHT_PIXELS
PLDLLIMPEXP_DRIVER void plD_dispatch_init_jpeg(PLDispatchTable *pdt)
plD_polyline_fp pl_polyline
void(* plD_init_fp)(struct PLStream_struct *)