summaryrefslogtreecommitdiffstats
path: root/src/helper/png-write.cpp
diff options
context:
space:
mode:
authorMarc Jeanmougin <marc@jeanmougin.fr>2016-09-25 21:59:45 +0000
committerMarc Jeanmougin <marcjeanmougin@free.fr>2016-09-25 21:59:45 +0000
commitee2e7c9c9907008de656773b98e1239a7f1af2a9 (patch)
tree3cc31212215d81a5b8ecf383c70025b31a4dc3ba /src/helper/png-write.cpp
parentChanged order of selection items (diff)
downloadinkscape-ee2e7c9c9907008de656773b98e1239a7f1af2a9.tar.gz
inkscape-ee2e7c9c9907008de656773b98e1239a7f1af2a9.zip
Exposes to the user additional PNG settings: Interlacing, grayscale, bit depth, alpha, compression level, PNG pHYs dpi.
Fixed bugs: - https://launchpad.net/bugs/170650 (bzr r15131)
Diffstat (limited to 'src/helper/png-write.cpp')
-rw-r--r--src/helper/png-write.cpp77
1 files changed, 46 insertions, 31 deletions
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 682aee9b2..f270dcc95 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -123,8 +123,8 @@ void PngTextList::add(gchar const* key, gchar const* text)
static bool
sp_png_write_rgba_striped(SPDocument *doc,
gchar const *filename, unsigned long int width, unsigned long int height, double xdpi, double ydpi,
- int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data),
- void *data)
+ int (* get_rows)(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth),
+ void *data, bool interlace, int color_type, int bit_depth, int zlib)
{
g_return_val_if_fail(filename != NULL, false);
g_return_val_if_fail(data != NULL, false);
@@ -184,22 +184,28 @@ sp_png_write_rgba_striped(SPDocument *doc,
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
+
+ png_set_compression_level(png_ptr, zlib);
+
png_set_IHDR(png_ptr, info_ptr,
width,
height,
- 8, /* bit_depth */
- PNG_COLOR_TYPE_RGB_ALPHA,
- PNG_INTERLACE_NONE,
+ bit_depth,
+ color_type,
+ interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
- /* otherwise, if we are dealing with a color image then */
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- /* if the image has an alpha channel then */
- sig_bit.alpha = 8;
- png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ if ((color_type&2) && bit_depth == 16) {
+ // otherwise, if we are dealing with a color image then
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ // if the image has an alpha channel then
+ if (color_type&4)
+ sig_bit.alpha = 8;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+ }
PngTextList textList;
@@ -248,7 +254,10 @@ sp_png_write_rgba_striped(SPDocument *doc,
/* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
/* note that if sRGB is present the cHRM chunk must be ignored
* on read and must be written in accordance with the sRGB profile */
- png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 + 0.5), unsigned(ydpi / 0.0254 + 0.5), PNG_RESOLUTION_METER);
+ if(xdpi < 0.0254 ) xdpi = 0.0255;
+ if(ydpi < 0.0254 ) ydpi = 0.0255;
+
+ png_set_pHYs(png_ptr, info_ptr, unsigned(xdpi / 0.0254 ), unsigned(ydpi / 0.0254 ), PNG_RESOLUTION_METER);
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr);
@@ -271,15 +280,18 @@ sp_png_write_rgba_striped(SPDocument *doc,
*/
png_bytep* row_pointers = new png_bytep[ebp->sheight];
-
- r = 0;
- while (r < static_cast<png_uint_32>(height)) {
- void *to_free;
- int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data);
- if (!n) break;
- png_write_rows(png_ptr, row_pointers, n);
- g_free(to_free);
- r += n;
+ int number_of_passes = interlace ? png_set_interlace_handling(png_ptr) : 1;
+
+ for(int i=0;i<number_of_passes; ++i){
+ r = 0;
+ while (r < static_cast<png_uint_32>(height)) {
+ void *to_free;
+ int n = get_rows((unsigned char const **) row_pointers, &to_free, r, height-r, data, color_type, bit_depth);
+ if (!n) break;
+ png_write_rows(png_ptr, row_pointers, n);
+ g_free(to_free);
+ r += n;
+ }
}
delete[] row_pointers;
@@ -308,7 +320,7 @@ sp_png_write_rgba_striped(SPDocument *doc,
*
*/
static int
-sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data)
+sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, void *data, int color_type, int bit_depth)
{
struct SPEBP *ebp = (struct SPEBP *) data;
@@ -343,14 +355,17 @@ sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, v
ebp->drawing->render(dc, bbox);
cairo_surface_destroy(s);
- *to_free = px;
-
// PNG stores data as unpremultiplied big-endian RGBA, which means
// it's identical to the GdkPixbuf format.
convert_pixels_argb32_to_pixbuf(px, ebp->width, num_rows, stride);
+
+ *to_free = px;
- for (int r = 0; r < num_rows; r++) {
- rows[r] = px + r * stride;
+ // If a custom bit depth or color type is asked, then convert rgb to grayscale, etc.
+ if(color_type !=6 || bit_depth != 8){
+ const guchar* new_data = pixbuf_to_png(rows, px, num_rows, ebp->width, stride, color_type, bit_depth);
+ *to_free = (void*) new_data;
+ free(px);
}
return num_rows;
@@ -385,10 +400,10 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned int (*status) (float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib)
{
return sp_export_png_file(doc, filename, Geom::Rect(Geom::Point(x0,y0),Geom::Point(x1,y1)),
- width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only);
+ width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only, interlace, color_type, bit_depth, zlib);
}
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
@@ -397,7 +412,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned (*status)(float, void *),
void *data, bool force_overwrite,
- const std::vector<SPItem*> &items_only)
+ const std::vector<SPItem*> &items_only, bool interlace, int color_type, int bit_depth, int zlib)
{
g_return_val_if_fail(doc != NULL, EXPORT_ERROR);
g_return_val_if_fail(filename != NULL, EXPORT_ERROR);
@@ -468,7 +483,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
ebp.px = g_try_new(guchar, 4 * ebp.sheight * width);
if (ebp.px) {
- write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp);
+ write_status = sp_png_write_rgba_striped(doc, filename, width, height, xdpi, ydpi, sp_export_get_rows, &ebp, interlace, color_type, bit_depth, zlib);
g_free(ebp.px);
}