1 /* png_img.c
2
3 MolScript v2.1.2
4
5 PNG image.
6
7 This implementation is based on the PNG Reference Library 1.0
8 version 0.96 and zlib v1.0.4. It relies on the 'image.c' code,
9 and therefore implicitly on OpenGL and GLX.
10
11 Copyright (C) 1997-1998 Per Kraulis
12 12-Sep-1997 started
13 21-Dec-1997 identified minor memory leak in PNG library; not fixed
14 */
15
16 #include <assert.h>
17 #include <stdlib.h>
18
19 #include <GL/gl.h>
20
21 #include <png.h>
22 #include <zlib.h>
23
24 #include "clib/str_utils.h"
25 #include "clib/dynstring.h"
26
27 #include "png_img.h"
28 #include "global.h"
29 #include "graphics.h"
30 #include "image.h"
31 #include "opengl.h"
32
33
34 /*============================================================*/
35 static int compression_level = Z_DEFAULT_COMPRESSION;
36 static png_structp png_ptr;
37 static png_infop info_ptr;
38 static png_text text_ptr[4];
39
40
41 /*------------------------------------------------------------*/
42 void
pngi_set(void)43 pngi_set (void)
44 {
45 ogl_set();
46
47 output_first_plot = pngi_first_plot;
48 output_finish_output = pngi_finish_output;
49 output_start_plot = ogl_start_plot_general;
50
51 output_pickable = NULL;
52
53 output_mode = PNG_MODE;
54 }
55
56
57 /*------------------------------------------------------------*/
58 void
pngi_first_plot(void)59 pngi_first_plot (void)
60 {
61 int count = 0;
62 dynstring *software_info;
63
64 image_first_plot();
65 set_outfile ("wb");
66
67 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
68 if (png_ptr == NULL)
69 yyerror ("png_img: could not create PNG image structure");
70 info_ptr = png_create_info_struct (png_ptr);
71 if (info_ptr == NULL)
72 yyerror ("png_img: could not create PNG info structure");
73 if (setjmp (png_jmpbuf(png_ptr))) yyerror ("png_img: could not setjmp");
74
75 png_init_io (png_ptr, outfile);
76 png_set_compression_level (png_ptr, compression_level);
77 png_set_IHDR (png_ptr, info_ptr, output_width, output_height, 8,
78 PNG_COLOR_TYPE_RGB, NULL, NULL, NULL);
79
80 if (title) {
81 text_ptr[count].key = "Title";
82 text_ptr[count].text = title;
83 text_ptr[count++].compression = PNG_TEXT_COMPRESSION_NONE;
84 }
85 text_ptr[count].key = "Software";
86 software_info = ds_create (program_str);
87 ds_cat (software_info, ", ");
88 ds_cat (software_info, copyright_str);
89 text_ptr[count].text = software_info->string;
90 text_ptr[count++].compression = PNG_TEXT_COMPRESSION_NONE;
91 if (user_str[0] != '\0') {
92 text_ptr[count].key = "Author";
93 text_ptr[count].text = user_str;
94 text_ptr[count++].compression = PNG_TEXT_COMPRESSION_NONE;
95 }
96 png_set_text (png_ptr, info_ptr, text_ptr, count);
97
98 png_write_info (png_ptr, info_ptr);
99
100 ds_delete (software_info);
101 }
102
103
104 /*------------------------------------------------------------*/
105 void
pngi_finish_output(void)106 pngi_finish_output (void)
107 {
108 int row;
109 unsigned char *buffer; /* this ought to be png_bytep? */
110
111 image_render();
112
113 buffer = malloc (output_width * 3 * sizeof (unsigned char));
114
115 for (row = output_height - 1; row >= 0; row--) {
116 glReadPixels (0, row, output_width, 1, GL_RGB, GL_UNSIGNED_BYTE, buffer);
117 png_write_row (png_ptr, (png_bytep) buffer);
118 }
119
120 free (buffer);
121
122 png_write_end (png_ptr, NULL);
123 png_destroy_write_struct (&png_ptr, &info_ptr);
124
125 image_close();
126 }
127
128
129 /*------------------------------------------------------------*/
130 int
pngi_set_compression(char * level)131 pngi_set_compression (char *level)
132 {
133 assert (level);
134 assert (*level);
135
136 if (str_eq (level, "default")) {
137 compression_level = Z_DEFAULT_COMPRESSION;
138 } else if (str_eq (level, "speed")) {
139 compression_level = Z_BEST_SPEED;
140 } else if (str_eq (level, "size")) {
141 compression_level = Z_BEST_COMPRESSION;
142 } else if (str_eq (level, "none")) {
143 compression_level = Z_NO_COMPRESSION;
144 } else {
145 return FALSE;
146 }
147 return TRUE;
148 }
149