django-imagekit
django-imagekit copied to clipboard
How to add watermark and create thumbnail without watermark?
I need to fit user uploaded image to 1000px and put a watermark. Also I need to create thumbnail (without watermark).
class Photo(models.Model):
image = ProcessedImageField(upload_to='photo',
processors=[
ResizeToFit(1000, 1000, upscale=False),
Watermark(),
],
format='JPEG')
thumbnail = ImageSpecField(source='image',
processors=[
ResizeToFill(200, 200),
],
format='JPEG')
The trouble is that the thumbnail is created from the already processed image. How to create a thumbnail from the original image, given that the original image should not be saved?
When i trying
def save(self, *args, **kwargs):
self.thumbnail.generate()
super(Photo, self).save(*args, **kwargs)
it raises exception "I/O operation on closed file".
In order to generate thumbnails without watermark with ImageSpecField
you need to have somewhere the original image. If your reason to not want the original image be saved is for security (someone not to guess the path to original image) you can use different storage and save originals outside MEDIA_ROOT
.
If you do not want to store the original to save space then probably will be better to create the watermark in the form directly with pilkit
(django-imagekit
is using it under the hood) and assign it to the normal ImageField
(You don't want ImageSpecField
, because this is not a real field and you need the orignal to be available all the time because cached thumbnails can be deleted and django-imagekit need to recreate them on request). I know that it is not ideal but you can try.
so did you actually solve it (the whole thing?) Because I actually need the exact same thing
Unfortuanly I have no find solution with django-imagekit
or easy_thumbnails
, so I wrote model save handler using pilkit
:
from pilkit.processors import ProcessorPipeline, Transpose, ResizeToFit, ResizeToFill
class Photo(models.Model):
item = models.ForeignKey(Item)
image = RestrictedImageField(upload_to=get_image_filename)
preview = models.ImageField(upload_to=get_preview_filename, blank=True)
thumbnail = models.ImageField(upload_to=get_thumbnail_filename, blank=True)
def _img_to_field(self, im, quality=80):
"""
Saves Pillow image to model field as JPEG.
"""
buffer = BytesIO()
im.save(buffer, format='JPEG', quality=quality)
return InMemoryUploadedFile(buffer, None, self.image.name, 'image/jpeg', buffer.getbuffer().nbytes, None, None)
def save(self, *args, **kwargs):
# New file uploaded
if isinstance(self.image.file, UploadedFile):
with Image.open(self.image.file) as uploaded_image:
# White background for semi-transparent images
if uploaded_image.mode == 'RGBA':
background = Image.new('RGB', uploaded_image.size, (255, 255, 255))
background.paste(uploaded_image, mask=uploaded_image.split()[3])
uploaded_image = background
if uploaded_image.mode != 'RGB':
uploaded_image = uploaded_image.convert('RGB')
logo_path = os.path.join(settings.BASE_DIR, 'classifieds/watermark.png')
logo = Image.open(logo_path)
image = ProcessorPipeline([
Transpose(), # EXIF rotate
ResizeToFit(1200, 1200, upscale=False),
]).process(uploaded_image)
image = watermark(image, logo, (image.width - logo.width - 20,
image.height - logo.height - 20), opacity=0.5)
self.image = self._img_to_field(image)
thumbnail = ProcessorPipeline([
Transpose(),
ResizeToFill(240, 180),
]).process(uploaded_image)
self.thumbnail = self._img_to_field(thumbnail)
preview = ProcessorPipeline([
Transpose(),
ResizeToFill(500, 375),
]).process(uploaded_image)
preview = watermark(preview, logo, (preview.width - logo.width - 20,
preview.height - logo.height - 20), opacity=0.5)
self.preview = self._img_to_field(preview)
super(Photo, self).save(*args, **kwargs)
RestrictedImageField is models.ImageField with size and formats validating, watermark module - http://code.activestate.com/recipes/362879-watermark-with-pil/
Fields: original image & watemark & thumbnail without watermark
class Photo(models.Model):
original_img = ProcessedImageField(upload_to='photo',
processors=[
ResizeToFit(1000, 1000, upscale=False),
],
format='JPEG')
image = ImageSpecField(source='original_img',
processors=[
ResizeToFit(1000, 1000, upscale=False),
Watermark(),
],
format='JPEG')
thumbnail = ImageSpecField(source='original_img',
processors=[
ResizeToFill(200, 200),
],
format='JPEG')
class Watermark(object): def process(self, image): # Code for adding the watermark goes here. return image
class Photo(models.Model): original_image = models.ImageField(upload_to='photos') watermarked_image = ImageSpec([Watermark()], image_field='original_image', format='JPEG', options={'quality': 90})_