Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding image masking feature via resources/images/filter.go and mask.go #13106

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

trickkiste
Copy link

Hi there,
I have added an image masking feature to the HUGO image filter stack.

It takes a grayscale mask image (or interprets a color image as such), where black indicates which sections of the base image should become transparent and white the opaque sections.

The mask is resized to the size of the base image. If anybody has a need for applying masks without resizing, please propose how to add such a switch.

Here is an example on how to use this feature:

{{ $base := $.root.Page.Resources.Get .block.image }}
{{ $mask := resources.Get "images/masks/mask3.png" }}
{{ $filter := images.Mask $mask }}
{{ $img := $base.Fill "Center 620x452 png q90 Lanczos" }}
{{ $masked := $img | images.Filter $filter }}

Here is a sample mask image:
mask3

Thank you for your feedback or at best inclusion of my patch.

My kind regards
Markus

@CLAassistant
Copy link

CLAassistant commented Dec 3, 2024

CLA assistant check
All committers have signed the CLA.

@bep
Copy link
Member

bep commented Dec 4, 2024

What's the practical use case(s) for this in a Hugo site?

@trickkiste
Copy link
Author

trickkiste commented Dec 6, 2024

What's the practical use case(s) for this in a Hugo site?

Thank you for your interest. Here is the use case and an example layout:

Some layouts require the editors applying such transparency masks to their images to show up as intended on the website. This of course requires that editors have some basic skills using image editing software like Adobe Photoshop. However, in the majority of scenarios, where you use a CMS like DecapCMS, the people writing your content will not be savvy in Photoshop. Still, you want the layout to just work with any image the editors throw at it.

So this feature allows our editors to upload any image they want and not only is it resized automatically to the dimensions we want but also the transparency mask is automatically applied, so our layout always looks just right!

See an example of this with a demo image here:

Screen Shot 2024-12-06 at 14 51 51

This feature therefore allows for more complex layouts in combination with CMSes available for HUGO. Our layout here for example, can't efficiently work without it.

I hope you find the feature useful and include it in mainline.

My kind regards,
Markus

@bep
Copy link
Member

bep commented Dec 10, 2024

@jmooring what do you think about this? It's obviously useful, but I'm debating about whether this may be better to do in CSS, e.g. https://www.w3schools.com/css/css3_masking.asp

@trickkiste
Copy link
Author

@bep @jmooring I would argue, more capable image manipulation tools in HUGO can hardly hurt. We cannot know all use cases, where this might come in handy.

@bep
Copy link
Member

bep commented Dec 10, 2024

HUGO can hardly hurt

But every new knob in Hugo comes at a cost.

@jmooring
Copy link
Member

jmooring commented Dec 10, 2024

Here's a before and after example with the background color of the body element set to #666.

image

code to generate the above
{{ $pathBase := "images/original.jpg" }}
{{ $pathMask := "images/mask.png" }}

{{ with resources.Get $pathMask }}
  {{ $filter := images.Mask . }}
  {{ with resources.Get $pathBase }}
    {{ with . | images.Filter $filter }}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{ end }}
  {{ else }}
    {{ errorf "Unable to get resource %q" $pathBase }}
  {{ end }}
{{ else }}
  {{ errorf "Unable to get resource %q" $pathMask }}
{{ end }}

So the masking part works, but I think it might be more useful if you could set the canvas color. This would be expressed as an RGB or RGBA hexadecimal color, with a default value of ffffffff (opaque white). A value of ffffff00 makes the canvas transparent. This is how we handle the canvas color with the images.Padding filter.

Please don't spend any time implementing the canvas color option until this proposal is accepted.

It's a nice addition to the filter collection, but I have no idea if anyone will use it.

@bep
Copy link
Member

bep commented Dec 11, 2024

@trickkiste OK; let's add this, but we need an optional color option (default white). So the example above could look like:

{{ $pathBase := "images/original.jpg" }}
{{ $pathMask := "images/mask.png" }}

{{ with resources.Get $pathMask }}
  {{ $opts := dict "color" "#ffffff00" }}
  {{ $filter := images.Mask . $opts }}
  {{ with resources.Get $pathBase }}
    {{ with . | images.Filter $filter }}
      <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
    {{ end }}
  {{ else }}
    {{ errorf "Unable to get resource %q" $pathBase }}
  {{ end }}
{{ else }}
  {{ errorf "Unable to get resource %q" $pathMask }}
{{ end }}

Also, could you add a new Markdown page to the /docs folder in this project as part of this PR.

I will add a basic test as part of #13129

@bep bep modified the milestones: v0.140.0, v0.141.0 Dec 11, 2024
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.

4 participants