2009-12-19 20 views
5

此圖像是用PIL創建的。看看這張圖片中的g和y是如何切斷的?我怎樣才能防止這一點?字體與PIL剪輯

http://img109.imageshack.us/img109/8874/screenshotep.png

創建此圖像的代碼是非常直截了當(略):

import Image, ImageDraw, ImageFont 

im = Image.new("RGBA", (200, 200), 'white') 
draw = ImageDraw.Draw(im) 

font = ImageFont.truetype("VeraSe.ttf", 12) 

draw.text(
      (1, 1), 
      " %s: " % "ggjyfFwe__", 
      font=font, 
      fill='black' 
) 

draw.text(
      (1, 30), 
      " %s" % 15, 
      font=font, 
      fill='black' 
) 

im.show() 

我有一些不同的字體試了一下,它總是被剪掉。令人驚訝; y,谷歌「PIL字體剪輯」返回很少有用的命中...我在Ubuntu 9.10上使用python 2.6.4和PIL 1.1.6

+0

更好地告訴我們你試過的具體字體,以及你在哪個平臺上。我剛剛在Win7上用consola.ttf嘗試過,並且沒有看到你看到的背景覆蓋。 –

+0

不幸的是,我沒有VeraSe.ttf在這裏,你還沒有提到你的平臺。我懷疑Linux,而不是Windows,並且這是一個特定於平臺的問題。 –

+0

對於我來說,使用Python 9.10中Python 2.6的PIL 1.1.7的georgia.ttf(msttcorefonts包的一部分)也會發生這種情況。這似乎是PIL的一個問題,無論它臨時呈現的緩衝區不夠高。 –

回答

0

我的建議是,在創建圖像對象之前,獲取文本所需的大小。

這是使用font.getsize("text")documentation)完成的。

在我製作的圖片生成腳本中,我首先通過調用font.getsize("Åj")(如果您只需要US-ASCII,您可以找到"Aj"的高度)的等價函數來找到一行文本的最大高度。然後我計算了所需的圖像高度和線偏移量,包括邊距和線間距。

+0

我已經嘗試過類似的東西。如果線條高度不夠,PIL將重疊文本而不是剪裁它... – priestc

1

我無法使用迄今爲止提到的方法解決某些字體的問題,所以我最終使用aggdraw作爲PIL文本drawig方法的透明替代品。

您的代碼重寫,以aggdraw會是什麼樣子:

import Image 
import aggdraw 

im = Image.new("RGBA", (200, 200), 'white') 
draw = aggdraw.Draw(im) 

# note that the color is specified in the font constructor in aggdraw 
font = aggdraw.Font((0,0,0), "VeraSe.ttf", size=12, opacity=255) 

draw.text((1, 1), " %s: " % "ggjyfFwe__", font) # no color here 
draw.text((1, 30), " %s" % 15, font) 

draw.flush() # don't forget this to update the underlying PIL image! 

im.show() 
+0

工程!雖然Aggdraw需要在Windows上進行一些修補,但是對於崩潰(http://comments.gmane.org/gmane.comp.python.image/1959)的aggdraw.cxx和使用Freetype2(從gnuwin32獲得一個)的setup.py進行構建。 – ogurets

0

「蟲」 依然存在,2012年,與Ubuntu 11.10。 Fontsize 11,12,13和15將下劃線完全剪切。

#!/usr/bin/env python 
""" demonstrates clipping of descenders for certain font sizes """ 
import Image, ImageDraw, ImageFont 
fontPath = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf" 
im = Image.new('L', (256, 256)) 
ys=15 
for i in range(10,21): 
    fh = ImageFont.truetype(fontPath, i) 
    sometext="%dgt_}" % (i) 
    ImageDraw.Draw(im).text((10, ys),sometext , 254, fh) 
    ys+=i+5 
im.show() 
+1

查看下面的替代使用aggdraw ... –

0

這是一個適合我的kludge。這是關於gnud的答案的一個變種。 (與我希望的評論相比,值得單獨回答與評論不同)我已經測試了很多單詞展示位置,並且一直執行此操作。

如果繪製的文本未完全達到字體的整個高度,則可能會發生裁剪。正如gnud指出的那樣,通過使用諸如「Aj」(我使用「Fj」)這樣的字符,您可以避免此錯誤。

每當一個字放在:

1)做一個draw.textsize(文字,字體=字體)你需要的單詞。存儲高度/寬度。 2)在單詞的末尾添加'Fj'(spaceFJ),並重新設置文本大小並存儲第三個高度/寬度。

4)您將使用第2項中的單詞(末尾帶有'Fj')進行實際文字繪製。有了這個附錄將保持字體不被剪輯。

4)在你進行實際的文本繪製之前,裁剪'Fj'所在的圖像(需要crop.load()以避免延遲複製)。然後繪製文本,並將裁剪後的圖像重新放在'Fj'上。

這個過程避免了剪輯,看起來合理的表現,併產生完整的,未剪輯的文本。以下是我爲此使用的一段Python代碼的複製/粘貼。部分例子,但希望它增加了一些見解。

# note: xpos & ypos were previous set = coordinates for text draw 
    #  the hard-coded addition of 4 to c_x likely will vary by font 
    #  (I only use one font in this process, so kludged it.) 
    width, height = draw.textsize(word, font=font) 
    word2 = word + ' Fj' 
    width2, height2 = draw.textsize(word2, font=font) 
    # crop to overwrite ' Fj' with previous image bits 
    c_w = width2 - width 
    c_h = height2 
    c_x = xpos + width + 4 
    c_y = ypos 
    box = (c_x, c_y, c_x + c_w, c_y + c_h) 
    region = img.crop(box) 
    region.load() 
    draw.text((xpos, ypos), word2, (0,0,0), font=font) 
    img.paste(region, box)