我希望实现几个功能,以增加我的程序的输出。 我想将一列文本的背景设置为某种颜色,以便它 更清楚的是列属于一起。
一张图片胜过千言万语: 我想转换这个:
Pos. :123456789012345
Name. :ABCDEFGHIJKLMNO
Str. :SOMESTRINGSOMET <---- indented by half a row, Column number superscripted
Str. :SOM SOMET
Str. :SOMESTRIN ET
到此:
我怎么能用python做到这一点?是否有一个框架可以让我这样做? 我把它转换成了乳胶,但我不能让上标数字起作用。它们需要在文本之上,但不能充当角色,因为图片的列之间存在关系。
示例:A位于位置1.它具有属性S和O,这就是为什么它位于这两个之上,这就是为什么有一个半字符的缩进。 S有上标170,T有上标185。
特别难的也是Str部分被半个字符移动的部分。我希望有一个例子可以集成到我的程序中。
答案 0 :(得分:2)
有可能提出棘手的解决方案,考虑单倍间距字体,可以解决您的问题。但他们只是等着失败。您帖子中的灰色列可以完全按照图中的颜色添加,但我选择不改变字母中的颜色(因为我发现它更具可读性)。
有可能提出PIL:
略微改变字体:
接下来更多“严重”字体更改,所有字体都按原样生成。
接下来是生成这些数字的代码。我并没有真正做到这一点,它可以在很多方面得到改善。将此视为您需要做的事情的一个示例,可能会为您的问题找到解决方案。要使用任何类型的字体,您需要一个实际的排版系统,例如LaTeX。
import sys
import Image, ImageDraw, ImageFont
# Assumption: some other piece of code separates the data in the following
# format.
line1 = [("Pos. :", 0), ("123456789012345", 0)]
line2 = [("Name. :", 0), ("ABCDEFGHIJKLMNO", 0)]
line3 = [("Str. ", 0), (":", -0.5), ("SOMESTRINGSOMEST", -0.5)]
line4 = [("Wave 1:", 0), ("_XXXX_X____X_X_", 0)]
line5 = [("Wave 2:", 0), ("__XX_XXX_X__X_X", 0)]
line_data = [line1, line2, line3, line4, line5]
# Texts to draw over the last element, in specific positions,
# of lines present in line_data.
subscript = {
2: { # Meaning: third item in line_data
0: "170", # Meaning: draw "170" over the first char
len(line3[-1][0]) - 1: "185", # Draw "185" over the last char
7: "180", # Meaning: draw "180" over the eight char
},
4: {5: "hi"},
3: {6: "ops"}
}
# If the following fonts are not mono spaced, you are going to suffer.
#
# Normal font.
font = ImageFont.truetype('FreeMono.ttf', 40)
# Font for subscript.
font_tiny = ImageFont.truetype('FreeMono.ttf', 20)
im = Image.new("RGBA", (1000, 1000), 'white')
draw = ImageDraw.Draw(im)
line_offset = 4
start_y = 6
width_A, height_A = font.getsize('A')
_, height_tiny_A = font_tiny.getsize('A')
# Collect even columns from the last item of list line1.
even_columns = []
x = 0
for i, (text, _) in enumerate(line1):
for j, letter in enumerate(text):
if i == len(line1) - 1 and not j % 2:
even_columns.append(x)
x += width_A
# Write all lines.
width = 0
l_start_y = start_y
for di, data in enumerate(line_data):
x = 0
for i, (text, xoff) in enumerate(data):
for j, letter in enumerate(text):
# Apply x offset.
extra = width_A * xoff
draw.text((x + extra, l_start_y), letter, font=font, fill='black')
x += width_A
width = max(x, width)
l_start_y += height_A + line_offset
# Collect letter positions from the lines that will have subscripts.
letter_pos = {}
for k in subscript:
letter_pos[k] = {}
x = sum(len(text) for text, _ in line_data[k][:-1]) * width_A
text, xoff = line_data[k][-1]
for i in range(len(text)):
extra = width_A * xoff
letter_pos[k][i] = x + extra
x += width_A
# Write all subscripts.
for k, v in subscript.items():
line = line_data[k]
for pos, text in v.items():
x = letter_pos[k][pos]
y = start_y + (line_offset + height_A) * k
y -= height_tiny_A * 0.4 # XXX A poor heuristic that worked here.
draw.text((x, y), text, font=font_tiny, fill='black')
width = max(width, int(x + font_tiny.getsize(text)[0]))
# Draw grey columns.
columns = Image.new(im.mode, im.size, 'white')
mask = Image.new("L", im.size, 'white')
for x in even_columns:
columns.paste((128, 128, 128), (x, line_offset, x + width_A, l_start_y))
mask.paste(164, (x, line_offset, x + width_A, l_start_y), )
im = Image.composite(im, columns, mask)
# Crop and save the resulting image.
im.crop((0, 0, width, l_start_y + 2)).save(sys.argv[1])
答案 1 :(得分:1)
这实际上是一个LaTeX问题而不是Python问题 - 也就是说,如果你确定了你希望你的Python脚本生成的标记,那么实际生成它是相当容易的。
在这种情况下,我认为您可以使用相当复杂的表(\begin{table}...\end{table}
)获得所需的效果,其中每个单元格跨越两列,并且使用一列作为偏移量来获取你想要的“半角色”。如果在LaTeX中有一种更简单的方法可以做到这一点,那就不会让我感到惊讶了(它有更多的库可以保存在脑中),但这是我想到的。所以你的表看起来像这样:
+------+--+--+--+--+--+--+--+
| pos. | | 1 | 2 | 3 | ...
+------+--+--+--+--+--+--+--+
| name.| | A | B | C | ...
+------+--+--+--+--+--+--+--+--+
| | 170 | | | | ...
+------+--+--+--+--+--+--+--+--+
| Str. | S | O | M | E | ...
+------+--+--+--+--+--+--+--+--+
(其中+
表示实际列的位置,大多数单元格跨越两列。上面带有“170”的行将使用\tiny
或某些此类命令。)
我的建议是首先手动生成一个LaTeX文件,它可以做你想要的(或你选择文件的其他格式化语言);然后担心编写一些python代码来生成它。
答案 2 :(得分:0)
虽然PIL适用于简单的东西,但如果你使用SVG,你还有很多选择。您可以使用pySVG(方便的pySVG tutorial)或svgwrite以编程方式创建SVG,或仅将print
用作文本。然后使用ImageMagick(在命令行上为convert
或使用pythonmagicwand从python)将SVG渲染为您想要的任何栅格类型。在微调SVG时,您可以使用文本编辑器对其进行编辑,并在Web浏览器中查看它:)
# make some text in any font, any size, any effects
import pysvg
s = svg()
myStyle = StyleBuilder()
myStyle.setFontFamily(fontfamily="Verdana")
myStyle.setFontSize("5em")
myStyle.setFilling("blue")
t1 = text("Hello World", 0, 100)
t1.set_style(myStyle.getStyle())
s.addElement(t1)
s.save('test.svg')
from pythonmagickwand.image import Image
img = Image('test.svg')
img.format = 'PNG'
img.save('test.png')