Since #2652138: Image styles do not play nicely with SVGs is closed, but not backported to D7, I created this new issue.
Please feel free to edit/close this issue if there's a more suitable way to track it.
Original description:
Currently, it's not possible to use SVGs with image styles, because the image style system only works with raster graphics. The core Image module is unaware of the distinction, and may attempt to process SVGs anyway, which can result in errors and other user-facing ugliness. This also makes it impossible to display vector and raster images side-by-side in a single image field with an image style applied, since it will not be able to display all the images in the field consistently.
The most straightforward solution to avoid the "ugliness" for me was to add a couple of lines in image_style_path: if the uri ends with "svg", always serve the original and not the derivative image:
function image_style_path($style_name, $uri) {
$scheme = file_uri_scheme($uri);
if ($scheme) {
$path = file_uri_target($uri);
}
else {
$path = $uri;
$scheme = file_default_scheme();
}
if (pathinfo($uri, PATHINFO_EXTENSION) == 'svg') {
return $scheme. '://'.$path;
}
return $scheme . '://styles/' . $style_name . '/' . $scheme . '/' . $path;
}
This does not prevent someone to directly call the functions that process the image but, unless I'm missing something, they shouldn't be triggered at all because the URLs ://styles/' . $style_name will never be called.
Also, AKAIK SVG may or may not have a "native" height and width. So the output you get by always showing the original may dependent totally on the size of the containing HTML element.
To make sure the size of the SVG would match the size of a raster image displayed with the same image style, I used hook_preprocess_image_style to set the height attributes based on the resize effect, if exists. ( I only set height so aspect ratio is maintained)
It does the job greatly but of course is a funny way of handling image styles.
function mymodule_preprocess_image_style(array &$variables) {
if (pathinfo($variables['path'], PATHINFO_EXTENSION) == 'svg') {
if ($variables['style_name'] != "default") {
$styles=image_styles();
if (!empty($styles[$variables['style_name']]['effects'])) {
$scale_effect = array_filter($styles[$variables['style_name']]['effects'], function($item) {
return ($item['name'] == "image_scale");
});
if (!empty($scale_effect) &&
!empty(reset($scale_effect)['data']['width'])) {
$variables['attributes']['width'] = reset($scale_effect)['data']['width'];
}
}
}
}
}
| Comment | File | Size | Author |
|---|---|---|---|
| #7 | image-3048602-styles-do-no-support-svg-7.patch | 1.28 KB | pbattino |
| #3 | image-3048602-styles-do-no-support-svg.patch | 490 bytes | pbattino |
Comments
Comment #2
pbattino commentedComment #3
pbattino commentedPatch for image.module
Comment #4
pbattino commentedComment #5
pbattino commentedLast famous words...
image_style_path() is not just used when derivative images are shown, but also to build the URIs of at the time of flushing the derivative images, by the function image_path_flush() . If I return the untouched URI, the original image will be flushed too... : /
I modified image_path_flush() to make sure the original URI is not affected. I also added a variable (an array) where other extensions can be added on top of SVG.
Comment #7
pbattino commentedtypo, re-submitting
Comment #8
poker10 commentedThanks for reporting this.
Where comes the
image_vector_typesvariable from? If it is a new variable, we would need to define it somewhere.I would prefer if we solve this more universally like the D8 approach. The D8 approach works a way that the image toolkit returns an information if the extension is supported or not and according to this information the image derivative is/is not created.
Either way, this would also need tests.