Coder Social home page Coder Social logo

matthewwithanm / django-imagekit Goto Github PK

View Code? Open in Web Editor NEW
2.2K 2.2K 276.0 2.15 MB

Automated image processing for Django. Currently v4.0

Home Page: http://django-imagekit.rtfd.org/

License: BSD 3-Clause "New" or "Revised" License

Python 99.86% HTML 0.14%

django-imagekit's Introduction

Build Status

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you. If you need to programmatically generate one image from another, you need ImageKit.

ImageKit comes with a bunch of image processors for common tasks like resizing and cropping, but you can also create your own. For an idea of what's possible, check out the Instakit project.

For the complete documentation on the latest stable version of ImageKit, see ImageKit on RTD.

Installation

  1. Install Pillow. (If you're using an ImageField in Django, you should have already done this.)
  2. pip install django-imagekit
  3. Add 'imagekit' to your INSTALLED_APPS list in your project's settings.py

Usage Overview

Specs

You have one image and you want to do something to it to create another image. But how do you tell ImageKit what to do? By defining an image spec.

An image spec is a type of image generator that generates a new image from a source image.

Defining Specs In Models

The easiest way to use define an image spec is by using an ImageSpecField on your model class:

from django.db import models
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar = models.ImageField(upload_to='avatars')
    avatar_thumbnail = ImageSpecField(source='avatar',
                                      processors=[ResizeToFill(100, 50)],
                                      format='JPEG',
                                      options={'quality': 60})

profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg
print(profile.avatar_thumbnail.width)  # > 100

As you can probably tell, ImageSpecFields work a lot like Django's ImageFields. The difference is that they're automatically generated by ImageKit based on the instructions you give. In the example above, the avatar thumbnail is a resized version of the avatar image, saved as a JPEG with a quality of 60.

Sometimes, however, you don't need to keep the original image (the avatar in the above example); when the user uploads an image, you just want to process it and save the result. In those cases, you can use the ProcessedImageField class:

from django.db import models
from imagekit.models import ProcessedImageField
from imagekit.processors import ResizeToFill

class Profile(models.Model):
    avatar_thumbnail = ProcessedImageField(upload_to='avatars',
                                           processors=[ResizeToFill(100, 50)],
                                           format='JPEG',
                                           options={'quality': 60})

profile = Profile.objects.all()[0]
print(profile.avatar_thumbnail.url)    # > /media/avatars/MY-avatar.jpg
print(profile.avatar_thumbnail.width)  # > 100

This is pretty similar to our previous example. We don't need to specify a "source" any more since we're not processing another image field, but we do need to pass an "upload_to" argument. This behaves exactly as it does for Django ImageFields.

Note

You might be wondering why we didn't need an "upload_to" argument for our ImageSpecField. The reason is that ProcessedImageFields really are just like ImageFields—they save the file path in the database and you need to run syncdb (or create a migration) when you add one to your model.

ImageSpecFields, on the other hand, are virtual—they add no fields to your database and don't require a database. This is handy for a lot of reasons, but it means that the path to the image file needs to be programmatically constructed based on the source image and the spec.

Defining Specs Outside of Models

Defining specs as models fields is one very convenient way to process images, but it isn't the only way. Sometimes you can't (or don't want to) add fields to your models, and that's okay. You can define image spec classes and use them directly. This can be especially useful for doing image processing in views— particularly when the processing being done depends on user input.

from imagekit import ImageSpec
from imagekit.processors import ResizeToFill

class Thumbnail(ImageSpec):
    processors = [ResizeToFill(100, 50)]
    format = 'JPEG'
    options = {'quality': 60}

It's probably not surprising that this class is capable of processing an image in the exact same way as our ImageSpecField above. However, unlike with the image spec model field, this class doesn't define what source the spec is acting on, or what should be done with the result; that's up to you:

source_file = open('/path/to/myimage.jpg', 'rb')
image_generator = Thumbnail(source=source_file)
result = image_generator.generate()

Note

You don't have to use open! You can use whatever File-like object you want—including a model's ImageField.

The result of calling generate() on an image spec is a file-like object containing our resized image, with which you can do whatever you want. For example, if you wanted to save it to disk:

dest = open('/path/to/dest.jpg', 'wb')
dest.write(result.read())
dest.close()

Using Specs In Templates

If you have a model with an ImageSpecField or ProcessedImageField, you can easily use those processed image just as you would a normal image field:

<img src="{{ profile.avatar_thumbnail.url }}" />

(This is assuming you have a view that's setting a context variable named "profile" to an instance of our Profile model.)

But you can also generate processed image files directly in your template—from any image—without adding anything to your model. In order to do this, you'll first have to define an image generator class (remember, specs are a type of generator) in your app somewhere, just as we did in the last section. You'll also need a way of referring to the generator in your template, so you'll need to register it.

from imagekit import ImageSpec, register
from imagekit.processors import ResizeToFill

class Thumbnail(ImageSpec):
    processors = [ResizeToFill(100, 50)]
    format = 'JPEG'
    options = {'quality': 60}

register.generator('myapp:thumbnail', Thumbnail)

Note

You can register your generator with any id you want, but choose wisely! If you pick something too generic, you could have a conflict with another third-party app you're using. For this reason, it's a good idea to prefix your generator ids with the name of your app. Also, ImageKit recognizes colons as separators when doing pattern matching (e.g. in the generateimages management command), so it's a good idea to use those too!

Warning

This code can go in any file you want—but you need to make sure it's loaded! In order to keep things simple, ImageKit will automatically try to load an module named "imagegenerators" in each of your installed apps. So why don't you just save yourself the headache and put your image specs in there?

Now that we've created an image generator class and registered it with ImageKit, we can use it in our templates!

generateimage

The most generic template tag that ImageKit gives you is called "generateimage". It requires at least one argument: the id of a registered image generator. Additional keyword-style arguments are passed to the registered generator class. As we saw above, image spec constructors expect a source keyword argument, so that's what we need to pass to use our thumbnail spec:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file %}

This will output the following HTML:

<img src="/media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />

You can also add additional HTML attributes; just separate them from your keyword args using two dashes:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file -- alt="A picture of Me" id="mypicture" %}

Not generating HTML image tags? No problem. The tag also functions as an assignment tag, providing access to the underlying file object:

{% load imagekit %}

{% generateimage 'myapp:thumbnail' source=source_file as th %}
<a href="{{ th.url }}">Click to download a cool {{ th.width }} x {{ th.height }} image!</a>
thumbnail

Because it's such a common use case, ImageKit also provides a "thumbnail" template tag:

{% load imagekit %}

{% thumbnail '100x50' source_file %}

Like the generateimage tag, the thumbnail tag outputs an <img> tag:

<img src="/media/CACHE/images/982d5af84cddddfd0fbf70892b4431e4.jpg" width="100" height="50" />

Comparing this syntax to the generateimage tag above, you'll notice a few differences.

First, we didn't have to specify an image generator id; unless we tell it otherwise, thumbnail tag uses the generator registered with the id "imagekit:thumbnail". It's important to note that this tag is *not* using the Thumbnail spec class we defined earlier; it's using the generator registered with the id "imagekit:thumbnail" which, by default, is imagekit.generatorlibrary.Thumbnail.

Second, we're passing two positional arguments (the dimensions and the source image) as opposed to the keyword arguments we used with the generateimage tag.

Like with the generateimage tag, you can also specify additional HTML attributes for the thumbnail tag, or use it as an assignment tag:

{% load imagekit %}

{% thumbnail '100x50' source_file -- alt="A picture of Me" id="mypicture" %}
{% thumbnail '100x50' source_file as th %}

Using Specs in Forms

In addition to the model field above, there's also a form field version of the ProcessedImageField class. The functionality is basically the same (it processes an image once and saves the result), but it's used in a form class:

from django import forms
from imagekit.forms import ProcessedImageField
from imagekit.processors import ResizeToFill

class ProfileForm(forms.Form):
    avatar_thumbnail = ProcessedImageField(spec_id='myapp:profile:avatar_thumbnail',
                                           processors=[ResizeToFill(100, 50)],
                                           format='JPEG',
                                           options={'quality': 60})

The benefit of using imagekit.forms.ProcessedImageField (as opposed to imagekit.models.ProcessedImageField above) is that it keeps the logic for creating the image outside of your model (in which you would use a normal Django ImageField). You can even create multiple forms, each with their own ProcessedImageField, that all store their results in the same image field.

Processors

So far, we've only seen one processor: imagekit.processors.ResizeToFill. But ImageKit is capable of far more than just resizing images, and that power comes from its processors.

Processors take a PIL image object, do something to it, and return a new one. A spec can make use of as many processors as you'd like, which will all be run in order.

from imagekit import ImageSpec
from imagekit.processors import TrimBorderColor, Adjust

class MySpec(ImageSpec):
    processors = [
        TrimBorderColor(),
        Adjust(contrast=1.2, sharpness=1.1),
    ]
    format = 'JPEG'
    options = {'quality': 60}

The imagekit.processors module contains processors for many common image manipulations, like resizing, rotating, and color adjustments. However, if they aren't up to the task, you can create your own. All you have to do is define a class that implements a process() method:

class Watermark(object):
    def process(self, image):
        # Code for adding the watermark goes here.
        return image

That's all there is to it! To use your fancy new custom processor, just include it in your spec's processors list:

from imagekit import ImageSpec
from imagekit.processors import TrimBorderColor, Adjust
from myapp.processors import Watermark

class MySpec(ImageSpec):
    processors = [
        TrimBorderColor(),
        Adjust(contrast=1.2, sharpness=1.1),
        Watermark(),
    ]
    format = 'JPEG'
    options = {'quality': 60}

Note that when you import a processor from imagekit.processors, imagekit in turn imports the processor from PILKit. So if you are looking for available processors, look at PILKit.

Admin

ImageKit also contains a class named imagekit.admin.AdminThumbnail for displaying specs (or even regular ImageFields) in the Django admin change list. AdminThumbnail is used as a property on Django admin classes:

from django.contrib import admin
from imagekit.admin import AdminThumbnail
from .models import Photo

class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field='thumbnail')

admin.site.register(Photo, PhotoAdmin)

To use specs defined outside of models:

from django.contrib import admin
from imagekit.admin import AdminThumbnail
from imagekit import ImageSpec
from imagekit.processors import ResizeToFill
from imagekit.cachefiles import ImageCacheFile

from .models import Photo

class AdminThumbnailSpec(ImageSpec):
    processors = [ResizeToFill(100, 30)]
    format = 'JPEG'
    options = {'quality': 60 }

def cached_admin_thumb(instance):
    # `image` is the name of the image field on the model
    cached = ImageCacheFile(AdminThumbnailSpec(instance.image))
    # only generates the first time, subsequent calls use cache
    cached.generate()
    return cached

class PhotoAdmin(admin.ModelAdmin):
    list_display = ('__str__', 'admin_thumbnail')
    admin_thumbnail = AdminThumbnail(image_field=cached_admin_thumb)

admin.site.register(Photo, PhotoAdmin)

AdminThumbnail can even use a custom template. For more information, see imagekit.admin.AdminThumbnail.

Management Commands

ImageKit has one management command—generateimages—which will generate cache files for all of your registered image generators. You can also pass it a list of generator ids in order to generate images selectively.

Community

Please use the GitHub issue tracker to report bugs with django-imagekit. A mailing list also exists to discuss the project and ask questions, as well as the official #imagekit channel on Freenode.

Contributing

We love contributions! And you don't have to be an expert with the library—or even Django—to contribute either: ImageKit's processors are standalone classes that are completely separate from the more intimidating internals of Django's ORM. If you've written a processor that you think might be useful to other people, open a pull request so we can take a look!

You can also check out our list of open, contributor-friendly issues for ideas.

Check out our contributing guidelines for more information about pitching in with ImageKit.

django-imagekit's People

Contributors

alexerson avatar bmispelon avatar bryanveloso avatar claymation avatar cyberdelia avatar danxshap avatar dulacp avatar ebrelsford avatar fladi avatar jaap3 avatar jacobsvante avatar jdriscoll avatar joshourisman avatar kronuz avatar lettertwo avatar matthewwithanm avatar mkai avatar mrigor avatar nex2hex avatar nthall avatar ptone avatar q0w avatar richleland avatar ron8mcr avatar ryanbagwell avatar saijim avatar saulshanabrook avatar timgates42 avatar vstoykov avatar x-yuri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-imagekit's Issues

django-imagekit unit tests failing

Is anyone else getting failing unit tests? As a side effect, the test images are not getting destroyed at the end of the tests as well.

lib.py - AccessInit: has collision: 3 for both 1 and 1

I did a clean install of my Django dev environment, and got stuck here. I Google-d quite for sometime to figure this out, seems like it's a namespace thing.

Anyone else having this problem ? Or is it something I did wrong ? From what I've searched, this problem seems to have been solved ?

I have to remove the below codes in lib.py to get it working again.

I'm using latest clone of django, imagekit and PIL binaries from here


#try:
#   import Image
#   import ImageFile
#   import ImageFilter
#   import ImageEnhance
#   import ImageColor
# except ImportError:
try:
    from PIL import Image
    from PIL import ImageFile
    from PIL import ImageFilter
    from PIL import ImageEnhance
    from PIL import ImageColor
except ImportError:
    raise ImportError('ImageKit was unable to import the Python Imaging Library. Please confirm it`s installed and available on your current Python path.')

Adjust Is Not Transparency-Compatible

With the addition of the AutoConvert processor, ImageKit can now handle different transparency formats a lot more intelligently than it used to; the Adjust processor needs to be updated to match.

The first problem is that the processor converts to 'RGB'. This is a pretty quick fix as we can just change this to RGBA. Unfortunately, that's not quite enough: PIL's color and contrast filters don't behave as expected with transparencies. That's because both of their implementations involve converting the image to L mode:

class Color(_Enhance):
    "Adjust image colour balance"
    def __init__(self, image):
        self.image = image
        self.degenerate = image.convert("L").convert(image.mode)

class Contrast(_Enhance):
    "Adjust image contrast"
    def __init__(self, image):
        self.image = image
        mean = int(ImageStat.Stat(image.convert("L")).mean[0] + 0.5)
        self.degenerate = Image.new("L", image.size, mean).convert(image.mode)

So basically, we have to write new versions of these two that don't.

Any takers? (:

pre_cache delayed job

Hey, I have my Photo model as you can see below, and I would like to have the 4 different image sizes created when a new photo is uploaded, or there abouts. I was wondering if there's been any attempt to use something like celery to have a background queue for generating images?

thanks.

class Photo(models.Model):
    user = models.ForeignKey(User)
    title = models.CharField(max_length = 100, blank=True)
    description = models.TextField(blank=True)
    is_active = models.BooleanField(default=False)
    original_image = models.ImageField(upload_to = imagefield_upload_to)

    thumbnail = ImageSpec(
        processors = [
            resize.Crop(width=100, height=100),
            Adjust(sharpness=1.2),
        ],
        image_field = 'original_image',
        format = 'JPEG',
        quality = 85,
        pre_cache = True,
        cache_to = 'photos/t',
    )

    large_image = ImageSpec(
        processors = [
            resize.Fit(width=1024, height=1024),
            Adjust(sharpness=1.2),
        ],
        image_field = 'original_image',
        format = 'JPEG',
        quality = 85,
        pre_cache = True,
        cache_to = 'photos/l',
    )

    medium_image = ImageSpec(
        processors = [
            resize.Fit(width=640, height=640),
            Adjust(sharpness=1.2),
        ],
        image_field = 'original_image',
        format = 'JPEG',
        quality = 85,
        pre_cache = True,
        cache_to = 'photos/m',
    )

    small_image = ImageSpec(
        processors = [
            resize.Fit(width=240, height=240),
            Adjust(sharpness=1.2),
        ],
        image_field = 'original_image',
        format = 'JPEG',
        quality = 85,
        pre_cache = True,
        cache_to = 'photos/s',
    )

    def __unicode__(self):
        return u'%s by %s' % (self.title, self.user.username)

Progressive JPEG support?

Is there any support planned for Progressive JPEGs? (of course, only in case the target format is JPEG)

This would be quite useful since progressive JPEGs seem to be the preferred way of displaying photos for online photo apps.

Pip install gives version 0.4

It'd be ideal if the pip version of this was at least 1.0 instead of 0.4. The version on github and the version on pip are almost totally different now but the install instructions stil recommend pip.

trying to create a display image isn't working

here's the code in my model. The thumbnail works great. But the display isn't working. Suggestions welcome.

from imagekit.models import ImageSpec
from imagekit.processors import resize, Adjust

class Speaker(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    bio = models.TextField(blank=True)
    original_image = models.ImageField(upload_to='speaker_photos')
    display = ImageSpec(image_field='original_image', options={'quality': 70})
    thumbnail = ImageSpec([Adjust(contrast=1.2, sharpness=1.1), resize.Crop(50, 50)], image_field='original_image', options={'quality': 50})

Images Unnecessarily Regenerated

A nasty bug in the extension suggestion algorithm can cause images to be unnecessarily regenerated and even duplicated on the filesystem.

The reason is that IK relies on PIL's EXTENSION list to map formats to extensions. However, under normal circumstances, this list isn't populated until an image is opened or saved. Therefore, the first time a spec is accessed (assuming you haven't already used PIL to do something else), you can wind up with a different (wrong) suggested extension. IK will then check for the existence of the file with the wrong extension. Of course, it won't exist, so IK will generate a new image. Since Image.open will have been called in the course of generating the image, the new suggested filename will be correct. This process will be repeated exactly each subsequent time (since the file with the incorrect extension still won't exist) but since a file with the correct extension will already exist, the storage backend will append a count, resulting in a filesystem full of duplicate images!

ProcessedImageField does not process 'default' kwarg

While poorly documented, Django's ImageField supports the 'default' option for field value.

on a related note, while the value of the default is made available as the path to the ProcessedImageField, any imagespec that references will run into trouble like this:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Users/preston/Projects/code/forks/django-imagekit/imagekit/models.py", line 178, in url
    self.generate()
  File "/Users/preston/Projects/code/forks/django-imagekit/imagekit/models.py", line 191, in generate
    if lazy and (getattr(self, '_file', None) or self.storage.exists(self.name)):
  File "/Users/preston/UNIX/src/django-trunk-svn/django/core/files/storage.py", line 230, in exists
    return os.path.exists(self.path(name))
  File "/Users/preston/UNIX/src/django-trunk-svn/django/core/files/storage.py", line 246, in path
    raise SuspiciousOperation("Attempted access to '%s' denied." % name)
SuspiciousOperation: Attempted access to '/Users/preston/Projects/code/fotw/project/fotw_project/static/image/missing_thumbnail.jpg' denied.

Rename ImageSpecFile._create

Since @hzy- came up with a pretty straightforward use case for generating files manually (#51), I think we should probably make _create a non-underscore function. I'm thinking generate() would probably be a better name, but we can bikeshed on that. I'm also thinking that we should change the "lazy" kwarg to default to true so that people don't accidentally regenerate files all the time.

Tox

I eventually want to have a nice CI thing going here (first: more tests). Tox seems to be the flavor of the day when it comes to hassle-free testing, so I'll just leave this here for myself.

http://tox.testrun.org/en/latest/

Update readme example for removed options parameter

In v.1.0.3 on pypi the options parameter has been removed from the ImageSpec init.py, so installing via pip and using the instructions on the readme on github throws errors. Change the readme here to reflect the new syntax:

formatted_image = ImageSpec(image_field='original_image', format='JPEG',
        quality=90)

Manual PIL installation required on setup

Hello,

Documentation says 'pip install django-imagekit' is enough to install imagekit but if you don't have PIL/Pillow installed in your environment you can't use imagekit until you install these.

Is changing documentation the right way or setup.py?

Regards.

Complete tutorial on how to upload, update and delete images using ImageKit

Is there a complete tutorial on how to upload, update and delete images using ImageKit?

On my project I want for example to update avatar images if an avatar image exits for that user. So my script should be able to update the database table but also delete the existing image and upload the new one.

Typo in docs file 'Enchance' should be 'Enhance'

In the following locations:
django-imagekit/docs/tutorial.rst
django-imagekit/README.rst

class EnchanceThumb(processors.Adjustment):
contrast = 1.2
sharpness = 1.1

class Thumbnail(ImageSpec):
access_as = 'thumbnail_image'
pre_cache = True
processors = [ResizeThumb, EnchanceThumb]

ikflush memory leak?

I want to make thumbnails for over 10000 JPEG files.
python2.6 manage.py ikflush app
makes some thumbnails and abnormally ends.

Traceback (most recent call last):
File "manage.py", line 11, in
File "/usr/lib/python2.6/site-packages/django/core/management/init.py", line 438, in execute_manager
File "/usr/lib/python2.6/site-packages/django/core/management/init.py", line 379, in execute
File "/usr/lib/python2.6/site-packages/django/core/management/base.py", line 191, in run_from_argv
File "/usr/lib/python2.6/site-packages/django/core/management/base.py", line 220, in execute
File "/usr/lib/python2.6/site-packages/imagekit/management/commands/ikflush.py", line 15, in handle
File "/usr/lib/python2.6/site-packages/imagekit/management/commands/ikflush.py", line 34, in flush_cache
File "/usr/lib/python2.6/site-packages/imagekit/specs.py", line 67, in _create
File "/usr/lib/python2.6/site-packages/imagekit/specs.py", line 50, in _get_imgfile
File "/usr/lib/python2.6/site-packages/imagekit/utils.py", line 6, in img_to_fobj
File "/usr/lib64/python2.6/tempfile.py", line 475, in TemporaryFile
File "/usr/lib64/python2.6/tempfile.py", line 228, in _mkstemp_inner
OSError: [Errno 24] Too many open files: '/tmp/tmp3zbmaD'

imege not deleted

When deleting a file image model (like the one in the example) neither file or thumbnail are removed from the FS.

Support pluggable image manipulation backends

Add support for a pluggable backends system for image manipulations so that other image libraries other than PIL (like ImageMagick) could be used to manipulate images.

Also, I'd like a pony please. ;)

Broken Celery

When I try to fire up ./manage.py celeryd after integrating the latest imagekit into my models, I get this error:

AttributeError: 'ImageSpecFile' object has no attribute 'source_file'

https://gist.github.com/1352084

Am I doing something wrong (hopefully) or is celery incompatible with imagekit?

Thanks,
Dave

ImageSpec in reusable application

Hello,
is there any way how to define ImageSpec fields dynamically please? I have reusable application Photo and I would like define different photo variants per project (for example in project1 fields thumbnail, catalog and in project2 fields thumbnail and detail; in both cases there will be different crop sizes for ImageSpec fields).

I used ImageKit in past, and that time I should define effectivelly specs.py per project with own photo variants.

Is something like this possible in this new "Field API" approach please?

Thanks for any hint.

image in feeds.py

I am getting an error when an thumbnail doesn't exist in the cache for an image used in a rss feed.
handler.addQuickElement(u"url", show.img_itunes_sm.url) from https://github.com/rizumu/django-podcasting/blob/master/podcasting/feeds.py

The error is triggerd in utils.py when calling img.save():

    ipdb> img
    <PIL.Image.Image image mode=RGB size=1000x1000 at 0x3A64290>
    ipdb> img.save(tmp, format, **kwargs)
    Suspension not allowed here
    *** IOError: encoder error -2 when writing image file

and the traceback

 Environment:

Request Method: GET
Request URL: http://snowprayers.net/feeds/podcasts/snowprayers/itunes/mp3/rss/


Traceback:
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/newrelic-0.5.58.122/newrelic/hooks/framework_django.py" in __call__
  327.                     return self.__wrapped(*args, **kwargs)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/contrib/syndication/views.py" in __call__
  39.         feedgen.write(response, 'utf-8')
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/django/utils/feedgenerator.py" in write
  214.         self.add_root_elements(handler)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/podcasting/feeds.py" in add_root_elements
  39.         handler.addQuickElement(u"itunes:image", attrs={"href": show.img_itunes_lg.url})
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in url
  159.         self._create(True)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in _create
  184.             img, content = self._process_content(self.name, fp)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/models.py" in _process_content
  135.                                   optimize=True)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/imagekit/utils.py" in img_to_fobj
  18.     img.save(tmp, format, **kwargs)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/Image.py" in save
  1439.             save_handler(self, fp, filename)
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/JpegImagePlugin.py" in _save
  471.     ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
File "/home/deploy/.virtualenvs/snowprayers/lib/python2.7/site-packages/PIL/ImageFile.py" in _save
  501.                 raise IOError("encoder error %d when writing image file" % s)

Exception Type: IOError at /feeds/podcasts/snowprayers/itunes/mp3/rss/
Exception Value: encoder error -2 when writing image file

I'll attempt to figure it out over the weekend.

What is the right way to delete a photo?

Hi. What is the right way to delete a ImageModel?
I tried this 3 ways:

  1. Trying to delete using the ImageModel.delete() method:
    photo.delete()
    
    What happens: This cleans the cache, but "forget" the original image on the disk
  2. Trying to delete the original image before calling the ImageModel.delete() method:
    photo.original_image.delete()
    photo.delete()
    
    What happens: This deletes the original image, but "forget" about the cached ones
  3. Trying to delete the original image after calling ImageModel.delete()
    # photo.id == 1
    photo.delete()
    # photo.id == None
    photo.original_image.delete()
    # photo.id == 2
    
    What happens: This will clean the cache and delete the original_image, but then it will re-create the model with no images.

So, how can I delete the cache, the original image and the database entry?
Thanks!

Dynamically assign processors and etc.

I want to assign the processors parameter for each instance.
For example, a ImageSpec is following;

display  = ImageSpec([Adjust(contrast=1.2, sharpness=1.1),Transpose(Transpose.ROTATE_90),
        resize.Fit(300, None)], image_field='original_image',
        format='JPEG', quality=90,cache_to=my_cache_to)

and I want to change contrast, sharpness, and the Transpose method at runtime for each instance.

I found the similar request at #11 issue.
#11 expects more general way, but I don't have a good idea for #11

My idea is;

  1. change "processors" of ImageSpec() to check callable or not, like "cache_to".
  2. the callable "processors" gets parameters from instance of Model and generates processors array

Is it an effective change or not?

ProcessedImageField does not take django.core.files.File as content

If I have a regular imagefield, I can call it's save method with a django File object as the content

but with a ProcessedImageField, this causes PIL to choke

instead the content needs to be a plain python file like

open('/some/path.jpg', 'rb')

Not sure if the solution is some form of isinstance check?

  File "/Users/preston/Projects/Python/virtualenvs/fotw/src/imagekit/imagekit/models.py", line 339, in save
    img, content = self._process_content(new_filename, content)
  File "/Users/preston/Projects/Python/virtualenvs/fotw/src/imagekit/imagekit/models.py", line 125, in _process_content
    img = open_image(content)
  File "/Users/preston/Projects/Python/virtualenvs/fotw/src/imagekit/imagekit/utils.py", line 34, in open_image
    img = Image.open(target)
  File "/Library/Python/2.6/site-packages/PIL/Image.py", line 1980, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

getting/saving ImageProcessor attrs stored in a model

I guess this is half question, half request.
So, let's say I have a model class PersonPhoto(ImageModel) (among others) that will be used in various places on a site, in various shapes. It has ImageSpecs of FacebookStyleThumb, SmallPortrait, SmallLandscape. The width and height of these would be, say, 50,50, 120,170, and 170,120 respectively.

I would love to take PersonPhoto instances and be able to use some fancy js (jCrop) to define cropboxes for the various ImageSpecs, enforcing the aspect ratio defined by their width/height. Then save that cropbox in the DB. I have it working, but it's hacky and am now trying to do it a "better" way.

To store the cropbox dimensions, I'm thinking something like this:

class CropBox(models.Model):
    some_sort_of_unique_imagespec_value = models.CharField(max_length=255, help_text='')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    x = models.PositiveSmallIntegerField(help_text='')
    y = models.PositiveSmallIntegerField(help_text='')
    x2 = models.PositiveSmallIntegerField(help_text='')
    y2 = models.PositiveSmallIntegerField(help_text='')

    class Meta:
        unique_together = (('some_sort_of_unique_imagespec_value', 'content_type', 'object_id'), ) 

I'm not sure of the best way to easily get and save cropbox instances.
Do I handle getting the cropbox instance in def process() of a custom crop ImageProcessor, using its classname as the some_sort_of_unique_imagespec_value... But if I did that, I'm not seeing an easy way to "save" cropbox dimensions. Maybe it should be handled in a custom ImageSpec.... or maybe an Accessor attribute... or maybe I'm thinking about this all wrong...

Anything that could be done on the imagekit side, at a low level, that might make a path to something like this more clear?

showing a thumbnail image in admin add page causes the error

In order to show a thumbnail image, add following lines to admin.py;

class PhotoAdmin(admin.ModelAdmin):
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
list_display = ('caption, 'admin_thumbnail')
fields = ['admin_thumbnail', 'original_image', 'caption']

The thumbnail is shown in the list and the detail page.
But when adding a new photo, the error occurs;

File "/usr/lib/python2.6/site-packages/django/template/debug.py" in render_node

  1.         result = node.render(context)
    
    File "/usr/lib/python2.6/site-packages/django/template/debug.py" in render
  2.         output = self.filter_expression.resolve(context)
    
    File "/usr/lib/python2.6/site-packages/django/template/base.py" in resolve
  3.             obj = self.var.resolve(context)
    
    File "/usr/lib/python2.6/site-packages/django/template/base.py" in resolve
  4.         value = self._resolve_lookup(context)
    
    File "/usr/lib/python2.6/site-packages/django/template/base.py" in _resolve_lookup
  5.                         current = current()
    
    File "/usr/lib/python2.6/site-packages/django/contrib/admin/helpers.py" in contents
  6.         f, attr, value = lookup_field(field, obj, model_admin)
    
    File "/usr/lib/python2.6/site-packages/django/contrib/admin/util.py" in lookup_field
  7.         value = attr(obj)
    
    File "/usr/lib/python2.6/site-packages/imagekit/admin.py" in call
  8.             obj, self.image_field))
    

Exception Type: TemplateSyntaxError at /admin/lupines/photo/add/
Exception Value: Caught Exception while rendering: The property - None is not defined on thumbnail.

And local values are;

self imagekit.admin.AdminThumbnail object at 0xa6409ac
obj Photo: - None
thumbnail ImageSpecFile: None

wrapping Image.copy causing an adverse impact on memory use

f570bd0 changed the way images were opened, and wraps the original copy method with one that tries to preserve extra imagekit related info.

however this results in the image data being retained somehow in memory - I'm not sure exactly how or where.

commenting out this line:

img.copy = types.MethodType(_wrap_copy(img.copy), img, img.__class__)

results in a substantially reduced memory footprint

I've created a quick sample app/project to demonstrate this - if you watch the process memory - you can see it climb.

https://github.com/ptone/imagefoobar (note this is using the new Django 1.4/trunk layout)

cc @lettertwo

Calling `generate()` in `post_save` Receiver Doesn't Create Image

The intent is great — as I understand it, refresh the spec files when instance is saved because the image may have been updated — but it wreaks havoc when the image spec url accessor isn't used in templates and pre_cache is not set to True.

When pre-cache is True, the spec files are generated immediately after deletion. But if a post_save handler is the desired method to generate spec files when the instance is created (to work well with celery, for instance), and calling the image size directly in templates isn't ideal (in my use-case, because I'm using cloudfiles for spec file storage and there's a second or three lag during this operation) then images vanish on future instance saves and never get regenerated.

wrong output file on input file extension change.

In a model,
I have an attached spec with a "Format" processor so that my thumbnail images are all in jpeg.

I first upload a jpeg file say "a.PNG". spec works fine and produces "a_thumbnail.jpg" file with the format: (file_name - a)_(spec_name - thumbnail).(processor_output_extension - JPEG)

But,
when i upload a file after the first one say "a.TIF" (same name - different extension).
spec works again output file format will be: "a_thumbnail.jpg" again. Since this file already generated for previous image, it just uses this one, which is really bad!

A solution may be to include "original_file_extension" in the cached file name.
Technically speaking:
options.py line 17:
cache_filename_format = "%(filename)s_%(specname)s_%(original_extension)s.%(extension)s"

Allow for a "missing image" image setting

If an imagespec references an imagefield that does not have a file, this will raise a ValueError exception.

This can cause entire gallery pages or the admin to err even if the issue is just with a single model

I propose a setting: IMAGEKIT_MISSING_IMAGE which would be a str URL, or a callable (not sure what if any args it would take, maybe the original imagespec - or the model instance?)

This would then be the URL used for ie, model_instance.thumbnail_imagespec.url

a callable would allow something like the use of http://placehold.it

Converting from .png (in "Palette" mode) to .jpeg doesn't work

Specifying an explicit format="JPEG" does not work when the input file is in PNG format. Works fine when input is JPEG (haven't tested the usual suspects such as GIF, TIFF yet). Also works fine when format= is NOT specified.

class ZDPlainImage(EncryptedPKModel):

    original = ImageField(max_length=500, upload_to="uploads")

     # ImageKit generated image variations
     thumbnail = ImageSpec([resize.Fit(width=250)], image_field='original', format="JPEG", quality=90)
     display = ImageSpec([resize.Fit(width=650, upscale=False)], image_field='original', format="JPEG", quality=90)

Looks like this used to work well with the old 0.4 version. I updated to the latest django-imagekit today, made the necessary changes (got rid of separate "spec") and found that this doesn't work with the latest version.

Saving images via django admin

Anyone else encountering an issue using the ImageModel in an Admin form - uploading a file causes the file pre_save signal to be called which instantiates an InMemoryUploadedFile and fails when it tries to test if the '_committed' Attribute exists.

Traceback of the error I get:

File "/var/www/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  111.                         response = callback(request, *callback_args, **callback_kwargs)
File "/var/www/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
  307.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  93.                     response = view_func(request, *args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  79.         response = view_func(request, *args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
  197.             return view(request, *args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
  28.             return bound_func(*args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  93.                     response = view_func(request, *args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
  24.                 return func(self, *args2, **kwargs2)
File "/var/www/lib/python2.7/site-packages/django/db/transaction.py" in inner
  217.                 res = func(*args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
  982.                 self.save_model(request, new_object, form, change=True)
File "/var/www/lib/python2.7/site-packages/django/contrib/admin/options.py" in save_model
  665.         obj.save()
File "/var/www/yipit/apps/deal/models.py" in save
  198.         super(Deal, self).save(*args, **kwargs)
File "/var/www/src/django-imagekit/imagekit/models.py" in save
  124.         super(ImageModel, self).save(*args, **kwargs)
File "/var/www/lib/python2.7/site-packages/django/db/models/base.py" in save
  460.         self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/var/www/lib/python2.7/site-packages/django/db/models/base.py" in save_base
  504.                 self.save_base(cls=parent, origin=org, using=using)
File "/var/www/lib/python2.7/site-packages/django/db/models/base.py" in save_base
  525.                         values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
File "/var/www/lib/python2.7/site-packages/django/db/models/fields/files.py" in pre_save
  253.         if file and not file._committed:

Exception Type: AttributeError
Exception Value: 'InMemoryUploadedFile' object has no attribute '_committed'

Would appreciate any input on this. Thanks,
Nitya

File rename processor

Just an idea, how about a processor that can rename the file on save, eg, renaming the file to the primary key of the object.

InlineModelAdmin

How can we admin a model contains a thumbnail with InlineModelAdmin or not?

For example, put these lines to admin.py;

class PhotoInline(admin.TabularInline):
model = Photo
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
fields = ('admin_thumbnail', 'caption')

class ProductAdmin(admin.ModelAdmin):
inlines = [
PhotoInline,
]

This cause the following error;
Exception Type: ImproperlyConfigured
Exception Value: 'PhotoInline.fields' refers to field 'admin_thumbnail' that is missing from the form.

Sharing specs across models -- DRY?

With the old ImageKit API, I was able to create a single spec module at the site root that I could share across all of my image models within a project. This allowed me to have standard image sizes to use in various layouts. All I'd have to do is have that model inherit ImageModel and provide the path to the spec file.

Now, it seems that for each model that I want these ImageSpecs, I'll have to recreate each of the specs as fields on each individual model. And if I want to add or change specs, I'd need to edit each and every model.

Am I missing something with how this new API works? Is there a way to specify specs without having to spell out all the properties each time?

One thought that I had was to create an abstract model mixin that contains the site-wide specs have each of the models with images inherit that mixin. But this would require being very careful that the imageField be named the same field name.

The other problem is working with third party apps. Previously, I could create a proxy model that would give a third party model the ImageModel behavior and attach the spec file to it. I suppose I could do something similar now, but again the issue of field names remains.

Missing processors?

I'm probably doing something stupid, but I've been trying to follow the documentation, and it appears files are missing from the downloads. ProcessorPipeline and AutoConvert are not in processors/resize.py, which is the only file in that directory; therefore attempting to generate any new image fails. I've tried cloning the git archive and downloading the tar files, neither contains anything except resize.py in the processor directory.

ImportError: cannot import name ImageModel

Following the docs.

Step 1. pip install django-imagekit:
Successfully installed django-imagekit

Step 2. add "from imagekit.models import ImageModel" to my model
ImportError: cannot import name ImageModel

lib.py - AccessInit: has collision: 3 for both 1 and 1

I did a clean install of my Django dev environment, and got stuck here. I Google-d quite for sometime to figure this out, seems like it's a namespace thing.

Anyone else having this problem ? Or is it something I did wrong ? From what I've searched, this problem seems to have been solved ?

I have to remove the below codes in lib.py to get it working again.

I'm using latest clone of django, imagekit and PIL binaries from here


#try:
#   import Image
#   import ImageFile
#   import ImageFilter
#   import ImageEnhance
#   import ImageColor
# except ImportError:
try:
    from PIL import Image
    from PIL import ImageFile
    from PIL import ImageFilter
    from PIL import ImageEnhance
    from PIL import ImageColor
except ImportError:
    raise ImportError('ImageKit was unable to import the Python Imaging Library. Please confirm it`s installed and available on your current Python path.')

Admin thumbnail templates missing

When using the Admin thumbnails the ticket located in /virtualenv/.../templates/imagekit/admin are not found.
If I move those into my local template directory it works fine. Somehow it's not finding that template directory.

Default Image Request

It would be great for imagekit to be able to accept and process a default image. (ie, if no image supplied, use the image specified in the parameter 'default' instead)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.