From e362cec58fb273941e3aea562ba042e2e9b95c98 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 24 May 2015 13:11:43 +0200 Subject: Respect PDF image 'interpolate' value on import. (bzr r14171) --- src/extension/internal/pdfinput/pdf-parser.cpp | 47 +++++++++++++++++++++---- src/extension/internal/pdfinput/svg-builder.cpp | 36 ++++++++++++------- src/extension/internal/pdfinput/svg-builder.h | 17 ++++----- 3 files changed, 73 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index cc0b38515..836c34c32 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -2780,12 +2780,14 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) Dict *dict; int width, height; int bits; + GBool interpolate; StreamColorSpaceMode csMode; GBool mask; GBool invert; Object maskObj, smaskObj; GBool haveColorKeyMask, haveExplicitMask, haveSoftMask; GBool maskInvert; + GBool maskInterpolate; Object obj1, obj2; // get info from the stream @@ -2828,6 +2830,19 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } obj1.free(); + // image interpolation + dict->lookup("Interpolate", &obj1); + if (obj1.isNull()) { + obj1.free(); + dict->lookup("I", &obj1); + } + if (obj1.isBool()) + interpolate = obj1.getBool(); + else + interpolate = gFalse; + obj1.free(); + maskInterpolate = gFalse; + // image or mask? dict->lookup(const_cast("ImageMask"), &obj1); if (obj1.isNull()) { @@ -2884,7 +2899,7 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) obj1.free(); // draw it - builder->addImageMask(state, str, width, height, invert); + builder->addImageMask(state, str, width, height, invert, interpolate); } else { // get color space and color map @@ -2986,6 +3001,16 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } int maskBits = obj1.getInt(); obj1.free(); + maskDict->lookup("Interpolate", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("I", &obj1); + } + if (obj1.isBool()) + maskInterpolate = obj1.getBool(); + else + maskInterpolate = gFalse; + obj1.free(); maskDict->lookup(const_cast("ColorSpace"), &obj1); if (obj1.isNull()) { obj1.free(); @@ -3071,6 +3096,16 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) goto err2; } obj1.free(); + maskDict->lookup("Interpolate", &obj1); + if (obj1.isNull()) { + obj1.free(); + maskDict->lookup("I", &obj1); + } + if (obj1.isBool()) + maskInterpolate = obj1.getBool(); + else + maskInterpolate = gFalse; + obj1.free(); maskInvert = gFalse; maskDict->lookup(const_cast("Decode"), &obj1); if (obj1.isNull()) { @@ -3092,14 +3127,14 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) // draw it if (haveSoftMask) { - builder->addSoftMaskedImage(state, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskColorMap); + builder->addSoftMaskedImage(state, str, width, height, colorMap, interpolate, + maskStr, maskWidth, maskHeight, maskColorMap, maskInterpolate); delete maskColorMap; } else if (haveExplicitMask) { - builder->addMaskedImage(state, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskInvert); + builder->addMaskedImage(state, str, width, height, colorMap, interpolate, + maskStr, maskWidth, maskHeight, maskInvert, maskInterpolate); } else { - builder->addImage(state, str, width, height, colorMap, + builder->addImage(state, str, width, height, colorMap, interpolate, haveColorKeyMask ? maskColors : static_cast(NULL)); } delete colorMap; diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index a3abb4045..58e2030d9 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -1485,7 +1485,9 @@ void png_flush_base64stream(png_structp png_ptr) * */ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height, - GfxImageColorMap *color_map, int *mask_colors, bool alpha_only, bool invert_alpha) { + GfxImageColorMap *color_map, bool interpolate, + int *mask_colors, bool alpha_only, + bool invert_alpha) { // Create PNG write struct png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); @@ -1655,6 +1657,13 @@ Inkscape::XML::Node *SvgBuilder::_createImage(Stream *str, int width, int height Inkscape::XML::Node *image_node = _xml_doc->createElement("svg:image"); sp_repr_set_svg_double(image_node, "width", 1); sp_repr_set_svg_double(image_node, "height", 1); + if( !interpolate ) { + SPCSSAttr *css = sp_repr_css_attr_new(); + // This should be changed after CSS4 Images widely supported. + sp_repr_css_set_property(css, "image-rendering", "optimizeSpeed"); + sp_repr_css_change(image_node, css, "style"); + sp_repr_css_attr_unref(css); + } // PS/PDF images are placed via a transformation matrix, no preserveAspectRatio used image_node->setAttribute("preserveAspectRatio", "none"); @@ -1715,9 +1724,9 @@ Inkscape::XML::Node *SvgBuilder::_createMask(double width, double height) { } void SvgBuilder::addImage(GfxState * /*state*/, Stream *str, int width, int height, - GfxImageColorMap *color_map, int *mask_colors) { + GfxImageColorMap *color_map, bool interpolate, int *mask_colors) { - Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, mask_colors); + Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, interpolate, mask_colors); if (image_node) { _container->appendChild(image_node); Inkscape::GC::release(image_node); @@ -1725,7 +1734,7 @@ void SvgBuilder::addImage(GfxState * /*state*/, Stream *str, int width, int heig } void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int height, - bool invert) { + bool invert, bool interpolate) { // Create a rectangle Inkscape::XML::Node *rect = _xml_doc->createElement("svg:rect"); @@ -1742,7 +1751,8 @@ void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int heigh // Scaling 1x1 surfaces might not work so skip setting a mask with this size if ( width > 1 || height > 1 ) { - Inkscape::XML::Node *mask_image_node = _createImage(str, width, height, NULL, NULL, true, invert); + Inkscape::XML::Node *mask_image_node = + _createImage(str, width, height, NULL, interpolate, NULL, true, invert); if (mask_image_node) { // Create the mask Inkscape::XML::Node *mask_node = _createMask(1.0, 1.0); @@ -1762,13 +1772,13 @@ void SvgBuilder::addImageMask(GfxState *state, Stream *str, int width, int heigh } void SvgBuilder::addMaskedImage(GfxState * /*state*/, Stream *str, int width, int height, - GfxImageColorMap *color_map, + GfxImageColorMap *color_map, bool interpolate, Stream *mask_str, int mask_width, int mask_height, - bool invert_mask) { + bool invert_mask, bool mask_interpolate) { Inkscape::XML::Node *mask_image_node = _createImage(mask_str, mask_width, mask_height, - NULL, NULL, true, invert_mask); - Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, NULL); + NULL, mask_interpolate, NULL, true, invert_mask); + Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, interpolate, NULL); if ( mask_image_node && image_node ) { // Create mask for the image Inkscape::XML::Node *mask_node = _createMask(1.0, 1.0); @@ -1795,13 +1805,13 @@ void SvgBuilder::addMaskedImage(GfxState * /*state*/, Stream *str, int width, in } void SvgBuilder::addSoftMaskedImage(GfxState * /*state*/, Stream *str, int width, int height, - GfxImageColorMap *color_map, + GfxImageColorMap *color_map, bool interpolate, Stream *mask_str, int mask_width, int mask_height, - GfxImageColorMap *mask_color_map) { + GfxImageColorMap *mask_color_map, bool mask_interpolate) { Inkscape::XML::Node *mask_image_node = _createImage(mask_str, mask_width, mask_height, - mask_color_map, NULL, true); - Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, NULL); + mask_color_map, mask_interpolate, NULL, true); + Inkscape::XML::Node *image_node = _createImage(str, width, height, color_map, interpolate, NULL); if ( mask_image_node && image_node ) { // Create mask for the image Inkscape::XML::Node *mask_node = _createMask(1.0, 1.0); diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h index f1ce02cf0..ad15c9c06 100644 --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -112,17 +112,17 @@ public: // Image handling void addImage(GfxState *state, Stream *str, int width, int height, - GfxImageColorMap *color_map, int *mask_colors); + GfxImageColorMap *color_map, bool interpolate, int *mask_colors); void addImageMask(GfxState *state, Stream *str, int width, int height, - bool invert); + bool invert, bool interpolate); void addMaskedImage(GfxState *state, Stream *str, int width, int height, - GfxImageColorMap *color_map, + GfxImageColorMap *color_map, bool interpolate, Stream *mask_str, int mask_width, int mask_height, - bool invert_mask); + bool invert_mask, bool mask_interpolate); void addSoftMaskedImage(GfxState *state, Stream *str, int width, int height, - GfxImageColorMap *color_map, + GfxImageColorMap *color_map, bool interpolate, Stream *mask_str, int mask_width, int mask_height, - GfxImageColorMap *mask_color_map); + GfxImageColorMap *mask_color_map, bool mask_interpolate); // Transparency group and soft mask handling void pushTransparencyGroup(GfxState *state, double *bbox, @@ -180,8 +180,9 @@ private: bool is_stroke=false); // Image/mask creation Inkscape::XML::Node *_createImage(Stream *str, int width, int height, - GfxImageColorMap *color_map, int *mask_colors, - bool alpha_only=false, bool invert_alpha=false); + GfxImageColorMap *color_map, bool interpolate, + int *mask_colors, bool alpha_only=false, + bool invert_alpha=false); Inkscape::XML::Node *_createMask(double width, double height); // Style setting SPCSSAttr *_setStyle(GfxState *state, bool fill, bool stroke, bool even_odd=false); -- cgit v1.2.3