JavaScript

【JavaScript】JPG画像のEXIF情報を取得して回転表示させる

JPEG画像はフォトビューワー等で表示すると正しい向きに表示されていても、ブラウザにアップロードすると、向きがおかしく表示されることがある。

JPEG画像はEXIFデータを保持しており、その中のOrientationが画像の回転や反転情報となるため、Orientationの値を反映してブラウザで表示させる。

EXIF情報の取得はexif.jsを用いる。

exif.jsはCDNでも公開されており、本記事ではCDNを利用する。

exif情報の取得や画像の読込処理は非同期で行われるため、ネストが深くなるのを避けるために、async/awaitを用いる。

exif.jsの設定(html)

<script type="text/javascript" src="{{ url_for('static', filename='js/rotate_image.js') }}"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.min.js"></script>
<form method="post" enctype="multipart/form-data">
  <input type="file" name="imgFile" id="imgFile">
</form>
<img id="imgPreview">

ファイルが選択された時に、JavaScriptでブラウザに表示する。

画像回転表示のメイン処理(js)

/*
 * 画像ファイル選択時にブラウザに表示する
 */
document.getElementById("imgFile")
    .addEventListener("change", async function (e) {
    
    let imgElement = new Image();

    //imgタグの要素取得
    let imgPreview = document.getElementById("imgPreview");

    if (e.target.files[0]){
        //exif情報を取得する。
        //取得には時間がかかるのでasync/awaitを使って処理を待つ。
        let orientation = await getOrientation(e.target.files[0]);

        //orientationから回転角度を設定する
        const angle = setAngle(orientation);
        
        //blobUrlを作成する
        let blobUrl = window.URL.reateObjectURL(e.target.files[0]);

        //blobURLから画像データを読み込む
        //画像の読込には時間がかかるのでasync/awaitで処理を待つ。
        imgElenent = await loadImage(blobUrl);
        
        imgPreview.src = imgElement.src;

        //transformで回転角度を設定する。
        imgPreview.style.transform = "rotate(" + angle + "deg)";
        
    }
});

 

exifdata.Orientation取得処理

exif情報の取得は非同期で行われるため、Promiseを使って処理を待つ。exif情報を取得した際に、そのままfunction内で処理を進めることも可能だが、コールバックが重なってネストが深くなるのを避けるために、Promiseを使う。

function getOrientation(imgFile){
    return new Promise( (resolve, reject) => {
        EXIF.getData(imgFile, function() {
            resolve(imgFile.exifdata.Orientation);
            //取得したimgFile.exifdata.Orientationに対し、function内で処理を進めることも可能
        });
    });
}

回転角度の設定処理

取得したOrientationの値に合わせて、回転させる角度を設定する。

function setAngle(orientation){
    switch(orientation){
    case 1:    //回転なし
        angle = 0;
        break;
    case 3:    //元画像を180度回転しているので、180度回転させて元に戻す。
        angle = 180;
        break;
    case 6:    //元画像を270度回転しているので、90度回転させて元に戻す。
        angle = 90;
        break;
    case 8:    //元画像を90度回転しているので、270度回転させて元に戻す。
        angle = 270;
        break;
    default:
        angle = 0;
        break;
    }
    return angle;
}
    

画像データの読み込み処理

ここまでで必要な回転角度は取得できたので、画像データを取得して回転表示させる。画像データ読込も非同期なのでPromiseを使用する。

function loadImage(blobImg){
    return new Promise( (resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = (e) => reject(e);
        img.src = blobImg;
    });
}

画像を90度回転させると、縦と横が入れ替わるため、場合によっては、画像のサイズを取得し、回転角度に合わせて表示させることも必要かもしれない。