VirtualBox

source: vbox/trunk/src/libs/libpng-1.2.8/contrib/gregbook/writepng.c@ 11115

Last change on this file since 11115 was 6395, checked in by vboxsync, 17 years ago

export libpng and zlib so Windows and OS/2 build cleanly.

  • Property svn:eol-style set to native
File size: 11.5 KB
Line 
1/*---------------------------------------------------------------------------
2
3 wpng - simple PNG-writing program writepng.c
4
5 ---------------------------------------------------------------------------
6
7 Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
8
9 This software is provided "as is," without warranty of any kind,
10 express or implied. In no event shall the author or contributors
11 be held liable for any damages arising in any way from the use of
12 this software.
13
14 Permission is granted to anyone to use this software for any purpose,
15 including commercial applications, and to alter it and redistribute
16 it freely, subject to the following restrictions:
17
18 1. Redistributions of source code must retain the above copyright
19 notice, disclaimer, and this list of conditions.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, disclaimer, and this list of conditions in the documenta-
22 tion and/or other materials provided with the distribution.
23 3. All advertising materials mentioning features or use of this
24 software must display the following acknowledgment:
25
26 This product includes software developed by Greg Roelofs
27 and contributors for the book, "PNG: The Definitive Guide,"
28 published by O'Reilly and Associates.
29
30 ---------------------------------------------------------------------------*/
31
32
33#include <stdlib.h> /* for exit() prototype */
34
35#include "png.h" /* libpng header; includes zlib.h and setjmp.h */
36#include "writepng.h" /* typedefs, common macros, public prototypes */
37
38
39/* local prototype */
40
41static void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
42
43
44
45void writepng_version_info(void)
46{
47 fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
48 PNG_LIBPNG_VER_STRING, png_libpng_ver);
49 fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
50 ZLIB_VERSION, zlib_version);
51}
52
53
54
55
56/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
57 * unexpected pnmtype; note that outfile might be stdout */
58
59int writepng_init(mainprog_info *mainprog_ptr)
60{
61 png_structp png_ptr; /* note: temporary variables! */
62 png_infop info_ptr;
63 int color_type, interlace_type;
64
65
66 /* could also replace libpng warning-handler (final NULL), but no need: */
67
68 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
69 writepng_error_handler, NULL);
70 if (!png_ptr)
71 return 4; /* out of memory */
72
73 info_ptr = png_create_info_struct(png_ptr);
74 if (!info_ptr) {
75 png_destroy_write_struct(&png_ptr, NULL);
76 return 4; /* out of memory */
77 }
78
79
80 /* setjmp() must be called in every function that calls a PNG-writing
81 * libpng function, unless an alternate error handler was installed--
82 * but compatible error handlers must either use longjmp() themselves
83 * (as in this program) or exit immediately, so here we go: */
84
85 if (setjmp(mainprog_ptr->jmpbuf)) {
86 png_destroy_write_struct(&png_ptr, &info_ptr);
87 return 2;
88 }
89
90
91 /* make sure outfile is (re)opened in BINARY mode */
92
93 png_init_io(png_ptr, mainprog_ptr->outfile);
94
95
96 /* set the compression levels--in general, always want to leave filtering
97 * turned on (except for palette images) and allow all of the filters,
98 * which is the default; want 32K zlib window, unless entire image buffer
99 * is 16K or smaller (unknown here)--also the default; usually want max
100 * compression (NOT the default); and remaining compression flags should
101 * be left alone */
102
103 png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
104/*
105 >> this is default for no filtering; Z_FILTERED is default otherwise:
106 png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
107 >> these are all defaults:
108 png_set_compression_mem_level(png_ptr, 8);
109 png_set_compression_window_bits(png_ptr, 15);
110 png_set_compression_method(png_ptr, 8);
111 */
112
113
114 /* set the image parameters appropriately */
115
116 if (mainprog_ptr->pnmtype == 5)
117 color_type = PNG_COLOR_TYPE_GRAY;
118 else if (mainprog_ptr->pnmtype == 6)
119 color_type = PNG_COLOR_TYPE_RGB;
120 else if (mainprog_ptr->pnmtype == 8)
121 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
122 else {
123 png_destroy_write_struct(&png_ptr, &info_ptr);
124 return 11;
125 }
126
127 interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
128 PNG_INTERLACE_NONE;
129
130 png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
131 mainprog_ptr->sample_depth, color_type, interlace_type,
132 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
133
134 if (mainprog_ptr->gamma > 0.0)
135 png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
136
137 if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */
138 png_color_16 background;
139
140 background.red = mainprog_ptr->bg_red;
141 background.green = mainprog_ptr->bg_green;
142 background.blue = mainprog_ptr->bg_blue;
143 png_set_bKGD(png_ptr, info_ptr, &background);
144 }
145
146 if (mainprog_ptr->have_time) {
147 png_time modtime;
148
149 png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
150 png_set_tIME(png_ptr, info_ptr, &modtime);
151 }
152
153 if (mainprog_ptr->have_text) {
154 png_text text[6];
155 int num_text = 0;
156
157 if (mainprog_ptr->have_text & TEXT_TITLE) {
158 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
159 text[num_text].key = "Title";
160 text[num_text].text = mainprog_ptr->title;
161 ++num_text;
162 }
163 if (mainprog_ptr->have_text & TEXT_AUTHOR) {
164 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
165 text[num_text].key = "Author";
166 text[num_text].text = mainprog_ptr->author;
167 ++num_text;
168 }
169 if (mainprog_ptr->have_text & TEXT_DESC) {
170 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
171 text[num_text].key = "Description";
172 text[num_text].text = mainprog_ptr->desc;
173 ++num_text;
174 }
175 if (mainprog_ptr->have_text & TEXT_COPY) {
176 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
177 text[num_text].key = "Copyright";
178 text[num_text].text = mainprog_ptr->copyright;
179 ++num_text;
180 }
181 if (mainprog_ptr->have_text & TEXT_EMAIL) {
182 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
183 text[num_text].key = "E-mail";
184 text[num_text].text = mainprog_ptr->email;
185 ++num_text;
186 }
187 if (mainprog_ptr->have_text & TEXT_URL) {
188 text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
189 text[num_text].key = "URL";
190 text[num_text].text = mainprog_ptr->url;
191 ++num_text;
192 }
193 png_set_text(png_ptr, info_ptr, text, num_text);
194 }
195
196
197 /* write all chunks up to (but not including) first IDAT */
198
199 png_write_info(png_ptr, info_ptr);
200
201
202 /* if we wanted to write any more text info *after* the image data, we
203 * would set up text struct(s) here and call png_set_text() again, with
204 * just the new data; png_set_tIME() could also go here, but it would
205 * have no effect since we already called it above (only one tIME chunk
206 * allowed) */
207
208
209 /* set up the transformations: for now, just pack low-bit-depth pixels
210 * into bytes (one, two or four pixels per byte) */
211
212 png_set_packing(png_ptr);
213/* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */
214
215
216 /* make sure we save our pointers for use in writepng_encode_image() */
217
218 mainprog_ptr->png_ptr = png_ptr;
219 mainprog_ptr->info_ptr = info_ptr;
220
221
222 /* OK, that's all we need to do for now; return happy */
223
224 return 0;
225}
226
227
228
229
230
231/* returns 0 for success, 2 for libpng (longjmp) problem */
232
233int writepng_encode_image(mainprog_info *mainprog_ptr)
234{
235 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
236 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
237
238
239 /* as always, setjmp() must be called in every function that calls a
240 * PNG-writing libpng function */
241
242 if (setjmp(mainprog_ptr->jmpbuf)) {
243 png_destroy_write_struct(&png_ptr, &info_ptr);
244 mainprog_ptr->png_ptr = NULL;
245 mainprog_ptr->info_ptr = NULL;
246 return 2;
247 }
248
249
250 /* and now we just write the whole image; libpng takes care of interlacing
251 * for us */
252
253 png_write_image(png_ptr, mainprog_ptr->row_pointers);
254
255
256 /* since that's it, we also close out the end of the PNG file now--if we
257 * had any text or time info to write after the IDATs, second argument
258 * would be info_ptr, but we optimize slightly by sending NULL pointer: */
259
260 png_write_end(png_ptr, NULL);
261
262 return 0;
263}
264
265
266
267
268
269/* returns 0 if succeeds, 2 if libpng problem */
270
271int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */
272{
273 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
274 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
275
276
277 /* as always, setjmp() must be called in every function that calls a
278 * PNG-writing libpng function */
279
280 if (setjmp(mainprog_ptr->jmpbuf)) {
281 png_destroy_write_struct(&png_ptr, &info_ptr);
282 mainprog_ptr->png_ptr = NULL;
283 mainprog_ptr->info_ptr = NULL;
284 return 2;
285 }
286
287
288 /* image_data points at our one row of image data */
289
290 png_write_row(png_ptr, mainprog_ptr->image_data);
291
292 return 0;
293}
294
295
296
297
298
299/* returns 0 if succeeds, 2 if libpng problem */
300
301int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */
302{
303 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
304 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
305
306
307 /* as always, setjmp() must be called in every function that calls a
308 * PNG-writing libpng function */
309
310 if (setjmp(mainprog_ptr->jmpbuf)) {
311 png_destroy_write_struct(&png_ptr, &info_ptr);
312 mainprog_ptr->png_ptr = NULL;
313 mainprog_ptr->info_ptr = NULL;
314 return 2;
315 }
316
317
318 /* close out PNG file; if we had any text or time info to write after
319 * the IDATs, second argument would be info_ptr: */
320
321 png_write_end(png_ptr, NULL);
322
323 return 0;
324}
325
326
327
328
329
330void writepng_cleanup(mainprog_info *mainprog_ptr)
331{
332 png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
333 png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
334
335 if (png_ptr && info_ptr)
336 png_destroy_write_struct(&png_ptr, &info_ptr);
337}
338
339
340
341
342
343static void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
344{
345 mainprog_info *mainprog_ptr;
346
347 /* This function, aside from the extra step of retrieving the "error
348 * pointer" (below) and the fact that it exists within the application
349 * rather than within libpng, is essentially identical to libpng's
350 * default error handler. The second point is critical: since both
351 * setjmp() and longjmp() are called from the same code, they are
352 * guaranteed to have compatible notions of how big a jmp_buf is,
353 * regardless of whether _BSD_SOURCE or anything else has (or has not)
354 * been defined. */
355
356 fprintf(stderr, "writepng libpng error: %s\n", msg);
357 fflush(stderr);
358
359 mainprog_ptr = png_get_error_ptr(png_ptr);
360 if (mainprog_ptr == NULL) { /* we are completely hosed now */
361 fprintf(stderr,
362 "writepng severe error: jmpbuf not recoverable; terminating.\n");
363 fflush(stderr);
364 exit(99);
365 }
366
367 longjmp(mainprog_ptr->jmpbuf, 1);
368}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette