python - 如何正确创建具有所需大小和分辨率(PNG、JPG、JPEG)的新图像?

标签 python image size python-imaging-library resolution

我想使用 Pillow 创建一个 PNG。 PNG 稍后用于标签打印。因此,我尝试使用 PIL 创建一个新图像,添加一些文本、一个多边形和一个二维码。但是,我发现很难获得合适的图像尺寸(与 7.5 cm x 5.5 cm 的标签尺寸相关)。我只是通过尝试和错误到达那里(它大致是 (275, 204))。保存时,PNG 的分辨率很差,打印时也是如此。

如何正确计算图像大小以及如何提高分辨率以将图像另存为 PNG(或 JPG 或 JPEG)。

到目前为止,这是我的代码:

import qrcode
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 

# Create qr code instance
qr = qrcode.QRCode(
    version = 1,
    error_correction = qrcode.constants.ERROR_CORRECT_H,
    box_size = 4,
    border = .2,
)

text = "test"
# Create new image

img = Image.new('RGB', (275, 204), color = (220,220,220))

# Add data
qr.add_data(text)
qr.make(fit=True)

# Create an image from the QR Code instance
qrc = qr.make_image(fill_color='black', back_color='white')

draw = ImageDraw.Draw(img)

font1 = ImageFont.truetype("arial.ttf", 25)
font2 = ImageFont.truetype("arial.ttf", 60)

draw.text((65, 150),text,(0,0,0),font=font1)
draw.text((115, 120),text,(0,0,0),font=font2)
draw.polygon(((5, 20), (50, 34), (50, 6)), fill=0)
img.paste(qrc, (80,25))

img.show()

#img.save("image.png", dpi = (300,300))

最佳答案

您需要为所有要绘制的元素设置相对(标签)坐标和大小(以厘米为单位),然后计算相应的图像坐标和大小(以像素为单位)w.r.t.所需的分辨率。这会以某种方式变得麻烦,但我想不出另一种独立于分辨率的方法。

在下文中,我省略了整个 QR 码,以确保内容至少具有一点可读性。

为了比较,您的代码(没有二维码)在我的机器上生成了这张图片:

Comparison

如果我在 Photoshop 中打开该图像,它显示 9.7 cm x 7.2 cm at 72 dpi。如果我手动计算分辨率,我将得到以下结果:

275 pixels / 7.5 cm * (2.54 cm/inch) = ca. 93 dpi
204 pixels / 5.5 cm * (2.54 cm/inch) = ca. 94 dpi

稍后我们将需要 94 dpi。

我根据您的原始图像估算了相对(标签)坐标和大小。

现在,首先让我们看一下整个代码:

from PIL import Image, ImageDraw, ImageFont

# Set up parameters
w_cm, h_cm = (7.5, 5.5)             # Real label size in cm
res_x, res_y = (300, 300)           # Desired resolution
res_y_old = 94                      # Old y resolution (204 / 5.5 * 2.54)

# Inch-to-cm factor
f = 2.54

# Determine image size w.r.t. resolution
w = int(w_cm / f * res_x)
h = int(h_cm / f * res_y)

# Create new image with proper size
img = Image.new('RGB', (w, h), color=(220, 220, 220))

# Draw elements
draw = ImageDraw.Draw(img)


def draw_text(x_cm, y_cm, font_size):
    font = ImageFont.truetype('arial.ttf', int(font_size / (res_y_old / res_y)))
    x, y = (int(x_cm / f * res_x), int(y_cm / f * res_y))
    draw.text((x, y), 'test', (0, 0, 0), font=font)


# Draw texts
draw_text(1.875, 4, 25)
draw_text(3.15, 3.25, 60)

# Polygon
coords_cm = [(0.15, 0.5), (1.35, 0.9), (1.35, 0.1)]
coords = [(int(c[0] / f * res_x), int(c[1] / f * res_y)) for c in coords_cm]
draw.polygon(tuple(coords), fill=(0, 0, 0))

# Save image
img.save('image.png', dpi=(res_x, res_y))

然后,让我们看看输出:

Output

如果我在 Photoshop 中打开该图像,它显示 7.5 cm x 5.5 cm at 300 dpi,这正是我们想要的。

关于字体大小:我想,您手动设置这些字体大小以获得特定的外观。不幸的是,以磅为单位的字体大小被调整为在显示器上具有一定的高度,但它们不会缩放以进行打印(或“打印”图像)。这就是为什么,我们需要缩放字体 w.r.t。旧分辨率和新分辨率,以保持原始图像所需的文本外观。

其他一切都是重复转换相对坐标和大小。如果需要进一步的解释,请随时询问!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.5
Pillow:      8.1.0
----------------------------------------

关于python - 如何正确创建具有所需大小和分辨率(PNG、JPG、JPEG)的新图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62690745/

相关文章:

python - 为什么这种Python多线程方法比单线程方法需要更多的时间来解决相同的任务?

python - 从 shell 脚本获取 pytest 退出代码

java - 如何访问正在运行的 jar 上方的文件夹

javascript - 尝试使用 Ajax 获取图像时出现访问控制源问题

html - 我的图像没有改变大小

python - 将 POST 请求限制为 Pyramid 上的最大大小

html - 当我找不到 <img> 标签时,如何从网站获取图片?

c# - 带有 bigint 的 SqlDbType 参数的大小是多少?

C# 创建一个固定大小的哈希表

python - 如何使用 SCP 或 SSH 将文件复制到 Python 中的远程服务器?