Conversation
scaleImage(..., target_format="AVIF") encodes a scale in another format than the original, animations included where the target supports them. pre_scale reports the target format's mimetype, so stable scale URLs get the right extension before the scale exists. AVIF uploads keep their format when scaled instead of becoming JPEG.
|
@MrTango thanks for creating this Pull Request and helping to improve Plone! TL;DR: Finish pushing changes, pass all other checks, then paste a comment: To ensure that these changes do not break other parts of Plone, the Plone test suite matrix needs to pass, but it takes 30-60 min. Other CI checks are usually much faster and the Plone Jenkins resources are limited, so when done pushing changes and all other checks pass either start all Jenkins PR jobs yourself, or simply add the comment above in this PR to start all the jobs automatically. Happy hacking! |
Plain scales of an AVIF upload are JPEG (PNG with alpha, first frame of an animation), so browsers without AVIF support can show them. pre_scale reports image/jpeg for them.
|
Since I support AVIF in plone-pgthumbor I was curious if you run into the very same problems. It follows my AI-assistet analysis CMYK sources produce AVIF files Chrome refuses to decode
Repro on this branch: import io
from PIL import Image, ImageCms
from plone.scale.scale import scaleImage
data = open("src/plone/scale/tests/data/cmyk.jpg", "rb").read()
out, _, _ = scaleImage(data, 300, 300, target_format="AVIF")
icc = Image.open(io.BytesIO(out)).info["icc_profile"]
print(ImageCms.ImageCmsProfile(io.BytesIO(icc)).profile.xcolor_space) # 'CMYK'Open the resulting file in Chrome: broken image. Combined with plone/plone.namedfile#228, where the AVIF Thumbor's PIL engine hit the same thing and converts to sRGB before encoding AVIF (see the comment in Smaller things
Assisted-by: Claude Fable 5.1 |
Scales of CMYK images were converted with a plain mode conversion and still carried the CMYK profile, now attached to RGB pixels. Browsers ignore that in a JPEG, but Chrome refuses to decode such an AVIF, and every scale of a print image carried the profile's half megabyte. The conversion now goes through the embedded profile, after scaling as it costs per pixel, and yields an sRGB profile. At save time a profile is only embedded when its color space matches the pixels, which also covers scales that became greyscale.
Guessing JPEG for the plain scale of an AVIF original is wrong when the fallback needs alpha and becomes PNG, and it duplicated the format policy of scaleImage in the storage. As for any other format that is re-encoded, the scale reports its real mimetype once generated.
At Pillow's default speed 6, encoding a 2000 px image as AVIF takes about four times as long as at speed 8, for the same file size. The parameter lets callers make that trade-off.
|
@jensens thx, i addressed it now. |
Scaling only changes the format of an AVIF original when target_format says so, like for PNG and WEBP originals. The JPEG fallback for browsers without AVIF support is requested by plone.namedfile in its avif_with_fallback mode; in its disabled mode nothing is converted.
scaleImage(..., target_format="AVIF")encodes a scale in another format than the original, animations included where the target supports them.pre_scalereports the target format's mimetype, so stable URLs of such scales get the right extension before the scale exists.speedpasses the AVIF encoder's trade-off between encoding time and file size.Plain scales of AVIF originals are JPEG (PNG with alpha): the fallback for browsers without AVIF support, next to the AVIF twins plone.namedfile#228 generates.
Scales of CMYK images are converted to sRGB through their embedded profile, and a scale only embeds a profile that matches its pixels. A CMYK profile on RGB pixels made AVIF scales undecodable in Chrome and added half a megabyte to every scale of a print image.
Needs:
plone/plone.outputfilters#116
plone/plone.namedfile#228
plone/plone.formwidget.namedfile#109
plone/plone.app.upgrade#387
plone/plone.base#137
and:
plone/plone.app.linkintegrity#129
or for 6.2
plone/plone.app.linkintegrity#131
the PLIP for this is here: plone/Products.CMFPlone#4384