13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /* pngwrite.c - general routines to write a PNG file
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Last changed in libpng 1.6.19 [November 12, 2015]
33 * Copyright (c) 1998-2015 Glenn Randers-Pehrson
34 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
35 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
36 *
37 * This code is released under the libpng license.
38 * For conditions of distribution and use, see the disclaimer
39 * and license in png.h
40 */
41
42 #include "pngpriv.h"
43 #if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
44 # include <errno.h>
45 #endif
46
47 #ifdef PNG_WRITE_SUPPORTED
48
49 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
50 /* Write out all the unknown chunks for the current given location */
51 static void
52 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
53 unsigned int where)
54 {
55 if (info_ptr->unknown_chunks_num != 0)
56 {
57 png_const_unknown_chunkp up;
58
59 png_debug(5, "writing extra chunks");
60
61 for (up = info_ptr->unknown_chunks;
62 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
63 ++up)
64 if ((up->location & where) != 0)
65 {
1463 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1464 png_set_invert_alpha(png_ptr);
1465 #else
1466 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1467 #endif
1468
1469 /* ----------------------- end of transformations ------------------- */
1470
1471 /* Write the bits */
1472 png_write_image(png_ptr, info_ptr->row_pointers);
1473
1474 /* It is REQUIRED to call this to finish writing the rest of the file */
1475 png_write_end(png_ptr, info_ptr);
1476
1477 PNG_UNUSED(params)
1478 }
1479 #endif
1480
1481
1482 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1483 # ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
1484 /* Initialize the write structure - general purpose utility. */
1485 static int
1486 png_image_write_init(png_imagep image)
1487 {
1488 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1489 png_safe_error, png_safe_warning);
1490
1491 if (png_ptr != NULL)
1492 {
1493 png_infop info_ptr = png_create_info_struct(png_ptr);
1494
1495 if (info_ptr != NULL)
1496 {
1497 png_controlp control = png_voidcast(png_controlp,
1498 png_malloc_warn(png_ptr, (sizeof *control)));
1499
1500 if (control != NULL)
1501 {
1502 memset(control, 0, (sizeof *control));
1503
1515
1516 png_destroy_write_struct(&png_ptr, NULL);
1517 }
1518
1519 return png_image_error(image, "png_image_write_: out of memory");
1520 }
1521
1522 /* Arguments to png_image_write_main: */
1523 typedef struct
1524 {
1525 /* Arguments: */
1526 png_imagep image;
1527 png_const_voidp buffer;
1528 png_int_32 row_stride;
1529 png_const_voidp colormap;
1530 int convert_to_8bit;
1531 /* Local variables: */
1532 png_const_voidp first_row;
1533 ptrdiff_t row_bytes;
1534 png_voidp local_row;
1535 } png_image_write_control;
1536
1537 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1538 * do any necessary byte swapping. The component order is defined by the
1539 * png_image format value.
1540 */
1541 static int
1542 png_write_image_16bit(png_voidp argument)
1543 {
1544 png_image_write_control *display = png_voidcast(png_image_write_control*,
1545 argument);
1546 png_imagep image = display->image;
1547 png_structrp png_ptr = image->opaque->png_ptr;
1548
1549 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1550 display->first_row);
1551 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1552 png_uint_16p row_end;
1553 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1554 int aindex = 0;
1942 png_image_write_main(png_voidp argument)
1943 {
1944 png_image_write_control *display = png_voidcast(png_image_write_control*,
1945 argument);
1946 png_imagep image = display->image;
1947 png_structrp png_ptr = image->opaque->png_ptr;
1948 png_inforp info_ptr = image->opaque->info_ptr;
1949 png_uint_32 format = image->format;
1950
1951 /* The following four ints are actually booleans */
1952 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1953 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
1954 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1955 int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
1956
1957 # ifdef PNG_BENIGN_ERRORS_SUPPORTED
1958 /* Make sure we error out on any bad situation */
1959 png_set_benign_errors(png_ptr, 0/*error*/);
1960 # endif
1961
1962 /* Default the 'row_stride' parameter if required. */
1963 if (display->row_stride == 0)
1964 display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
1965
1966 /* Set the required transforms then write the rows in the correct order. */
1967 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
1968 {
1969 if (display->colormap != NULL && image->colormap_entries > 0)
1970 {
1971 png_uint_32 entries = image->colormap_entries;
1972
1973 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
1974 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
1975 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
1976 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1977
1978 png_image_set_PLTE(display);
1979 }
1980
1981 else
1982 png_error(image->opaque->png_ptr,
1983 "no color-map for color-mapped image");
1984 }
2121 /* Otherwise this is the case where the input is in a format currently
2122 * supported by the rest of the libpng write code; call it directly.
2123 */
2124 else
2125 {
2126 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
2127 ptrdiff_t row_bytes = display->row_bytes;
2128 png_uint_32 y = image->height;
2129
2130 while (y-- > 0)
2131 {
2132 png_write_row(png_ptr, row);
2133 row += row_bytes;
2134 }
2135 }
2136
2137 png_write_end(png_ptr, info_ptr);
2138 return 1;
2139 }
2140
2141 int PNGAPI
2142 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2143 const void *buffer, png_int_32 row_stride, const void *colormap)
2144 {
2145 /* Write the image to the given (FILE*). */
2146 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2147 {
2148 if (file != NULL)
2149 {
2150 if (png_image_write_init(image) != 0)
2151 {
2152 png_image_write_control display;
2153 int result;
2154
2155 /* This is slightly evil, but png_init_io doesn't do anything other
2156 * than this and we haven't changed the standard IO functions so
2157 * this saves a 'safe' function.
2158 */
2159 image->opaque->png_ptr->io_ptr = file;
2160
2161 memset(&display, 0, (sizeof display));
2162 display.image = image;
2163 display.buffer = buffer;
2164 display.row_stride = row_stride;
2165 display.colormap = colormap;
2166 display.convert_to_8bit = convert_to_8bit;
2167
2168 result = png_safe_execute(image, png_image_write_main, &display);
2178 return png_image_error(image,
2179 "png_image_write_to_stdio: invalid argument");
2180 }
2181
2182 else if (image != NULL)
2183 return png_image_error(image,
2184 "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2185
2186 else
2187 return 0;
2188 }
2189
2190 int PNGAPI
2191 png_image_write_to_file(png_imagep image, const char *file_name,
2192 int convert_to_8bit, const void *buffer, png_int_32 row_stride,
2193 const void *colormap)
2194 {
2195 /* Write the image to the named file. */
2196 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2197 {
2198 if (file_name != NULL)
2199 {
2200 FILE *fp = fopen(file_name, "wb");
2201
2202 if (fp != NULL)
2203 {
2204 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2205 row_stride, colormap) != 0)
2206 {
2207 int error; /* from fflush/fclose */
2208
2209 /* Make sure the file is flushed correctly. */
2210 if (fflush(fp) == 0 && ferror(fp) == 0)
2211 {
2212 if (fclose(fp) == 0)
2213 return 1;
2214
2215 error = errno; /* from fclose */
2216 }
2217
2218 else
2236 return 0;
2237 }
2238 }
2239
2240 else
2241 return png_image_error(image, strerror(errno));
2242 }
2243
2244 else
2245 return png_image_error(image,
2246 "png_image_write_to_file: invalid argument");
2247 }
2248
2249 else if (image != NULL)
2250 return png_image_error(image,
2251 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2252
2253 else
2254 return 0;
2255 }
2256 # endif /* STDIO */
2257 #endif /* SIMPLIFIED_WRITE */
2258 #endif /* WRITE */
|
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25 /* pngwrite.c - general routines to write a PNG file
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Last changed in libpng 1.6.19 [November 12, 2015]
33 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
34 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
35 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
36 *
37 * This code is released under the libpng license.
38 * For conditions of distribution and use, see the disclaimer
39 * and license in png.h
40 */
41
42 #include "pngpriv.h"
43 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
44 # include <errno.h>
45 #endif /* SIMPLIFIED_WRITE_STDIO */
46
47 #ifdef PNG_WRITE_SUPPORTED
48
49 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
50 /* Write out all the unknown chunks for the current given location */
51 static void
52 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
53 unsigned int where)
54 {
55 if (info_ptr->unknown_chunks_num != 0)
56 {
57 png_const_unknown_chunkp up;
58
59 png_debug(5, "writing extra chunks");
60
61 for (up = info_ptr->unknown_chunks;
62 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
63 ++up)
64 if ((up->location & where) != 0)
65 {
1463 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1464 png_set_invert_alpha(png_ptr);
1465 #else
1466 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1467 #endif
1468
1469 /* ----------------------- end of transformations ------------------- */
1470
1471 /* Write the bits */
1472 png_write_image(png_ptr, info_ptr->row_pointers);
1473
1474 /* It is REQUIRED to call this to finish writing the rest of the file */
1475 png_write_end(png_ptr, info_ptr);
1476
1477 PNG_UNUSED(params)
1478 }
1479 #endif
1480
1481
1482 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1483 /* Initialize the write structure - general purpose utility. */
1484 static int
1485 png_image_write_init(png_imagep image)
1486 {
1487 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1488 png_safe_error, png_safe_warning);
1489
1490 if (png_ptr != NULL)
1491 {
1492 png_infop info_ptr = png_create_info_struct(png_ptr);
1493
1494 if (info_ptr != NULL)
1495 {
1496 png_controlp control = png_voidcast(png_controlp,
1497 png_malloc_warn(png_ptr, (sizeof *control)));
1498
1499 if (control != NULL)
1500 {
1501 memset(control, 0, (sizeof *control));
1502
1514
1515 png_destroy_write_struct(&png_ptr, NULL);
1516 }
1517
1518 return png_image_error(image, "png_image_write_: out of memory");
1519 }
1520
1521 /* Arguments to png_image_write_main: */
1522 typedef struct
1523 {
1524 /* Arguments: */
1525 png_imagep image;
1526 png_const_voidp buffer;
1527 png_int_32 row_stride;
1528 png_const_voidp colormap;
1529 int convert_to_8bit;
1530 /* Local variables: */
1531 png_const_voidp first_row;
1532 ptrdiff_t row_bytes;
1533 png_voidp local_row;
1534 /* Byte count for memory writing */
1535 png_bytep memory;
1536 png_alloc_size_t memory_bytes; /* not used for STDIO */
1537 png_alloc_size_t output_bytes; /* running total */
1538 } png_image_write_control;
1539
1540 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1541 * do any necessary byte swapping. The component order is defined by the
1542 * png_image format value.
1543 */
1544 static int
1545 png_write_image_16bit(png_voidp argument)
1546 {
1547 png_image_write_control *display = png_voidcast(png_image_write_control*,
1548 argument);
1549 png_imagep image = display->image;
1550 png_structrp png_ptr = image->opaque->png_ptr;
1551
1552 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1553 display->first_row);
1554 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1555 png_uint_16p row_end;
1556 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1557 int aindex = 0;
1945 png_image_write_main(png_voidp argument)
1946 {
1947 png_image_write_control *display = png_voidcast(png_image_write_control*,
1948 argument);
1949 png_imagep image = display->image;
1950 png_structrp png_ptr = image->opaque->png_ptr;
1951 png_inforp info_ptr = image->opaque->info_ptr;
1952 png_uint_32 format = image->format;
1953
1954 /* The following four ints are actually booleans */
1955 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1956 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
1957 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1958 int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
1959
1960 # ifdef PNG_BENIGN_ERRORS_SUPPORTED
1961 /* Make sure we error out on any bad situation */
1962 png_set_benign_errors(png_ptr, 0/*error*/);
1963 # endif
1964
1965 /* Default the 'row_stride' parameter if required, also check the row stride
1966 * and total image size to ensure that they are within the system limits.
1967 */
1968 {
1969 const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
1970
1971 if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
1972 {
1973 png_uint_32 check;
1974 const png_uint_32 png_row_stride = image->width * channels;
1975
1976 if (display->row_stride == 0)
1977 display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
1978
1979 if (display->row_stride < 0)
1980 check = -display->row_stride;
1981
1982 else
1983 check = display->row_stride;
1984
1985 if (check >= png_row_stride)
1986 {
1987 /* Now check for overflow of the image buffer calculation; this
1988 * limits the whole image size to 32 bits for API compatibility with
1989 * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
1990 */
1991 if (image->height > 0xFFFFFFFF/png_row_stride)
1992 png_error(image->opaque->png_ptr, "memory image too large");
1993 }
1994
1995 else
1996 png_error(image->opaque->png_ptr, "supplied row stride too small");
1997 }
1998
1999 else
2000 png_error(image->opaque->png_ptr, "image row stride too large");
2001 }
2002
2003 /* Set the required transforms then write the rows in the correct order. */
2004 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
2005 {
2006 if (display->colormap != NULL && image->colormap_entries > 0)
2007 {
2008 png_uint_32 entries = image->colormap_entries;
2009
2010 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2011 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
2012 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
2013 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2014
2015 png_image_set_PLTE(display);
2016 }
2017
2018 else
2019 png_error(image->opaque->png_ptr,
2020 "no color-map for color-mapped image");
2021 }
2158 /* Otherwise this is the case where the input is in a format currently
2159 * supported by the rest of the libpng write code; call it directly.
2160 */
2161 else
2162 {
2163 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
2164 ptrdiff_t row_bytes = display->row_bytes;
2165 png_uint_32 y = image->height;
2166
2167 while (y-- > 0)
2168 {
2169 png_write_row(png_ptr, row);
2170 row += row_bytes;
2171 }
2172 }
2173
2174 png_write_end(png_ptr, info_ptr);
2175 return 1;
2176 }
2177
2178
2179 static void (PNGCBAPI
2180 image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
2181 png_size_t size)
2182 {
2183 png_image_write_control *display = png_voidcast(png_image_write_control*,
2184 png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
2185 const png_alloc_size_t ob = display->output_bytes;
2186
2187 /* Check for overflow; this should never happen: */
2188 if (size <= ((png_alloc_size_t)-1) - ob)
2189 {
2190 /* I don't think libpng ever does this, but just in case: */
2191 if (size > 0)
2192 {
2193 if (display->memory_bytes >= ob+size) /* writing */
2194 memcpy(display->memory+ob, data, size);
2195
2196 /* Always update the size: */
2197 display->output_bytes = ob+size;
2198 }
2199 }
2200
2201 else
2202 png_error(png_ptr, "png_image_write_to_memory: PNG too big");
2203 }
2204
2205 static void (PNGCBAPI
2206 image_memory_flush)(png_structp png_ptr)
2207 {
2208 PNG_UNUSED(png_ptr)
2209 }
2210
2211 static int
2212 png_image_write_memory(png_voidp argument)
2213 {
2214 png_image_write_control *display = png_voidcast(png_image_write_control*,
2215 argument);
2216
2217 /* The rest of the memory-specific init and write_main in an error protected
2218 * environment. This case needs to use callbacks for the write operations
2219 * since libpng has no built in support for writing to memory.
2220 */
2221 png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
2222 image_memory_write, image_memory_flush);
2223
2224 return png_image_write_main(display);
2225 }
2226
2227 int PNGAPI
2228 png_image_write_to_memory(png_imagep image, void *memory,
2229 png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
2230 const void *buffer, png_int_32 row_stride, const void *colormap)
2231 {
2232 /* Write the image to the given buffer, or count the bytes if it is NULL */
2233 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2234 {
2235 if (memory_bytes != NULL && buffer != NULL)
2236 {
2237 /* This is to give the caller an easier error detection in the NULL
2238 * case and guard against uninitialized variable problems:
2239 */
2240 if (memory == NULL)
2241 *memory_bytes = 0;
2242
2243 if (png_image_write_init(image) != 0)
2244 {
2245 png_image_write_control display;
2246 int result;
2247
2248 memset(&display, 0, (sizeof display));
2249 display.image = image;
2250 display.buffer = buffer;
2251 display.row_stride = row_stride;
2252 display.colormap = colormap;
2253 display.convert_to_8bit = convert_to_8bit;
2254 display.memory = png_voidcast(png_bytep, memory);
2255 display.memory_bytes = *memory_bytes;
2256 display.output_bytes = 0;
2257
2258 result = png_safe_execute(image, png_image_write_memory, &display);
2259 png_image_free(image);
2260
2261 /* write_memory returns true even if we ran out of buffer. */
2262 if (result)
2263 {
2264 /* On out-of-buffer this function returns '0' but still updates
2265 * memory_bytes:
2266 */
2267 if (memory != NULL && display.output_bytes > *memory_bytes)
2268 result = 0;
2269
2270 *memory_bytes = display.output_bytes;
2271 }
2272
2273 return result;
2274 }
2275
2276 else
2277 return 0;
2278 }
2279
2280 else
2281 return png_image_error(image,
2282 "png_image_write_to_memory: invalid argument");
2283 }
2284
2285 else if (image != NULL)
2286 return png_image_error(image,
2287 "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
2288
2289 else
2290 return 0;
2291 }
2292
2293 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
2294 int PNGAPI
2295 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2296 const void *buffer, png_int_32 row_stride, const void *colormap)
2297 {
2298 /* Write the image to the given (FILE*). */
2299 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2300 {
2301 if (file != NULL && buffer != NULL)
2302 {
2303 if (png_image_write_init(image) != 0)
2304 {
2305 png_image_write_control display;
2306 int result;
2307
2308 /* This is slightly evil, but png_init_io doesn't do anything other
2309 * than this and we haven't changed the standard IO functions so
2310 * this saves a 'safe' function.
2311 */
2312 image->opaque->png_ptr->io_ptr = file;
2313
2314 memset(&display, 0, (sizeof display));
2315 display.image = image;
2316 display.buffer = buffer;
2317 display.row_stride = row_stride;
2318 display.colormap = colormap;
2319 display.convert_to_8bit = convert_to_8bit;
2320
2321 result = png_safe_execute(image, png_image_write_main, &display);
2331 return png_image_error(image,
2332 "png_image_write_to_stdio: invalid argument");
2333 }
2334
2335 else if (image != NULL)
2336 return png_image_error(image,
2337 "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2338
2339 else
2340 return 0;
2341 }
2342
2343 int PNGAPI
2344 png_image_write_to_file(png_imagep image, const char *file_name,
2345 int convert_to_8bit, const void *buffer, png_int_32 row_stride,
2346 const void *colormap)
2347 {
2348 /* Write the image to the named file. */
2349 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2350 {
2351 if (file_name != NULL && buffer != NULL)
2352 {
2353 FILE *fp = fopen(file_name, "wb");
2354
2355 if (fp != NULL)
2356 {
2357 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2358 row_stride, colormap) != 0)
2359 {
2360 int error; /* from fflush/fclose */
2361
2362 /* Make sure the file is flushed correctly. */
2363 if (fflush(fp) == 0 && ferror(fp) == 0)
2364 {
2365 if (fclose(fp) == 0)
2366 return 1;
2367
2368 error = errno; /* from fclose */
2369 }
2370
2371 else
2389 return 0;
2390 }
2391 }
2392
2393 else
2394 return png_image_error(image, strerror(errno));
2395 }
2396
2397 else
2398 return png_image_error(image,
2399 "png_image_write_to_file: invalid argument");
2400 }
2401
2402 else if (image != NULL)
2403 return png_image_error(image,
2404 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2405
2406 else
2407 return 0;
2408 }
2409 #endif /* SIMPLIFIED_WRITE_STDIO */
2410 #endif /* SIMPLIFIED_WRITE */
2411 #endif /* WRITE */
|