6b5016621fe64e288f1f8f3985c1d68b7ead5019
[rrdtool.git] / src / gdpng.c
1 /*****************************************************************************
2  * RRDtool 1.2.23  Copyright by Tobi Oetiker, 1997-2007
3  *****************************************************************************
4  * gdpng.c  add PNG output routine to gd library
5  *****************************************************************************/
6
7 #include <png.h>
8 #include <gd.h>
9 #include <stdlib.h>
10
11 typedef struct _jmpbuf_wrapper {
12     jmp_buf   jmpbuf;
13 } jmpbuf_wrapper;
14
15 static jmpbuf_wrapper gdPngJmpbufStruct;
16
17 void gdImagePng(
18     gdImagePtr im,
19     FILE * out)
20 {
21     int       i;
22     png_colorp palette;
23     png_structp png_write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
24                                                         (png_voidp) NULL,
25                                                         /* we would need to point to error handlers
26                                                            here to do it properly */
27                                                         (png_error_ptr) NULL,
28                                                         (png_error_ptr) NULL);
29     png_infop info_ptr = png_create_info_struct(png_write_ptr);
30
31     if (setjmp(gdPngJmpbufStruct.jmpbuf)) {
32         png_destroy_write_struct(&png_write_ptr, &info_ptr);
33         return;
34     }
35
36     palette = (png_colorp) png_malloc(png_write_ptr,
37                                       im->colorsTotal * sizeof(png_color));
38     if (palette == NULL) {
39         png_destroy_write_struct(&png_write_ptr, &info_ptr);
40         return;
41     }
42
43
44     png_init_io(png_write_ptr, out);
45     png_set_write_status_fn(png_write_ptr, NULL);
46     png_set_IHDR(png_write_ptr, info_ptr,
47                  im->sx, im->sy, im->colorsTotal > 16 ? 8 : 4,
48                  PNG_COLOR_TYPE_PALETTE,
49                  im->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
50                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
51     for (i = 0; i < im->colorsTotal; i++) {
52         palette[i].red = im->red[i];
53         palette[i].green = im->green[i];
54         palette[i].blue = im->blue[i];
55     }
56     png_set_PLTE(png_write_ptr, info_ptr, palette, im->colorsTotal);
57
58     /* choose between speed (1) and space (9) optimisation */
59     /* we want to be fast ... */
60     png_set_compression_level(png_write_ptr, 1);
61     png_set_filter(png_write_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
62     /* store file info */
63     png_write_info(png_write_ptr, info_ptr);
64     png_set_packing(png_write_ptr);
65     png_write_image(png_write_ptr, im->pixels);
66     png_write_end(png_write_ptr, info_ptr);
67     png_free(png_write_ptr, palette);
68     png_destroy_write_struct(&png_write_ptr, &info_ptr);
69 }