2つの画像を合成する[アルファブレンド]
誰もがコーディングできるJavascriptで画像を合成する方法をご紹介します。画像の合成はゲームや画像処理の分野で用いられ「アルファブレンド」とも呼ばれます。
このサンプルはHTML5のcanvasに対応しているブラウザが必要となります。
動作確認
IE11 / Edge / Chrome /FireFox
※IE9/IE10は未確認ですが動作するかも知れません。
画像の合成 - 単色
単色と画像の合成となります。
スライダーを0にすると原画像、128にすると半透明、255にすると赤色になります。
画像の合成 - 2つの画像
原画像1、原画像2の二つの画像を合成します。
スライダーを0にすると原画像1、128にすると半透明、255にすると原画像2になります。
| 原画像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で画像処理がさくさくできるはずなんです。
関連記事
プチモンテ ※この記事を書いた人
![]() | |
![]() | 💻 ITスキル・経験 サーバー構築からWebアプリケーション開発。IoTをはじめとする電子工作、ロボット、人工知能やスマホ/OSアプリまで分野問わず経験。 画像処理/音声処理/アニメーション、3Dゲーム、会計ソフト、PDF作成/編集、逆アセンブラ、EXE/DLLファイルの書き換えなどのアプリを公開。詳しくは自己紹介へ |
| 🎵 音楽制作 BGMは楽器(音源)さえあれば、何でも制作可能。歌モノは主にロック、バラード、ポップスを制作。歌詞は抒情詩、抒情的な楽曲が多い。楽曲制作は🔰2023年12月中旬 ~ | |









