cool-certificate, 一個好玩的證書生成工具

  • 2019 年 12 月 25 日
  • 筆記

前幾天同學發過來一張無人機駕駛證的照片,瞬間覺得很高大上,仔細一詢問,原來是用軟體生成的圖片,網址是:http://wx.znl.cn/app/index.php?i=120&c=entry&id=1&do=index&m=bi_pic。 當訪問該網站的時候,用戶輸入用戶名,然後就生成包含用戶名的駕照照片。我接著想能不能自己做一個類似這樣的東西呢,經過思考發現,其實操作比較簡單,即將用戶姓名寫入到影像上的合適位置即可。因為我之前已經有一些用Python 的Django框架做小的網站的經驗,而且Python PIL模組可以完成這個任務,所以我立即想到, 能不能結合兩者,建立一個網站,讓用戶輸入姓名,然後將用戶姓名傳入到後台,後台調用PIL函數,將名字寫到圖片的相應位置上,然後返回給用戶呢?經過思考我發現這種思路是可行的,而且工作量貌似也不是很大,所以今天早上開始做了做,在無人機駕照的基礎上又增加了2個有趣的證件:潛水證和超級帥哥證,今晚終於作出了一個粗糙的結果(網站頁面使用了原始和簡單的HTML標籤),可以在這裡訪問。程式碼已經上傳到github上了。下面記下來實現過程中的一些思考。

整體實現流程

  1. 用Django實現網站前端和後端,展示頁面給用戶,讀取用戶輸入
  2. 當用戶輸入後,利用POST方法返回用戶名到伺服器端
  3. 對特定的證件和已給的用戶,利用PIL中的ImageFont模組來在證件照片的相應用戶名空當處寫上用戶名,然後保存處理後的圖片。用戶名應該寫在哪裡需要手工確定(我用Windows 的畫圖工具中找到具體的位置坐標)
  4. 將生成的圖片返回給網站頁面

實現的一些細節問題

將文字寫到圖片上

這裡使用PIL(Python Image Library)來做,利用了其中的ImageFont模組,核心的程式碼段如下:

img = Image.open(img_path)                                                                                                                                                   draw = ImageDraw.Draw(img)     font = ImageFont.truetype(font_path, font_size)     #NOTE: django get parameter as unicode, so don't need to encode to unicode.                                                                                                  draw.text(word_pos, name, word_color, font=font)     img.save(out_img_path)

One things you must notice is that Django return stirng in the unicode format, so you dont』t have to do unicode(name, 'utf-8') anymore. 用戶輸入姓名時,生成包含姓名的證件圖片,保存在本地。 在實際操作中發現,有些字體不支援部分中文,所以我在網上下了Aria Unicode字體,經測試發現能顯示所有中文字體。

Django返回處理圖片的格式

我最初想的是用戶點擊確定按鈕後,跳轉到新的頁面,在這個頁面上單獨顯示處理後的照片,所以response類型設置成image/jpeg即可。但實際操作中出現問題,只返回照片似乎有一些問題,所以我修改實現,在傳給Template的時候,傳遞一個參數done, 如果當前沒有增加用戶姓名,則該值為0,否則為1。在Template中,如果值為0,則展示未處理的模板圖片;如果值為1,則顯示處理後的圖片。

靜態文件目錄的設置

Django將CSS,JS和Image圖片都看作靜態文件,推薦在app目錄下建立static目錄來保存這些文件。這裡需要進行一定的設置,將保存模板圖片和生成圖片的目錄imgs增加到static目錄下,設置程式碼如下:

# in settings.py  SITE_ROOT = os.path.join(os.path.abspath(os.path.dirname(__file__)),'')  STATIC_ROOT = os.path.join(SITE_ROOT,'static')  STATIC_URL = '/static/'    #最後關鍵部分需要添加上STATICFILE_DIRS的配置  STATICFILES_DIRS = (      ("css", os.path.join(STATIC_ROOT,'css')),      ("js", os.path.join(STATIC_ROOT,'js')),      ("imgs", os.path.join(STATIC_ROOT,'imgs')),  )

經過這樣設置,在調用imgs目錄下的圖片時就可以這樣調用了:

<img src = "{% static "imgs/feiji.jpg"%}">