Modify images on the fly before creating scales

I got the requirement to add an image overlay, sort of what The Guardian is doing on its pictures on Twitter that have a "The Guardian" box on top, to some of the images our users are adding.

As a bonus, not only one overlay image, but actually two, for the big image scales I need to use one overlay image, and fo the smaller ones another one.

I played this afternoon with Pillow and it is really easy to make the composition, now the question comes to: do I need to fork plone.scale (or somewhere else) to do that, or is componetized enough so that I can override the default machinery?

Lastly, I mentioned that only some images need to have these overlay images on top, for that I would need access to the content object itself, not only the image, to decide which kind of overlay to apply.

Any examples or pointers would be greatly appreciated :bowing_man:

Some brainstorming:

  • You could add the images 'another way' (if that is OK for your users to have another way to add images). For example, you could have for example a form that asks for an image and 'constructs' the image by using PIL.

  • You could have an action that adds a watermark (what you call 'box') to the image and 'resaves' it.

  • You could add a view to the image that uses PIL to add the watermark (you will have to disable the 'normal view' (maybe it can be done by having a workflow so the image is not published, but the view shows it 'anyway'.

  • You could have a workflow that adds the watermark.

You should consider if you need the original image 'available' (probably you dont).

If you go for the view, I have some (very) old code that maybe could help a little (it converted a greyscale image to color)

Also: you should google 'PIL add watermark'

@espenmn thanks for the tips an ideas, but our usage is quite specific, so it needs to be completely automatic.

After a few hours of hacking I managed to make a really rough prototype:

Surprisingly it works like a charm for our use case which is to have only the overlay image only when the content object is on a certain workflow state. Image scales get recreated when the object workflow state is changed :tada:

The big downside, is of course, that I had to fork plone.namedfile :slightly_frowning_face:

Does that mean that the overlay should be removed when you change workflow state ?
(if not I think you could just use a script that gets called when changing workflow state ( reading the blob file and resaving it)

PS: If the original image is still there, I think it is possible to get it by using the @@download view

:frowning: yes that is a downside.
Speaking from ignorance here, was there no way to adapt it with the component architecture?

It looks like your working with a browser view, in that case, you could try registering your own @@images browser view that calls your own class with your custom code:

I think adding a browser layer is all you need to ensure that your code "wins". Again, speaking from theory here.

<browser:page
    name="images"
    for=".interfaces.IImageScaleTraversable"
    class=".scaling.ImageScaling"
    allowed_attributes="scale"
    permission="zope2.View"
    layer="my.package.interfaces.override_iimagescaletraversable"
    />

The @@download view will still make it possible to 'steal' the image (if that is what they are afraid of (?))

we're using a different approach to create a featured image for some content that is shared on Twitter using PhantomJS.

you may want to take a look at this:

this, for instance, was created using a background image and some text fields from the content type instance:

ask @rodfersou for details on the implementation.