5

プログラムの出力を甘くするために、いくつかの機能を実現しようとしています。テキストの列の背景を特定の色に設定して、列が一緒に属していることがより明確になるようにしたいと考えています。

百聞は一見に如かず: これを変換したい:

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 があります。そのため、これら 2 つの上にあり、半文字のインデントがあります。S の上付き文字は 170、T の上付き文字は 185 です。

特に難しいのは、Str 部分が半文字ずれる部分です。これを私のプログラムに統合する例を示したいと思います。

4

3 に答える 3

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])
于 2012-12-18T04:07:16.720 に答える
1

これは、実際には Python の質問というよりも LaTeX の質問です。つまり、Python スクリプトで生成するマークアップを決定した場合、実際にそれを生成するのはかなり簡単です。

\begin{table}...\end{table}この場合、それぞれのセルが 2 つの列にまたがり、必要な「半文字」を取得するためのオフセットとして 1 つの列が使用される、かなり複雑なテーブル ( ) で必要な効果をおそらく得ることができると思います。LaTeX でこれを行う簡単な方法があったとしても驚かないでしょう (LaTeX には頭に入れておくよりもはるかに多くのライブラリがあります) が、それが頭に浮かぶものです。したがって、テーブルは次のようになります。

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

( +s は実際の列がどこにあるかを示し、ほとんどのセルは 2 つの列にまたがっています。「170」を含む行は、\tinyまたはそのようなコマンドを使用します。)

私の提案は、最初に手動でLaTeXファイルを生成して遊んでみることです。そして、それを生成するための Python コードを書くことについて心配します。

于 2012-12-13T15:08:43.250 に答える
0

PIL は単純なものには問題なく機能しますが、SVG を使用する場合はさらに多くのオプションがあります。pySVG (便利なpySVG チュートリアル) または 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')
于 2012-12-18T21:37:48.087 に答える