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

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

ただいまの
回答率

90.13%

canvasにて変換した画像の戻しができません

解決済

回答 1

投稿

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

kihokutarou

score 22

canvasにて書き込んだものを画像に保存することはできました。
以前の質問にて、当方の「Chromeにて完全にローカルで完結したい」という希望に対して、回答者様より一るの方法として「--allow-file-access-from-filesフラグを付けて起動」と助言を受け解決に至りました。

今回躓いたのは、この「画像化したもの」をもう一度キャンパス上に戻したい、という部分で困っています。
下記にありますが、

function chgImg2()
{
  var png = canvas.toDataURL("image/png");
  document.getElementById("newImg2").src = png;
}


にて画像に書き出しました。おそらくputImageDataで戻すのだと思いますが、キャンパス上ではデフォルトの状態ではなく、ローカルから画像を取り出して絵画しているため、うまくいっていないような気がします。下記コードで、いわゆる「キャンパスの背景」をロードしている関係でしょうか。またはローカルから画像を呼び出して描写している機能が邪魔をしている?

onload = function() {
  draw();
};
function draw() {
  var canvas = document.getElementById("drawArea");
  if ( ! canvas || ! canvas.getContext ) { return false; }
  var ctx = canvas.getContext("2d");
  /* Imageオブジェクトを生成 */
  var img = new Image();
  img.src = "a.jpg?" + new Date().getTime();

流れとしては、
1 ローカルの画像を呼び出す
2 canvasで様々書き込む
3 画像に変換して保存する
4 別な書き込み等をする
5 3にて保存した画像をキャンパス上に再度呼び出す

ということをしたいと思っています。
当方かなりの素人で勉強中ですが、どなたかご教示ください。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>汎用お絵かきチャレンジ</title>
    <link rel="stylesheet" type="text/css" href="wboard.css">
</head>
<body>

<div class="wrapper">
<form>
<p>
&nbsp;&nbsp;色&nbsp;
<input type="button" class="b1" style="background: #000000;" value=" " onclick="change_black()">
<input type="button" class="b1" style="background: #ff0000;" value=" " onclick="change_red()">
<input type="button" class="b1" style="background: #00ff00;" value=" " onclick="change_green()">
<input type="button" class="b1" style="background: #0000ff;" value=" " onclick="change_blue()">
<input type="button" class="b1" style="background: #ffffff;" value=" " onclick="change_white()">
&nbsp;&nbsp;線幅&nbsp;
<input type="button" class="b2" value="8px" onclick="change_8()">
<input type="button" class="b2" value="16px" onclick="change_16()">
&nbsp;&nbsp;
<input type="button" class="b2" value="全面" onclick="spread()">
<input type="button" class="b2" value="消去" onclick="clr()">
<font size="5" color="#ff0000"><a href="javascript:location.reload();">最初から</a></font>
&nbsp;&nbsp;画像&nbsp;
<input id="ufile" name="ufile" type="file" accept="image/jpeg,image/png">
<input type="button" value="画像に変換" onclick="chgImg()">
<input type="button" value="画像に変換2" onclick="chgImg2()">
</form>


<canvas id="drawArea"></canvas>
<img id="newImg">
<img id="newImg2">


<script src="wboard.js"></script>
<script src="jquery.min.js"></script>
<script type="text/javascript" src="jquery-ui-1.8.12.custom.min.js"></script>
<script type="text/javascript" src="jquery.ui.touch-punch.js"></script>

 <script>
         $(function(){

             // id="ufile"の変化でコールバック
             $("#ufile").change(function(){
                 // 選択ファイルの有無をチェック
                 if (!this.files.length) {
                     alert('ファイルが選択されていません');
                     return;
                 }

                 // Formからファイルを取得
                 var file = this.files[0];

                 // (1) HTMLのCanvas要素の取得
                 var canvas = $("#drawArea");

                 // (2) getContext()メソッドで描画機能を有効にする
                 var ctx = canvas[0].getContext('2d');

                 // 描画イメージインスタンス化
                 var image = new Image();

                 // File API FileReader Objectでローカルファイルにアクセス
                 var fr = new FileReader();

                 // ファイル読み込み読み込み完了後に実行 [非同期処理]
                 fr.onload = function(evt) {

                     // 画像がロードされた後にcanvasに描画を行う [非同期処理]
                     image.onload = function() {
                         // (3) プレビュー(Cnavas)のサイズを指定
                         var cnvsH = ctx.canvas.height;
                         var cnvsW = image.naturalWidth*cnvsH/image.naturalHeight;
                         // (4) Cnavasにサイズアトリビュートを設定する
                         canvas.attr('width', cnvsW);
                         canvas.attr('height', cnvsH);
                         // (5) 描画
                         ctx.drawImage(image, 100, 0, cnvsW, cnvsH);
                     }
                     // 読み込んだ画像をimageのソースに設定
                     image.src = evt.target.result;
                 }

                 // fileを読み込む データはBase64エンコードされる
                 fr.readAsDataURL(file);
             })
        })
</script>
</body>
</html>
onload = function() {
  draw();
};
function draw() {
  var canvas = document.getElementById("drawArea");
  if ( ! canvas || ! canvas.getContext ) { return false; }
  var ctx = canvas.getContext("2d");
  /* Imageオブジェクトを生成 */
  var img = new Image();
  img.src = "a.jpg?" + new Date().getTime();
  /* 画像が読み込まれるのを待ってから処理を続行 */
  img.onload = function() {
    ctx.drawImage(img, 0, 0,ctx.canvas.width, ctx.canvas.height);
  }
}

var canvas = document.getElementById("drawArea");
var ctx = canvas.getContext("2d");
var width = window.innerWidth;
var height = window.innerHeight;
var x = 0, y = 0;
var color = "#000000";
var line = 13;
canvas.width = width;
canvas.height = height - 70;

canvas.addEventListener("mousedown", touchStartHandler, false);
canvas.addEventListener("mouseup", touchEndHandler, false);

canvas.addEventListener("touchstart", ttouchStartHandler, false);
canvas.addEventListener("touchend", ttouchEndHandler, false);

function touchStartHandler(e) {
    e.preventDefault();
    getTouchPoint(e);
    ctx.beginPath();
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.moveTo(x, y);
    canvas.addEventListener("mousemove", touchMoveHandler, false);
}

function touchMoveHandler(e) {
    e.preventDefault();
    getTouchPoint(e);
    ctx.lineWidth = line; //線の太さ
    ctx.strokeStyle = color; //線の色
    ctx.lineTo(x, y);
    ctx.stroke();
}

function touchEndHandler(e) {
    e.preventDefault();
    ctx.closePath();
    canvas.removeEventListener("mousemove", touchMoveHandler, false);
}

function getTouchPoint(e) {
    x = e.clientX - canvas.offsetLeft;
    y = e.clientY - canvas.offsetTop;
}

function ttouchStartHandler(e) {
    e.preventDefault();
    getTTouchPoint(e);
    ctx.beginPath();
    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.moveTo(x, y);
    canvas.addEventListener("touchmove", ttouchMoveHandler, false);
}

function ttouchMoveHandler(e) {
    e.preventDefault();
    getTTouchPoint(e);
    ctx.lineWidth = line; //線の太さ
    ctx.strokeStyle = color; //線の色
    ctx.lineTo(x, y);
    ctx.stroke();
}

function ttouchEndHandler(e) {
    e.preventDefault();
    ctx.closePath();
    canvas.removeEventListener("touchmove", ttouchMoveHandler, false);
}

function getTTouchPoint(e) {
    var touch = e.touches[0];
    x = touch.pageX - canvas.offsetLeft;
    y = touch.pageY - canvas.offsetTop;
}

function spread() {
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    document.getElementById("ClickSound").play();
}

function clr() {
    cntx = canvas.getContext("2d");
    cntx.clearRect(0, 0, canvas.width, canvas.height);
    document.getElementById("ClickSound").play();
}

function change_black() {
    color = "#000000";
    document.getElementById("ClickSound").play();
}
function change_red() {
    color = "#ff0000";
    document.getElementById("ClickSound").play();
}
function change_green() {
    color = "#00ff00";
    document.getElementById("ClickSound").play();
}
function change_blue() {
    color = "#0000ff";
    document.getElementById("ClickSound").play();
}
function change_white() {
    color = "#ffffff";
    document.getElementById("ClickSound").play();
}
function change_8() {
    line = 8;
    document.getElementById("ClickSound").play();
}
function change_16() {
    line = 16;
    document.getElementById("ClickSound").play();
}
//canvasデータを画像に変換にする関数
function chgImg()
{
  var png = canvas.toDataURL("image/png");
  document.getElementById("newImg").src = png;
}
function chgImg2()
{
  var png = canvas.toDataURL("image/png");
  document.getElementById("newImg2").src = png;
}


よろしくお願いします。

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+4

CanvasRenderingContext2DオブジェクトのdrawImageメソッドに渡すことの出来るオブジェクトは以下のとおりです.

  • HTMLImageElement(img要素)/Imageオブジェクト
  • HTMLCanvasElement(canvas要素)オブジェクト
  • ImageBitmapオブジェクト
  • HTMLVideoElement(video要素)オブジェクト

ですから, 

ctx.drawImage(document.getElementById("newImg"), 0, 0);


と記述することで, newImgに保管したCanvasグラフィックをcanvas要素に書き戻すことが可能です.

NOTE:
但し, Imageオブジェクトの書き戻しには画像の読み込みが完了(loadイベントの発生以降)している必要があります.


NOTE:
canvas要素の使い方については個人的にまとめたものがあるので, こちらも参考となさって下さい.
http://defghi1977.html.xdomain.jp/tech/canvasMemo/canvasMemo.htm

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/28 23:04 編集

    今あなたに必要なのは, 今あるコードを弄ることではなく, 別のプロジェクトとして「img要素で表示されている画像をcanvas要素に書き戻す」短いスクリプトを1から書いてみることです. その行為を通して正しいcanvas要素の使い方が判れば自ずとどうすればよいかが判るはずです.
    (後ちょっとのところまで来ているので, ぜひあなた自身の力で解決してみて下さい)

    キャンセル

  • 2018/01/28 23:35 編集

    承知しました。というかご指摘は痛感しています。勉強します。
    もしよければ最後に一つヒントをください。
    var fr = newimg
    frという変数に保存してあったimgのアドレスを入れるべきだと思っているのですが、そしてどうもここが怪しいと思うのですが、
    function chgImg()
    {
    var png = canvas.toDataURL("image/png");
    document.getElementById("newImg").src = png;
    }
    でで保存したnewimg指定はあっていますか?もしくは考える方向性としては見当違いでしょうか。


    お気に障るようであればご返信はいりませんが、できればぜひ・・・。

    追伸
    ctx.drawImage(document.getElementById("newImg"), 0, 0);
    のみの記述でできました・・・。load関係が心配ですが。。。
    ありがとうございます。

    キャンセル

  • 2018/01/28 23:54

    いつ変数newimgを定義したのですか?
    ---
    結論から申し上げると, ここで躓く理由がわからないのです. となると提示した回答の中身を一切理解していない(出来ていない)ことになる. であれば, あなたに足りないのはまず(canvas要素を扱う以前の)コードを読み解く為の基礎的な力であり, いたずらに解決策を提示することはあなたのためにならないと判断したまでです.

    キャンセル

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

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