TOP > カテゴリ > JavaScript >

2つの画像を合成する[アルファブレンド]

誰もがコーディングできるJavascriptで画像を合成する方法をご紹介します。画像の合成はゲームや画像処理の分野で用いられ「アルファブレンド」とも呼ばれます。

このサンプルはHTML5のcanvasに対応しているブラウザが必要となります。

動作確認

IE11 / Edge / Chrome /FireFox
※IE9/IE10は未確認ですが動作するかも知れません。

画像の合成 - 単色

単色と画像の合成となります。

スライダーを0にすると原画像、128にすると半透明、255にすると赤色になります。

0/255

画像の合成 - 2つの画像

原画像1、原画像2の二つの画像を合成します。

スライダーを0にすると原画像1、128にすると半透明、255にすると原画像2になります。

0/255

原画像1
原画像2
合成先

プログラムコード - 単色

単色のアルファブレンドはHTML5の標準機能で合成しています。context.fillStyleプロパティに「rgba()」でアルファを設定してるだけです。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="range" id="a_range" min="0" max="255" value="0" onmouseup="onMouseUp1();" style="padding:0;"> 
<span id="msg_a">0/255</span>
<br>
<br>
<canvas id="MyCanvas"></canvas>
<img id="img_src" src="test.gif" style="display:none;">
<script>    
  // キャンバスの取得
  var canvas = document.getElementById("MyCanvas");
  
  if (canvas.getContext) {
    // コンテキストの取得
    var ctx = canvas.getContext("2d");     
    // イメージの取得           
    var image = document.getElementById("img_src");

    // イメージが読み込まれた
    image.addEventListener("load", function () {
      
      canvas.width  = image.width;
      canvas.height = image.height;
        
      // キャンバスに画像を描画
      ctx.drawImage(image,0,0);
    },false);
  }    

  function onMouseUp1(){
    
    document.getElementById('msg_a').innerHTML = a_range.value +'/255';
    
    // キャンバスに画像を描画
    ctx.drawImage(image,0,0);
      
    ctx.fillStyle = 'rgba(255,0,0,'+ a_range.value / 255 +')';
    ctx.fillRect(0,0,image.width,image.height);      
  }    
</script>
</body>
</html> 

プログラムコード - 2つの画像

2つの画像のアルファブレンドはcontext.getImageData()で取得した原画像1と原画像2の画像データ(ImageData)をアルファブレンドの公式で算出して合成先へ設定します。これは画像処理で一般的に使用される手法となります。

配列の添え字の部分は画像データがRGBAの順番に格納されていますのでこのようになります。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="range" id="blend_range" min="0" max="255" value="0" onmouseup="onMouseUp2();" style="padding:0;"> 
<span id="msg_blend">0/255</span>
<br>
<br>
<table>
  <tr><td>ソース1</td><td><canvas id="canvas_src1"></canvas></td></tr>
  <tr><td>ソース2</td><td><canvas id="canvas_src2"></canvas></td></tr>
  <tr><td>合成先</td><td><canvas id="canvas_dst" width="1" height="1"></canvas></td></tr>        
</table>
<p></p>
<img id="img_src1" src="test1.gif" style="display:none;">
<img id="img_src2" src="test2.png" style="display:none;">  
<script>    
  // キャンバスの取得
  var src1_canvas = document.getElementById("canvas_src1");
  var src2_canvas = document.getElementById("canvas_src2");
  var dst_canvas  = document.getElementById("canvas_dst");
  var src1_ctx = src1_canvas.getContext("2d"); 
  var src2_ctx = src2_canvas.getContext("2d");
  var dst_ctx = dst_canvas.getContext("2d");       
  var src1_img = document.getElementById("img_src1");
  var src2_img = document.getElementById("img_src2");
  var src1 = null;
  var src2 = null;
   
  // イメージが読み込まれた
  src1_img.addEventListener("load", function () {
    
    src1_canvas.width  = src1_img.width;
    src1_canvas.height = src1_img.height;
      
    // キャンバスに画像を描画
    src1_ctx.drawImage(src1_img,0,0);
    
    // イメージデータの取得
    src1 = src1_ctx.getImageData(0,0,src1_img.width, src1_img.height);
  },false);
  
  // イメージが読み込まれた
  src2_img.addEventListener("load", function () {
    
    src2_canvas.width  = src2_img.width;
    src2_canvas.height = src2_img.height;
    
    // キャンバスに画像を描画
    src2_ctx.drawImage(src2_img,0,0);
          
    // イメージデータの取得
    src2 = src2_ctx.getImageData(0,0,src2_img.width, src2_img.height);
  },false);    
      

  // RGBの範囲
  function set255(value){
    if (value > 255) return 255;
    if (value < 0)   return 0;
    return value;
  }

  function onMouseUp2(){
    var height = src1_img.height;
    var width  = src1_img.width;
    var cnt = 0;
    
    document.getElementById('msg_blend').innerHTML = blend_range.value +'/255';      
    
    dst_canvas.width  = src1_img.width;
    dst_canvas.height = src1_img.height;

    var dst = dst_ctx.createImageData(src1_img.width, src1_img.height);     
    
    var amount = blend_range.value / 255;
    for (var y = 0; y < height; y++) {
      for (var x = 0;x < width; x++) {
        dst.data[(cnt*4)]   = set255(Math.round((1 - amount) * src1.data[(cnt*4)]   + (amount * src2.data[(cnt*4)])));
        dst.data[(cnt*4)+1] = set255(Math.round((1 - amount) * src1.data[(cnt*4)+1] + (amount * src2.data[(cnt*4)+1])));
        dst.data[(cnt*4)+2] = set255(Math.round((1 - amount) * src1.data[(cnt*4)+2] + (amount * src2.data[(cnt*4)+2]))); 
        dst.data[(cnt*4)+3] = 255; 
        cnt++;
      }
    }    
    // キャンバスに画像を設定
    dst_ctx.putImageData(dst,0,0);  
  }    
</script>
</body>
</html> 

注意事項

Chromeをお使いの方はローカルで実行するとセキュリティエラーが発生します。このエラーを回避するには「Uncaught SecurityErrorのエラー回避方法」をご覧ください。

既知の問題

IEとEdgeではcreateImageData()、getImageData()で取得した画像データ(ImageData)へのアクセスは非常に低速です。ChromeやFireFox並に高速であれば、Javascriptで画像処理がさくさくできるはずなんです。





関連記事



公開日:2016年02月20日
記事NO:01784