A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

Overview

django-versatileimagefield

Github Actions Status Coverage Status Latest Version

A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creating new images from the one assigned to the field.

Click here for a quick overview of what it is, how it works and whether or not it's the right fit for your project.

Compatibility

  • Python:
    • 3.6
    • 3.7
    • 3.8
    • 3.9
  • Django:
    • 2.0.x
    • 2.1.x
    • 2.2.x
    • 3.0.x
    • 3.1.x
    • 3.2.x

NOTE: Python 3.6 does not have support for Django <= 1.x.

NOTE: The 1.4 release dropped support for Django 1.5.x & 1.6.x.

NOTE: The 1.7 release dropped support for Django 1.7.x.

NOTE: The 2.1 release dropped support for Django 1.9.x.

Documentation

Full documentation available at Read the Docs.

Code

django-versatileimagefield is hosted on github.

Running Tests

If you're running tests on Mac OSX you'll need libmagic installed. The recommended way to do this is with homebrew:

$ brew install libmagic

Note: Some systems may also be necessary to install the non-python Pillow build dependencies.

You'll also need tox:

$ pip install tox

To run the entire django-versatileimagefield test matrix, that is, run all tests on all supported combination of versions of python, django and djangorestframework:

$ tox

If you just want to run tests against a specific tox environment first, run this command to list all available environments:

$ tox -l

Then run this command, substituting {tox-env} with the environment you want to test:

$ tox -e {tox-env}
Comments
  • Trying to get this to work with django-storages

    Trying to get this to work with django-storages

    I'm using Google Cloud Storage to serve up images.

    class PhotoSerializer(serializers.ModelSerializer, TaggitSerializer):
        owner = serializers.CharField(source='owner.username', read_only=True)
        tags = TagListSerializerField()
        photo = VersatileImageFieldSerializer(
             sizes=[
                ('full_size', 'url'),
                ('thumbnail', 'thumbnail__250x250')
            ]
        )
    

    When I try to upload images from my front end, I am getting errors like this:

    google.cloud.exceptions.NotFound: 404 File does not exist: __sized__/img/u/1/pexels-photo-thumbnail-250x250-70.jpg

    opened by EvanZ 12
  • Support WEBP sizers and filters

    Support WEBP sizers and filters

    Adding support for WEBP resizing. This is an issue presented by some users and happened with me. Currently, trying to resize WEBP images results in some errors. This PR fixes them.

    Fixes #151

    opened by iamjazzar 11
  • Fixed usage with cloud storage backends

    Fixed usage with cloud storage backends

    Some (all?) cloud storage backends won't provide a URL for a file that doesn't yet exist. This fixes that but attempting to get a resized_url, but if it fails, we create the resized_image first, and then grab it's url.

    opened by camflan 11
  • Still show the widget even if thumbnailing fails/crashes

    Still show the widget even if thumbnailing fails/crashes

    When an image is not uploaded completely the sizers crash. This has been discussed several times before (resp. crashes when the image file does not exist etc.), and fixes have been rejected. (I do not fully agree with the resolution, but that's not the point of this pull request.)

    However, it should still be possible to remove or replace these files again. The current implementation which calls .thumbnail['300x300'] prevents this by causing the whole fieldset containing the versatile image field admin widget to disappear.

    opened by matthiask 11
  • Cleaner processed filenames using hash of options?

    Cleaner processed filenames using hash of options?

    We would like to cleanup the generated thumbnail paths/filenames.

    By default DVIF will generate a long concatenation of all the filters and parameters used to generate the image in a human readable but a little messy looking URL (many segments with double underscores, numbers, dots and dashes). Since some of our image URL's are somewhat visible to our users we'd like to clean this up if possible.

    Our existing thumbnailer (an old easythumbnails hackjob) also did this, but we've added a simple hashing function that takes the options concatenation and hashes it to make a compact chunky block of characters.

    Because it uses a hashing function it is still generating unique names for each combination of options.

    // so instead of something like this:
    thumbs/images/foo-desaturate__75__fancify-0-7__1-23-crop-c0-75__0-25-400x400.jpg
    
    // get something like this
    thumbs/images/foo-ff8765ab-400x400.jpg
    

    In our existing site we use an md5 binary hash encoded in (crockford) base32 alphabet and trimmed for length. These are fairly compact string (unlike hex) but non-scary (no casing or specials chars).

    Maybe DVIF could provide an option to have the user supply a hashing function like this? Could be a simple dot-separated path to an importable callback so people can bring their own hashers.

    opened by Bartvds 11
  • delete_sized_images() fails with custom upload_to

    delete_sized_images() fails with custom upload_to

    I have a custom upload_to path:

    def file_name(instance, path):
        filename = os.path.basename(path)
        sepFilename = os.path.splitext(filename)
        newFilename = slugify(sepFilename[0]) + sepFilename[1]
        year = str(instance.album.year)
        album_slug = instance.album.slug
    
        return '/'.join([year, album_slug, newFilename])
    
    #...
    
    class Image(BaseMedia):
        file = VersatileImageField(upload_to=file_name)
        #...
    

    When I run delete_sized_images() the files are not deleted. The problem is the custom path is both appended by get_sized_root_folder() and prepended by sizer_regex.

    Example:

    def delete_sized_images(self):
        #...
        print(self.get_sized_root_folder()) # __sized__/2015/sd/
        print(self.sizer_regex.pattern)     # 2015/sd/g0043229-(thumbnail|crop)-(\d+)x(\d+)(?:-\d+)?.JPG
        #...
    

    Thank you for your time.

    opened by neic 8
  • ValueError at ... The file cannot be reopened.

    ValueError at ... The file cannot be reopened.

    I'm using PPOIField, but when I save (using the admin) an exception is raised in /versatileimagefield/forms.py when data.open() is called.

    My images are saved from external urls to s3, maybe this info and this link are useful.

    Django==1.8.11
    boto==2.39.0
    django-s3-storage==0.9.8
    django-versatileimagefield==1.3
    
    opened by fabiocaccamo 8
  • Image format conversions

    Image format conversions

    Hi, we're using versatile image field to feed a PWA. We'd like to be able to provide images in different formats as well. For example, browsers that support webp would request the images in webp, while primitive ones like Safari can fall back to png.

    We'd like to know if this is achievable through custom sizers and filters. If so, could you give us a simple example?

    Our plan B is to use PIL to generate multiple formats on upload. The different formats are then saved each in a versatile image field. For this to work, we'll need to know what image formats are supported. WebP doesn't seem to appear in the list here for example https://django-versatileimagefield.readthedocs.io/en/latest/writing_custom_sizers_and_filters.html#pre-processor-naming-convention

    opened by khalibloo 7
  • Remove deprecation warning on Django 2.0 and newer

    Remove deprecation warning on Django 2.0 and newer

    Latest Pytest throws deprecation warnings into the console, this PR gets rid of one of them. context keyword argument of from_db_value was dropped in Django 2.0 and will be deprecated in Django 3.0

    opened by Pacu2 7
  • ValueError in django/forms/fields.py when editing an Object that uses VersatileImageField

    ValueError in django/forms/fields.py when editing an Object that uses VersatileImageField

    Django raises an ValueError when I edit an object which uses the VersatileImageField. Creating the object is no problem. Whether the VersatileImageField uses a ppoi or not does not matter. Switching back to the default ImageField solves the problem. I also removed the cache settings in VERSATILEIMAGEFIELD_SETTINGS (does that actually deactivate the cache?)

    Django Version: 1.7 Python Version: 2.7.6 Installed Applications:

    ('django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'core',
     'versatileimagefield')
    

    Installed Middleware:

    ('django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware')
    

    Traceback:

    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
      111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
      567.                 return self.admin_site.admin_view(view)(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
      105.                     response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
      52.         response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
      204.             return view(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
      1440.         return self.changeform_view(request, object_id, form_url, extra_context)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
      29.             return bound_func(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
      105.                     response = view_func(request, *args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
      25.                 return func.__get__(self, type(self))(*args2, **kwargs2)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/db/transaction.py" in inner
      394.                 return func(*args, **kwargs)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
      1394.                     change_message = self.construct_change_message(request, form, formsets)
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/contrib/admin/options.py" in construct_change_message
      972.         if form.changed_data:
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/forms.py" in changed_data
      440.                 elif field._has_changed(initial_value, data_value):
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/fields.py" in _has_changed
      1082.             if field._has_changed(field.to_python(initial), data):
    File "/Users/Gregor/Projekte/adClouds/www/venv/lib/python2.7/site-packages/django/forms/fields.py" in to_python
      652.                 file = BytesIO(data.read())
    
    Exception Type: ValueError at /admin/core/cinema/1/
    Exception Value: I/O operation on closed file
    
    opened by gregorvolkmann 7
  • Django 3 doesn't contain 'six' anymore

    Django 3 doesn't contain 'six' anymore

    See https://docs.djangoproject.com/en/3.0/releases/3.0/#removed-private-python-2-compatibility-apis

      File "/home/tic/Development/karrot-docker/karrot-backend/karrot/groups/models.py", line 13, in <module>
        from versatileimagefield.fields import VersatileImageField
      File "/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/versatileimagefield/fields.py", line 12, in <module>
        from .files import VersatileImageFieldFile, VersatileImageFileDescriptor
      File "/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/versatileimagefield/files.py", line 9, in <module>
        from django.utils import six
    ImportError: cannot import name 'six' from 'django.utils' (/home/tic/Development/karrot-docker/karrot-backend/env/lib/python3.7/site-packages/django/utils/__init__.py)
    
    opened by tiltec 6
  • Question: Crop as circle

    Question: Crop as circle

    Hi, is there a possibility to make a circle version of a image, it will be really usefull when u work with agm-map directive on angular and u dont have control about the image icon.

    opened by breakiboy 0
  • Deleted unnecessary default_app_config settings starting with django3.2

    Deleted unnecessary default_app_config settings starting with django3.2

    Warning problem solving python3.9/site-packages/django/apps/registry.py:91: RemovedInDjango41Warning: 'versatileimagefield' defines default_app_config = 'versatileimagefield.apps.VersatileImageFieldConfig'. Django now detects this configuration automatically. You can remove default_app_config.

    opened by LeeHanYeong 0
  • Question: is it possible to use this app with static files?

    Question: is it possible to use this app with static files?

    Hi all,

    this is a question, not an issue. Is it possible to use this app with static files?

    Something like generating thumbnail from a file path.

    Thank you

    opened by carlotm 0
  • VersatileImageFieldWarmer regenerate images for delete rendition key set

    VersatileImageFieldWarmer regenerate images for delete rendition key set

    Image are initially created with proper rendition key set.

    warmer = VersatileImageFieldWarmer(
                            instance_or_queryset=queryset,
                            rendition_key_set=[('large_horiz', 'crop__1200x600')],
                            image_attr=field,
                            verbose=True,
                        )
    warmer.warm()                  
    

    Then, when rendition set sized images are deleted from media/__sized__/ re-running warm doesn't create new image but if we change rendition_key_set to rendtion_key_set=[[('large_horiz', 'crop__1250x600')] images are created. Even when we run delete_sized_images, delete_all_created_images, delete_filtered_images, delete_filtered_sized_images and delete_sized_images. Images are not regenerated

    opened by roshanshrestha01 0
  • Deleting all created images for the image without extension fails

    Deleting all created images for the image without extension fails

    When trying to delete all created images with the use of delete_all_created_images method I get the AssertionError. I find out that the sized images are created with extension jpg when the base image is without extension. It causes an error during deletion as the algorithm is looking for a file with the same extension as the base one.

    Steps to reproduce:

    1. Save in VersatileImageField file without extension in the name.
    2. Create some thumbnails.
    3. Try to remove all created images with the use of delete_all_created_images.
    4. You will get the AssertionError.
    opened by IKarbowiak 0
A utility for quickly cropping large collections of images.

Crop Tool A utility for quickly cropping large collections of images. Inspired by Derrick Schultz's dataset-tools. Setup It's suggested that you use A

dusk (they/them) 6 Nov 14, 2021
Tool made for the FWA Yearbook Team to resize multiple images quickly.

ImageResize Tool Tool made for the FWA Yearbook Team to resize multiple images quickly. Make sure to check this repo for future updates How to Use The

LGobin 1 Jan 7, 2022
Easily turn large sets of image urls to an image dataset. Can download, resize and package 100M urls in 20h on one machine.

img2dataset Easily turn large sets of image urls to an image dataset. Can download, resize and package 100M urls in 20h on one machine. Also supports

Romain Beaumont 1.4k Jan 1, 2023
Random collage/montage generator with drop-shadow

Random Collage Example Usage These are the sample input files in $PWD for the below examples: 1.png 2.png 3.png 4.png 5.png 6.png 7.png 8.png 9.png 10

M B 1 Dec 7, 2021
Django helper application to easily and non-destructively crop arbitrarily large images in admin and frontend.

django-image-cropping django-image-cropping is an app for cropping uploaded images via Django's admin backend using Jcrop. Screenshot: django-image-cr

Jonas und der Wolf GmbH 546 Jan 3, 2023
💯 Watermark your images with one line of command

Watermarker ?? Watermark your images with one line of command ?? $ pip3 install

Orhan Emre Dikicigil 3 May 1, 2022
An python script to convert images to upscaled versions made out of one-colour emojis.

ABOUT This is an python script to convert png, jpg and gif(output isnt animated :( ) images to scaled versions made out of one-colour emojis. Please n

null 0 Oct 19, 2022
Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image

Face-Detacher Quickly 'anonymize' all people in an image. This script will put a black bar over all eye-pairs in an image This is a small python scrip

Don Cato 1 Oct 29, 2021
missing-pixel-filler is a python package that, given images that may contain missing data regions (like satellite imagery with swath gaps), returns these images with the regions filled.

Missing Pixel Filler This is the official code repository for the Missing Pixel Filler by SpaceML. missing-pixel-filler is a python package that, give

SpaceML 11 Jul 19, 2022
Python framework for creating and scaling up production of vector graphics assets.

Board Game Factory Contributors are welcome here! See the end of readme. This is a vector-graphics framework intended for creating and scaling up prod

Adam Volný 5 Jul 13, 2022
Small wrapper around 3dmol.js and html2canvas for creating self-contained HTML files that display a 3D molecular representation.

Description Small wrapper around 3dmol.js and html2canvas for creating self-contained HTML files that display a 3D molecular representation. Double cl

David Meijer 1 Dec 2, 2021
Typesheet is a tiny Python script for creating transparent PNG spritesheets from TrueType (.ttf) fonts.

typesheet typesheet is a tiny Python script for creating transparent PNG spritesheets from TrueType (.ttf) fonts. I made it because I couldn't find an

Grayson Chao 12 Dec 23, 2022
Simple program to easily view Euler parameters in 3D.

Simple program to easily view Euler parameters in 3D.

null 5 Aug 20, 2021
impy is an all-in-one image analysis library, equipped with parallel processing, GPU support, GUI based tools and so on.

impy is All You Need in Image Analysis impy is an all-in-one image analysis library, equipped with parallel processing, GPU support, GUI based tools a

null 24 Dec 20, 2022
A quick and dirty QT Statusbar implementation for grabbing GIFs from Tenor, since there is no offical or unofficial one I found. This was intended for use under Linux, however it was also functional enough on MacOS.

Statusbar-TenorGIF App for Linux A quick and dirty QT Statusbar implementation for grabbing GIFs from Tenor, since there is no offical one and I didnt

Luigi DaVinci 1 Nov 1, 2021
Program to export all new icons from the latest Fortnite patch

Assets Exporter This program allows you to generate all new icons of a patch in png! Requierements Python >=3.8 (installed on your computer) If you wa

ᴅᴊʟᴏʀ3xᴢᴏ 6 Jun 24, 2022
HyperBlend is a new type of hyperspectral image simulator based on Blender.

HyperBlend version 0.1.0 This is the HyperBlend leaf spectra simulator developed in Spectral Laboratory of University of Jyväskylä. You can use and mo

SILMAE 2 Jun 20, 2022
New program to export a Blender model to the LBA2 model format.

LBA2 Blender to Model 2 This is a new program to export a Blender model to the LBA2 model format. This is also the first publicly released version of

null 2 Nov 30, 2022