Skip to content

BUG: dpi parameter not working properly when converting from svg in python #1424

Description

@Czoczaj

When parsing this svg to png:

temp.svg:

<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="1000mm" version="1.1" width="1000mm" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs></defs>
<rect fill="#ffffff" height="1000mm" width="1000mm" x="0" y="0" />

with:

import pyvips
image = pyvips.Image.svgload("temp.svg", dpi=25.4)
image.write_to_file("output_test.png")

output_test's dimensions are 353mm x 353mm (and 353px x 353px). (Should be 1000mm x 1000mm and 1000px x 1000px)

also, intrestingly enough - with image = pyvips.Image.svgload("temp.svg", dpi=x) dimensions of the image scale roughly according to x^1.86

Activity

  1. jcupitt commented on Sep 2, 2026

    @jcupitt
    Member

    Hi @Czoczaj,

    Thanks for reporting this. I agree, I think the scaling is wrong for non-pixel dimensions, it looks like we're applying the dpi scale twice in this case.

    I'll make a quick PR.

  2. jcupitt commented on Sep 3, 2026

    @jcupitt
    Member

    I did some digging and I'm not certain this is easily fixable with the librsvg API.

    The problem seems to be with the use of physical dimensions in SVG sizing. For eg. "1000mm" in the header to work, you need to call rsvg_handle_set_dpi() before load. This will then automatically scale the drawing for you nicely. However, if a pixel dimension is used (eg. "1000px") then librsvg does NOT use it to scale the header or drawing and you must apply a scale yourself during rendering.

    The bug you're seeing is what happens when a SVG with physical dimensions in the header is rescaled: the dpi is applied twice, so you get something close to the square of dpi (the ^1.8 you saw).

    I think perhaps the solution is to use the dpi= parameter to ONLY change the way physical dimensions in the header are interpreted (and the dpi recorded in the output image), and not the rendering scale. The scale= parameter could ONLY change the rendering scale.

    I'll make an experimental branch so we can try this out. It looks likely to break some old code, unfortunately :(

    (I think the other bug you opened is also fixed by this change)

  3. jcupitt commented on Sep 3, 2026

    @jcupitt
    Member

    I made a PR on libvips with some examples, and credited you. Let's move any discussion there.

    Thanks for reporting this!

    (edit: your other bug is different, sorry)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions