Django ImageField在处理时保持原始图像比例

时间:2019-04-02 10:05:27

标签: python django django-models

在我的models.py中,我得到了一个名为Post的类和一个名为postcover的ImageField。 我想将所有图像保存为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)

有什么方法可以在保持格式的同时设置最大宽度和高度吗?

更新:

如果我这样尝试(请参见下面的帖子):

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 :(得分:1)

也许您可以这样尝试:

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

答案 1 :(得分:0)

为了更好地理解,我已经在stackoverflow上的另一篇文章中讨论了此问题,使用此解决方案,还可以为图像设置固定的基高,如果您使用PNG格式,则这特别有用,因为它的大小。如果您正在使用例如jpg格式使用此方法时,在处理带有上载的png文件的颜色或透明背景时会遇到问题,因此请确保您具有像这样的适当的字段验证器,该验证器仅允许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)

请记住,您需要两个超级语句,否则这种流程根本无法正常工作。