Skip to content
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

Images (SVG) always maximally scaled #76

Closed
nicesw123 opened this issue Dec 19, 2014 · 25 comments
Closed

Images (SVG) always maximally scaled #76

nicesw123 opened this issue Dec 19, 2014 · 25 comments
Assignees

Comments

@nicesw123
Copy link

Hi there!

asciidoctor-pdf always scales small_image.svg to fit the width entirely into the pdf.

I see this as being ok (it is definitely better than the image-cut-off that one gets with asciidoctor-fopub asciidoctor/asciidoctor-fopub#43) ; but just note: it is not possible to decrease the width, should one like to do this.

Here is sample.adoc that you can test with html5, pdf (via asciidoctor-fopub), pdf (via asciidoctor-pdf)
[depends only of small_image.svg, that you can copy-paste from below]

= Test scaling of small image
:toc:

Here comes the image `small_image.svg`:

image::small_image.svg[]

== Scale the image (to make it easier to view)

image::small_image.svg[Small Image, width=1000]

[[small_image]]
[source,asciidoc]
image::small_image.svg[Small Image, width=1000]

=== Good for html5

The <<small_image,above scaled image>> is rendered nicely for html5

=== Bad for asciidoctor-fopub (docbook)

The <<small_image,above scaled image>> is clipped when rendered to pdf via asciidoctor-fopub

.Render to pdf via asciidoctor-fopub (docbook)
[source]
asciidoctor -b docbook -d book -a data-uri! sample.adoc
~/asciidoc/asciidoctor-fopub/fopub sample.xml

=== OK for asciidoctor-pdf (but always maximally scaled)

The `width`-scaling is ignored by asciidoctor-pdf:
there the <<small_image,image>> is always maximally scaled.

.Render to pdf via asciidoctor-pdf
[source]
asciidoctor-pdf sample.adoc

The scaling does not harmonize nicely between html5 and asciidoctor-fopub.

  • What fits nicely in html5, is unfortunately cut-off for pdf output

I believe there should be a possibility to scale to fit the width, but preventing cut-off of an image.

Source of image small_image.svg (for copy-pasting):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<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"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   width="200"
   height="20"
   id="svg2"
   version="1.1"
   inkscape:version="0.48.5 r10040"
   sodipodi:docname="New document 1">
  <defs
     id="defs4" />
  <sodipodi:namedview
     id="base"
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1.0"
     inkscape:pageopacity="0.0"
     inkscape:pageshadow="2"
     inkscape:zoom="5.6"
     inkscape:cx="103.58874"
     inkscape:cy="-23.239855"
     inkscape:document-units="px"
     inkscape:current-layer="layer1"
     showgrid="false"
     inkscape:object-paths="true"
     inkscape:object-nodes="true"
     inkscape:snap-global="true"
     fit-margin-top="0"
     fit-margin-left="0"
     fit-margin-right="0"
     fit-margin-bottom="0"
     inkscape:window-width="1680"
     inkscape:window-height="948"
     inkscape:window-x="0"
     inkscape:window-y="31"
     inkscape:window-maximized="1" />
  <metadata
     id="metadata7">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <g
     inkscape:label="Layer 1"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(-5.6806582,-850.69528)">
    <g
       id="g3037"
       transform="matrix(0.90352131,0,0,1,3.7342666,-9.1071429)">
      <rect
         y="864.97888"
         x="9.0913725"
         height="4.5456862"
         width="51.731339"
         id="rect2985"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="60.822712"
         height="4.5456862"
         width="51.731339"
         id="rect2985-9"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="112.55405"
         height="4.5456862"
         width="51.731339"
         id="rect2985-96"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="164.28539"
         height="4.5456862"
         width="51.731339"
         id="rect2985-6"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
    </g>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="22.841372"
       y="859.5246"
       id="text3088"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090"
         x="22.841372"
         y="859.5246">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="71.990654"
       y="859.56769"
       id="text3088-0"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6"
         x="71.990654"
         y="859.56769">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="119.49065"
       y="859.3891"
       id="text3088-0-8"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6-6"
         x="119.49065"
         y="859.3891">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="162.8835"
       y="859.56769"
       id="text3088-0-8-8"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6-6-6"
         x="162.8835"
         y="859.56769">small text</tspan></text>
    <g
       id="g3037-0"
       transform="matrix(0.90352131,0,0,1,3.7342666,-4.5614275)">
      <rect
         y="864.97888"
         x="9.0913725"
         height="4.5456862"
         width="51.731339"
         id="rect2985-7"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="60.822712"
         height="4.5456862"
         width="51.731339"
         id="rect2985-9-9"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="112.55405"
         height="4.5456862"
         width="51.731339"
         id="rect2985-96-3"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
      <rect
         y="864.97888"
         x="164.28539"
         height="4.5456862"
         width="51.731339"
         id="rect2985-6-2"
         style="fill:none;stroke:#000000;stroke-width:0.78902733;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
    </g>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="22.841377"
       y="864.07037"
       id="text3088-3"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-4"
         x="22.841377"
         y="864.07037">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="71.990662"
       y="864.11346"
       id="text3088-0-1"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6-66"
         x="71.990662"
         y="864.11346">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="119.49067"
       y="863.93488"
       id="text3088-0-8-0"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6-6-8"
         x="119.49067"
         y="863.93488">small text</tspan></text>
    <text
       xml:space="preserve"
       style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
       x="162.88351"
       y="864.11346"
       id="text3088-0-8-8-4"
       sodipodi:linespacing="125%"><tspan
         sodipodi:role="line"
         id="tspan3090-6-6-6-9"
         x="162.88351"
         y="864.11346">small text</tspan></text>
  </g>
</svg>
@DavidGamba
Copy link
Contributor

This is what I do in this case:

ifdef::pdf[]
// widths in percent of the page width
:width100: 450
:width50: 275
:width25: 137
endif::[]
ifndef::pdf[]
:data-uri:
:width100: 1000
:width50: 500
:width25: 250
endif::[]

And then in the doc itself:

image::image.png[, width={width100}]

I set the pdfattribute when building a pdf.

@mojavelinux
Copy link
Member

Also, keep in mind, this is what the scaledwidth attribute is for. It's not super clear, but in general the scaledwidth attribute is for PDF and the width attribute is for HTML5.

See https://github.com/asciidoctor/asciidoctor-pdf/blob/master/lib/asciidoctor-pdf/converter.rb#L578

It's very likely we're going to have to think about how to get more fine-grained control because I recognize that we aren't covering all the use cases.

@mojavelinux mojavelinux added this to the v1.6.0 milestone Dec 20, 2014
@chanibal
Copy link

+1. Currently unusable for asciidoctor-diagram. The diagrams require a constant dpi per document (a width in pt is provided in the svg's).

@mojavelinux mojavelinux self-assigned this Apr 1, 2015
@gembin
Copy link

gembin commented Apr 5, 2015

+1.

@deepankarsharma
Copy link

+1, running into this issue using asciidoctor-diagram to generate svgs.

@mojavelinux mojavelinux modified the milestones: v1.5.0, v1.6.0 May 11, 2015
@mojavelinux
Copy link
Member

I'll move this to 1.5.0 since it seems to be a showstopper for more and more users.

@mojavelinux
Copy link
Member

It's important to understand that there is a way to control the width of SVGs in PDF. It's just that the name of the attribute is different (and has slightly different semantics).

When converting to PDF, you should use the scaledwidth attribute instead of (or in addition to) the width attribute. The scaledwidth attribute takes precedence in the PDF backend.

There is one major different with scaledwidth though. The value is a percentage width of the bounds (available width) rather than an absolute value. The reason for this is both historical (compatibility with AsciiDoc Python) and because a PDF can have vastly different scaling and therefore it helps to think in these terms for consistency.

Here's how you would write your image macro so that the SVG is not maximally scaled.

image::small-image.svg[Small Image, 600, scaledwidth=50%]

That at least addresses the title of this issue, which is that this value cannot be controlled.

Now, I realize that we still don't have all the necessary controls, so I'd like to proceed by making sure we have a way to handle the essential use cases for scaling images in the PDF.

@mojavelinux
Copy link
Member

Looking at it closer, I now see that scaledwidth doesn't work if width is set when using the DocBook toolchain (a2x, fopub). This should actually be fixed by what we put into the DocBook output...but that's a separate issue.

@mojavelinux
Copy link
Member

I set the pdf attribute when building a pdf.

You can also check for backend-pdf, which is set when using Asciidoctor PDF.

@mojavelinux
Copy link
Member

I did some testing and it appears that Asciidoctor Diagram will pass through the scaledwidth attribute. Thus, to get a usable result for Asciidoctor PDF, please use:

[graphviz, graphviz-example, svg, scaledwidth=15%]
....
digraph g {
    a -> b
    b -> c
    c -> d
    d -> a
}
....

Asciidoctor PDF will ignore the width attribute if you set it (as it is intended for HTML). The DocBook toolchain (fopub and a2x) will not, so you need to leave it out when doing PDF through that toolchain.

@mojavelinux
Copy link
Member

...and when using SVGs, you are correct that the width attribute is ignore completely by Asciidoctor PDF.

@mojavelinux
Copy link
Member

I did some more thinking about this in the following thread.

http://discuss.asciidoctor.org/Unit-of-measure-for-image-dimensions-tp3040p3222.html

I think the solution is that we need width attributes per backend. It's kind of like scaledwidth, except that it's not changing the semantics at the same time.

The current width and height attributes in the image block are meant to be metadata only. They communicate to the processor the original rasterized dimensions of the image (or, in the case of SVG, the original viewport). These values are pixels.

We then need a way to control the scaling of the image. I propose the following attributes:

  • csswidth
  • cssheight (however, this breaks responsiveness of the image, so I recommend against using it)
  • pdfwidth
  • pdfheight

These attributes can take a value and a unit (e.g., pdfwidth=15cm, pdfwidth=50%). This way, we have a very clear way to control the width on different canvases.

What do you think about the css and pdf prefixes? Should we use screenwidth and printwidth instead? Any other ideas?

@mojavelinux
Copy link
Member

I want to clarify why the code behaves the way it does currently to help you think about a solution. I decided not to honor the width attribute for SVGs since the width is usually set for the HTML backend and is assumed to be a pixel value. The PDF canvas is in points and usually a very different size than the HTML canvas. Thus, you can't simply use that value in the PDF directly.

What we could do is if scaledwidth is not set (and pdfwidth isn't set either), we could take the width value and convert it from px to pt. Then, we could use that calculated value. wdyt? Good short term solution? I could try it, see how it goes. (Btw, I'd do the same thing for all image types).

mojavelinux added a commit to mojavelinux/asciidoctor-pdf that referenced this issue Jun 23, 2015
- use native image width scaled by 75% by default
- allow explicit width to be set using pdfwidth attribute
- make alt text a link if image cannot be resolved and link attribute is present
- align alt text to honor image alignment
- add helper method to calculate pt from measurement value (number with units)
- don't advance to new page if already at top of page
- code cleanups
mojavelinux added a commit to mojavelinux/asciidoctor-pdf that referenced this issue Jun 23, 2015
- use native image width scaled by 75% by default
- allow explicit width to be set using pdfwidth attribute
- make alt text a link if image cannot be resolved and link attribute is present
- align alt text to honor image alignment
- add helper methods to convert to pt from string or number
- don't advance to new page if already at top of page
- code cleanups
@mojavelinux
Copy link
Member

I've proposed a fix. See #218

The fix does a couple things.

  1. If the pdfwidth attribute is specified, it's assumed to be a measurement value, with or without units (e.g., 150pt, 5in, 200); default units is pt
  2. Otherwise, if the scaledwidth attribute is specified, it's assumed to be a percentage width of the current bounds; note that pdfwidth can also be a percentage with same behavior
  3. Otherwise, if no width attribute is specified, it uses the native pixel width of the image (after scaling pixels to points by multiplying value by 75%)
  4. Otherwise, if the width attribute is specified, this value is used (after scaling pixels to points by multiplying value by 75%)

What I have not yet done is scale down the image to fit the page if no width is specified. Perhaps we need a maxwidth attribute (and/or maxpdfwidth).

@mojavelinux
Copy link
Member

To align with behavior we added to the listing block, perhaps instead of maxwidth, we should honor the autofit option for this purpose.

[%autofit]
image::small_image.svg[width=1000]

@mojavelinux
Copy link
Member

To clarify, autofit is assumed to mean scale down in this context, not scale up.

@mojavelinux
Copy link
Member

Another option is to scale the image down to fit on the page if only the width attribute is specified. If the pdfwidth attribute is specified, then that value is used as is, even if it makes the image larger than the page.

mojavelinux added a commit to mojavelinux/asciidoctor-pdf that referenced this issue Jun 24, 2015
- default to native image width scaled by 75% by default
- allow explicit width to be set using pdfwidth attribute
- enforce max width of 100%, except for pdfwidth or scaledwidth
- make alt text a link if image cannot be resolved and link attribute is present
- align alt text to honor image alignment
- add helper methods to convert to pt from string or number
- don't advance to new page if already at top of page
- code cleanups and optimizations
@mojavelinux
Copy link
Member

I decided to implement such that if neither the pdfwidth or scaledwidth attributes are specified, the maximum width of the image is the width of the current bounds / box. The pdfwidth and scaledwidth attributes can be used to override this behavior with an explicit value.

mojavelinux added a commit to mojavelinux/asciidoctor-pdf that referenced this issue Jun 24, 2015
- default to native image width scaled by 75% by default
- allow explicit width to be set using pdfwidth attribute
- enforce max width of 100%, except for pdfwidth or scaledwidth
- make alt text a link if image cannot be resolved and link attribute is present
- align alt text to honor image alignment
- add helper methods to convert to pt from string or number
- don't advance to new page if already at top of page
- code cleanups and optimizations
mojavelinux added a commit that referenced this issue Jun 24, 2015
resolves #76 allow fine-grained control over image width
@wolandscat
Copy link

should the scaledwith attribute affect the HTML output as well? Both scaledwidth and pdfwidth (used on their own) appear to scale as expected in the PDF output, but I am not seeing anything in the HTML output to scale the images. Ideally, I want scaledwidth="80%" to scale the image to 80% of the text column width in all output forms.

@mojavelinux
Copy link
Member

should the scaledwith attribute affect the HTML output as well?

Not using scaledwidth. scaledwidth was really only introduced for the DocBook toolchain where this value had meaning.

You can set a percentage width for HTML using the width attribute.

image::diagram.png[width=80%]

However, technically this produces invalid HTML because as of HTML5, the width value can only be unitless (CSS pixel). We don't currently accommodate percentage scaling any other way in the HTML backend. Something to discuss.

@mojavelinux
Copy link
Member

I want to mention that I missed a use case with SVGs. If a width is set in the SVG and it's wider than the page, than the image is not being fit to the page. I didn't realize that Prawn SVG wouldn't handle this case. I've filed a follow-up issue: #242.

@wolandscat
Copy link

I've found that just using [width=x%] does the right thing for both HTML and PDF PNG diags. SVGs are still broken in terms of colour and scaling.

@mojavelinux
Copy link
Member

I'm confident that the fix for #242 will address the remaining scaling issues.

@wolandscat
Copy link

I would still be interested in being having landscape pages in the PDF output for wide diagrams that have been made with that intention - which is pretty common. Since some diagrams might simply be wide because they were obtained in some strange way (e.g. very high-res screenshot), there's no way to infer whether a landscape page would be needed or not. Therefore it would have to be indicated explicitly, perhaps in the image macro, e.g. 'landscape'.

(proposal moved to #250)

The more I think about it, the more I think landscape images with float/nofloat need to be supported in PDFs, as this is extremely common in publishing and documentation. Shall I raise a new issue on that?

@mojavelinux
Copy link
Member

Shall I raise a new issue on that?

Please do. This is very useful analysis. I like each issue to be very focused on a single task. That gives the task the best chance to be addressed and helps keep the conversation on track.

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

No branches or pull requests

8 participants