Skip to content

Add perceptual compression to process_image#3118

Draft
BezPowell wants to merge 1 commit into
getzola:nextfrom
BezPowell:perceptual-image
Draft

Add perceptual compression to process_image#3118
BezPowell wants to merge 1 commit into
getzola:nextfrom
BezPowell:perceptual-image

Conversation

@BezPowell
Copy link
Copy Markdown
Contributor

IMPORTANT: Please do not create a Pull Request adding a new feature without discussing it first.

The place to discuss new features is the forum: https://zola.discourse.group/
If you want to add a new feature, please open a thread there first in the feature requests section.

Sanity check:

  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

Code changes

(Delete or ignore this section for documentation changes)

  • Are you doing the PR on the next branch?

If the change is a new feature or adding to/changing an existing one:

  • Have you created/updated the relevant documentation page(s)?

This draft pr is an alternative implementation of perceptual image compression to #3113. Instead of adding perceptual compression as a post-processing step as the previous pr does, this incorporates it directly into the process_image function.

How it works?

A new image_encoders section is added to the site config. This allows configuration minimum and maximum quality values per image format, as well as the number of binary search 'iterations' to make when doing perceptual compression:

[image_encoders]
jpeg = { min_quality = 30, max_quality = 95 }
webp = { min_quality = 20, encode_iterations = 4 }

This global encoder configuration is then passed to the function performing enqueued image processing functions. When encoding images, a check is made: if there is no global configuration for that format, Zola's default image encoding code is used. Otherwise, if there is a global configuration for the relevant format, that is used to run perceptual image encoding, with the passed quality level used to infer the target DSSIM value.

In the example above, any calls to process_image in templates that set format to jpeg or webp would use perceptual encoding with the configured min, max, and iterations values. Any calls to process_image in templates that set format to png or avif, however, would continue to use Zola's existing image encoding (i.e. single pass at the configured quality level).

Pros of this approach

  • Output format and quality can be set on an image by image basis: While global min and max values are set in config.toml (to avoid over cluttering process_image with multiple new parameters), the target quality can still be configured per image.
  • Less duplication: Compressed images are output to the existing processed_images folder.
  • Ability to preview images: As perceptual compression is done at build-time, users can see the final images when developing the site from serve.

Cons of this approach

  • Slower serve: As perceptual compression is run regardless of build command, processing images for serve is considerably slower using this method.
  • Identical file hashes: As ImageOp parameters are untouched with this method, the hash of files encoded via the new method is identical to those of the same quality level without the global config. Users wanting to quickly update all images to the new format would currently have to deleted processed_images for the changes to take effect.

My thoughts

In my opinion, this method of adding support for perceptual image compression if less invasive to Zola's existing code base, and should make it easier for users to add to existing sites (just add a line to config.toml, no need to also update any calls to process_image to change quality). However, it does substantially slow down image processing, which could be significant for those wishing a quick iteration time using serve. Furthermore, as the pr currently stands, perceptually compressed and non-compressed images have identical hashes. This would probably need to be overcome for the feature to be more useful.

@Keats
Copy link
Copy Markdown
Collaborator

Keats commented Mar 16, 2026

I have seen that, and the other PR but I don't have time right now to review properly. I will do so ASAP

@BezPowell
Copy link
Copy Markdown
Contributor Author

@Keats Sorry for the delay in responding. I've just moved house, which was far more difficult than originally envisaged, so haven't had any free time for a while - I totally understand!

Once you have had time to look at both options, please let me know your thoughts. I'm still keen to add this as, if we can iron out some of the problems with either approach, I think it would be a really useful feature and something (as far as I am aware) no other SSG lets you do 'out of the box'. I have used a post-processing script (imagemin) in the past, but haven't yet figured out how to avoid running it every time the site is published. If we could add something to Zola that allows us to utilise the build cache it would speed up subsequent publishes enormously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants