djangodjango-imagekit

(Django) How to transfer value from field to the custom ImageKit processor inside the model?


I use Django ImageKit to process/crop uploaded photos. I added my own custom processor to add text to the photo (like watermark):

# ./example/processors.py

from django.conf import settings
from PIL import Image, ImageDraw, ImageFont

_default_font = ImageFont.truetype(settings.TEXT_OVERLAY_FONT_REGULAR, 24)


def add_text_overlay(image, text, font=_default_font):
    rgba_image = image.convert('RGBA')
    text_overlay = Image.new('RGBA', rgba_image.size, (255, 255, 255, 0))

    image_draw = ImageDraw.Draw(text_overlay)
    text_size_x, text_size_y = image_draw.textsize(text, font=font)
    text_xy = ((rgba_image.size[0] / 2) - (text_size_x / 2), (rgba_image.size[1] / 2) - (text_size_y / 2))

    image_draw.text(text_xy, text, font=font, fill=(255, 255, 255, 255))
    image_with_text_overlay = Image.alpha_composite(rgba_image, text_overlay)

    return image_with_text_overlay


class TextOverlayProcessor(object):
    def __init__(self, text='Lorem ipsum dolor sit amet'):
        """
        :param text: The overlay text, string.

        """
        self.text = text

    def process(self, img):
        return add_text_overlay(image=img, text=self.text)

But how to transfer value from field to the custom ImageKit processor inside the model? Something like this:

# ./example/models.py

from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
from .processors import TextOverlayProcessor


class Example(models.Model):
    description = models.CharField('Description', ...)
    image = models.ImageField('Picture', default=None)

    image_800x800 = ImageSpecField(
        source='image',
        processors=[
            ResizeToFill(800, 800), 
            TextOverlayProcessor(text=self.description) # but `self` is wrong and raise error
        ], 
        format='JPEG',
        options={'quality': 100}
    )
    ...

I will be glad to explanatory comments and/or use cases.


Solution

  • The short answer is https://stackoverflow.com/a/27914831/6543526

    From official docs:

    Often, when using an ImageSpecField, you may want the spec to vary based on properties of a model. (For example, you might want to store image dimensions on the model and then use them to generate your thumbnail.) Now that we know how to access the source image from our spec, it’s a simple matter to extract its model and use it to create our processors list. In fact, ImageKit includes a utility for getting this information.