Debian, Dojo, Django, Python

Делюсь опытом в описанных технологиях. Блог в первую очередь выполняет роль памяток для меня самого.

Показаны сообщения с ярлыком PIL. Показать все сообщения
Показаны сообщения с ярлыком PIL. Показать все сообщения

Django - изменить размер изображения перед сохранением

Как изменить размер изображения перед сохранением? Никак. Но далее я опишу путь, на который указал пользователь StackOwerflow в своём ответе вот на этот вопрос.

Вкратце:

  • Сохраняем объект
  • Проверяем наличие данных в нужном поле типа ImageField
  • Открываем сохранённое изображение и меняем его свойства, как нам нужно

Пример

from PIL import Image
from django import models

from os import path

# Максимальный размер изображения по большей стороне
_MAX_SIZE = 300

class CarManufacter(models.Model):
    """Производитель автомобилей, два поля
       name - название, строка
       logo - логотип, изображение
    """
    name = models.CharField(
        'Наименование',
        max_length=100,
        unique=True
    )
    logo = models.ImageField(
        upload_to=path.join('car', 'manufacter', 'logo'),
        null=True,
        blank=True
    )

    def save(self, *args, **kwargs):
        # Сначала - обычное сохранение
        super(CarManufacter, self).save(*args, **kwargs)

        # Проверяем, указан ли логотип
        if self.logo:
            filepath = self.logo.path
            width = self.logo.width
            height = self.logo.height

            max_size = max(width, height)

            # Может, и не надо ничего менять?
            if max_size > _MAX_SIZE:
                # Надо, Федя, надо
                image = Image.open(filename)
                # resize - безопасная функция, она создаёт новый объект, а не
                # вносит изменения в исходный, поэтому так
                image = image.resize(
                    (round(width / max_size * _MAX_SIZE),  # Сохраняем пропорции
                    round(height / max_size * _MAX_SIZE)),
                    Image.ANTIALIAS
                )
                # И не забыть сохраниться
                image.save(filename)

Сборка PIL с зависимостями (Debian 7)

Данная статья рассказывает о том, как правильно собрать PIL для поддержки различных форматов.

Описание проблемы

Несмотря на то, что уже давно существует и активно развивается библиотека Pillow, импортирующая функции для обработки изображений средствами Python, в некоторых проектах до сих пор используется устаревший (последняя версия вышла в 2009 году) модуль PIL. Если Вы из тех "везунчиков", кому приходится поддерживать старые проекты, то эта статья для Вас. При установке PIL в виртуальное окружение вводится команда
pip install pil
После этого начинается процесс загрузки расширения и его сборки, выводится куча сообщений, и в самом конце можно увидеть следующий текст:
PIL 1.1.7 SETUP SUMMARY
--------------------------------------------------------------------
version       1.1.7
platform      linux2 2.6.8 (unknown, Jan 26 2013, 14:35:25)
              [GCC 4.7.2]
--------------------------------------------------------------------
*** TKINTER support not available (Tcl/Tk 8.5 libraries needed)
*** JPEG support not available
*** ZLIB (PNG/ZIP) support not available
*** FREETYPE2 support not available
*** LITTLECMS support not available
--------------------------------------------------------------------
To add a missing option, make sure you have the required
library, and set the corresponding ROOT variable in the
setup.py script.
Что означает примерно следующее: модуль успешно собран, но работать не будет, т.к. ни одно из требующихся расширений установлено не было. Немного погуглив, я натолкнулся на кучу форумов, где описывалось решение, заключающееся в создании символических ссылок на нужные библиотеки в каталоге /usr/lib, однако, ни одно из этих решений не оказалось рабочим. В этой статье я описываю своё решение сборки PIL с поддержкой практически всех нужных расширений.

Установка

Для сборки и установки PIL с зависимостями нам потребуются некоторые дополнительные пакеты
  • python2.6-dev - заголовочные файлы для сборки Python2.6. Если используете другой - указываете другой.
  • libjpeg62-dev - для поддержки JPEG (в Debian есть также libjpeg8-dev, но она не подойдёт)
  • zlib1g-dev - поддержка PNG
  • libfreetype6-dev - поддержка шрифтов
  • liblcms1-dev - поддержка LITTLE CMS. Что это такое, я не знаю, можно не ставить.
Вводим команду:
apt-get install libjpeg62-dev zlib1g-dev libfreetype6-dev liblcms1-dev
Все необходимые зависимости, в том числе GCC, если он не установлен, установятся сами. Итак, необходимые системные пакеты установлены. Теперь нужно будет сделать несколько дополнительных действий с самой библиотекой. Первым делом её нужно скачать с официального сайта.
wget http://effbot.org/downloads/Imaging-1.1.7.tar.gz
Распакуем архив:
tar xfv Imaging-1.1.7.tar.gz
Зайдём в созданную папку и отредактируем файл setup.py
cd Imaging-1.1.7
nano setup.py
Тут нужно внести следующие изменения:
TCL_ROOT = NONE
JPEG_ROOT = NONE
ZLIB_ROOT = NONE
TIFF_ROOT = NONE
FREETYPE_ROOT = NONE
LCMS_ROOT = NONE
заменяем на
TCL_ROOT = '/usr/lib/x86_64-linux-gnu/'
JPEG_ROOT = '/usr/lib/x86_64-linux-gnu/'
ZLIB_ROOT = '/usr/lib/x86_64-linux-gnu/'
TIFF_ROOT = '/usr/lib/x86_64-linux-gnu/'
FREETYPE_ROOT = '/usr/lib/x86_64-linux-gnu/'
LCMS_ROOT = '/usr/lib/x86_64-linux-gnu/'
В x86-системах вместо x86_64 нужно вводить i386. Тем самым мы указываем, откуда брать библиотеки. Теперь можно попробовать собрать PIL со всеми расширениями (без реальной установки):
python setup.py build_ext -i
Если сообщение выглядит примерно так:
--------------------------------------------------------------------
PIL 1.1.7 SETUP SUMMARY
--------------------------------------------------------------------
version       1.1.7
platform      linux2 2.6.8 (unknown, Jan 26 2013, 14:35:25)
              [GCC 4.7.2]
--------------------------------------------------------------------
*** TKINTER support not available (Tcl/Tk 8.5 libraries needed)
--- JPEG support available
--- ZLIB (PNG/ZIP) support available
--- FREETYPE2 support available
--- LITTLECMS support available
--------------------------------------------------------------------
To add a missing option, make sure you have the required
library, and set the corresponding ROOT variable in the
setup.py script.
можно смело устанавливать PIL в виртуальное окружение Вашего проекта. Перед этим рекомендую удалить старую версию через
pip uninstall pil -y
и удалить файлы в каталоге lib/site-packages виртуального окружения:
cdsitepackages
rm -rf PIL*
Установка PIL:
python setup.py install

Заключение

В некоторых проектах БАРС Груп используется PIL, он прописан в зависимостях для установки их пакетов через setup-tools. В этом случае я делаю так:
  • Устанавливаю PIL
  • Устанавливаю пакет, провожу миграции и т.д.
  • Удаляю PIL и ставлю Pillow, т.к. Pillow импортирует те же самые функции и пространства имён, что и PIL.