sync with trunk
[luatex.git] / source / libs / poppler / poppler-0.33.0 / goo / PNGWriter.cc
blobc9d5199d040936dce3999d08afe5c455c5c0e508
1 //========================================================================
2 //
3 // PNGWriter.cc
4 //
5 // This file is licensed under the GPLv2 or later
6 //
7 // Copyright (C) 2009 Warren Toomey <wkt@tuhs.org>
8 // Copyright (C) 2009 Shen Liang <shenzhuxi@gmail.com>
9 // Copyright (C) 2009, 2011 Albert Astals Cid <aacid@kde.org>
10 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
11 // Copyright (C) 2010, 2011, 2013 Adrian Johnson <ajohnson@redneon.com>
12 // Copyright (C) 2011 Thomas Klausner <wiz@danbala.tuwien.ac.at>
13 // Copyright (C) 2012 Pino Toscano <pino@kde.org>
15 //========================================================================
17 #include "PNGWriter.h"
19 #ifdef ENABLE_LIBPNG
21 #include <zlib.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include "poppler/Error.h"
26 #include "goo/gmem.h"
28 #include <png.h>
30 struct PNGWriterPrivate {
31 PNGWriter::Format format;
32 png_structp png_ptr;
33 png_infop info_ptr;
34 unsigned char *icc_data;
35 int icc_data_size;
36 char *icc_name;
37 bool sRGB_profile;
40 PNGWriter::PNGWriter(Format formatA)
42 priv = new PNGWriterPrivate;
43 priv->format = formatA;
44 priv->icc_data = NULL;
45 priv->icc_data_size = 0;
46 priv->icc_name = NULL;
47 priv->sRGB_profile = false;
50 PNGWriter::~PNGWriter()
52 /* cleanup heap allocation */
53 png_destroy_write_struct(&priv->png_ptr, &priv->info_ptr);
54 if (priv->icc_data) {
55 gfree(priv->icc_data);
56 free(priv->icc_name);
59 delete priv;
62 void PNGWriter::setICCProfile(const char *name, unsigned char *data, int size)
64 priv->icc_data = (unsigned char *)gmalloc(size);
65 memcpy(priv->icc_data, data, size);
66 priv->icc_data_size = size;
67 priv->icc_name = strdup(name);
70 void PNGWriter::setSRGBProfile()
72 priv->sRGB_profile = true;
75 bool PNGWriter::init(FILE *f, int width, int height, int hDPI, int vDPI)
77 /* libpng changed the png_set_iCCP() prototype in 1.5.0 */
78 #if PNG_LIBPNG_VER < 10500
79 png_charp icc_data_ptr = (png_charp)priv->icc_data;
80 #else
81 png_const_bytep icc_data_ptr = (png_const_bytep)priv->icc_data;
82 #endif
84 /* initialize stuff */
85 priv->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
86 if (!priv->png_ptr) {
87 error(errInternal, -1, "png_create_write_struct failed");
88 return false;
91 priv->info_ptr = png_create_info_struct(priv->png_ptr);
92 if (!priv->info_ptr) {
93 error(errInternal, -1, "png_create_info_struct failed");
94 return false;
97 if (setjmp(png_jmpbuf(priv->png_ptr))) {
98 error(errInternal, -1, "png_jmpbuf failed");
99 return false;
102 /* write header */
103 png_init_io(priv->png_ptr, f);
104 if (setjmp(png_jmpbuf(priv->png_ptr))) {
105 error(errInternal, -1, "Error during writing header");
106 return false;
109 // Set up the type of PNG image and the compression level
110 png_set_compression_level(priv->png_ptr, Z_BEST_COMPRESSION);
112 // Silence silly gcc
113 png_byte bit_depth = -1;
114 png_byte color_type = -1;
115 switch (priv->format) {
116 case RGB:
117 bit_depth = 8;
118 color_type = PNG_COLOR_TYPE_RGB;
119 break;
120 case RGBA:
121 bit_depth = 8;
122 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
123 break;
124 case GRAY:
125 bit_depth = 8;
126 color_type = PNG_COLOR_TYPE_GRAY;
127 break;
128 case MONOCHROME:
129 bit_depth = 1;
130 color_type = PNG_COLOR_TYPE_GRAY;
131 break;
133 png_byte interlace_type = PNG_INTERLACE_NONE;
135 png_set_IHDR(priv->png_ptr, priv->info_ptr, width, height, bit_depth, color_type, interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
137 png_set_pHYs(priv->png_ptr, priv->info_ptr, hDPI/0.0254, vDPI/0.0254, PNG_RESOLUTION_METER);
139 if (priv->icc_data)
140 png_set_iCCP(priv->png_ptr, priv->info_ptr, priv->icc_name, PNG_COMPRESSION_TYPE_BASE, icc_data_ptr, priv->icc_data_size);
141 else if (priv->sRGB_profile)
142 png_set_sRGB(priv->png_ptr, priv->info_ptr, PNG_sRGB_INTENT_RELATIVE);
144 png_write_info(priv->png_ptr, priv->info_ptr);
145 if (setjmp(png_jmpbuf(priv->png_ptr))) {
146 error(errInternal, -1, "error during writing png info bytes");
147 return false;
150 return true;
153 bool PNGWriter::writePointers(unsigned char **rowPointers, int rowCount)
155 png_write_image(priv->png_ptr, rowPointers);
156 /* write bytes */
157 if (setjmp(png_jmpbuf(priv->png_ptr))) {
158 error(errInternal, -1, "Error during writing bytes");
159 return false;
162 return true;
165 bool PNGWriter::writeRow(unsigned char **row)
167 // Write the row to the file
168 png_write_rows(priv->png_ptr, row, 1);
169 if (setjmp(png_jmpbuf(priv->png_ptr))) {
170 error(errInternal, -1, "error during png row write");
171 return false;
174 return true;
177 bool PNGWriter::close()
179 /* end write */
180 png_write_end(priv->png_ptr, priv->info_ptr);
181 if (setjmp(png_jmpbuf(priv->png_ptr))) {
182 error(errInternal, -1, "Error during end of write");
183 return false;
186 return true;
189 #endif