第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。実現していく過程での記録など。読書、IT系、旅行、お金に関係する話などの話題。

インラインで(テキストで)画像をHTMLに埋め込む (Go,Javaで画像データをBase64に)

通常 HTML に画像を埋め込む場合には、画像ファイルがあって、その画像ファイルを img タグの src 属性で参照することになります。

<img src="example.png" alt="サンプル画像">

画像ファイルを表示させるには、この方法だけではなく、Data URI スキームと言われる仕様があり、インラインで(テキストで)画像を HTML に埋め込むことも可能です。以下のような感じになり、画像データがBase64のデータとしてテキストで埋め込まれています。(Base64データが長いので割愛しています)

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANIAAADSCAIAAACw+wkVAAALX0lEQVR42u2drXLcWBCFBxgEGBgEDPADBBgE+MEMAgLMDf0IAQZ+BANDP0hAQIChgeGLi6+ffv269evLrO7v7/fbrcetHiLs7Ozu7u7vNkNNufhij+jbnmb4t/W8/Nzj1W86/N+//4dM7shnvNMRQVXV1cxs...==">

今回はこれをどうやるのか、というお話です。

なぜインラインでわざわざ埋め込むの?何がうれしいのか?ですが、HTML の中に画像情報をデータとして埋め込んで1セット(1ファイル)で扱えるので、HTTP のリクエスト数を減らせるメリットがあります。また、プログラムで動的に画像データを生成する場合などには、ファイルに書き出すこと無しにそのまま HTML に埋め込めるのでなかなか便利です。

Data URI スキームとは

Data URI スキームは、インラインで画像を HTML に埋め込む仕様で、RFC 2397 で定義されている標準仕様です。

ja.wikipedia.org tools.ietf.org

現在ではほとんどのブラウザで対応されています。

caniuse.com

IE、Edge にちょっと制限があります。上記サイトに詳細はありますが、ざっくりとは以下の通りです。

  • 容量制限。IE8 は最大 32KB まで。それ以外は、最大 4GB まで。

img タグに Base64 データで埋め込む書式は以下のような感じで定義されています。

data:[<mediatype>][;base64],<data>

<data>部に画像データを Base64 に変換したデータを埋め込みます。

Go で画像データを Base64 のテキストデータに

画像データの Base64 データへの変換ですが、どのようにやるのでしょうか。画像データをアップロードすれば Base64 データを作成してくれる Web のサービスなどもありますが、ここでは、実装してみます。

package main

import (
    "encoding/base64"
    "fmt"
    "log"
    "os"
)

func main() {
    var err error
    file, err := os.Open("1adeddb3a3462f52a576abddb359e55e.png")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    fi, _ := file.Stat()
    size := fi.Size()
    data := make([]byte, size)

    if _, err = file.Read(data); err != nil {
        log.Fatal(err)
    }

    fmt.Println(base64.StdEncoding.EncodeToString(data))
}

上記を実行すると標準出力に画像ファイル(1adeddb3a3462f52a576abddb359e55e.png)の Base64 データが出力されます。

Data URI Scheme sample data

出力された Base64 データを Data URI スキームの書式に倣って HTML に貼り付けます。

Data URI Scheme Sample HTML

正しく表示されているようです。

f:id:dr_taka_n:20190914084626p:plain:w300

Base64 自体が冗長なデータフォーマットですので、実際の画像データよりサイズが大きくなってしまうというデメリットもありますが、使いどころはありそうです。

Java で画像データを Base64 のテキストデータに

Java (1.8)でもやってみましたので、メモしておきます。

package com.example.sample;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;

public class Main {

    public static void main(String[] args) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            BufferedImage image = ImageIO.read(new File("1adeddb3a3462f52a576abddb359e55e.png"));
            ImageIO.write(image, "png", outputStream);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }

        String base64EncodedImageString = Base64.getEncoder().encodeToString(outputStream.toByteArray());
        System.out.println(base64EncodedImageString);
    }
}