找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 24|回复: 4

[经验] 获取一张图片的长和宽

[复制链接]
发表于 昨天 10:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 被诅咒的章鱼 于 2025-8-23 10:34 编辑

这两天偶然研究到我之前写的一些东西,然后有一个需求是“获取一张图片的长和宽”。
两个月前我使用的方法是用pygame把这个图片load一下,使用的是gamedir+相对路径的方式,但是安卓端的图片不存放在gamedir里,所以这件事之后以我手动填写图片的长宽结束。

不过这两天又提起这件事,我找到了一些新的解法,刚好几年前有人问过,遂做一个解答。


这里介绍两种办法
第一种:renpy.image_size()
文档连接在这里
用法很简单,入参是图片的路径,返回值是图片的长和宽,没有太多好说的。
第二种:Image("path/image").load().get_size()
这个是今早重新翻源码的时候发现的办法,注意入参是在Image后面入参,而不是在load或者get_size里,返回值同样是图片的长和宽。


然后说一下这两种方法的区别,主要区别是:第一种方法运行的相当慢,因为它是从磁盘读取文件(文档里也明确说了),而Image函数大概是有图像缓存,因此运行速度要比第一种方法快好几个数量级。

然后我们在这里讲一下第二种方法的原理吧:
当Image函数的入参是一个basestring(字符串)的时候,他会返回一个Image对象
renpy/display/im.py文件,
[RenPy] 纯文本查看 复制代码
def image():
    if:
        # 省略if的内容

        pass
    elif isinstance(arg, basestring):
        return Image(arg, **properties)



这个Image对象里有一个load函数
renpy/display/im.py文件,
[RenPy] 纯文本查看 复制代码
class Image(ImageBase):

    def load(self, unscaled=False):

        # Unscaled is no longer used.

        cache.add_load_log(self.filename)

        try:

            try:
                filelike = renpy.loader.load(self.filename, directory="images")
                filename = self.filename
                force_size = None
            except renpy.webloader.DownloadNeeded as e:
                renpy.webloader.enqueue(e.relpath, 'image', self.filename)
                # temporary placeholder:
                filelike = open(os.path.join('_placeholders', e.relpath), 'rb')
                filename = 'use_png_format.png'
                force_size = e.size

            with filelike as f:
                surf = renpy.display.pgrender.load_image(f, filename)

            if force_size is not None:
                # avoid size-related exceptions (e.g. Crop on a smaller placeholder)
                surf = renpy.display.pgrender.transform_scale(surf, force_size)

            if self.is_svg:
                width, height = surf.get_size()

                width = int(width * renpy.display.draw.draw_per_virt * self.dpi / 96)
                height = int(height * renpy.display.draw.draw_per_virt * self.dpi / 96)

                if filename != self.filename:

                    # This should only run for placeholder images.
                    surf = renpy.display.pgrender.transform_scale(surf, (width, height))

                else:

                    filelike = renpy.loader.load(self.filename, directory="images")

                    with filelike as f:
                        surf = renpy.display.pgrender.load_image(filelike, filename, size=(width, height))

            return surf



在不报错的情况下会返回一个叫surf的东西
那么这个surf是什么呢?实际上我们没有必要知道,因为从代码中可以看出它是load_image这个函数的返回值,如果我们一直往前看的话就会牵扯到更多的文件,在这里没有必要了,因为源码中其实明确告诉了我们surf有一个叫做get_size的方法,它会返回surf的长和宽,这就足够了

所以以上就是获取图片大小的两种办法,经过测试加载一张4k的截屏文件,renpy.image_size()用时大概0.15秒左右,而Image几乎是一瞬间就能返回值……



 楼主| 发表于 昨天 10:04 | 显示全部楼层
我焯为什么代码片段变成这样了(
回复 支持 抱歉

使用道具 举报

发表于 昨天 11:26 | 显示全部楼层
Aaron栩生阿龙 发表于 2025-8-22 10:04
我焯为什么代码片段变成这样了(

文档编译器自带插入代码功能
回复 支持 抱歉

使用道具 举报

 楼主| 发表于 昨天 23:05 | 显示全部楼层
blurred 发表于 2025-8-22 11:26
文档编译器自带插入代码功能

我知道,但是不是很好用(
回复 支持 抱歉

使用道具 举报

发表于 11 小时前 | 显示全部楼层
帮楼主略微调整了一下代码部分的显示。

补充两句,返回结果suf是pygame中的Surface对象。
Surface对象是内存中十分接近bitmap的一种存在,其核心部分是一个由RGB(A)像素值组成的二维数组。
常见的jpg和png图片都是压缩过的,会解压成类似bitmap的数据放入Surface对象中,之后再传给图形API和GPU进行渲染等处理。
回复 支持 抱歉

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|RenPy中文空间 ( 苏ICP备17067825号|苏公网安备 32092302000068号 )

GMT+8, 2025-8-23 22:05 , Processed in 0.061374 second(s), 24 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表