|
| 1 | +--- |
| 2 | +html_meta: |
| 3 | + "description": "Image resolution and scaling in Plone Classic UI" |
| 4 | + "property=og:description": "Image resolution and scaling in Plone Classic UI" |
| 5 | + "property=og:title": "Image resolving and scaling" |
| 6 | + "keywords": "Plone, Classic UI, classic-ui, image, resize, scale" |
| 7 | +--- |
| 8 | + |
| 9 | +(classic-ui-images-label)= |
| 10 | + |
| 11 | +# Image handling |
| 12 | + |
| 13 | +The default content types and behaviors use the field `plone.namedfile.NamedBlobImage` for all images. |
| 14 | + |
| 15 | +For this field, image scaling and HTML tag creation is provided by the `plone.namedfile.scaling` module, specifically in the [`ImageScaling`](https://github.com/plone/plone.namedfile/blob/ecf33a2bc7a8c61888909bc383b3e08d80888e43/plone/namedfile/scaling.py#L350) view. |
| 16 | + |
| 17 | +Given a Dexterity content type named `news-item1` with a `plone.namedfile.NamedBlobImage` field named `image`, we can use the following APIs to access the image scales and manage scales. |
| 18 | + |
| 19 | +```{note} |
| 20 | +We will use the image object as context in the following examples. |
| 21 | +``` |
| 22 | + |
| 23 | +(classic-ui-images-default-scales-label)= |
| 24 | + |
| 25 | +## Default scales |
| 26 | + |
| 27 | +In `/@@imaging-controlpanel` Plone allows you to configure which scales are available and what dimensions they should have. By default we have the following scales configured: |
| 28 | + |
| 29 | +* large 768:768 |
| 30 | +* preview 400:400 |
| 31 | +* mini 200:200 |
| 32 | +* thumb 128:128 |
| 33 | +* tile 64:64 |
| 34 | +* icon 32:32 |
| 35 | +* listing 16:16 |
| 36 | + |
| 37 | +You can add or change scales as you like. |
| 38 | + |
| 39 | + |
| 40 | +(classic-ui-images-image-resolving-by-uri-label)= |
| 41 | + |
| 42 | +## Image resolving by URI |
| 43 | + |
| 44 | +Plone can resolve an image scale via URI in different ways. |
| 45 | + |
| 46 | + |
| 47 | +(classic-ui-images-by-field-and-scale-name-label)= |
| 48 | + |
| 49 | +### By field and scale name |
| 50 | + |
| 51 | +Given our `news-item1` with the field `image`, we can get the name scale `thumb` as follows: |
| 52 | + |
| 53 | +`http://localhost:8080/Plone/news-item1/@@images/image/thumb` |
| 54 | + |
| 55 | +To get the original image, you can leave out the scale: |
| 56 | + |
| 57 | +`http://localhost:8080/Plone/news-item1/@@images/image` |
| 58 | + |
| 59 | + |
| 60 | +(classic-ui-images-by-cacheable-scale-uid-name-label)= |
| 61 | + |
| 62 | +### By cacheable scale UID name |
| 63 | + |
| 64 | +When an image scale is created, it will be cached under the name `UID.EXT` (i.e. `f4c34254b44ba351af7393bfe0296664.jpeg`) in the object annotations. |
| 65 | +Scaling keeps the uploaded formats, except for TIFF which ends up as JPEG. |
| 66 | +It can be resolved as follows: |
| 67 | + |
| 68 | +`http://localhost:8080/Plone/news-item1/@@images/3d182f34-8773-4f20-a79d-8774c3151b7e.jpeg` |
| 69 | + |
| 70 | +This is useful for caching URLs in Varnish or the browser. |
| 71 | +In case the uploaded image or scale definitions have changed, they will be saved again under a different UID. |
| 72 | +This changes the URL and forces either the browser, or a cache proxy such as Varnish, to fetch it again. |
| 73 | + |
| 74 | + |
| 75 | +(classic-ui-images-image-tag-label)= |
| 76 | + |
| 77 | +## Image tag |
| 78 | + |
| 79 | +To get an HTML tag for a scaled image, you can use the `ImageScaling` view as follows: |
| 80 | + |
| 81 | +```python |
| 82 | +from plone import api |
| 83 | + |
| 84 | +scale_util = api.content.get_view("images", context, request) |
| 85 | +tag = scale_util.tag("image", scale="mini") |
| 86 | +``` |
| 87 | + |
| 88 | +To get a specific image size: |
| 89 | + |
| 90 | +```python |
| 91 | +from plone import api |
| 92 | + |
| 93 | +scale_util = api.content.get_view("images", context, request) |
| 94 | +tag = scale_util.tag("image", width="600", height="200") |
| 95 | +``` |
| 96 | + |
| 97 | +The complete list of arguments with their default values is shown in the following example. |
| 98 | + |
| 99 | +```python |
| 100 | +from plone import api |
| 101 | + |
| 102 | +scale_util = api.content.get_view("images", context, request) |
| 103 | +tag = scale_util.tag( |
| 104 | + fieldname=None, |
| 105 | + scale=None, |
| 106 | + height=None, |
| 107 | + width=None, |
| 108 | + direction="thumbnail" |
| 109 | +) |
| 110 | +``` |
| 111 | + |
| 112 | +If you pass additional kwargs to `tag`, they become attributes on `tag`. |
| 113 | + |
| 114 | + |
| 115 | +(classic-ui-images-image-scaling-no-tag-creation-label)= |
| 116 | + |
| 117 | +## Image scaling without tag creation |
| 118 | + |
| 119 | +To get the scaling information only without creating an HTML tag, you can use the `ImageScaling` view as follows: |
| 120 | + |
| 121 | +```python |
| 122 | +from plone import api |
| 123 | + |
| 124 | +scale_util = api.content.get_view("images", context, request) |
| 125 | +# The default `Image` content type's field name is "image". |
| 126 | +# On the following line of code, "image" is the field name. |
| 127 | +image_scale = scale_util.scale("image", scale="mini") |
| 128 | +print(image_scale.url) |
| 129 | +print(image_scale.width) |
| 130 | +print(image_scale.height) |
| 131 | +``` |
| 132 | + |
| 133 | +This will produce the following output: |
| 134 | + |
| 135 | +```console |
| 136 | +http://localhost:8080/Plone/news-item1/@@images/3d182f34-8773-4f20-a79d-8774c3151b7e.jpeg |
| 137 | +200 |
| 138 | +110 |
| 139 | +``` |
| 140 | + |
| 141 | +The most important properties are the following: |
| 142 | + |
| 143 | +- `data` |
| 144 | +- `fieldname` |
| 145 | +- `height` |
| 146 | +- `mimetype` |
| 147 | +- `srcset` |
| 148 | +- `srcset_attribute` |
| 149 | +- `tag` |
| 150 | +- `uid` |
| 151 | +- `url` |
| 152 | +- `width` |
| 153 | + |
| 154 | +You can directly create an HTML tag from `image_scale`: |
| 155 | + |
| 156 | +```pycon |
| 157 | +>>> print(image_scale.tag()) |
| 158 | + |
| 159 | +<img src="http://localhost:8080/Plone/news/newsitem1/@@images/9f676d46-0cb3-4512-a831-a5db4079bdfa.jpeg" alt="News Item 1!" title="News Item 1" height="21" width="32" srcset="http://localhost:8080/Plone/news/newsitem1/@@images/4a68513c-cffd-4de0-8a35-80627945b80f.jpeg 2x, http://localhost:8080/Plone/news/newsitem1/@@images/c32929c6-cb89-4ce7-846f-38adf29c09a4.jpeg 3x" /> |
| 160 | +``` |
| 161 | + |
| 162 | +Instead of using the configured named scales, you can get an HTML tag with any specific size in pixels: |
| 163 | + |
| 164 | +```python |
| 165 | +from plone import api |
| 166 | + |
| 167 | +scale_util = api.content.get_view("images", context, request) |
| 168 | +tag = scale_util.scale("image", width="600", height="200") |
| 169 | +``` |
| 170 | + |
| 171 | +(classic-ui-images-using-image_scale0-in-templates-label)= |
| 172 | + |
| 173 | +### Using image_scale in templates |
| 174 | + |
| 175 | +You could use the URL-variant from above, but that would be an uncached version. |
| 176 | +To create a cached scale in a page template you can do the following: |
| 177 | + |
| 178 | +```xml |
| 179 | +<div tal:define="scale_view context/@@images; |
| 180 | + image_scale python: scale_view.scale('image', 'mini')"> |
| 181 | + <img |
| 182 | + src="${python: image_scale.url}" |
| 183 | + width="${python: image_scale.width" |
| 184 | + height="${python: image_scale.height}" |
| 185 | + > |
| 186 | +</div> |
| 187 | +``` |
| 188 | + |
| 189 | +Or you can get the HTML tag back, and replace the current tag with it: |
| 190 | + |
| 191 | +```xml |
| 192 | +<div tal:define="scale_view context/@@images"> |
| 193 | + <img tal:replace="structured python: scale_view.tag('image', 'mini')"> |
| 194 | +</div> |
| 195 | +``` |
| 196 | + |
| 197 | +You can also provide the following keyword arguments to set `title`, `alt`, or `css_class` for the generated tag: |
| 198 | + |
| 199 | +```xml |
| 200 | +<div tal:define="scale_view context/@@images"> |
| 201 | + <img tal:replace="structured python: scale_view.tag('banner', 'mini', title='The Banner', alt='Alternative text', css_class='banner')"> |
| 202 | +</div> |
| 203 | +``` |
| 204 | + |
| 205 | +(classic-ui-images-get-image_scale-by-cached-uid-name-label)= |
| 206 | + |
| 207 | +### Get image_scale by cached UID name |
| 208 | + |
| 209 | +If you only have the cached image name from an URL and need to get the image scale, unfortunately you can't use restrictedTraverse(), as this will not be able to resolve the scale. But you can use this workaround, by calling the `publishTraverse` method in `ImageScaling` directly: |
| 210 | + |
| 211 | +```python |
| 212 | +import re |
| 213 | +from plone import api |
| 214 | + |
| 215 | +uri = "http://localhost:8080/Plone/news-item1/@@images/3d182f34-8773-4f20-a79d-8774c3151b7e.jpeg" |
| 216 | +image_url = re.compile(r"(.*@@images)\/([a-zA-Z0-9.-]*)\/?([a-zA-Z]*)") |
| 217 | + |
| 218 | +url_match = image_url.match(uri) |
| 219 | +groups = url_match.groups() |
| 220 | +# ("http://localhost:8080/Plone/news-item1", "3d182f34-8773-4f20-a79d-8774c3151b7e.jpeg") |
| 221 | +scale_util = api.content.get_view("images", context, request) |
| 222 | +image_scale = scaling_util.publishTraverse(context.REQUEST, groups[1]) |
| 223 | +``` |
| 224 | + |
| 225 | + |
| 226 | +(classic-ui-images-scaling-direction-label)= |
| 227 | + |
| 228 | +## Scaling `direction` |
| 229 | + |
| 230 | +The default direction is `thumbnail`. |
| 231 | + |
| 232 | +Other options are: |
| 233 | + |
| 234 | +* `down` |
| 235 | +* `keep` |
| 236 | +* `scale-crop-to-fill` |
| 237 | +* `scale-crop-to-fit` |
| 238 | +* `thumbnail` |
| 239 | +* `up` |
| 240 | + |
| 241 | + |
| 242 | +(classic-ui-images-permissions-label)= |
| 243 | + |
| 244 | +## Permissions |
| 245 | + |
| 246 | +The `ImageScaling` view explicitly checks the permissions of the current user. |
| 247 | +To access image scales, which are normally not accessible to the current user, override the `validate_access` method in `plone.namedfile.scaling.ImageScale`. |
0 commit comments