Django ImageField сохраняет исходное соотношение изображения при обработке - PullRequest
0 голосов
/ 02 апреля 2019

в моем models.py я получил класс с именем Post with и ImageField с именем postcover. Я хочу сохранить каждое изображение в формате PNG, который до сих пор работал нормально, но я понятия не имею, как можно сохранить фактическое соотношение сторон изображения после обработки изображения, потому что в настоящее время я статически конвертирую его в формат 4: 3, сохраняя при этом 500 на 375 пикселей.

def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        if self.postcover:
            if os.path.exists(self.postcover.path):
                imageTemproary = Image.open(self.postcover)
                outputIoStream = BytesIO()
                imageTemproaryResized = imageTemproary.resize((500, 375))
                imageTemproaryResized.save(outputIoStream, format='PNG')
                outputIoStream.seek(0)
                self.postcover = InMemoryUploadedFile(outputIoStream, 'ImageField',
                                                  "%s.png" % self.postcover.name.split('.')[0], 'image/png',
                                                  sys.getsizeof(outputIoStream), None)
        super(Post, self).save(*args, **kwargs)

Есть ли способ установить максимальную ширину и высоту, сохраняя формат?

UPDATE:

если я попробую это так (см. Пост ниже):

def save(self, *args, **kwargs):
    super(Post, self).save(*args, **kwargs)
    if self.postcover:
        if os.path.exists(self.postcover.path):
            imageTemproary = Image.open(self.postcover)
            outputIoStream = BytesIO()
            baseheight = 500
            hpercent = (baseheight / float(self.postcover.size[1]))
            wsize = int((float(self.postcover.size[0]) * float(hpercent)))
            imageTemproaryResized = imageTemproary.resize((wsize, baseheight))
            imageTemproaryResized.save(outputIoStream, format='PNG')
            outputIoStream.seek(0)
            self.postcover = InMemoryUploadedFile(outputIoStream, 'ImageField',
                                              "%s.png" % self.postcover.name.split('.')[0], 'image/png',
                                              sys.getsizeof(outputIoStream), None)
    super(Post, self).save(*args, **kwargs)

Я просто получаю сообщение об ошибке:

Объект int не является подписным

Ответы [ 2 ]

0 голосов
/ 06 апреля 2019

Для лучшего понимания я уже обсуждал эту проблему в другом посте здесь, посвященном stackoverflow, с этим решением также можно установить фиксированную базовую высоту для вашего изображения, это особенно полезно, если вы используете формат PNG из-за его размер. Если вы используете, например, В формате jpg с этим методом вы столкнетесь с проблемами при обработке цветов или прозрачного фона с загруженными файлами png, поэтому убедитесь, что у вас есть валидатор поля propper, такой как этот, который просто позволяет загружать jpeg или просто использовать png ...:

validators.py

def image_file_extension(value):
    ext = os.path.splitext(value.name)[1]  # [0] returns path+filename
    valid_extensions = ['.jpg']
    if not ext.lower() in valid_extensions:
        raise ValidationError(u'Unsupported file extension, allowed is: jpg')

models.py

   def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        if self.postcover:
            if os.path.exists(self.postcover.path):
                image = Image.open(self.postcover)
                outputIoStream = BytesIO()
                baseheight = 500
                hpercent = baseheight / image.size[1]
                wsize = int(image.size[0] * hpercent)
                imageTemproaryResized = image.resize((wsize, baseheight))
                imageTemproaryResized.save(outputIoStream, format='PNG')
                outputIoStream.seek(0)
                self.postcover = InMemoryUploadedFile(outputIoStream, 'ImageField',
                                                      "%s.png" % self.postcover.name.split('.')[0], 'image/png',
                                                      sys.getsizeof(outputIoStream), None)
        super(Post, self).save(*args, **kwargs)

Пожалуйста, имейте в виду, что вам нужно два супер оператора, иначе этот тип потока не будет работать вообще.

0 голосов
/ 02 апреля 2019

Может быть, вы можете попробовать так:

image = Image.open(self.postcover)
baseheight = 500
hpercent = (baseheight / float(image.size[1]))
wsize = int((float(image.size[0]) * float(hpercent)))
imageTemproaryResized = image.resize((wsize, baseheight))

Для получения дополнительной информации, пожалуйста, проверьте этот пост: https://ruddra.com/posts/play-with-pillow/#resize-image

...