【问题标题】:Generating an image thumbnail that is <10KB and did not lose proportions生成小于 10KB 且不丢失比例的图像缩略图
【发布时间】:2009-07-02 15:22:30
【问题描述】:

请注意,谷歌索引的每张图片都有一个小的thumbnail。 这些缩略图是:

  1. 小于 10KB。
  2. 宽高比例与原图一致。

我想编写一个函数(在 python 中),该函数将获取图像并使用这些属性创建缩略图。

编辑: 所以现在有 3 个答案,而且都对了一半。

我需要一个功能,不仅可以按比例调整图像大小,还可以确保文件大小小于 10KB。我该怎么做?

【问题讨论】:

  • 这不是重复的!正如我现在在“编辑”中所说,我需要一个不仅可以按比例调整图像大小的函数,而且还需要确保大小小于 10KB。

标签: python image-processing python-imaging-library


【解决方案1】:

this short post 中,Mike Fletcher 和 effbot 展示了(并讨论了详细的变体)一种出色的方法来完成您想要完成的任务。

编辑:至于 10K 的要求,很难(至少可以说;-)根据图像的格式来预测图像的压缩程度,因为今天的压缩算法是如此微妙.如果您希望缩略图尽可能大(以像素为单位),同时满足

例如,这里有一个“二分搜索”方法来获得正确的大小(可能有更好的策略!),用大量的打印语句 &c 来解释发生了什么......:

import Image
import cStringIO
import math
import os
import stat

# try no more than 10 times, then give up
MAX_TRIES = 10

def getThumbnail(filename, max_bytes=(10*1024)):
    '''Get a thumbnail image of filename, <max_bytes'''
    original_size = os.stat(filename)[stat.ST_SIZE]
    print "Original file size: %.1f KB" % (original_size/1024.)
    image = Image.open(filename)
    image.load()
    print "Original image size: %dx%d pixels" % image.size
    min_bytes = int(0.9 * max_bytes)
    largest_side = max(image.size)
    smallest_side = 16
    for attempt in range(MAX_TRIES):
        try_side = (largest_side + smallest_side) / 2
    print "Attempt #%d of %d" % (attempt+1, MAX_TRIES)
    print "Side must be within [%d:%d], now trying %d" % (
        smallest_side, largest_side, try_side)
    thumb = image.copy()
    thumb.thumbnail((try_side,try_side), Image.ANTIALIAS)
    afile = cStringIO.StringIO()
    thumb.save(afile, "PNG")
    resulting_size = len(afile.getvalue())
    afile.close()
    print "Reduced file size: %.1f KB" % (resulting_size/1024.)
    print "Reduced image size: %dx%d pixels" % thumb.size
    if min_bytes <= resulting_size <= max_bytes:
        print "Success!"
        return thumb
    elif resulting_size > max_bytes:
        print "Too large (>%d), reducing more" % max_bytes
        largest_side = try_side
    else:
        print "Too small (<%d), reducing less" % min_bytes
        smallest_side = try_side
    print "too many attempts, returning what I've got!"
    return thumb

def main():
    thumb = getThumbnail("pyth.png")
    print "Reduced image size: %dx%d pixels" % thumb.size
    print "Saving to thumb.png"
    thumb.save("thumb.png")
    thumb_size = os.stat("thumb.png")[stat.ST_SIZE]
    print "Reduced file size: %.1f KB" % (thumb_size/1024.)
    print "Done, bye!"

if __name__ == '__main__':
    main()

【讨论】:

    【解决方案2】:

    你读过PIL documentation吗?有一个 image.thumbnail 方法。

    【讨论】:

      【解决方案3】:

      使用 PIL,请参阅此处的示例代码以调整大小以保持纵横比

      How do I resize an image using PIL and maintain its aspect ratio?

      看看如何在目录上做类似的事情

      Resize images in directory

      所以上面的链接描述了如何使用 PIL 调整图像大小,现在谈到你的最大大小为 10KB 的问题,这可以很容易地实现,例如

      假设所需大小为 100x100,我们使用 JPEG 压缩,100% JPEG 质量每像素大约需要 9 位(请参阅http://en.wikipedia.org/wiki/JPEG),这意味着 100x100 图像的大小为 100x100x9/(1024x8) = 11KB,因此quality=100 你几乎达到了你的目标,但如果你仍然想要 10KB,你可以设置 quality=90,通常你可以将质量作为参数传递给 resize 函数,如果图像大小高于 10KB,则将质量降低 10%,但我认为这不是必需的,在 90% 的质量下,所有 JPEG 图像都小于 10KB。

      另外请注意,如果不压缩,RGB 图像的图像大小也只有 30KB,如果将大小减小到 60x60 像素,不进行任何压缩的图像大小将只有 10KB,即您可以使用 bmp 图像,如果您想要更小尺寸但无损压缩你可以选择PNG。

      因此,总而言之,您的 10KB 目标很容易实现。

      【讨论】:

        猜你喜欢
        • 2017-12-21
        • 2013-05-29
        • 1970-01-01
        • 2011-09-03
        • 2018-10-28
        • 2011-06-03
        • 2014-10-24
        • 1970-01-01
        • 2012-01-27
        相关资源
        最近更新 更多