SVG <image> rendering in firefox is off - firefox

Firefox's rendering of <image> elements is pixelated. The same image with the same width/height appears nicely as an <img>. It also works correctly as an svg <image> in Chrome.
Example:
The left portion is the svg <image> referencing a png, the right is a normal <img> referencing the same image.
Working example:
<svg height="53" width="60"
xmlns="http://www.w3.org/2000/svg">
<image href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" width="60" height="53" x="0" y="0" />
</svg>
<img src="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" width="60px" height="53px"/>
How do I make the svg image render properly? I've tried all the options listed here https://developer.mozilla.org/en-US/docs/Web/SVG/Element/image (image-rendering, shape-rendering, preserveAspectRatio, etc.).

This was caused by a bug, resolved in firefox 67.
https://bugzilla.mozilla.org/show_bug.cgi?id=1534188

Related

Save images to PDF - images within SVG elements are blurry, whereas images in <img> are sharp

See reproduced example here - https://codepen.io/canovice/pen/eYRmYKR - command + P to print, I've taken this screenshot of the print/pdf output:
Problem: On web, both images are sharp. On print and save to PDF, the logo in the <img> tag remains sharp, whereas the logo in the <svg> using <svg:pattern>, <svg:image>, <svg:rect> with the fill attribute, is blurry.
Purpose: Our web app has many SVG graphs (think scatterplots) that use the team logos in place of the scatterplot dots. We want users to be able to print these graphs, and save these graphs to PDF, with sharp images. Here's a screenshot of the graph on web, with the sharp logos. When we save this as PDF, we get blurry logos.
We are using react.js and d3.js to build our web app and create our svg graphs, although we are hoping for a solution specific to the html & css of SVG elements.
Wrapping a raster graphic image inside a svg name does not make it a true scalable vector graphic. The method used is a "gradient fill with image" thus not as efficient as using true SVG objects with true colour gradient fills.
To get png in svg wrapping keep it simple
<div>
<svg width="2000" height="2000" >
<rect x="0" y="0" height="1000" width="1000" style="fill: #f0fff0"/>
<image x="30" y="00" width="160" height="160" xlink:href="103735.png" />
<image x="300" y="50" width="160" height="160" xlink:href="103735.png" />
</svg>
</div>

Providing a fallback for webp images within svg elements without additional requests

I have an <svg> element using a .webp image in the <image> element. It works for Chrome and Opera, but in Firefox, nothing is displayed, so I tried adding another <image> element containing the png. Now it works in Firefox, but upon inspection in the Chrome DevTools, both images were loaded as seen in the number of requests.
How can I force only 1 request (1 image to load) while providing a fallback for the webp image within the svg element for such browsers currently not supporting webp? The code is:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500">
<image xlink:href="image.webp" width="500" height="500"/>
<image xlink:href="image.png" width="500" height="500"/>
</svg>

Image to be grayed in IE 9+

I want image to be grayed in IE 9+ and when I hover mouse it show original
Everything is working fine but thing is that when I do hover it scales image
find code in below fiddle
Fiddle
The scaling is caused by your jpg being slightly larger (105×58) than your svg (96×53). When the jpg is referenced by <image> it is scaled to fit the dimensions of <image>. This works as expected for the grayed image, but fails for the hover effect. On hover you set opacity:0 for the <image> which renders the svg's background visible. The background image, however, is not scaled to fit the dimensions, but rather clipped to your svg's size. Hence the difference in scale.
To circumvent these problems I would prefer another approach getting rid of the background image. You could just place the original coloured image right underneath the grayed image. The grayed image will then obscure the coloured image until opacity is set to 0 on hover:
<image x="0" y="0" width="96" height="53" xlink:href="https://dl.dropboxusercontent.com/u/18190667/img.jpg" />
<image class="gray" filter="url('#filtersPicture')" x="0" y="0" width="96" height="53" xlink:href="https://dl.dropboxusercontent.com/u/18190667/img.jpg" />
Check the updated JSFiddle.

How to specify the portion of the image to be rendered inside SVG:image tag?

I have a PNG file with lots of icons on it. I want to use it in my SVG. I use the svg:image tag:
<image xlink:href="icons.png" height="50px" width="50px"></image>
This renders the whole image. How can I specify the portion of the file to be rendered? (I need an SVG-equivalent of CSS's background-position attribute)
Update
I suspect preserveAspectRatio attribute to be what I need, but can not figure out how to use it with <image>. See this example.
You can use preserveAspectRatio to achieve this affect in a limited way. But you are limited by the positioning options that preserveAspectRatio provides. So as long as your sprite has a maximum of 3x3 images or are positioned at the corners or sides, it would work.
The are a couple of other ways I can think of to achieve the same effect in a more flexible way.
Use the clip or clip-path style properties along with careful positioning of the image on the page
Embed the image inside another <svg> element and use viewBox to select the part of the sprite you want.
The following example demonstrates the three main techniques above.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="8cm" viewBox="0 0 400 400" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>Testing image elements</desc>
<!-- Outline the drawing area in blue -->
<rect fill="none" stroke="blue"
x="1" y="1" width="398" height="398"/>
<!-- Use preserveAspectRatio to show the top 64 pixels of the image (Stack Overflow logo) -->
<image x="100px" y="100px" width="238px" height="64px" xlink:href="http://cdn.sstatic.net/stackoverflow/img/sprites.png"
preserveAspectRatio="xMinYMin slice"/>
<!-- Use a CSS clip rectangle to show a small facebook logo from the sprite. Logo is at 150,1000 with dimensions 19x19.
Positioned at 100,200 in the SVG (-50+150, -800+1000). Could also use a clip-path for this. -->
<image x="-50px" y="-800px" width="238px" height="1073px" xlink:href="http://cdn.sstatic.net/stackoverflow/img/sprites.png"
clip="rect(200 100 219 119)" />
<!-- Use a svg viewBox to show the facebook logo from the sprite.
By setting our viewBox to the bounds of the logo, the renderer will scale it to fit the specified width and height.
Which in this case is 19x19 - the same size as the sprite. -->
<svg x="100px" y="300px" width="19px" height="19px" viewBox="150 1000 19 19" version="1.1">
<image x="0px" y="0px" width="238px" height="1073px" xlink:href="http://cdn.sstatic.net/stackoverflow/img/sprites.png" />
</svg>
</svg>

SVG <use> scales but <image> not

I want to embed some SVG into SVG.
Therefor I want to use the <image> element since I want to keep my SVG separated.
But when I include my SVG like that:
<image xlink:href="svgs/munitionsmangel.svg" width="20" height="20" x="120" y="70" />
It works, but does not scale the SVG up when I zoom with my browser, it just stays small.
But when I embed just the same SVG file as a symbol and include it like that:
<use xlink:href="#munitionsmangel" width="20" height="20" x="80" y="70" />
it just scales up like a charm.
What is the problem here?
Edit: Seems like this is a bug with Firefox, in the current version 21
Chrome scales up the image as well...
Even more strange, if I include a raster image with image, both Firefox and Chrome scale it...
Edit 2: Even IE 9 has the desired behaviour, although its rendering of background colors is a bit strange, so its only Firefox which sucks
Since this really seems like a bug in Firefox, I will use the <use />-tag instead, maybe in combination with XMLHttpRequest to insert the <symbol /> dynamically.
Or even only XMLHttpRequest with inserting the node directly.
I cannot think of a better solution, so if there is really a better answer, just post it!

Resources