編集 - javascript 画像 回転




JSクライアント側Exifオリエンテーション:JPEGイメージの回転とミラーリング (6)

デジタルカメラの写真は、しばしばEXIFの "orientation"タグを付けてJPEG形式で保存されます。 正しく表示するには、どの向きが設定されているかによってイメージを回転/ミラーリングする必要がありますが、ブラウザはこの情報を無視してイメージをレンダリングします。 大規模な商用Webアプリケーションであっても、EXIFオリエンテーションのサポートは不十分です1 。 同じソースには、JPEGが持つ8つの異なる向きの素敵な要約もあります:

サンプル画像は4入手可能です。

質問はクライアント側でイメージを回転/ミラーリングして、正しく表示され、必要に応じてさらに処理できるようにする方法です。

方向属性2を含むEXIFデータを解析するためのJSライブラリがあります。 Flickrは、大規模な画像を解析する際に起こりうるパフォーマンスの問題を指摘し、Webワーカー3使用を必要としていました3

コンソールツールは画像の向きを正しく変更できます。 この問題を解決するPHPスクリプトは6で入手できます


@fareed namroutiの答えに加えて、

イメージがファイル入力要素からブラウズされる必要がある場合は、これを使用する必要があります

<input type="file" name="file" id="file-input"><br/>
image after transform: <br/>
<div id="container"></div>

<script>
    document.getElementById('file-input').onchange = function (e) {
        var image = e.target.files[0];
        window.loadImage(image, function (img) {
            if (img.type === "error") {
                console.log("couldn't load image:", img);
            } else {
                window.EXIF.getData(image, function () {
                    console.log("load image done!");
                    var orientation = window.EXIF.getTag(this, "Orientation");
                    var canvas = window.loadImage.scale(img,
                        {orientation: orientation || 0, canvas: true, maxWidth: 200});
                    document.getElementById("container").appendChild(canvas);
                    // or using jquery $("#container").append(canvas);
                });
            }
        });
    };
</script>

OK @ user3096626に加えて、私は誰かがコード例を提供した場合、それはより役立つと思う、次の例は、画像の向きを修正する方法を示すURL(リモート画像)から来る:

解決策1:javascriptを使用する(推奨)

  1. ロードイメージライブラリはurlイメージ(ファイル/ blob)からexifタグを抽出しないため、 exif-jsJavaScript-Load-Image javascriptライブラリの両方を使用しますので、最初にこれらのライブラリを次のようにページに追加してください:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.1.0/exif.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-scale.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-orientation.min.js"></script>
    

    exif-jsのバージョン2.2に問題があることに注意してください 。2.1を使用しました。

  2. 基本的には

    a - window.loadImage()を使用して画像をロードする

    b - window.EXIF.getData()を使用してexifタグをwindow.EXIF.getData()

    c - 画像をキャンバスに変換し、 window.loadImage.scale()を使用して画像の向きを固定します。

    d - 文書にキャンバスを配置する

どうぞ :)

window.loadImage("/your-image.jpg", function (img) {
  if (img.type === "error") {
    console.log("couldn't load image:", img);
  } else {
    window.EXIF.getData(img, function () {
        var orientation = EXIF.getTag(this, "Orientation");
        var canvas = window.loadImage.scale(img, {orientation: orientation || 0, canvas: true});
        document.getElementById("container").appendChild(canvas); 
        // or using jquery $("#container").append(canvas);

    });
  }
});

もちろんキャンバスオブジェクトからbase64としてイメージを取得し、それをimg src属性に配置することもできます。そうすればjQueryを使用することができます;)

$("#my-image").attr("src",canvas.toDataURL());

ここに完全なコードはあります:github: https://github.com/digital-flowers/loadimage-exif-example : https://github.com/digital-flowers/loadimage-exif-example

解決策2:html(ブラウザのハック)

非常に速くて簡単なハックがありますが、ほとんどのブラウザは画像が新しいタブの中に直接HTML内に開かれていれば正しい向きで画像を表示します(LOLはなぜわかりません)ので、基本的にiframeを使って画像を表示できますiframe src属性を画像URLとして直接渡すことで、

<iframe src="/my-image.jpg"></iframe>

解決策3:cssを使用する(iosのfirefox&safariのみ)

画像の向きを修正するためにcss3属性がありますが、問題はFirefoxとSafari / iosでしか動作しません。すぐに言及する価値があります。すぐにすべてのブラウザ(ブラウザのサポート情報をcaniuseから利用できるようになります)

img {
   image-orientation: from-image;
}

Mederrのコンテキスト変換は完全に機能します。 オリエンテーションを抽出する必要がある場合は、 この関数のみを使用してください。EXIF読み込みライブラリは必要ありません。 以下は、Base64イメージの方向を再設定するための関数です。 それはそれのための謎です 。 私はオリエンテーション抽出のデモでフィドルを準備しました。

function resetOrientation(srcBase64, srcOrientation, callback) {
  var img = new Image();    

  img.onload = function() {
    var width = img.width,
        height = img.height,
        canvas = document.createElement('canvas'),
        ctx = canvas.getContext("2d");

    // set proper canvas dimensions before transform & export
    if (4 < srcOrientation && srcOrientation < 9) {
      canvas.width = height;
      canvas.height = width;
    } else {
      canvas.width = width;
      canvas.height = height;
    }

    // transform context before drawing image
    switch (srcOrientation) {
      case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
      case 3: ctx.transform(-1, 0, 0, -1, width, height ); break;
      case 4: ctx.transform(1, 0, 0, -1, 0, height ); break;
      case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
      case 6: ctx.transform(0, 1, -1, 0, height , 0); break;
      case 7: ctx.transform(0, -1, -1, 0, height , width); break;
      case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
      default: break;
    }

    // draw image
    ctx.drawImage(img, 0, 0);

    // export base64
    callback(canvas.toDataURL());
  };

  img.src = srcBase64;
};

githubプロジェクトのJavaScript-Load-Imageは、EXIFの向きの問題を完全に解決し、8つのexif方向の画像を正しく回転/ミラーリングします。 javascriptのexifオリエンテーションのオンラインデモをご覧ください。

イメージはHTML5キャンバスに描画されます。 その正しいレンダリングは、 js/load-image-orientation.jsキャンバス操作によって実装されています。

これで誰かが時間を節約し、このオープンソースの宝石について検索エンジンを教えてくれることを願っています:)


入力コントロールのファイルを持っている人には、その方向性が分からず、少し怠け者であり、@WunderBartが提供するコードがリンクされているコードでリンクされていますhttps://.com/a/32490603 )、オリエンテーションを検索します。

function getDataUrl(file, callback2) {
        var callback = function (srcOrientation) {
            var reader2 = new FileReader();
            reader2.onload = function (e) {
                var srcBase64 = e.target.result;
                var img = new Image();

                img.onload = function () {
                    var width = img.width,
                        height = img.height,
                        canvas = document.createElement('canvas'),
                        ctx = canvas.getContext("2d");

                    // set proper canvas dimensions before transform & export
                    if (4 < srcOrientation && srcOrientation < 9) {
                        canvas.width = height;
                        canvas.height = width;
                    } else {
                        canvas.width = width;
                        canvas.height = height;
                    }

                    // transform context before drawing image
                    switch (srcOrientation) {
                        case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
                        case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
                        case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
                        case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
                        case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
                        case 7: ctx.transform(0, -1, -1, 0, height, width); break;
                        case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
                        default: break;
                    }

                    // draw image
                    ctx.drawImage(img, 0, 0);

                    // export base64
                    callback2(canvas.toDataURL());
                };

                img.src = srcBase64;
            }

            reader2.readAsDataURL(file);
        }

        var reader = new FileReader();
        reader.onload = function (e) {

            var view = new DataView(e.target.result);
            if (view.getUint16(0, false) != 0xFFD8) return callback(-2);
            var length = view.byteLength, offset = 2;
            while (offset < length) {
                var marker = view.getUint16(offset, false);
                offset += 2;
                if (marker == 0xFFE1) {
                    if (view.getUint32(offset += 2, false) != 0x45786966) return callback(-1);
                    var little = view.getUint16(offset += 6, false) == 0x4949;
                    offset += view.getUint32(offset + 4, little);
                    var tags = view.getUint16(offset, little);
                    offset += 2;
                    for (var i = 0; i < tags; i++)
                        if (view.getUint16(offset + (i * 12), little) == 0x0112)
                            return callback(view.getUint16(offset + (i * 12) + 8, little));
                }
                else if ((marker & 0xFF00) != 0xFF00) break;
                else offset += view.getUint16(offset, false);
            }
            return callback(-1);
        };
        reader.readAsArrayBuffer(file);
    }

そのように簡単に呼び出すことができます

getDataUrl(input.files[0], function (imgBase64) {
      vm.user.BioPhoto = imgBase64;
});

私は混合ソリューション(PHP + CSS)を使用しています。

コンテナは以下の目的で必要です。

  • div.imgCont2コンテナを回転させる必要がありました。
  • div.imgCont1コンテナはdiv.imgCont1に必要 - width:150% ;
  • div.imgCont画像がzoomOutの場合、スクロールバーに必要なコンテナ。

<?php
    $image_url = 'your image url.jpg';
    $exif = @exif_read_data($image_url,0,true);
    $orientation = @$exif['IFD0']['Orientation'];
?>

<style>
.imgCont{
    width:100%;
    overflow:auto;
}
.imgCont2[data-orientation="8"]{
    transform:rotate(270deg);
    margin:15% 0;
}
.imgCont2[data-orientation="6"]{
    transform:rotate(90deg);
    margin:15% 0;
}
.imgCont2[data-orientation="3"]{
    transform:rotate(180deg);
}
img{
    width:100%;
}
</style>

<div class="imgCont">
  <div class="imgCont1">
    <div class="imgCont2" data-orientation="<?php echo($orientation) ?>">
      <img src="<?php echo($image_url) ?>">
    </div>
  </div>
</div>




exif