在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展示圖片的例子

可以打開源碼以供參考



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM