1 //========================================================================
5 // This file is licensed under the GPLv2 or later
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"
25 #include "poppler/Error.h"
30 struct PNGWriterPrivate
{
31 PNGWriter::Format format
;
34 unsigned char *icc_data
;
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
);
55 gfree(priv
->icc_data
);
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
;
81 png_const_bytep icc_data_ptr
= (png_const_bytep
)priv
->icc_data
;
84 /* initialize stuff */
85 priv
->png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
87 error(errInternal
, -1, "png_create_write_struct failed");
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");
97 if (setjmp(png_jmpbuf(priv
->png_ptr
))) {
98 error(errInternal
, -1, "png_jmpbuf failed");
103 png_init_io(priv
->png_ptr
, f
);
104 if (setjmp(png_jmpbuf(priv
->png_ptr
))) {
105 error(errInternal
, -1, "Error during writing header");
109 // Set up the type of PNG image and the compression level
110 png_set_compression_level(priv
->png_ptr
, Z_BEST_COMPRESSION
);
113 png_byte bit_depth
= -1;
114 png_byte color_type
= -1;
115 switch (priv
->format
) {
118 color_type
= PNG_COLOR_TYPE_RGB
;
122 color_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
126 color_type
= PNG_COLOR_TYPE_GRAY
;
130 color_type
= PNG_COLOR_TYPE_GRAY
;
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
);
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");
153 bool PNGWriter::writePointers(unsigned char **rowPointers
, int rowCount
)
155 png_write_image(priv
->png_ptr
, rowPointers
);
157 if (setjmp(png_jmpbuf(priv
->png_ptr
))) {
158 error(errInternal
, -1, "Error during writing bytes");
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");
177 bool PNGWriter::close()
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");