New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Low resolution PNG output #207
Comments
Good question. This is more a ReportLab question than a svglib one, but by reading RL code, looks like you should be able to play with the |
I managed to successfully resize properly with this answer. However, upon resizing, I realised that the edges were extremely jagged. |
Having the same issue with a different svg image. drawToFile's dpi argument does not work, it just modifies the size of the output file but not its resolution. Adding this comment just in case a solution or follow up is added. |
I would also first scale it like you did. If the result looks jagged that could be because of its path definition, but I see it does contain cubic Bézier curves like in this pretty similar example here: https://www.sitepoint.com/closer-look-svg-path-data/ Maybe you want to compare with that? The test suite perfectly runs most flags from Wikipedia and they should be full of such curves. Else I hope @replabrobin can shere any insight about any renderPM limitations? |
without the actual svg it's hard to answer any question like this. If I squash the large image the flats disappear, so are the curves bezier? I think the assertion in renderPM is 1pixel == 1pt for PDF compatibility. The dpi value is not used internally in the drawing code, but is passed to PIL via im.save. |
@replabrobin The SVG file I used is liked above in a gist. |
It's not working for me; I just see the loading gif for a few seconds and then "Sorry, something went wrong. Reload?" |
I'm afraid not, as before just the placeholder circling and then something went wrong. I am using chromium 83 on arch linux latest |
<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 47.5 47.5" style="enable-background:new 0 0 47.5 47.5;" xml:space="preserve" version="1.1" id="svg2"><metadata id="metadata8"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata><defs id="defs6"><clipPath id="clipPath16" clipPathUnits="userSpaceOnUse"><path id="path18" d="M 0,38 38,38 38,0 0,0 0,38 Z"/></clipPath></defs><g transform="matrix(1.25,0,0,-1.25,0,47.5)" id="g10"><g id="g12"><g clip-path="url(#clipPath16)" id="g14"><g transform="translate(23.8555,36.2422)" id="g20"><path id="path22" style="fill:#5dadec;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -14.98,-6.266 12.537,-9.733 c 2.632,-2.224 6.377,-2.937 9.769,-1.518 4.826,2.018 7.096,7.577 5.072,12.413 C 10.377,-0.266 4.824,2.019 0,0"/></g><g transform="translate(13.8931,18.3184)" id="g24"><path id="path26" style="fill:#5dadec;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -10.843,8.398 -1.913,-13.246 c -0.534,-2.855 0.502,-5.902 2.958,-7.802 3.493,-2.705 8.518,-2.067 11.224,1.425 C 4.131,-7.732 3.493,-2.707 0,0"/></g><g transform="translate(29.2324,11.3027)" id="g28"><path id="path30" style="fill:#5dadec;fill-opacity:1;fill-rule:nonzero;stroke:none" d="m 0,0 -8.156,4.689 -0.033,-9.222 c -0.088,-2 0.904,-3.981 2.75,-5.041 2.63,-1.512 5.976,-0.594 7.478,2.051 C 3.539,-4.879 2.629,-1.51 0,0"/></g></g></g></g></svg> |
Thanks I'll take a look later |
Hi I had a look at this problem and it seems to me that the internal libart code is scaling after discretization instead of scaling before. I'll see if there's a better way to do curves in _renderPM. |
OK I looked in the _renderPM code and it seems that our smoothness is dictated by the parameter 0.25 passed into vpath = art_bez_path_to_vec(self->path, 0.25) which converts beziers into vector paths. Everywhere that is used it is followed eventually in _renderPM.c by a call to I wonder if that is the source of the problem we are scaling after vectorizing; we should be able to scale all the control points before scaling. It seems to make sense for scales > 1, but perhaps not when scaling < 1. |
@replabrobin What is the state of this? I find the very same effect as shown below (recorded inside a Jupyter notebook). import io
import requests
from ipywidgets import interact
from PIL import Image
from reportlab.graphics import renderPM, renderPDF
from svglib.svglib import svg2rlg
svg = requests.get("https://simpleicons.org/icons/apple.svg").text
svg_file = io.StringIO(svg)
@interact(scale=(1, 20, 1))
def render(scale=1):
drawing = svg2rlg(svg_file)
drawing.scale(scale, scale)
drawing.width *= scale
drawing.height *= scale
f = io.BytesIO()
renderPM.drawToFile(drawing, f, fmt="PNG")
f.seek(0)
im = Image.open(f)
return im
im = render() import base64
import io
import requests
from IPython.display import Markdown
from ipywidgets import interact
from reportlab.graphics import renderPDF
from svglib.svglib import svg2rlg
svg = requests.get("https://simpleicons.org/icons/apple.svg").text
svg_file = io.StringIO(svg)
@interact(scale=(1, 20, 1))
def render(scale=1):
drawing = svg2rlg(svg_file)
drawing.scale(scale, scale)
drawing.width *= scale
drawing.height *= scale
pdf_content = renderPDF.drawToString(drawing)
base64_pdf = base64.b64encode(pdf_content).decode("utf-8")
pdf_display = (
f'<embed src="data:application/pdf;base64,{base64_pdf}" '
'width="400" height="400" type="application/pdf">'
)
return Markdown(pdf_display)
md = render() |
The fix above doesn't seem to apply to stroke
|
Seems to just be a limitation of svglib: https://stackoverflow.com/questions/68242812/in-python-convert-svg-to-png-while-resizing-and-increasing-quality |
GOT IT FIGURED OUT You can just convert from SVG to PDF then from PDF to PNG: from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF
from pdf2image import convert_from_path
drawing = svg2rlg('card.svg')
renderPDF.drawToFile(drawing, 'card.pdf')
pages = convert_from_path('card.pdf', 600)
pages[0].save('card.png', 'PNG') All other implementations online either require Pillow (which is a massive pain, struggled with that for several hours during several days a while ago) or CairoSVG (which is near impossible to get working on Windows) |
I found this issue when trying to convert SVG inputs to PNG/PIL, without relying on pip install pymupdf svglib is needed to get this running import fitz
from svglib import svglib
from reportlab.graphics import renderPDF
# Convert svg to pdf in memory with svglib+reportlab
# directly rendering to png does not support transparency nor scaling
drawing = svglib.svg2rlg(path="input.svg")
pdf = renderPDF.drawToString(drawing)
# Open pdf with fitz (pyMuPdf) to convert to PNG
doc = fitz.Document(stream=pdf)
pix = doc.load_page(0).get_pixmap(alpha=True, dpi=300)
pix.save("output.png") This supports transparent backgrounds without corners and does not have the issue pointed out above. Cheers! |
To add a bit to the response by @M4a1x, if you don't want to save to a file, you can just do:
|
This is the SVG file that I am trying to convert.
Is there a way to make the output png a higher resolution? The rendered SVG on Github has a way higher resolution than the one outputted by the lib.
72 DPI (default)
1024 DPI
Python code:
The text was updated successfully, but these errors were encountered: