LoginSignup
30
28

More than 5 years have passed since last update.

スマフォのカメラロールの画像を使う

Posted at

やること

  1. カメラロールで画像を選択する
  2. ブラウザ上に表示する
  3. canvasで画像に効果をつける
  4. おまけ

準備

html,js,cssを準備しておく。
今回は↓のような構成。

構成
CameraRoll
 
 ┣━ index.html
 
 ┣━ js
    
    ┗━ script.js
 
 ┗━ css
      
      ┗━ style.css

カメラロールで画像を選択する

画像を選択させるためにinput要素をおく。
type="file"にしておくと、タップしたときに写真を撮るかカメラロールから選ぶかを選択するおなじみのアレが出てくる。
id属性はあとでjs側でつかうのでつけておく

index.html
<input type="file" id="file" />

おなじみのアレ

ブラウザ上に表示する

今のままではファイルを選択しても特に何も起きないので、選択したファイルをあれこれする処理をjsに書いていく。

jsでの主な処理は以下のとおり。

  1. ファイルが選択されたイベントをキャッチする
  2. FileReaderを使い、選択されたファイルをURL形式で読み込む
  3. 取得したURL形式のデータを、Imageオブジェクトのsrcに指定する

ではやっていきます。

ファイルが選択されたイベントをキャッチする

script.js
// 要素を取得
var input = document.getElementById('file');
// changeイベントでファイルの選択をキャッチ
input.addEventListener('change', function (e) {
  // 処理
  alert('ファイルが選択されました');
});

ここまででこんな感じ。

イベントをキャッチ

FileReaderを使い、選択されたファイルをURL形式で読み込む

FileReaderを使うことで、選択されたファイルをいろんな形式で扱えるようになる。
今回はURL形式で扱う。

script.js
var input = document.getElementById('file');
input.addEventListener('change', function (e) {
  // コールバック引数のsrcElementに、filesという名前で配列形式でファイルオブジェクトが格納されている
  // 今回は単一ファイルしか選択させないので、0番目に選択したファイルがある
  var file = e.srcElement.files[0];

  // FileReaderを初期化して、
  var fr = new FileReader();
  // ファイルが読み込み終わったあとの処理を書いておく
  fr.addEventListener('load', function() {
    // resultプロパティに読み込んだデータが入ってくる
    var url = fr.result;
    alert(url);
  });
  // 最後にreadAsDataURLメソッドに選択したファイルオブジェクトを渡すと
  // 上記resultプロパティにURL形式でデータが入る
  fr.readAsDataURL(file);
});

ここまででこんな感じ。
URL形式のデータ

取得したURL形式のデータを、Imageオブジェクトのsrcに指定する

前のステップまでで選択したファイルをURL形式のデータで扱うことができるようになっているので、あとはそんなに難しくない。

script.js
var input = document.getElementById('file');
input.addEventListener('change', function (e) {
  var file = e.srcElement.files[0];

  var fr = new FileReader();
  fr.addEventListener('load', function() {
    var url = fr.result;

    // Imageオブジェクトをつくり
    var img = new Image();
    // srcにurlを指定する
    img.src = url;
    // そのままだとでかすぎるのでサイズ調整して
    img.height = 200;
    // bodyに追加する
    document.body.appendChild(img);
  });
  fr.readAsDataURL(file);
});

するとこんな感じ。

Image

これまでずっとカメラロールからファイルを選択するという話をしてきたが、その場で写真を撮ってもいける。

シャッターを押すと↓みたいになるので、
シャッターを押したあと

Use Photoを押すとカメラロールのときと同じように表示される。

カメラロールと同じように表示される

canvasで画像に効果をつける

Imageオブジェクトで扱えるようになっているので、canvasに描き出すことも簡単。
まずは普通にcanvasに描きだしてみる。

script.js
var input = document.getElementById('file');
input.addEventListener('change', function (e) {
  var file = e.srcElement.files[0];

  var fr = new FileReader();
  fr.addEventListener('load', function() {
    var url = fr.result;

    var img = new Image();
    // onloadでcanvasに描き込む処理を書く
    img.onload = function () {
      // canvasをつくる
      var canvas = document.createElement('canvas');
      // canvasのwidthとheightは、imgと同じ値にする
      canvas.width = img.width;
      canvas.height = img.height;

      // 見た目上のサイズは小さめにしておく
      // heightはとりあえず200
      canvas.style.height = '200px';
      // widthはimgの比率を維持するように計算
      canvas.style.width = (img.width / img.height) * 200 + 'px';

      // canvasをbodyに追加する
      document.body.appendChild(canvas);

      // contextを取得
      var context = canvas.getContext('2d');
      // imgを描き込む
      context.drawImage(img, 0, 0, canvas.width, canvas.height);
    };
    img.src = url;
  });
  fr.readAsDataURL(file);
});

ここまででさっきとほぼ一緒になる。
canvasで書きだす

次になにか効果をつける。
いいのが思いつかなかったので、canvasで輪郭を検出してアートっぽくするでやった補色を使う。
描き換えの詳細もそちらを参考に。

script.js
var input = document.getElementById('file');
input.addEventListener('change', function (e) {
  var file = e.srcElement.files[0];

  var fr = new FileReader();
  fr.addEventListener('load', function() {
    var url = fr.result;

    var img = new Image();
    img.onload = function () {
      var canvas = document.createElement('canvas');
      canvas.width = img.width;
      canvas.height = img.height;

      canvas.style.height = '200px';
      canvas.style.width = (img.width / img.height) * 200 + 'px';

      document.body.appendChild(canvas);

      var context = canvas.getContext('2d');
      context.drawImage(img, 0, 0, canvas.width, canvas.height);

      // 補色を計算する関数
      var getComplementaryRGB = function (rgb) {
        var max = Math.max(rgb.r, rgb.g, rgb.b),
            min = Math.min(rgb.r, rgb.g, rgb.b),
            sum = max + min;
        return {
            r: sum - rgb.r,
            g: sum - rgb.g,
            b: sum - rgb.b
        };
      };

      // 描き込まれたデータを取得する
      var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
      var data = imageData.data;

      // 全ピクセル描き変える
      for (var i = 0, l = data.length; i < l; i += 4) {
        // rgbの値を取り出して
        var rgb = {
          r: data[i],
          g: data[i + 1],
          b: data[i + 2]
        };
        // 補色のrgbを計算する
        var complementaryRGB = getComplementaryRGB(rgb);
        // 計算したrgbで描き変える
        data[i] = complementaryRGB.r;
        data[i + 1] = complementaryRGB.g;
        data[i + 2] = complementaryRGB.b;
      }

      // 描き換えたdataをimageDataにもどし、描画する
      imageData.data = data;
      context.putImageData(imageData, 0, 0);
    };
    img.src = url;
  });
  fr.readAsDataURL(file);
});

するとこうなる。

補色で描き変える

ピッコロさんかな?

おまけ

ファイル選択のUIがダサいのでなんとかする。
カメラロールのアレを表示させるにはChoose Fileがタップ(クリック)されればいいだけなので、別のボタンを用意してそれがクリックされたらinputのclickメソッドを呼べばおk。

htmlに要素を追加する。
あとでどうとでもできるように、今回はとりあえずanchorタグを追加。

index.html
<input type="file" id="file" />
<a href="javascript:void(0);" id="button">Tap me!</a>

ダサいやつはcssで見えなくしておく。

style.css
#file {
  display: none;
}

jsにclick時の処理を追加。

script.js
// 略

// 要素を取得
var button = document.getElementById('button');
// clickされたら
button.addEventListener('click', function () {
  // inputのclickメソッドを呼ぶ
  input.click();
});

するとあのダサいやつを見なくてもよくなる。

補色で描き変える

demo

demo

30
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
28