質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

Exif情報を含むアップロード画像をCanvasで描画する際のExif内の回転情報を反映させる方法について

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,106

23appswork

score 9

 前提・実現したいこと

Canvasを用いてアップロードした画像をハート形に切り抜き、さらにハート形の枠をつけたものを描画する、というものを作っています。枠の色・大きさを変える、画像のサイズ・位置を変える、ところまではできたのですが、アップロードした画像をCanvasを用いて描画する際に、画像に含まれる回転情報を反映させて描画させたいのですが、うまく動作させることができません。

 Uncaught ReferenceError: h is not defined


というエラーメッセージが出ます。前回の質問でアドバイスいただいたexif.jsを用いて実現させたいと思いますが、わかる方がいらっしゃいましたら、ご教示お願い申し上げます。

 発生している問題・エラーメッセージ

index.html:117 Uncaught ReferenceError: h is not defined
    at Image.<anonymous> (index.html:117)
    at handleBinaryFile (exif.js:379)
    at getImageData (exif.js:386)
    at Function.EXIF.getData (exif.js:983)
    at Image.bgImg.onload (index.html:94)

 該当のソースコード

function canvasDraw() {

    ctx.clearRect(0, 0, 300, 300);
        var borderSize = document.getElementById('wakuSize').value;
        var amp = document.getElementById('gazouSize').value;
    var bgImg = new Image();
        bgImg.src = uploadImgSrc;
        bgImg.onload = function() {
        EXIF.getData(bgImg, function () {
              var width = bgImg.width;
              var height = bgImg.height;
              var rotate = 0;
              if (EXIF.pretty(this)) {
                if (EXIF.getAllTags(this).Orientation == 6) {
                  rotate = 90;
                } else if (EXIF.getAllTags(this).Orientation == 3) {
                  rotate = 180;
                } else if (EXIF.getAllTags(this).Orientation == 8) {
                  rotate = 270;
                }
              }
              if (rotate == 90 || rotate == 270) {
                canvas.width = height;
                canvas.height = width;
              } else {
                canvas.width = width;
                canvas.height = height;
              }
              if (rotate && rotate > 0) {
                ctx.rotate(rotate * Math.PI / 180);
                if (rotate == 90)
                  ctx.translate(0, -h);
                else if (rotate == 180)
                  ctx.translate(-w, -h);
                else if (rotate == 270)
                  ctx.translate(-w, 0);
              }
});

 全体のソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Language" content="ja">
<title>mask</title>
<style>
#test1 {position: absolute; z-index: 0;}
#test2 {position: absolute; z-index: 1;}
</style>
</head>
<body>
<p><input type="file" id="file" accept='image/*' value="画像を選択"></p>
<p>
    <input type="range" id="gazouSize" value="0.3" min="0.1" max="2.0" step="0.05"> 画像の拡大率<br>
    <input type="range" id="gazouX" value="0" min="-1000" max="1000" step="1"> 画像の X方向<br>
    <input type="range" id="gazouY" value="0" min="-1000" max="1000" step="1"> 画像の Y方向<br>
    <input type="color" id="st1Color" value="#e50031"> 枠色の変更<br>
    <input type="range" id="wakuSize" value="280" min="200" max="290" step="10"> 枠の太さ
    </p>


<div id="mask">
    <canvas id="test1"></canvas>
    <canvas id="test2"></canvas>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.js"></script>
<script type="text/javascript">
(function () {

var stage = document.getElementById('test1');
var ctx = stage.getContext('2d');
var width = 300;
var height = 300;
stage.width = width;
stage.height = height;
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 300, 300);
ctx.globalCompositeOperation = "destination-in";
var img = new Image(); 
img.addEventListener("load", function() {
}, false);
img.onload = function(){
ctx.drawImage(img,0, 0, 300, 300);
};
img.src = 'https://www.fastpic.jp/images.php?file=1088858754.png';

$('#st1Color').change(function() {
ctx.fillStyle = $(this).val();
ctx.globalCompositeOperation = "source-in";
ctx.fillRect(0, 0, 300, 300);
});

})();

(function () {
    var canvas = document.getElementById('test2');
    canvas.width = 300;
    canvas.height = 300;
    var ctx = canvas.getContext('2d');
    var file = document.getElementById('file');
    var uploadImgSrc;
    function loadLocalImage(e) {
    var fileData = e.target.files[0];
    if(!fileData.type.match('image.*')) {
        alert('画像を選択してください');
        return;
    }

    var reader = new FileReader();
    reader.onload = function() {
        uploadImgSrc = reader.result;
        canvasDraw();
    }

    reader.readAsDataURL(fileData);
    }


file.addEventListener('change', loadLocalImage, false); 



function canvasDraw() {

    ctx.clearRect(0, 0, 300, 300);
        var borderSize = document.getElementById('wakuSize').value;
        var amp = document.getElementById('gazouSize').value;
    var bgImg = new Image();
        bgImg.src = uploadImgSrc;
        bgImg.onload = function() {
        EXIF.getData(bgImg, function () {
              var width = bgImg.width;
              var height = bgImg.height;
              var rotate = 0;
              if (EXIF.pretty(this)) {
                if (EXIF.getAllTags(this).Orientation == 6) {
                  rotate = 90;
                } else if (EXIF.getAllTags(this).Orientation == 3) {
                  rotate = 180;
                } else if (EXIF.getAllTags(this).Orientation == 8) {
                  rotate = 270;
                }
              }
              if (rotate == 90 || rotate == 270) {
                canvas.width = height;
                canvas.height = width;
              } else {
                canvas.width = width;
                canvas.height = height;
              }
              if (rotate && rotate > 0) {
                ctx.rotate(rotate * Math.PI / 180);
                if (rotate == 90)
                  ctx.translate(0, -h);
                else if (rotate == 180)
                  ctx.translate(-w, -h);
                else if (rotate == 270)
                  ctx.translate(-w, 0);
              }
});
        ctx.globalCompositeOperation = 'source-over';
        ctx.drawImage(bgImg, 0, 0, bgImg.naturalWidth * amp, bgImg.naturalHeight * amp, );

        drawMask();
    }

    var drawMask = function () {
        ctx.globalCompositeOperation = 'destination-in';
        var maskImg = new Image();
        var borderSize = document.getElementById('wakuSize').value;
        maskImg.onload = function () {
        ctx.drawImage(maskImg, (300 - borderSize) / 2, (300 - borderSize) / 2 , borderSize, borderSize );
        };
        maskImg.src = 'https://www.fastpic.jp/images.php?file=1088858754.png';

            $('#wakuSize').change(function() {
            var borderSize = document.getElementById('wakuSize').value;
            var amp = document.getElementById('gazouSize').value;
            var x = document.getElementById('gazouX').value;
            var y = document.getElementById('gazouY').value;
            ctx.clearRect(0, 0, 300, 300);
        ctx.globalCompositeOperation = 'source-over';
        ctx.drawImage(bgImg, x, y, bgImg.naturalWidth * amp, bgImg.naturalHeight * amp);
            ctx.globalCompositeOperation = "destination-in";
            ctx.drawImage(maskImg, (300 - borderSize) / 2, (300 - borderSize) / 2 , borderSize, borderSize );
});


            $('#gazouSize').change(function() {
            var borderSize = document.getElementById('wakuSize').value;
            var amp = document.getElementById('gazouSize').value;
            var x = document.getElementById('gazouX').value;
            var y = document.getElementById('gazouY').value;
            ctx.clearRect(0, 0, 300, 300);
        ctx.globalCompositeOperation = 'source-over';
        ctx.drawImage(bgImg, x, y, bgImg.naturalWidth * amp, bgImg.naturalHeight * amp);
            ctx.globalCompositeOperation = "destination-in";
            ctx.drawImage(maskImg, (300 - borderSize) / 2, (300 - borderSize) / 2 , borderSize, borderSize );
});

            $('#gazouX').change(function() {
            var borderSize = document.getElementById('wakuSize').value;
            var amp = document.getElementById('gazouSize').value;
            var x = document.getElementById('gazouX').value;
            var y = document.getElementById('gazouY').value;
            ctx.clearRect(0, 0, 300, 300);
        ctx.globalCompositeOperation = 'source-over';
        ctx.drawImage(bgImg, x, y, bgImg.naturalWidth * amp, bgImg.naturalHeight * amp);
            ctx.globalCompositeOperation = "destination-in";
            ctx.drawImage(maskImg, (300 - borderSize) / 2, (300 - borderSize) / 2 , borderSize, borderSize );
});
            $('#gazouY').change(function() {
            var borderSize = document.getElementById('wakuSize').value;
            var amp = document.getElementById('gazouSize').value;
            var x = document.getElementById('gazouX').value;
            var y = document.getElementById('gazouY').value;
            ctx.clearRect(0, 0, 300, 300);
        ctx.globalCompositeOperation = 'source-over';
        ctx.drawImage(bgImg, x, y, bgImg.naturalWidth * amp, bgImg.naturalHeight * amp);
            ctx.globalCompositeOperation = "destination-in";
            ctx.drawImage(maskImg, (300 - borderSize) / 2, (300 - borderSize) / 2 , borderSize, borderSize );
});




    };


}


})();
</script>

</body>
</html>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+2

エラーメッセージは単純に「定義されていない変数hを使っている」ということです。
しっかりコードを読んだわけではないのですが、

ctx.translate(0, -h);


ここで使用されているhという変数が初期値も何もなしにいきなり使用されているからだと思います。
heightとして宣言されている変数が入るべきところでhを使っているのではないでしょうか。
同様にwという変数もwidthの間違いではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる