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'];
            }
        }
     }
  }
}

Comments

pbattino created an issue. See original summary.

pbattino’s picture

Issue tags: +svg, +media
pbattino’s picture

StatusFileSize
new490 bytes

Patch for image.module

pbattino’s picture

Status: Active » Needs review
pbattino’s picture

unless I'm missing something, they shouldn't be triggered at all because the URLs ://styles/' . $style_name will never be called.

Last 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.

Status: Needs review » Needs work

The last submitted patch, 5: image-3048602-styles-do-no-support-svg-5.patch, failed testing. View results

pbattino’s picture

Status: Needs work » Needs review
StatusFileSize
new1.28 KB

typo, re-submitting

poker10’s picture

Status: Needs review » Needs work
Issue tags: -media +Needs tests

Thanks for reporting this.

@@ -1102,6 +1103,9 @@ function image_style_path($style_name, $uri) {
     $path = $uri;
     $scheme = file_default_scheme();
   }
+  if (in_array(strtolower(pathinfo($uri, PATHINFO_EXTENSION)), array_change_key_case(variable_get('image_vector_types', array('svg'))))) {
+      return $scheme. '://'.$path;
+  }

Where comes the image_vector_types variable 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.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 7 security and bugfix support has ended as of 5 January 2025. If the issue verifiably applies to later versions, please reopen with details and update the version.