È possibile elaborare soluzioni complicate, considerando i caratteri con spaziatura singola, che potrebbero risolvere il problema. Ma stanno solo aspettando di fallire. Le colonne grigie nel tuo post possono essere aggiunte esattamente come nella tua figura, ma ho scelto di non farlo cambiare i colori nelle lettere (semplicemente perché lo trovo più leggibile in questo modo).
Ecco cosa possibile a venire con PIL:
cambiando leggermente i font:
più "gravi" le modifiche di carattere successivo, tutte prodotte con il codice come è.
E accanto è il codice per la generazione di queste figure. Non l'ho reso davvero carino, e può essere migliorato in molti modi. Consideralo come un esempio di ciò che dovrai fare per, forse, ottenere una soluzione al tuo problema. Per lavorare con qualsiasi tipo di carattere è necessario un sistema di composizione reale, come 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])
Inviare a LaTeX o qualche altro composizione/strumento di formattazione sembra la strada da percorrere. Python non viene fornito con una libreria di composizione. –
grazie per la rapida risposta. Ho realizzato il grafic "giusto" con l'illustratore. tuttavia non riesco a far funzionare quella roba anche con latex in questo momento :(aggiornerò una volta che avrò un ulteriore passo. – tarrasch
Questa domanda è limitata ai caratteri mono distanziati? – mmgp