- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在创建一个网络应用程序,提供动态图像和文本。绘制的每个字符串可能有多种颜色。
到目前为止,我已经创建了一个解析方法和一个渲染方法。 parse 方法只获取字符串,并从中解析颜色,它们的格式如下:“§aThis is green§rthis is white”(是的,它是 Minecraft)。这就是我的字体模块的样子:
# Imports from pillow
from PIL import Image, ImageDraw, ImageFont
# Load the fonts
font_regular = ImageFont.truetype("static/font/regular.ttf", 24)
font_bold = ImageFont.truetype("static/font/bold.ttf", 24)
font_italics = ImageFont.truetype("static/font/italics.ttf", 24)
font_bold_italics = ImageFont.truetype("static/font/bold-italics.ttf", 24)
max_height = 21 # 9, from FONT_HEIGHT in FontRederer in MC source, multiplied by
# 3, because each virtual pixel in the font is 3 real pixels
# This number is also returned by:
# font_regular.getsize("ABCDEFGHIJKLMNOPQRSTUVWXYZ")[1]
# Create the color codes
colorCodes = [0] * 32 # Empty array, 32 slots
# This is ported from the original MC java source:
for i in range(0, 32):
j = int((i >> 3 & 1) * 85)
k = int((i >> 2 & 1) * 170 + j)
l = int((i >> 1 & 1) * 170 + j)
i1 = int((i >> 0 & 1) * 170 + j)
if i == 6:
k += 85
if i >= 16:
k = int(k/4)
l = int(l/4)
i1 = int(i1/4)
colorCodes[i] = (k & 255) << 16 | (l & 255) << 8 | i1 & 255
def _get_colour(c):
''' Get the RGB-tuple for the color
Color can be a string, one of the chars in: 0123456789abcdef
or an int in range 0 to 15, including 15
'''
if type(c) == str:
if c == 'r':
c = int('f', 16)
else:
c = int(c, 16)
c = colorCodes[c]
return ( c >> 16 , c >> 8 & 255 , c & 255 )
def _get_shadow(c):
''' Get the shadow RGB-tuple for the color
Color can be a string, one of the chars in: 0123456789abcdefr
or an int in range 0 to 15, including 15
'''
if type(c) == str:
if c == 'r':
c = int('f', 16)
else:
c = int(c, 16)
return _get_colour(c+16)
def _get_font(bold, italics):
font = font_regular
if bold and italics:
font = font_bold_italics
elif bold:
font = font_bold
elif italics:
font = font_italics
return font
def parse(message):
''' Parse the message in a format readable by render
this will return a touple like this:
[((int,int),str,str)]
so if you where to send it directly to the rederer you have to do this:
render(pos, parse(message), drawer)
'''
result = []
lastColour = 'r'
total_width = 0
bold = False
italics = False
for i in range(0,len(message)):
if message[i] == '§':
continue
elif message[i-1] == '§':
if message[i] in "01234567890abcdef":
lastColour = message[i]
if message[i] == 'l':
bold = True
if message[i] == 'o':
italics = True
if message[i] == 'r':
bold = False
italics = False
lastColour = message[i]
continue
width, height = _get_font(bold, italics).getsize(message[i])
total_width += width
result.append(((width, height), lastColour, bold, italics, message[i]))
return result
def get_width(message):
''' Calculate the width of the message
The message has to be in the format returned by the parse function
'''
return sum([i[0][0] for i in message])
def render(pos, message, drawer):
''' Render the message to the drawer
The message has to be in the format returned by the parse function
'''
x = pos[0]
y = pos[1]
for i in message:
(width, height), colour, bold, italics, char = i
font = _get_font(bold, italics)
drawer.text((x+3, y+3+(max_height-height)), char, fill=_get_shadow(colour), font=font)
drawer.text((x, y+(max_height-height)), char, fill=_get_colour(colour), font=font)
x += width
它确实有效,但是应该在字体底线下方的字符,如 g、y 和 q,在底线上呈现,所以看起来很奇怪,这是一个例子:
关于如何使它们正确显示的任何想法?还是我必须制作自己的偏移表,然后手动将它们放在那里?
最佳答案
鉴于您无法从 PIL 获取偏移量,您可以通过切片图像来实现此目的,因为 PIL 适本地组合了多个字符。这里我有两种方法,但我认为第一种方法更好,尽管两者都只是几行。第一种方法给出了这个结果(它也是一个小字体的放大,这就是它被像素化的原因):
为了解释这里的想法,假设我想要字母“j”,而不是只制作一个“j”的图像,我制作一个“o j”的图像,因为这将使“j”正确对齐。然后我裁剪掉不需要的部分,只保留“j”(通过在“o”和“o j”上使用 textsize
)。
import Image, ImageDraw
from random import randint
make_color = lambda : (randint(50, 255), randint(50, 255), randint(50,255))
image = Image.new("RGB", (1200,20), (0,0,0)) # scrap image
draw = ImageDraw.Draw(image)
image2 = Image.new("RGB", (1200, 20), (0,0,0)) # final image
fill = " o "
x = 0
w_fill, y = draw.textsize(fill)
x_draw, x_paste = 0, 0
for c in "The quick brown fox jumps over the lazy dog.":
w_full = draw.textsize(fill+c)[0]
w = w_full - w_fill # the width of the character on its own
draw.text((x_draw,0), fill+c, make_color())
iletter = image.crop((x_draw+w_fill, 0, x_draw+w_full, y))
image2.paste(iletter, (x_paste, 0))
x_draw += w_full
x_paste += w
image2.show()
顺便说一句,我使用“o”,而不仅仅是“o”,因为相邻的字母似乎会稍微相互损坏。
第二种方法是制作整个字母表的图像,将其切片,然后重新粘贴在一起。这比听起来容易。这是一个示例,构建字典和连接到图像中的每一个都只有几行代码:
import Image, ImageDraw
import string
A = " ".join(string.printable)
image = Image.new("RGB", (1200,20), (0,0,0))
draw = ImageDraw.Draw(image)
# make a dictionary of character images
xcuts = [draw.textsize(A[:i+1])[0] for i in range(len(A))]
xcuts = [0]+xcuts
ycut = draw.textsize(A)[1]
draw.text((0,0), A, (255,255,255))
# ichars is like {"a":(width,image), "b":(width,image), ...}
ichars = dict([(A[i], (xcuts[i+1]-xcuts[i]+1, image.crop((xcuts[i]-1, 0, xcuts[i+1], ycut)))) for i in range(len(xcuts)-1)])
# Test it...
image2 = Image.new("RGB", (400,20), (0,0,0))
x = 0
for c in "This is just a nifty text string":
w, char_image = ichars[c]
image2.paste(char_image, (x, 0))
x += w
这是结果字符串的(放大)图像:
这是整个字母表的图像:
这里的一个技巧是我必须在原始字母表图像中的每个字符之间放置一个空格,否则相邻字符会相互影响。
我想如果您需要对有限范围的字体和字符执行此操作,那么预先计算字母表图像字典是个好主意。
或者,对于不同的方法,使用像 numpy 这样的工具,您可以轻松地确定上面 ichar
字典中每个字符的 yoffset(例如,沿每个水平行取最大值,然后找到非零索引的最大值和最小值)。
关于python - 带 PIL 的彩色文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19206840/
在 python 解释器中: >>> import PIL >>> PIL.Image Traceback (most recent call last): File "", line 1, in
我在 Pillow 中遇到过这个奇怪的错误,其中导入名称 PIL 需要全部小写而不是全部大写,但我从未见过 pil在任何地方都使用小写字母。这意味着我使用的导入 PIL 的所有 python 包和文件
有没有办法使用 PIL 截取驻留在我的服务器上的指定 HTML/Javascript 页面的屏幕截图? 我想编写一个脚本来更改该 HTML 页面上的一些参数,然后让 PIL 对其进行屏幕截图。 有什么
这是我所做的描述。 我正在尝试使用 PIL 编写程序,但是在尝试导入它时(如下所示),出现错误(也如下所示)。 from PIL import Image Here is the error. Tra
我正在尝试对图像进行简单的裁剪。这是代码 from PIL.Image import Image def get_image_half(image, half="upper"): if hal
我是一名新的Python用户,也是“Stack Overflow”中的新用户,当我尝试编译 tensorflow 代码时,我遇到了一些问题,并且我无法从网站上找到答案,所以我想从这里获得一些帮助,先谢
我知道 stackoverflow 上已经有很多与此问题相关的问题,我已经阅读了所有问题,但我仍然没有成功解决此问题。我希望有人能帮我解决这个问题。 我已经安装并重新安装了 Pillow 10 次。我
我得到错误: --------------------------------------------------------------------------- ImportError
我是机器学习的初学者,所以我试图创建一个模型来识别 Keras 博客中引用的图像。我已经在 Windows 10 上安装了 Anaconda 3 以及所有软件包,如tensorflow、keras、s
我正在尝试使用过滤器 FIND_EDGES 从图片中获取边缘,它在我的 Windows PC 上工作,但是当我在我的 Raspberry Pi 上运行相同的代码时,它给出了图像模式错误的错误。 最佳答
这个问题在 Python 环境中有一些答案,但这些解决方案不适用于我的 RStudio 环境。这是我的代码: library(keras) library(tensorflow) use_condae
我正在使用 Mac OS x 10.10.3 Yosemite 和 Python 2.7.9 |Anaconda 2.2.0 (x86_64) 来处理很多 python 的东西。我正在使用 Eclip
我正在遵循这个 SageMaker 指南并使用 1.12 cpu docker 文件。 https://github.com/aws/sagemaker-tensorflow-serving-cont
`from PIL import Image, ImageDraw, ImageFont image = Image.new('RGB', (950, 250), color=(255, 255, 2
我知道如何从图片中找到边缘。但我希望轮廓边缘更厚,例如宽度 9。 from PIL import Image, ImageFilter image = Image.open('your
我有多个白色背景的 PNG 图像,并且图像的某些部分充满了图案(可能是不同的颜色,黑色、蓝色、红色、黄色等)。 如何使用 Python PIL 库将所有这些图像合并为一张图像,以便所有非白色部分出
目前我正在尝试裁剪以下地址下文件夹内的所有图像:C:\\Users\\xie\\Desktop\\tiff\\Bmp然后将它们重新保存到同一个文件夹中。下面是我试图试验的代码,两者都运行没有错误但什么
虽然它们非常相似,但我确信 Pearson 相关相似度和调整余弦相似度之间存在一些差异,因为所有的论文和网页都将它们分为两种不同的类型。 然而,它们都没有提供明确的定义。 Here是其中一页。 谁能说
这是我的forms.py: class UploadImageForm(forms.ModelForm): class Meta: model = UserImages
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
我是一名优秀的程序员,十分优秀!