在網上有很多使用 python 的 pillow 庫進行圖片壓縮的教程,使用簡單,但是壓縮效果存在明顯的色彩不自然,這是因為 pillow 庫采取的壓縮算法沒有優化的問題。
這個系列實現一款簡單的壓縮工具,使用 pngquant 有損壓縮,壓縮率高達 80%, 而且壓縮后的圖片沒有明顯差異。
上一篇使用了 pngquant 圖片壓縮工具進行壓縮,並通過 click 命令行工具構建了 picom 包。這篇的主要功能是實現圖片上傳。
圖片上傳功能的實現
通過 pngquant 壓縮圖片后,得到一個 -fs8.png 為后綴的圖片。想要把圖片上傳到雲端,只需要把這個文件通過 API 發送給圖片存儲服務商就可以了。
先實現 sm.ms 網站的圖片上傳。官方提供了 API 文檔,照着文檔傳入參數就可以搞定,so easy.
上傳接口的參數說明:
-
content-type 為 multipart/form-data ; -
Authorization 為可選項,當不需要用戶管理時,可以不填; -
傳入文件的參數名為 smfile。
對應的 python 代碼:
api_addr = 'https://sm.ms/api/v2/upload'
files = {
"smfile": open(file, 'rb')
}
res = requests.post(url, files=files)
獲取上傳的圖片地址
文件上傳完畢以后,需要通過 API 的響應結果得到圖片的 URL。 sm.ms 的響應結果包含 2 種情況:
-
當圖片已經上傳過一次,會通過圖片的 hash 值判斷出重復。響應中的 code 為 image_repeated, 可以通過 images 取得之前已存在的圖片地址。
{
"code": "image_repeated",
"images": "https:..."
}
-
當圖片是第一次上傳,code 為 success, 可以通過 data 中的 url 獲取圖片地址。
{
"code": "success",
"data": {
"url": "https:..."
}
}
所以在上傳的函數中添加判斷,獲取圖片 url:
resp = res.json()
code = resp.get('code')
if code == 'image_repeated':
url = resp["images"]
return url
elif code == 'success':
return resp["data"]["url"]
因為有時候並不是上傳單張圖片,而是要上傳整個文件夾下面的圖片,一次性需要處理多張圖片的上傳操作,所以可以共用一個 session, 對應的上傳圖片類:
為命令行添加 --upload 可選參數
現在我可以選擇是否把圖片上傳到網上,如果需要上傳,就添加 --upload 參數;如果不需要上傳,就不傳這個命令行參數:
picom elephant.png -f --upload
增加 --upload 可選參數只需要在 cli 函數上多加一個 option, 然后添加上傳代碼就可以了:
最后得到的運行結果:
通過 yaml 記錄以及上傳過的圖片地址
上面上傳的圖片地址是在命令行顯示的,如果一次性使用還好,但是如果需要重復使用就需要把圖片的 URL 保存起來。
sm.ms 的賬號功能可以管理已經上傳的圖片。所以如果有 sm.ms 的賬號,就不需要這個保存的功能。 但是如果不想去注冊賬號,有一個委曲求全的辦法,就是在當前文件夾創建一個名為 uploaded_img.yaml 的文件,把已經上傳的圖片地址保存起來。
可以通過新建一個選項 --record 來選擇是否記錄在本地。python 可以通過 pyyaml 庫操作 yaml 文件,存儲上傳的圖片數據。 也可以通過 json 格式保存,大致的格式是這樣的:
{
"upload":[
{
"name": "elephant.png",
"url" : "http://img-server/ofos.png"
}
]
}
因為這個功能不是特別重要,甚至可以說雞肋,就不貼代碼了。
總結
上傳圖片功能非常簡單,只需要使用 requests 庫的基礎操作就可以完成各個圖床服務商的上傳操作。如果覺得 requests 庫的操作比較慢,可以采用 aiohttp 進行異步傳輸。 這個工具暫且不考慮加快傳輸速度,因為現在的圖床服務很多都是小本經營,沒什么盈利能力,為了能提供長久服務,還是盡量少的給別人壓力。
