【问题标题】:What is the implicit pixel density of a Pillow image when drawing text?绘制文本时枕头图像的隐含像素密度是多少?
【发布时间】:2021-05-29 02:35:13
【问题描述】:

我正在尝试在 python 中使用 Pillow 查找某些文本的大小,以磅为单位。据我了解,以磅为单位的字体大小对应于目标显示器或表面上的实际物理英寸,每英寸 72 磅。当我使用 Pillow 的 textsize 方法时,我可以找到以给定字体大小(以磅为单位)呈现的某些文本的像素大小,但不知道如何返回以英寸为单位的坐标系,因为我不知道'没有(也不能设置)图像的像素密度:

from PIL import Image, ImageFont, ImageDraw
image = Image.new('RGBA', (400, 300), (255, 255, 255))
font = ImageFont.truetype('/Library/Fonts/Arial.ttf', 16)
image.info['dpi'] = 100
print( ImageDraw.Draw(image).textsize('Loreum ipsum', font=font) )
image.info['dpi'] = 1000
print( ImageDraw.Draw(image).textsize('Loreum ipsum', font=font) )

将打印

(101, 18)
(101, 18)

我如何获得给定文本的大小以磅为单位

【问题讨论】:

  • 将点数乘以 dpi 因子
  • @WayToDoor,对,Pillow 在这里使用什么 DPI 因子?
  • 使用image.info['dpi'] 找出来?
  • @WayToDoor,新图像将image.info 设置为{};没有 DPI
  • 这很好,因为图像没有dpi信息。如果您设置了特定的 DPI 系数,那么您可以获得英寸数。如果您不这样做,则无法从图像中获取英寸数,因为这基本上是您在打印图像时设置的设置

标签: python python-3.x image python-imaging-library typography


【解决方案1】:

TL;DR

没有隐含的像素密度,因为 Pillow 文档不正确。创建字体时,您在 pixels 中指定 size,即使 Pillow 文档说它是以磅为单位的。它实际上是以像素为单位进行所有这些操作。

更多细节

ImageFont.truetype 的 Pillow 文档说 size 参数以点为单位。但是,查看ImageFont 模块的source,它会将size 参数传递给core.getfont

self.font = core.getfont(
    font, size, index, encoding, layout_engine=layout_engine
)

调用 ultimately leads 到调用 FT_Set_Pixel_Sizes,这是由 FreeType 库提供的。此调用转发给定的size,未修改。

error = FT_Set_Pixel_Sizes(self->face, 0, size);

FT_Set_Pixel_Sizes 状态的documentation

FT_EXPORT( FT_Error )
  FT_Set_Pixel_Sizes( FT_Face  face,
                      FT_UInt  pixel_width,
                      FT_UInt  pixel_height );

调用 FT_Request_Size 以请求标称尺寸(以像素为单位)。

face 目标人脸对象的句柄。

pixel_width 标称宽度,以像素为单位。

pixel_height 标称高度,以像素为单位。

因此,这里实际上根本不涉及物理距离,并且没有假定 ImageFont.truetypeImageDraw.textsize 的 DPI,尽管 Pillow 文档具有误导性。一切都以像素为单位,因此不需要 DPI。

旁注:您可能会注意到您要求的尺寸 (16) 并不完全等于您返回的尺寸 (18),但 FreeType 提到您要求的尺寸不一定你得到的大小,由字体本身决定。

【讨论】:

  • 很好的答案。感谢您深入研究这一点,并分享您的发现。我刚刚遇到了同样的问题。
【解决方案2】:

图像没有“隐式”像素密度,它们只是具有不同数量的像素。以像素为单位测量的任何东西的大小将取决于显示设备的 DPI 或每英寸点数。

例如,在 100 DPI 设备上,12 个像素看起来是 12/100 或 0.12 英寸长。要将英寸转换为点,请将它们乘以 72。所以 12 像素 → 0.12 英寸 * 72 → 8.84 点。

【讨论】:

  • 我明白这一点,但我不明白字体如何在不假设某些像素密度的情况下计算特定大小(以点为单位)的文本的大小(以像素为单位)。
  • 字体不计算任何东西,它们实际上只是数据文件。正在使用的文本绘图软件(本例中为 PIL/pillow)缩放字体文件中找到的字符形状数据,以便以指定的像素大小呈现每个字符/字形。
  • 好的,但是ImageFont.truetype 方法需要一个size in points,这让我感到困惑。如何建立点和像素之间的对应关系?
  • 使用基本代数,您可以使用我的回答中描述的数学关系将点转换为像素(假设您知道 - 或假设某些 - DPI 正在运行的设备渲染)。
  • 当然,我可以用一些代数计算出一些文本的英寸大小,因为它的大小(以像素为单位)和显示密度。但我想知道,例如,当我告诉 Pillow 以 12 磅的大小绘制文本时,它将使用多少像素来表示 12 磅的距离。
猜你喜欢
  • 2023-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
相关资源
最近更新 更多