Proposal to allow overriding the implicit viewBox of raster images used in the 'image' element

Introduction

SVG 1.1 section 5.7 says that when an 'image' element references a raster image the implicit 'viewBox' has a value of "0 0 raster-image-width raster-image-height".

This makes it difficult to cut out parts of raster images, such as an image that contains a multiple of sub-images, e.g like in this example Since this implicit viewbox can't be controlled you are forced to use other less intuitive methods (which are often more expensive) of getting the part of the raster image you want. E.g. clip, mask, pattern, clip-path to cut out a part of the image. In the www-svg discussion thread a question asked was why not use 'clip' to do this instead. One problem is that 'clip' only affects elements that establish viewports, and thus you'd need to use such an element as a wrapper, e.g an 'svg' element.

Currently the situation is that the author controls the viewport (destination) rectangle directly, but the viewbox (source) rectangle only indirectly for rendering an 'image' element.

Use-cases

Requirements

Proposal

If the 'image' element references a raster image and has a 'viewBox' attribute, then the 'viewBox' defines which part of the raster image to draw into the viewport (destination) rectangle.

Change

5.7 The 'image' element

The 'image' element indicates that the contents of a complete file are to be rendered into a given rectangle within the current user coordinate system. The 'image' element can refer to raster image files such as PNG or JPEG or to files with MIME type of "image/svg+xml". Conforming SVG viewers need to support at least PNG, JPEG and SVG format files.

The result of processing an 'image' is always a four-channel RGBA result. When an 'image' element references a raster image file such as PNG or JPEG files which only has three channels (RGB), then the effect is as if the object were converted into a 4-channel RGBA image with the alpha channel uniformly set to 1. For a single-channel raster image, the effect is as if the object were converted into a 4-channel RGBA image, where the single channel from the referenced object is used to compute the three color channels and the alpha channel is uniformly set to 1.

An 'image' element establishes a new viewport for the referenced file as described in Establishing a new viewport.  The bounds for the new viewport are defined by attributes x, y, width and height. The placement and scaling of the referenced image are controlled by the preserveAspectRatio attribute on the 'image' element.

When an 'image' element references an SVG image the preserveAspectRatio attribute as well as the clip and overflow properties on the root element in the referenced SVG image are ignored (in the same manner as the x, y, width and height attributes are ignored). Instead, the preserveAspectRatio attribute on the referencing 'image' element defines how the SVG image content is fitted into the viewport and the clip and overflow properties on the 'image' element define how the SVG image content is clipped (or not) relative to the viewport.

The value of the 'viewBox' attribute to use when evaluating the preserveAspectRatio attribute is defined by the referenced content. For content that clearly identifies a viewBox (e.g. an SVG file with the 'viewBox' attribute on the outermost svg element) that value should be used. For most raster content (PNG, JPEG) the bounds of the image should be used (i.e. the 'image' element has an implicit 'viewBox' of "0 0 raster-image-width raster-image-height"). For most raster content (PNG, JPEG) the bounds of the image should be used (i.e. the 'image' element has an implicit 'viewBox' of "0 0 raster-image-width raster-image-height"), however if a 'viewBox' is specified it overrides the implicit 'viewBox'. When a 'viewBox' for raster content is specified, any negative values for in the 'viewBox' will be clamped to zero, and values larger than the native dimensions of the raster image will be clamped to the native width and height respectively. Where no value is readily available (e.g. an SVG file with no 'viewBox' attribute on the outermost 'svg' element) the preserveAspectRatio attribute is ignored, and only the translate due to the 'x' & 'y' attributes of the viewport is used to display the content.

For example, if the image element referenced a PNG or JPEG and preserveAspectRatio="xMinYMin meet", then the aspect ratio of the raster would be preserved (which means that the scale factor from image's coordinates to current user space coordinates would be the same for both X and Y), the raster would be sized as large as possible while ensuring that the entire raster fits within the viewport, and the top/left of the raster would be aligned with the top/left of the viewport as defined by the attributes 'x', 'y', 'width' and 'height' on the 'image' element.  If the value of preserveAspectRatio was 'none' then aspect ratio of the image would not be preserved. The image would be fitted such that the top/left corner of the raster exactly aligns with coordinate (x, y) and the bottom/right corner of the raster exactly aligns with coordinate (x+width,y+height).

The resource referenced by the 'image' element represents a separate document which generates its own parse tree and document object model (if the resource is XML). Thus, there is no inheritance of properties into the image.

Unlike 'use', the 'image' element cannot reference elements within an SVG file.
 

Examples

Live svg testReference imageLegacy behaviour (Batik 1.7)
struct-image-1xx-f.svg.
struct-image-1x1-f.svg.

Open issues

Allowing percentages resolved relative to the native dimensions of a raster image

In some scenarios it may help if it's possible to define the 'viewBox' as percentage values relative to the native dimensions of the raster image.