0

I have a Python Flask application on RHEL 7 that I'm using to convert SVGs to PNGs through Wand. I was running into problems with font handling, but with Inkscape installed that fixed the issue. The SVG renderer switched automatically as expected.

I can run this code locally on my Mac, but when I do the text has been bolded and italicized, and all elements have a black border. I've installed Inkscape, and I've checked that MagickWand is correctly using Inkscape by converting with the verbose option.

$ convert -verbose test.svg test2.png
'inkscape' '/var/folders/8l/_jk6d2tn5cj6jp_rmq2t1tv92d_68s/T/magick-rLyLMnsG3Cxr89_XRGiGKQxpGFjJHxei' --export-filename='/var/folders/8l/_jk6d2tn5cj6jp_rmq2t1tv92d_68s/T/magick-HBEGlfBWo_vEuH6xZQh4BWPMWrTnNiKo.png' --export-dpi='96' --export-background='rgb(100%,100%,100%)' --export-background-opacity='1' > '/var/folders/8l/_jk6d2tn5cj6jp_rmq2t1tv92d_68s/T/magick-sepZd7k1yyDocNZD2p2RiJGdUnw6pKts' 2>&1
/var/folders/8l/_jk6d2tn5cj6jp_rmq2t1tv92d_68s/T/magick-HBEGlfBWo_vEuH6xZQh4BWPMWrTnNiKo.png PNG 300x150 300x150+0+0 8-bit sRGB 633B 0.010u 0:00.002

The problem seems to be with Wand, but I have no idea why it would render differently.

The (abridged) Flask code looks like this:

from base64 import b64encode
from flask import Flask, jsonify, request
from flask_cors import CORS
from wand.image import Image

def convert_svg_png(svg):
  img = Image(blob=svg.encode(), format='svg', resolution=300)
  png_data = img.make_blob(format='png')
  data = b64encode(png_data)

  return data.decode('ascii')

app = Flask(__name__)
CORS(app)

@app.route('/svgpng', methods=['POST'])
def svgpng():
  content = request.json
  imgData = convert_svg_png(content["svg"])
  response = jsonify({'image': imgData})
  response.headers.add('Access-Control-Allow-Origin', '*')
  return response

For example here's an SVG image I'm trying to convert:

Sample SVG

It looks exactly the same converted to PNG when I'm running the above code on RHEL7. But on Mac it looks like this:

enter image description here

The above image was generated from the following request:

curl --location --request POST 'http://localhost:5000/svgpng' \
--header 'Content-Type: application/json' \
--data-raw '{
    "svg": "<svg width=\"1280\" height=\"550\" xmlns=\"http://www.w3.org/2000/svg\"><g transform=\"translate(15, 100)\"><line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"100\" stroke=\"#a0a6a4\"></line><line x1=\"233.5\" y1=\"0\" x2=\"233.5\" y2=\"100\" stroke=\"#e8e8e8\"></line><line x1=\"467\" y1=\"0\" x2=\"467\" y2=\"100\" stroke=\"#e8e8e8\"></line><g><g><rect x=\"0\" y=\"15.925925925925924\" width=\"46.7\" height=\"68.14814814814815\" fill=\"#A90A24\"></rect><text x=\"23.35\" y=\"55\" fill=\"#FFFFFF\" font-family=\"'\''Bliss Pro'\''\" text-anchor=\"middle\">2</text></g><g><rect x=\"46.7\" y=\"15.925925925925924\" width=\"23.349999999999994\" height=\"68.14814814814815\" fill=\"#B2B5B6\"></rect><text x=\"58.375\" y=\"55\" fill=\"#FFFFFF\" font-family=\"'\''Bliss Pro'\''\" text-anchor=\"middle\">1</text></g><g><rect x=\"70.05\" y=\"15.925925925925924\" width=\"70.05\" height=\"68.14814814814815\" fill=\"#44A88B\"></rect><text x=\"105.07499999999999\" y=\"55\" fill=\"#FFFFFF\" font-family=\"'\''Bliss Pro'\''\" text-anchor=\"middle\">3</text></g><g><rect x=\"140.1\" y=\"15.925925925925924\" width=\"23.349999999999994\" height=\"68.14814814814815\" fill=\"#F7B718\"></rect><text x=\"151.77499999999998\" y=\"55\" fill=\"#FFFFFF\" font-family=\"'\''Bliss Pro'\''\" text-anchor=\"middle\">1</text></g><g><rect x=\"163.45\" y=\"15.925925925925924\" width=\"303.55\" height=\"68.14814814814815\" fill=\"#D3E3DB\"></rect><text x=\"315.225\" y=\"55\" fill=\"#FFFFFF\" font-family=\"'\''Bliss Pro'\''\" text-anchor=\"middle\">13</text></g></g></g></svg>"
}'

This returns a base64 encoded image.

The issue seems to stem from how Wand is loading a blob. If I try a trivial example loading from a file on the Mac, it works fine.

with Image(filename='test.svg') as img:
  with img.convert('png') as output_img:
      output_img.save(filename='test-file.png')

Switch to loading a blob from a string and I see the black lines:

testsvg2 = '<svg width=\"10\" height=\"10\"><rect x=\"2\" y=\"2\" width=\"5\" height=\"5\" fill=\"#FFFFFF\"></rect></svg>'
with Image(blob=testsvg2.encode()) as img:
  with img.convert('png') as output_img:
      output_img.save(filename='test-str.png')

Now let's say I try looking at the image that Wand has loaded:

testsvg2 = '<svg width=\"10\" height=\"10\"><rect x=\"2\" y=\"2\" width=\"5\" height=\"5\" fill=\"#FFFFFF\"></rect></svg>'
with Image(blob=testsvg2.encode()) as img:
  img.save(filename='svg-blob.svg')
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="10" height="10">
<g style="fill:black;fill-opacity:1;stroke:none;stroke-width:1;stroke-opacity:1;fill-rule:nonzero;">
<g style="fill:#FFFFFF;">
  <rect x="2" y="2" width="5" height="5"/>
</g>
</g>
</svg>

...that's not the SVG I was trying to convert! Where did that <g> element with the style attributes come from? That must be where it's coming from when converted to PNG, but how did that get there in the first place?

Here's my Mac setup:

  • macOS Monterey 12.6
  • Python 3.10.7
  • Flask 2.2.2
  • Wand 0.6.10
  • ImageMagick 7.1.0-49 Q16-HDRI x86_64 2047
  • Inkscape 1.2.1

Versus the RHEL7 setup:

  • Red Hat Enterprise Linux Server release 7.9 (Maipo)
  • Python 3.6.12
  • Flask 2.0.1
  • Wand 0.6.10
  • ImageMagick 6.9.10-68 Q16 x86_64 2021-09-22
  • Inkscape 0.92.2 (5c3e80d, 2017-08-06)

The only difference that doesn't look trivial to me is the Inkscape version, but again if it works with ImageMagick why not Wand too?

pcclarke
  • 68
  • 6
  • Please clarify. Does it run correctly in Imagemagick command line mode? You have an older release of both Imagemagick and Inkscape. You might try upgrading and try again. If you post your SVG file (zip it first), I could try on my Mac OSX Monterey with current Imagemagick 6.9.12-65 and Inkscape 1.2 – fmw42 Oct 10 '22 at 21:49
  • I included an example in the question of running `convert`, which does appear to be using Inkscape and did convert the SVG to PNG correctly. Let me know if there's another command I should be trying. – pcclarke Oct 11 '22 at 16:13
  • The version of ImageMagick I'm using on Mac is one point release old and Inkscape is the latest stable release. If anything, I should be downgrading them as the RHEL7 versions are older, but they work fine. The issue occurs regardless of SVG file I use, even something as simple as ``. – pcclarke Oct 11 '22 at 16:21
  • Does it work with Python Wand stand alone outside of your Flask? – fmw42 Oct 11 '22 at 16:22
  • Thanks for the tip. I updated my question to show what happens without Flask — Wand acting very strangely. – pcclarke Oct 11 '22 at 17:47
  • I think you need help from the Wand developer/maintainer, Eric McConville. – fmw42 Oct 11 '22 at 17:56

0 Answers0