1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/*---------------------------------------------------------------------------
2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project   wpng - simple PNG-writing program                             writepng.c
4893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
5893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project  ---------------------------------------------------------------------------
6893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
73cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III      Copyright (c) 1998-2007, 2017 Greg Roelofs.  All rights reserved.
8893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
9893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      This software is provided "as is," without warranty of any kind,
10893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      express or implied.  In no event shall the author or contributors
11893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      be held liable for any damages arising in any way from the use of
12893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      this software.
13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
14893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      The contents of this file are DUAL-LICENSED.  You may modify and/or
15893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      redistribute this software according to the terms of one of the
16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      following two licenses (at your option):
17893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
18893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
19893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      LICENSE 1 ("BSD-like with advertising clause"):
20893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
21893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      Permission is granted to anyone to use this software for any purpose,
22893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      including commercial applications, and to alter it and redistribute
23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      it freely, subject to the following restrictions:
24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
25893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      1. Redistributions of source code must retain the above copyright
26893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         notice, disclaimer, and this list of conditions.
27893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      2. Redistributions in binary form must reproduce the above copyright
28893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         notice, disclaimer, and this list of conditions in the documenta-
29893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         tion and/or other materials provided with the distribution.
30893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      3. All advertising materials mentioning features or use of this
31893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project         software must display the following acknowledgment:
32893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
33893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            This product includes software developed by Greg Roelofs
34893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            and contributors for the book, "PNG: The Definitive Guide,"
35893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            published by O'Reilly and Associates.
36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
37893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
38893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      LICENSE 2 (GNU GPL v2 or later):
39893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
40893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      This program is free software; you can redistribute it and/or modify
41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      it under the terms of the GNU General Public License as published by
42893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      the Free Software Foundation; either version 2 of the License, or
43893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      (at your option) any later version.
44893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
45893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      This program is distributed in the hope that it will be useful,
46893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      but WITHOUT ANY WARRANTY; without even the implied warranty of
47893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
48893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      GNU General Public License for more details.
49893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
50893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      You should have received a copy of the GNU General Public License
51893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      along with this program; if not, write to the Free Software Foundation,
52893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
53893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
54893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project  ---------------------------------------------------------------------------*/
55893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
56893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
57893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include <stdlib.h>     /* for exit() prototype */
58ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include <zlib.h>
59893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
60ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik#include "png.h"        /* libpng header, includes setjmp.h */
61893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#include "writepng.h"   /* typedefs, common macros, public prototypes */
62893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
63893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
64893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* local prototype */
65893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
66893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
67893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
68893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
69893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
70893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid writepng_version_info(void)
71893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
72893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project  fprintf(stderr, "   Compiled with libpng %s; using libpng %s.\n",
73893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    PNG_LIBPNG_VER_STRING, png_libpng_ver);
74893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project  fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    ZLIB_VERSION, zlib_version);
76893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
77893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
78893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
79893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
80893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
81893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
82893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *  unexpected pnmtype; note that outfile might be stdout */
83893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
84893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint writepng_init(mainprog_info *mainprog_ptr)
85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
86893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_structp  png_ptr;       /* note:  temporary variables! */
87893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_infop  info_ptr;
88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    int color_type, interlace_type;
89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
90893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
91893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* could also replace libpng warning-handler (final NULL), but no need: */
92893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett    png_ptr = png_create_write_struct(png_get_libpng_ver(NULL), mainprog_ptr,
94893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      writepng_error_handler, NULL);
95893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!png_ptr)
96893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 4;   /* out of memory */
97893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
98893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    info_ptr = png_create_info_struct(png_ptr);
99893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (!info_ptr) {
100893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, NULL);
101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 4;   /* out of memory */
102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* setjmp() must be called in every function that calls a PNG-writing
106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * libpng function, unless an alternate error handler was installed--
107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * but compatible error handlers must either use longjmp() themselves
108ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * (as in this program) or some other method to return control to
109ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * application code, so here we go: */
110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (setjmp(mainprog_ptr->jmpbuf)) {
112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 2;
114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
116893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* make sure outfile is (re)opened in BINARY mode */
118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_init_io(png_ptr, mainprog_ptr->outfile);
120893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* set the compression levels--in general, always want to leave filtering
123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * turned on (except for palette images) and allow all of the filters,
124893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * which is the default; want 32K zlib window, unless entire image buffer
125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * is 16K or smaller (unknown here)--also the default; usually want max
126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * compression (NOT the default); and remaining compression flags should
127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * be left alone */
128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/*
131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    >> this is default for no filtering; Z_FILTERED is default otherwise:
132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    >> these are all defaults:
134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_compression_mem_level(png_ptr, 8);
135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_compression_window_bits(png_ptr, 15);
136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_compression_method(png_ptr, 8);
137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */
138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* set the image parameters appropriately */
141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr->pnmtype == 5)
143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        color_type = PNG_COLOR_TYPE_GRAY;
144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    else if (mainprog_ptr->pnmtype == 6)
145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        color_type = PNG_COLOR_TYPE_RGB;
146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    else if (mainprog_ptr->pnmtype == 8)
147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    else {
149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 11;
151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
152893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project                                               PNG_INTERLACE_NONE;
155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      mainprog_ptr->sample_depth, color_type, interlace_type,
158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr->gamma > 0.0)
161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr->have_bg) {   /* we know it's RGBA, not gray+alpha */
164893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_color_16  background;
165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        background.red = mainprog_ptr->bg_red;
167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        background.green = mainprog_ptr->bg_green;
168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        background.blue = mainprog_ptr->bg_blue;
169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_bKGD(png_ptr, info_ptr, &background);
170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
171893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr->have_time) {
173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_time  modtime;
174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_tIME(png_ptr, info_ptr, &modtime);
177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr->have_text) {
180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_text  text[6];
181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        int  num_text = 0;
182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_TITLE) {
184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "Title";
186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->title;
187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_AUTHOR) {
190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "Author";
192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->author;
193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_DESC) {
196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "Description";
198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->desc;
199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_COPY) {
202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "Copyright";
204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->copyright;
205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_EMAIL) {
208893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "E-mail";
210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->email;
211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        if (mainprog_ptr->have_text & TEXT_URL) {
214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].key = "URL";
216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            text[num_text].text = mainprog_ptr->url;
217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project            ++num_text;
218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        }
219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_set_text(png_ptr, info_ptr, text, num_text);
220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* write all chunks up to (but not including) first IDAT */
224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_write_info(png_ptr, info_ptr);
226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* if we wanted to write any more text info *after* the image data, we
229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * would set up text struct(s) here and call png_set_text() again, with
230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * just the new data; png_set_tIME() could also go here, but it would
231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * have no effect since we already called it above (only one tIME chunk
232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * allowed) */
233893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
235893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* set up the transformations:  for now, just pack low-bit-depth pixels
236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * into bytes (one, two or four pixels per byte) */
237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_set_packing(png_ptr);
239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/*  png_set_shift(png_ptr, &sig_bit);  to scale low-bit-depth values */
240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* make sure we save our pointers for use in writepng_encode_image() */
243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    mainprog_ptr->png_ptr = png_ptr;
245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    mainprog_ptr->info_ptr = info_ptr;
246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* OK, that's all we need to do for now; return happy */
249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return 0;
251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
255893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* returns 0 for success, 2 for libpng (longjmp) problem */
258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint writepng_encode_image(mainprog_info *mainprog_ptr)
260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
263893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* as always, setjmp() must be called in every function that calls a
266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * PNG-writing libpng function */
267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (setjmp(mainprog_ptr->jmpbuf)) {
269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->png_ptr = NULL;
271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->info_ptr = NULL;
272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 2;
273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* and now we just write the whole image; libpng takes care of interlacing
277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * for us */
278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_write_image(png_ptr, mainprog_ptr->row_pointers);
280893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* since that's it, we also close out the end of the PNG file now--if we
283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * had any text or time info to write after the IDATs, second argument
284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * would be info_ptr, but we optimize slightly by sending NULL pointer: */
285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
286893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_write_end(png_ptr, NULL);
287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return 0;
289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* returns 0 if succeeds, 2 if libpng problem */
296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint writepng_encode_row(mainprog_info *mainprog_ptr)  /* NON-interlaced only! */
298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* as always, setjmp() must be called in every function that calls a
304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * PNG-writing libpng function */
305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (setjmp(mainprog_ptr->jmpbuf)) {
307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->png_ptr = NULL;
309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->info_ptr = NULL;
310893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 2;
311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* image_data points at our one row of image data */
315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_write_row(png_ptr, mainprog_ptr->image_data);
317893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return 0;
319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
324893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* returns 0 if succeeds, 2 if libpng problem */
326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint writepng_encode_finish(mainprog_info *mainprog_ptr)   /* NON-interlaced! */
328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
330893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
333893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* as always, setjmp() must be called in every function that calls a
334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * PNG-writing libpng function */
335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (setjmp(mainprog_ptr->jmpbuf)) {
337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->png_ptr = NULL;
339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        mainprog_ptr->info_ptr = NULL;
340893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        return 2;
341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* close out PNG file; if we had any text or time info to write after
345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * the IDATs, second argument would be info_ptr: */
346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_write_end(png_ptr, NULL);
348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    return 0;
350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid writepng_cleanup(mainprog_info *mainprog_ptr)
357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (png_ptr && info_ptr)
362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        png_destroy_write_struct(&png_ptr, &info_ptr);
363893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectstatic void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{
371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    mainprog_info  *mainprog_ptr;
372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    /* This function, aside from the extra step of retrieving the "error
374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * pointer" (below) and the fact that it exists within the application
375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * rather than within libpng, is essentially identical to libpng's
376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * default error handler.  The second point is critical:  since both
377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * setjmp() and longjmp() are called from the same code, they are
378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * guaranteed to have compatible notions of how big a jmp_buf is,
379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * regardless of whether _BSD_SOURCE or anything else has (or has not)
380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project     * been defined. */
381893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    fprintf(stderr, "writepng libpng error: %s\n", msg);
383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    fflush(stderr);
384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    mainprog_ptr = png_get_error_ptr(png_ptr);
386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    if (mainprog_ptr == NULL) {         /* we are completely hosed now */
387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fprintf(stderr,
388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project          "writepng severe error:  jmpbuf not recoverable; terminating.\n");
389893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        fflush(stderr);
390893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project        exit(99);
391893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    }
392893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project
393ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik    /* Now we have our data structure we can use the information in it
394ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * to return control to our own higher level code (all the points
395ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * where 'setjmp' is called in this file.)  This will work with other
396ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * error handling mechanisms as well - libpng always calls png_error
397ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * when it can proceed no further, thus, so long as the error handler
398ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     * is intercepted, application code can do its own error recovery.
399ca2bf81b02c99afa2e76b3b2c6eb232c239221e0Chris Craik     */
400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project    longjmp(mainprog_ptr->jmpbuf, 1);
401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project}
402