author="CKboss"
date="2022-4-19"
title="在Markdown中使用base64存圖片"
+++
在Markdown中使用base64存圖片
使用markdown最大的痛點之一就是上傳圖片時需要額外的圖床, 而圖床又很容意出問題導致圖片丟失.
如果可以把圖片以base64的方式存在markdown文件中, 就可以省去尋找可靠圖床的麻煩.
本文會介紹一個可行的在markdown中使用base64存儲圖片的方案
什么是Data URL
簡單來說, 就是先把圖片或附件轉成base64, 再利用類似 data:[<mediatype>][;base64],<datat>
的形式在html中展示.
DataURL可以方便的將附件以純文本的形式在網頁上保存, 這正是我們想要的.
但需注意, DataURL的缺點也很明顯, base64編碼后文件體積會大上30%, base64格式的圖片在瀏覽器上加載緩慢, base64過長的編碼會讓html文件難以編輯等.
圖片轉base64
有很多在線的工具都可以進行圖片到base64的轉換.
為了離線方便, 還可以使用如下的python代碼將圖片轉成data_url的形式:
import tkinter as tk
from tkinter import filedialog, messagebox
import pyperclip
import cv2
import os
import base64
import tempfile
from pathlib2 import Path
class ImageBase64Optim:
# base64 前綴
@classmethod
def get_img_base64_prefix(cls, img_type):
img_type_map = {
'jpg': 'data:image/jpeg;base64,',
'jpeg': 'data:image/jpeg;base64,',
'png': 'data:image/png;base64,',
}
return img_type_map[img_type.lower()]
# 短邊1080
@classmethod
def shot_edge_resize(cls, img, short_edge=720):
h,w,_ = img.shape
if max(h,w) < short_edge:
return img
if w <= h :
w2 = short_edge
h2 = int( short_edge * h / w + 0.5)
else:
w2 = int( short_edge * w / h + 0.5 )
h2 = short_edge
img = cv2.resize(img,(w2,h2))
return img
# 低質量的jpg
@classmethod
def trans_to_low_quality_img(cls, img_path, tmpimg):
img = cv2.imread(img_path)
img = ImageBase64Optim.shot_edge_resize(img)
cv2.imwrite(tmpimg,img,[cv2.IMWRITE_JPEG_QUALITY, 55])
@classmethod
def base64_img(cls, img_path):
"""
拿到圖片的base64編碼結果
:param img_path 圖片路徑
:rtype: str
"""
with tempfile.NamedTemporaryFile(mode='a+',suffix='.jpg',delete=False) as tmpimg:
tname = tmpimg.name
ImageBase64Optim.trans_to_low_quality_img(img_path,tname)
with open(tname, 'rb') as f:
compress_img_content = f.read()
# 對圖片內容編碼
ret_str = cls.get_img_base64_prefix(os.path.splitext(tname)[1][1:]) + str(base64.b64encode(compress_img_content), 'utf-8')
os.remove(tmpimg.name)
return ret_str
def process(img_path: str):
# img_path = Path('./Microsoft_Nostalgic_Windows_Wallpaper_4k.jpg')
img_path = Path(img_path)
ret = ImageBase64Optim.base64_img(img_path.as_posix())
return ret
def run_gui():
window = tk.Tk()
window.withdraw()
img_file_path = filedialog.askopenfilename()
ret = process(img_file_path)
pyperclip.copy(ret)
messagebox.showinfo(message="base64 already copy.")
def run_cli():
img_file_path = filedialog.askopenfilename()
ret = process(img_file_path)
print(ret)
if __name__=='__main__':
run_gui()
為了讓base64編碼后的圖片體積不過於龐大.
在此代碼中, 對於過大的輸入圖片會將其縮放到短邊1080像素, 同時還在進行jpeg編碼的過程中降低了原有圖像質量.
具體來說, 對於輸入的4k大小的圖片編碼后的base64大小可以控制在300k左右, 圖像質量會有些許損失, 不過對於個人blog來說, 還是足夠使用的.
在Markdown中使用
可以在markdown文件的最后一部分, 以 [p1]: data ......
的形式貼上轉碼后的圖片base64
在markdown文件的正文中, 以 ![][p1]
的形式使用圖片.
很多靜態網站的主題, 是可以自動忽略掉data內容的, 所以不用擔心文章最后有大量的base64編碼看起來像亂碼.
一個使用base64展示圖片的例子
可以打開源碼以供參考