2012-12-04 26 views
5

我期待实现一些功能,甜了我的程序的输出。 我想一列文本的背景设定为一个特定的颜色,使其更加 清楚,列属于一起。我如何在Python中格式化文本,就像在Illustrator中一样?

一张图片胜过千言万语: 我想转换此:

Pos. :123456789
Name. :ABCDEFGHIJKLMNO 
Str. :SOMESTRINGSOMET <---- indented by half a row, Column number superscripted 
Str. :SOM  SOMET 
Str. :SOMESTRIN ET 

这样:

example

我怎样才能做到这一点使用Python?有没有一个框架让我能够做到这一点? 我把它转换成胶乳,但是我不能让上尉编号工作。他们需要在文本之上,但不能作为角色,因为在图片的栏目之间存在关系。

示例:A在位置1.它具有属性S和O,这就是为什么它位于这两个顶部,这就是为什么有一半字符的缩进。 S具有上标170,T具有标185

特别难也是在海峡部分由character.I想一半有一个例子这种融入我的程序转移的一部分。

+3

输出到乳胶或其他一些排版/格式化工具似乎是要走的路。 Python不附带排版库。 –

+0

感谢您的快速回答。我用插画师制作了“正确”的图画。然而,我只是不能得到那些东西,即使与乳胶现在工作:(将更新一旦我进一步。 – tarrasch

+0

这个问题限于单间隔字体? – mmgp

回答

2

有可能拿出解决棘手,考虑单间距字体,可能会解决您的问题。但他们只是在等待失败。您的帖子中的灰色列可以完全按照您的图形添加,但我已选择不更改字母中的颜色(仅仅因为我发现它更易于阅读)。

下面是一些可以拿出PIL:

enter image description here

稍微改变字体:下一个

enter image description here

更 “严重” 字型变化,所有产生的代码原样。

  enter image description here   enter image description here

以及其次是用于生成这些图中的代码。我没有真正做到这一点,并且可以通过多种方式进行改进。把这看作是你需要做的一个例子,或许,为你的问题找到一个解决方案。要使用任何类型的字体,您需要一个实际的排版系统,例如LaTeX。

import sys 
import Image, ImageDraw, ImageFont 


# Assumption: some other piece of code separates the data in the following 
# format. 
line1 = [("Pos. :", 0), ("123456789", 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]) 
+0

awesomeness。正是我在找什么。如果我想要添加更多的行,如下面的Str?我只是改变'为di,枚举数据([line1,line2]):'为di,数据在枚举([line1,line2,linex]):? – tarrasch

+0

是的,那会但是你也需要在'for k,v in line3_1_top.iteritems():...'中调整图形,我会从添加一个'num_lines = x'开始,其中''x'是你的总行数写在你的案例中为4,在我的例子中为3,然后更改代码以绘制处理该下标的代码 – mmgp

+0

实际上我不需要重复该操作,我只是想以与str相同的方式添加更多行。你的代码比我的技能水平高:-)。一旦我得到那份工作,我将奖励赏金。我也想重复line_3_1位每10个字符左右,如列号 – tarrasch

1

这实在是超过一个Python的问题一个LaTeX问题 - 即,如果你确定你想你的Python脚本生成,则实际生成是相当容易的标记。

在这种情况下,我认为你可以用一个相当复杂的表格(\begin{table}...\end{table})得到你想要的效果,其中每个单元格跨越两列,一列用作偏移量以获得“半角“ 你要。如果有LaTeX中做到这一点(它有更多的方式比图书馆我可以保持我的头)一个简单的方法它不会让我感到吃惊,但这是一个想到的人。所以,你的表会是这个样子:

+------+--+--+--+--+--+--+--+ 
| pos. | | 1 | 2 | 3 |  ... 
+------+--+--+--+--+--+--+--+ 
| name.| | A | B | C |  ... 
+------+--+--+--+--+--+--+--+--+ 
|  | 170 |  |  |  | ... 
+------+--+--+--+--+--+--+--+--+ 
| Str. | S | O | M | E | ... 
+------+--+--+--+--+--+--+--+--+ 

(其中+小号指明实际列,且大部分细胞跨越两列该行以“170”就可以将使用\tiny或一些这样的命令。 )

我的建议是玩弄先产生用手LaTeX的文件你想要做什么(或您所选择的文件的一些其他格式化语言);然后担心编写一些Python代码来生成它。

0

尽管PIL的作品确定为简单的东西,你有很多更多的选择,如果你使用SVG。您可以使用pySVG(方便的pySVG tutorial)或svgwrite以编程方式创建您的SVG,或者将其作为文本创建为print。然后使用ImageMagick(在命令行中作为convert或从python使用pythonmagicwand)将SVG呈现为所需的任何栅格类型。虽然微调,您可以用文本编辑器编辑它,看看它在Web浏览器中的SVG :)

# 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') 
相关问题