如何使用 sorl-thumbnail 调整源大小?

发布于 2025-01-06 23:06:30 字数 1062 浏览 2 评论 0原文

我在网上搜索我的问题,但找不到明确的答案或任何示例。

基本上,我想使用 sorl 并希望在模型保存期间调整源图像的大小,将其大小调整为 640x480 大小,这样我最终就不会在磁盘上存储用户的原始 2.5 MB 文件。然后,我将使用 templatetags 从我的源代码中创建常规缩略图,如 sorl 中所述。

我遇到了一些参考资料,参考使用 ThumbnailField 模型字段,该字段应该在 sorl.thumbnail.fields 中可用。请参阅此处链接。但是,在我的最新 sorl 副本中,我没有看到任何 ThumbnailField 或 ImageWithThumbnailsField。我尝试将其导入模型因此失败。我看到这些参考文献虽然很旧,但想知道我是否可以使用最新的 sorl 来实现相同的目标。

另一方面,sorl 文档仅指示 sorl.thumbnail 中的 ImageField(请参阅此处)没有任何大小参数来控制源调整大小。

顺便说一句,我发现这个功能可以通过 easy_thumbnail 使用,它需要一个输入参数 source_resize。

任何帮助将不胜感激!

摘要

我接受了下面的答案,但是我觉得 sorl 对这个用例的自然支持非常有用 - 即向 sorl 的 ImageField 添加 resize_source 参数以允许调整源图像的大小。以下是为什么这在该领域有用的两个因素:

  1. 如果您的应用程序不需要它,则不存储用户的巨大原始图像。节省磁盘空间。

  2. 如果您没有特定的极高质量原因,则不要花费额外的 CPU 来调整巨大源图像的缩略图大小。为了避免这种情况,可以在模板中将嵌套标签写入较小尺寸图像的缩略图,但这很快就会变得烦人。

I was searching the web for my question and couldn't find a clear answeror any example.

Basically, I want to use sorl and want to resize the source image during the Model save time to resize it down to 640x480 size, so that I don't end-up storing user's original 2.5 MB files on the disk. I will then use templatetags to create regular thumbnails out of my source as documented in sorl.

I came across couple of sources refer to use ThumbnailField model field that is supposed to be available in sorl.thumbnail.fields. See the link here. However, in my up-to-date sorl copy from the trunk I don't see any ThumbnailField or ImageWithThumbnailsField. My attempt to import it in the model fails accordingly. I see these references are old though and wondering whether I can achieve the same with up-to-date sorl.

On the other hand sorl documentation indicates only ImageField from sorl.thumbnail (see here) that does not have any size argument to control the source resizing.

BTW, I see this functionality is available with easy_thumbnail that takes an input parameter source_resize.

Any help will be appreciated!

SUMMARY

I accepted the below answer, however I feel natural sorl support for this use case can be very useful - i.e. adding resize_source param to sorl's ImageField to allow resizing the source image. Below are two factors why this can be useful in the field:

  1. Not to store user's huge original images if your app has no need for it. Saving disk space.

  2. Not to spend extra CPU for resizing thumbnails from that huge source images if you don't have specific extreme high quality reasons. To avoid this one may write nested tags in templates to thumbnail from smaller size images but it can become annoying very soon.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沐歌 2025-01-13 23:06:30

我在上面的代码中发现了一个缺陷,如果有人想使用它,就会得到“str has no method chunk()”。这是我的修复:

    from sorl.thumbnail import get_thumbnail
    from django.core.files.base import ContentFile

 class Foo(models.Model):
    image = models.ImageField(upload_to...)


    def save(self, *args, **kwargs):
        if not self.id:  
            super(Foo, self).save(*args, **kwargs)  
            resized = get_thumbnail(self.image, "100x100" ...)
            self.image.save(resized.name, ContentFile(resized.read()), True)
        super(Foo, self).save(*args, **kwargs)

I found a flaw in the code above, got “str has no method chunck()”, if somebody want to use it. Here is my fix:

    from sorl.thumbnail import get_thumbnail
    from django.core.files.base import ContentFile

 class Foo(models.Model):
    image = models.ImageField(upload_to...)


    def save(self, *args, **kwargs):
        if not self.id:  
            super(Foo, self).save(*args, **kwargs)  
            resized = get_thumbnail(self.image, "100x100" ...)
            self.image.save(resized.name, ContentFile(resized.read()), True)
        super(Foo, self).save(*args, **kwargs)
画▽骨i 2025-01-13 23:06:30

您提到的 Sorl 的 ImageField 只是一个普通的 Django ImageField,具有管理缓存缩略图删除的附加好处。初始上传时没有调整大小 - 这是您必须通过您用来上传的视图手动实现的。 文档展示了如何进行此操作。您可以在该视图中使用 sorl 来执行实际的调整大小操作本身,使用 低级 API 考试

编辑

更快的替代方法是在使用 sorl 保存模型时仅调整图像大小。您可以执行类似以下操作(虽然完全未经测试!),

from sorl.thumbnail import get_thumbnail

class Foo(models.Model):
    image = models.ImageField(upload_to...)

    def save(self, *args, **kwargs):
        if not self.id:
            # Have to save the image (and imagefield) first
            super(Foo, self).save(*args, **kwargs)
            # obj is being created for the first time - resize
            resized = get_thumbnail(self.image, "100x100" ...)
            # Manually reassign the resized image to the image field
            self.image.save(resized.name, resized.read(), True)
        super(Foo, self).save(*args, **kwargs)

这意味着您将在磁盘上拥有同一图像的 2 个版本 - django 图像字段决定保存它的一个版本(upload_to 路径)还有一个缩略图已保存其调整大小的缩略图。这与图像上传并保存两次的事实一起,是这种方法的缺点。虽然实施起来更快

Sorl's ImageField that you mention, is just a normal Django ImageField with the added benefit of managing the deletion of cached thumbnails. There's no resizing done on the initial upload - that's something you have to implement yourself manually via the view you are using to upload. The docs show how to go about this. You can use sorl in that view to do the actual resize operation itself, using the low level API examlpes

EDIT

A quicker alternative is to just resize the image when the model is being saved using sorl. You can do something like the following (completely untested though!)

from sorl.thumbnail import get_thumbnail

class Foo(models.Model):
    image = models.ImageField(upload_to...)

    def save(self, *args, **kwargs):
        if not self.id:
            # Have to save the image (and imagefield) first
            super(Foo, self).save(*args, **kwargs)
            # obj is being created for the first time - resize
            resized = get_thumbnail(self.image, "100x100" ...)
            # Manually reassign the resized image to the image field
            self.image.save(resized.name, resized.read(), True)
        super(Foo, self).save(*args, **kwargs)

this will mean that you will have 2 versions of the same image on disk - one where the django image field decides to save it (upload_to path) and one where sorl thumbnail has saved it's resized thumbnail. This, along with the fact the image is uploaded and saved twice, are the disadvantages of this approach. It's quicker to implement though

未蓝澄海的烟 2025-01-13 23:06:30

我一直在寻找解决方案一段时间,最终编写了应用程序 django-resized

I was looking for solution for some time and eventually wrote app django-resized.

韬韬不绝 2025-01-13 23:06:30

以下代码使用 PIL 引擎(sorl-thumbnail 的一部分)裁剪名为 picture.jpg 的图像(使用 Python 3.8sorl-thumbnail== 进行测试12.6.3):

#
# Change this import to get the Engine of your underlying libraries.
# Options are: convert_engine, pgmagick_engine, pil_engine, vipsthumbnail_engine or wand_engine.
#
from sorl.thumbnail.engines.pil_engine import Engine

# This object has all we need
engine = Engine()

#
# When receiving data from a request
# you probably have a BytesIO instance ready to use like:
#
#   im = engine.get_image(my_bytes_io)
#
with open("picture.jpg", "rb") as f:
    im = engine.get_image(f)

im_crop = engine.crop(im, (535, 535), options={'crop': 'smart'})

im_crop.save("picture-thumb.jpg")

我不会修改 save 方法,而是有一个帮助函数来减小图像大小(使用上面的行),并在之前从 Django 视图或表单调用它更新图像字段。尽管它可以在 save 本身上完成。

另一方面,引擎 API 有更多有用的功能,可能会很有用!这个 API 自第一次提交以来就已经存在,所以在我看来,将来不太可能改变:createcropboxorientationflip_dimensions颜色空间remove_bordercalculate_scaling_factorscalecrop< /代码>, 圆角模糊填充写入清理get_image_ratio< /code>、get_image_infoget_imageget_image_sizeis_valid_image

The following code uses the PIL Engine (part of sorl-thumbnail) to crop an image called picture.jpg (tested using Python 3.8 and sorl-thumbnail==12.6.3):

#
# Change this import to get the Engine of your underlying libraries.
# Options are: convert_engine, pgmagick_engine, pil_engine, vipsthumbnail_engine or wand_engine.
#
from sorl.thumbnail.engines.pil_engine import Engine

# This object has all we need
engine = Engine()

#
# When receiving data from a request
# you probably have a BytesIO instance ready to use like:
#
#   im = engine.get_image(my_bytes_io)
#
with open("picture.jpg", "rb") as f:
    im = engine.get_image(f)

im_crop = engine.crop(im, (535, 535), options={'crop': 'smart'})

im_crop.save("picture-thumb.jpg")

Instead of modifying the save method, I would have a helper function for reducing the image size (with the lines above) and call it from the Django view or form before updating the image field. Though it would work doing it on the save itself.

On the other hand, the Engine API has more useful features that could be useful! This API has been there since the first commit so, in my opinion, it's unlikely to change in the future: create, cropbox, orientation, flip_dimensions, colorspace, remove_border, calculate_scaling_factor, scale, crop, rounded, blur, padding, write, cleanup, get_image_ratio, get_image_info, get_image, get_image_size, is_valid_image.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文