日記

日本語の勉強のためのブログ

【HTML/JS】画像を分割するプログラムを作成する

1. 背景

JavaScriptを用いた画像処理に興味があったので、まず簡単なプログラムを作成してみることにした。

2. 目的

画像を縦にm分割、横にn分割し、分割した画像を表示するプログラムを作成する。

3. プログラムの処理内容

(ユーザ側)

  1. ユーザが画像を入力する。
  2. ユーザが分割数(m×n)を指定する。
  3. ユーザが分割実行ボタンを押す。

(プログラム側)

  1. 画像を読み込む。
  2. 読み込んだ画像をm×n分割する。
  3. 各画像を表にまとめて表示する。

4. 作成したプログラムのデモ

分割数: 縦に 分割 × 横に 分割

result:

5. 作成したプログラム

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>wanna display an input image</title>
</head>
<body>
    <p>
        分割数: 
        縦に <input type="text" id="n_vertical" size="2" value="2">分割 
        x 
        横に <input type="text" id="n_holizontal" size="2" value="2">分割
    </p>
    <p>
        <input type="file" id="input_image" accept="image/*">
        <input type="submit" id="submit" value="分割!">
    </p>
    <p>
        result: <br>
        <div id="result_area"></div>
    </p>
    <script src="./wanna_input.js"></script>
</body>
</html>

JavaScript

// https://mementoo.info/archives/1617
const object = document.getElementById("input_image");
const submit = document.getElementById("submit");
const select_ver = document.getElementById("n_vertical");
const select_hol = document.getElementById("n_holizontal");
const result_area = document.getElementById("result_area");
const reader = new FileReader();

submit.addEventListener("click", () => {
    let n_ver = parseInt(select_ver.value);
    let n_hol = parseInt(select_hol.value);
    let file = object.files;
    reader.readAsDataURL(file[0]);

    // result全削除
    // https://www.ikemo3.com/inverted/javascript/remove-child-elements/
    result_area.innerHTML = "";

    reader.onload = () => {
        let image = new Image();
        image.onload = () => {
            // canvasの用意
            let canvas = document.createElement("canvas");
            let context = canvas.getContext("2d");

            // 描画に小数があるとぼやけて表示されてしまうらしいので
            // 思い切って端っこは切り捨てることにした
            let splitted_width  = Math.floor(image.width  / n_hol);
            let splitted_height = Math.floor(image.height / n_ver);
            canvas.width = splitted_width;
            canvas.height = splitted_height;

            // ここで分割処理
            // https://developer.mozilla.org/ja/docs/Web/HTML/Element/td
            let table = document.createElement("table");

            for (let y = 0, ny = 0; ny < n_hol; y += splitted_height, ++ny) {
                let tr = document.createElement("tr");
                for (let x = 0, nx = 0; nx < n_ver; x += splitted_width, ++nx) {
                    // https://developer.mozilla.org/ja/docs/Web/API/Canvas_API/Tutorial/Using_images#slicing
                    context.drawImage(image, x, y, splitted_width, splitted_height, 0, 0, splitted_width, splitted_height);
                    let url = canvas.toDataURL();
                    let td = document.createElement("td");
                    td.style = "border: 1px solid;";
                    td.innerHTML = "<img src='" + url + "'>";
                    tr.appendChild(td); 
                }
                table.appendChild(tr);
            }

            // "分割した画像をまとめた表"を表示する
            // https://developer.mozilla.org/ja/docs/Web/API/Node/appendChild
            result_area.appendChild(table);
        }
        image.src = reader.result;
    }
})

6. 参考リンク