markdown将图片转换为base64格式

1 背景

Markdown 是一种轻量级标记语言,使人可以将时间都花在撰写内容而不是调整格式上,用来写技术文档再合适不过了。但markdown有个痛点---添加图片不方便。

markdown添加图片的方法:

  • 方法1:插入本地图片(支持绝对路径和相对路径)
![avatar](/home/picture/1.png)
  • 方法2:插入网络图片
![avatar](https://baidu.com/pic/doge.png)

如果图片在本地,markdown中插入本地图片,这样做缺点很多:
1 本地图片路径更改或丢失导致markdown找不到图片;
2 分享不灵活,mk文档发给别人时,找不到图片路径。

插入网络图片,需要自己制造图床,写文档时并不方便,另外看文档时需要网络环境。

还有一种办法,用base64转码工具,把图片转成一段字符串,然后引用这段base64编码即可,这样添加图片比较方便,但是需要一些多的动作。

  • 方法3:图片转为base64
![avatar][doge] 

# 放在文章末尾
[doge]:data:image/png;base64,iVBORw0...... 

2 图片转为base64

2.1 剪切板图片转为base64

在添加图片时,大多数情况可以使用截图工具(常用snipaste),将截图复制到剪切板,然后运行python脚本,将剪切板的截图转为base64格式字符串,然后将此字符串贴回到剪切板,供我们粘贴使用。

img2base64.py内容如下:

(python3脚本,脚本来源于网络)

import base64
from PIL import Image
from PIL import ImageGrab
import pyperclip
from io import BytesIO

im = ImageGrab.grabclipboard()

def pil_base64(image):
    img_buffer = BytesIO()
    w, h = image.size
    # image.thumbnail((480, 480))
    image.save(img_buffer, format='JPEG', quality=95)
    byte_data = img_buffer.getvalue()
    base64_str = base64.b64encode(byte_data)
    return base64_str

if isinstance(im, Image.Image):
    print(im.format, im.size, im.mode)
    px = im.load()
    msg = str(pil_base64(im))
    msg = 'data:image/png;base64,' + msg[2:-2]
    #print(msg)
    pyperclip.copy(msg)

else:
    pass

为了方便使用,可以将这个脚本制作成exe可执行程序。

# 生成可执行文件

pip install pyinstaller
pyinstaller -F -w img2base64.py  #打包成exe, 在且不包含控制台,exe默认在dist目录下

2.2 将markdown本地图片转为base64格式

写markdown文档时,如果像2.1节一样,一张图一张图转base64,但效率比较低,我们也可以写文档时先临时插入本地图片,写完之后通过脚本一次性生成base64的形式。

脚本有如下要求:

  • 1 读取markdown文件,并用正则查找出所有的本地引用标签
  • 2 替换图片标签![image-name](url)![image-name][image-name]
  • 3 在md文件后面追加上base64编码 [image-name]:图片base64编码

mark2base64.py脚本如下:

import sys
import re
import base64
import chardet

images_suffix = ["gif", "png", "jpg", "jpeg"]

appendix = []

def transform(lines):
    newlines = []
    pattern = re.compile(r'!\[(.*)\]\((.*)\)', re.I) # 正则匹配
    for line in lines:
        li = pattern.findall(line)
        if not li:
            newlines.append(line)
            continue
        for match in li:
            img_name = match[0]
            img_path = match[1]
            if not img_name or not img_path:
                newlines.append(line)
                continue
            if 'http' in img_path: # skip http img
                newlines.append(line)
                continue
            suffix = img_path.rsplit(".")[1]
            if suffix in images_suffix:
                try:
                    with open(img_path, 'rb') as f:
                        image_bytes = base64.b64encode(f.read())
                except:
                    newlines.append(line)
                    continue
                image_str = str(image_bytes)
                #print(image_str)
                base64_pre = 'data:image/' + suffix + ';base64,'
                real_image_str = base64_pre + image_str[2:len(image_str) - 1]
                appendix.append('[' + img_name + ']' + ':' + real_image_str + '\n\n\n')
                line = line.replace('(' + img_path + ')', '[' + img_name + ']')
        newlines.append(line)    
                
    return newlines

def md_2_img(markdown_file):
    if not markdown_file.endswith('.md'):
        return
    code = chardet.detect(open(markdown_file, 'rb').read())['encoding']
    with open(markdown_file, 'r',  encoding=code) as mk:
        lines = mk.readlines()
    newlines = transform(lines)
    with open(markdown_file, 'w',  encoding=code) as mk:
        mk.writelines(newlines)
    with open(markdown_file, 'a+',  encoding=code) as mk:
        mk.write("\n\n")
        mk.write("".join(appendix))

if __name__ == '__main__':
    markdown_file = sys.argv[1]
    print(markdown_file)
    md_2_img(markdown_file)

参考:

  1. markdown中图片转base64
  2. 一款图片文件转 Base64 编码的 Python GUI 工具
posted @ 2022-10-17 07:55  sureZ_ok  阅读(1983)  评论(0编辑  收藏  举报