在Markdown中使用base64存图片
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展示图片的例子
可以打开源码以供参考