2015-01-19 1 views
0

Я использую Django-resized library для автоматического изменения размера загружаемых изображений. Проблема, с которой я сталкиваюсь, заключается в том, что при изменении размера изображения происходит падение качества изображения, несмотря на то, что качество настройки равно 100. Я не знаю достаточно о PIL, чтобы возиться с этим кодом, и я не уверен, как увеличьте IQ, поэтому мне нужно сделать условное условие, которое говорит, если ширина изображения> 600, то измените размер изображения (таким образом, изображения в пределах определенной ширины не будут изменены и попадут в IQ). Мой вопрос: должен ли я помещать условие if внутри конструктора для ResizedImageField? ИЛИ я должен помещать его в метод сохранения в ResizedImageFileField?Как изменить размер изображения, если max_width превышает x с PIL?

DJANGO МОДЕЛЬ

class MyModel(models.Model): 
    ... 
    image = ResizedImageField(max_width=500, max_height=300, upload_to='whatever') 

DJANGO-Отмасштабированный FORMS.PY

import os 
try: 
    from PIL import Image, ImageFile 
except ImportError: 
    import Image, ImageFile 

try: 
    # python3 
    from io import BytesIO as StringIO 
except ImportError: 
    # python2 
    from StringIO import StringIO 

from django.conf import settings 
from django.core.files.base import ContentFile 

try: 
    from sorl.thumbnail import ImageField 
except ImportError: 
    from django.db.models import ImageField 


DEFAULT_SIZE = getattr(settings, 'DJANGORESIZED_DEFAULT_SIZE', [1920, 1080]) 
DEFAULT_COLOR = (255, 255, 255, 0) 


class ResizedImageFieldFile(ImageField.attr_class): 

    def save(self, name, content, save=True): 
     new_content = StringIO() 
     content.file.seek(0) 
     thumb = Image.open(content.file) 
     thumb.thumbnail((
      self.field.max_width, 
      self.field.max_height 
      ), Image.ANTIALIAS) 

     if self.field.use_thumbnail_aspect_ratio: 
      img = Image.new("RGBA", (self.field.max_width, self.field.max_height), self.field.background_color) 
      img.paste(thumb, ((self.field.max_width - thumb.size[0])/2, (self.field.max_height - thumb.size[1])/2)) 
     else: 
      img = thumb 

     try: 
      img.save(new_content, format=thumb.format, **img.info) 
     except IOError: 
      ImageFile.MAXBLOCK = img.size[0] * img.size[1] 
      img.save(new_content, format=thumb.format, **img.info) 

     new_content = ContentFile(new_content.getvalue()) 

     super(ResizedImageFieldFile, self).save(name, new_content, save) 


class ResizedImageField(ImageField): 

    attr_class = ResizedImageFieldFile 

    def __init__(self, verbose_name=None, name=None, **kwargs): 
     //if self.max_width > 400: 
     self.max_width = kwargs.pop('max_width', DEFAULT_SIZE[0]) 
     self.max_height = kwargs.pop('max_height', DEFAULT_SIZE[1]) 
     self.use_thumbnail_aspect_ratio = kwargs.pop('use_thumbnail_aspect_ratio', False) 
     self.background_color = kwargs.pop('background_color', DEFAULT_COLOR) 
     super(ResizedImageField, self).__init__(verbose_name, name, **kwargs) 


try: 
    from south.modelsinspector import add_introspection_rules 
    rules = [ 
     (
      (ResizedImageField,), 
      [], 
      { 
       "max_width": ["max_width", {'default': DEFAULT_SIZE[0]}], 
       "max_height": ["max_height", {'default': DEFAULT_SIZE[1]}], 
       "use_thumbnail_aspect_ratio": ["use_thumbnail_aspect_ratio", {'default': False}], 
       "background_color": ["background_color", {'default': DEFAULT_COLOR}], 
      }, 
     ) 
    ] 
    add_introspection_rules(rules, ["^django_resized\.forms\.ResizedImageField"]) 
except ImportError: 
    pass 
+0

PIL не очень хорошо изменения размера, см http://stackoverflow.com/questions/23113163/antialias-vs-bicubic-in-pilpython-image-library –

ответ

0

Это, конечно, не очень. Я понимаю, что у меня много повторяющегося кода, но это единственный способ понять, как заставить его работать.

class ResizedImageFieldFile(ImageField.attr_class): 

    def save(self, name, content, save=True): 
     new_content = StringIO() 
     content.file.seek(0) 
     thumb = Image.open(content.file) 

     if thumb.size[0] > 900: 
      thumb.thumbnail((
       self.field.max_width, 
       self.field.max_height 
       ), Image.ANTIALIAS) 

      if self.field.use_thumbnail_aspect_ratio: 
       img = Image.new("RGBA", (self.field.max_width, self.field.max_height), self.field.background_color) 
       img.paste(thumb, ((self.field.max_width - thumb.size[0])/2, (self.field.max_height - thumb.size[1])/2)) 
      else: 
       img = thumb 

      try: 
       img.save(new_content, format=thumb.format, **img.info) 
      except IOError: 
       ImageFile.MAXBLOCK = img.size[0] * img.size[1] 
       img.save(new_content, format=thumb.format, **img.info) 
     else: 
      img = thumb 
      try: 
       img.save(new_content, format=thumb.format, **img.info) 
      except IOError: 
       ImageFile.MAXBLOCK = img.size[0] * img.size[1] 
       img.save(new_content, format=thumb.format, **img.info) 

     new_content = ContentFile(new_content.getvalue()) 

     super(ResizedImageFieldFile, self).save(name, new_content, save) 
0

Похоже, Джанго-изменения размера не предоставляют quality аргумента при сохранении. Этот аргумент будет проигнорирован для других форматов изображений, чем JPEG, поэтому вы всегда можете передать его без каких-либо проблем.

При использовании подушки (вилка PIL) вы можете использовать quality='keep', чтобы использовать ту же таблицу квантования, что и исходное изображение. В противном случае вы можете явно указать процент качества как целое (не использовать 100, он создает тупо большие изображения).

+0

Да, я забыл включить его в код, но я могу сохранить с качеством 100%, то, что я пытаюсь выяснить сейчас, - это где положить условие if – stephan

+0

Я бы поместил его в метод сохранения. – SmileyChris

+0

Я на работе, поэтому я не могу попробовать это сейчас, но должен ли я просто обернуть все содержимое метода сохранения в условии if? См. Мой ответ, который я разместил ниже. – stephan