From c5200a11ec773ecc9bc2d30ffadd0af4a2317741 Mon Sep 17 00:00:00 2001 From: oetiker Date: Fri, 15 Jun 2007 06:28:47 +0000 Subject: [PATCH] added interface to get rendered image via a pointer to allocated memory ... Evan Miller emmiller gmail.com git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1123 a5681a0c-68f1-0310-ab6d-d61299d08faa --- src/rrd.h | 10 ++++ src/rrd_graph.c | 133 ++++++++++++++++++++++++++++++++++++++++-------- src/rrd_graph.h | 2 + 3 files changed, 124 insertions(+), 21 deletions(-) diff --git a/src/rrd.h b/src/rrd.h index a7fe759..0403a26 100644 --- a/src/rrd.h +++ b/src/rrd.h @@ -87,6 +87,16 @@ extern "C" { FILE *, double *, double *); + + unsigned char *rrd_graph_in_memory( + int argc, + char **argv, + int *xsize, + int *ysize, + double *ymin, + double *ymax, + size_t * img_size); + int rrd_fetch( int, char **, diff --git a/src/rrd_graph.c b/src/rrd_graph.c index db82882..2d1785f 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -2873,7 +2873,7 @@ int graph_size_location( -static cairo_status_t cairo_write_func_file( +static cairo_status_t cairo_write_func_filehandle( void *closure, const unsigned char *data, unsigned int length) @@ -2883,6 +2883,25 @@ static cairo_status_t cairo_write_func_file( return CAIRO_STATUS_SUCCESS; } +static cairo_status_t cairo_copy_to_buffer( + void *closure, + const unsigned char *data, + unsigned int length) +{ + image_desc_t *im = closure; + + im->rendered_image = + realloc(im->rendered_image, im->rendered_image_size + length); + if (im->rendered_image == NULL) { + return CAIRO_STATUS_WRITE_ERROR; + } + + memcpy(im->rendered_image + im->rendered_image_size, data, length); + + im->rendered_image_size += length; + + return CAIRO_STATUS_SUCCESS; +} /* draw that picture thing ... */ int graph_paint( @@ -2965,21 +2984,30 @@ int graph_paint( break; case IF_PDF: im->gridfit = 0; - im->surface = - cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom, - im->yimg * im->zoom); + im->surface = strlen(im->graphfile) + ? cairo_pdf_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom) + : cairo_pdf_surface_create_for_stream(&cairo_copy_to_buffer, im, + im->ximg * im->zoom, + im->yimg * im->zoom); break; case IF_EPS: im->gridfit = 0; - im->surface = - cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom, - im->yimg * im->zoom); + im->surface = strlen(im->graphfile) + ? cairo_ps_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom) + : cairo_ps_surface_create_for_stream(&cairo_copy_to_buffer, im, + im->ximg * im->zoom, + im->yimg * im->zoom); break; case IF_SVG: im->gridfit = 0; - im->surface = - cairo_svg_surface_create(im->graphfile, im->ximg * im->zoom, - im->yimg * im->zoom); + im->surface = strlen(im->graphfile) + ? cairo_svg_surface_create(im->graphfile, im->ximg * im->zoom, + im->yimg * im->zoom) + : cairo_svg_surface_create_for_stream(&cairo_copy_to_buffer, im, + im->ximg * im->zoom, + im->yimg * im->zoom); cairo_svg_surface_restrict_to_version(im->surface, CAIRO_SVG_VERSION_1_1); break; @@ -3315,10 +3343,14 @@ int graph_paint( { cairo_status_t status; - if (strcmp(im->graphfile, "-") == 0) { + if (strlen(im->graphfile) == 0) { status = cairo_surface_write_to_png_stream(im->surface, - &cairo_write_func_file, + &cairo_copy_to_buffer, im); + } else if (strcmp(im->graphfile, "-") == 0) { + status = + cairo_surface_write_to_png_stream(im->surface, + &cairo_write_func_filehandle, (void *) stdout); } else { status = cairo_surface_write_to_png(im->surface, im->graphfile); @@ -3331,7 +3363,11 @@ int graph_paint( } break; default: - cairo_show_page(im->cr); + if (strlen(im->graphfile)) { + cairo_show_page(im->cr); + } else { + cairo_surface_finish(im->surface); + } break; } return 0; @@ -3433,9 +3469,6 @@ int rrd_graph( /* a dummy surface so that we can measure text sizes for placements */ im.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); im.cr = cairo_create(im.surface); - - - /* not currently using this ... */ im.graphhandle = stream; rrd_graph_options(argc, argv, &im); @@ -3444,11 +3477,17 @@ int rrd_graph( return -1; } + if (optind >= argc) { + rrd_set_error("missing filename"); + return -1; + } + if (strlen(argv[optind]) >= MAXPATH) { rrd_set_error("filename (including path) too long"); im_free(&im); return -1; } + strncpy(im.graphfile, argv[optind], MAXPATH - 1); im.graphfile[MAXPATH - 1] = '\0'; @@ -3505,6 +3544,60 @@ int rrd_graph( return 0; } +/* a simplified version of the above that just creates the graph in memory + and returns a pointer to it. */ + +unsigned char *rrd_graph_in_memory( + int argc, + char **argv, + char ***prdata, + int *xsize, + int *ysize, + double *ymin, + double *ymax, + size_t * img_size) +{ + image_desc_t im; + + rrd_graph_init(&im); + + /* a dummy surface so that we can measure text sizes for placements */ + im.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); + im.cr = cairo_create(im.surface); + + rrd_graph_options(argc, argv, &im); + if (rrd_test_error()) { + im_free(&im); + return NULL; + } + + rrd_graph_script(argc, argv, &im, 1); + if (rrd_test_error()) { + im_free(&im); + return NULL; + } + + /* Everything is now read and the actual work can start */ + + /* by not assigning a name to im.graphfile data will be written to + newly allocated memory on im.rendered_image ... */ + + (*prdata) = NULL; + if (graph_paint(&im, prdata) == -1) { + im_free(&im); + return NULL; + } + + *xsize = im.ximg; + *ysize = im.yimg; + *ymin = im.minval; + *ymax = im.maxval; + *img_size = im.rendered_image_size; + im_free(&im); + + return im.rendered_image; +} + void rrd_graph_init( image_desc_t *im) { @@ -3527,6 +3620,8 @@ void rrd_graph_init( im->yimg = 0; im->xsize = 400; im->ysize = 100; + im->rendered_image_size = 0; + im->rendered_image = NULL; im->step = 0; im->ylegend[0] = '\0'; im->title[0] = '\0'; @@ -3539,6 +3634,7 @@ void rrd_graph_init( im->symbol = ' '; im->viewfactor = 1.0; im->imgformat = IF_PNG; + im->graphfile[0] = '\0'; im->cr = NULL; im->surface = NULL; im->extra_flags = 0; @@ -4004,11 +4100,6 @@ void rrd_graph_options( } } - if (optind >= argc) { - rrd_set_error("missing filename"); - return; - } - if (im->logarithmic == 1 && im->minval <= 0) { rrd_set_error ("for a logarithmic yaxis you must specify a lower-limit > 0"); diff --git a/src/rrd_graph.h b/src/rrd_graph.h index de968a7..00ab15b 100644 --- a/src/rrd_graph.h +++ b/src/rrd_graph.h @@ -215,6 +215,7 @@ typedef struct image_desc_t { long xorigin, yorigin; /* where is (0,0) of the graph */ long ximg, yimg; /* total size of the image */ + size_t rendered_image_size; double zoom; double magfact; /* numerical magnitude */ long base; /* 1000 or 1024 depending on what we graph */ @@ -227,6 +228,7 @@ typedef struct image_desc_t { int extra_flags; /* flags for boolean options */ /* data elements */ + unsigned char *rendered_image; long prt_c; /* number of print elements */ long gdes_c; /* number of graphics elements */ graph_desc_t *gdes; /* points to an array of graph elements */ -- 2.30.2