「画像をデータURIスキームに変換したい」
「PythonでファイルをData URIで表現したい」
このような場合には、この記事の内容が参考となります。
 この記事では、Pythonで画像をData URIに変換する方法を解説しています。
本記事の内容
- Data URIとは?
 - Base64によるエンコード
 - MIMEタイプの判定
 - 【サンプルコード】画像からData URIへの変換
 
それでは、上記に沿って解説していきます。
Data URIとは?
Data URIは、正確にはData URI scheme(データURIスキーム)と言います。
 次のようなimgタグを見たことがあるでしょう。

このsrcの値が、Data URI形式のデータとなります。
Data URI形式のデータを初めて見たときは、驚いたことを覚えています。
そして、Data URIには構文が定められています。
data:[<MIME-type>][;charset=<encoding>][;base64],<data>
charsetとはありますが、無視します。
base64形式でエンコードする場合は、charsetは指定する必要がありません。
従って、基本的には次の構文を覚えましょう。
data:[<MIME-type>][;base64],<data>
また、Data URIにはメリット・デメリットが存在しています。
正直、今の時代に速度なんてそれほど気にすることはないと思います。
Data URIの最大のメリットは、画像を実際に作成する必要がないことだと捉えています。
 通常は、以下のようにパスに画像を配置しないといけません。
<img src="https://example.com/sample.jpg">
しかし、Data URIでは画像をサーバ上に配置する必要がありません。
これの何が嬉しいのか言うと、サーバの管理面で大いに助かります。
無駄な画像を作らないことで、ディスク容量が節約できます。
そして、無駄な画像を削除するcronを設定する必要もなくなります。
そもそも、画像設置用のディレクトリを設ける必要がありません。
そうなると、書き込み権限を与えて云々も不要になります。
つまり、余計なセキュリティホールを設けなくて済みます。
このように、サーバ管理の面では嬉しいことがあるのです。
 PythonでData URIの恩恵を受けるには、以下の点をクリアする必要があります。
- Base64によるエンコード
 - MIMEタイプの判定
 
以下では、これらについて説明します。
Base64によるエンコード
Python標準モジュールには、base64が用意されています。
そのため、PythonではBase64によるエンコードがデフォルトで利用可能です。
実際のコードを見た方が理解できるでしょう。
 まず、次の画像を用意します。
reddot.png

この画像を読み込んで、Base64でエンコードします。
 そのためのコードは、以下。
import base64
file_path = "reddot.png"
with open(file_path, "rb") as image_file:
    data = base64.b64encode(image_file.read())
    # 文字列に変換
    data_str = data.decode('utf-8')
    print(data_str)
上記を実行した結果は、以下となります。
iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
ここでのポイントは、2つあります。
 コード上に出てくる関数が、そのままポイントになります。
- b64encode
 - decode
 
それぞれを下記で説明します。
b64encode

渡す値も戻り値もbytes型のデータです。
 bytes型の入力値をbytes型のままBase64にエンコードして戻します。
decode

bytes型のデータを指定した文字コードの文字列に変換します。
指定する文字コードは、UTH-8固定で問題はないでしょう。
以上、Base64によるエンコードを説明しました。
 次は、MIMEタイプの判定を説明します。
MIMEタイプの判定
MIMEタイプの判定は、ピンからキリまであります。
ピンは、単純にファイル拡張子からMIMEタイプの判定する方法です。
しかし、この方法は拡張子詐欺に騙されてしまいます。
折角ならば、キリの方法でMIMEタイプの判定を行います。
キリの方法なら、拡張子詐欺には騙されません。
その方法を行うには、python-magicをインストールする必要があります。
 次の記事を参考にして、python-magicをインストールしてください。
では、MIMEタイプの判定を行います。
 コードは、以下を用います。
import magic
file_path = "reddot.png"
with open(file_path, "rb") as image_file:
    # MIMEタイプ取得
    mime_type = magic.from_buffer(image_file.read(), mime=True)
    print(mime_type)
上記を実行した結果は、以下。
image/png
以上、MIMEタイプの判定についての説明でした。
 最後に、実際に画像からData URIへの変換を行います。
【サンプルコード】画像からData URIへの変換
画像からData URIへの変換を行うのは、以下のコードとなります。
import base64
import magic
file_path = "reddot.png"
with open(file_path, "rb") as image_file:
    # bufに格納
    buf = image_file.read()
    # base64のdata取得
    data = base64.b64encode(buf)
    data_str = data.decode('utf-8')
    # MIMEタイプ取得
    mime_type = magic.from_buffer(buf, mime=True)
    # Data URI
    data_uri = "data:" + mime_type + ";base64," + data_str
    print(data_uri)
内容的には、説明してきたコードを組み合わせただけです。
 少し異なるのは、以下ぐらいでしょうか。
    # bufに格納
    buf = image_file.read()
上記コードを実行した結果は、以下となります。
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
Data URIの形式通りのデータにはなっています。
でも、モノをみないと信用できません。
確認のために、次のようなhtmlを用意します。
test.html
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
このhtmlをブラウザで確認しましょう。

ちゃんと画像として表示されていることが確認できました。
以上、画像からData URIへの変換を説明しました。
  
  
  
  

