JavaScript 作 ▸ 2017-11-18 15:01 CanvasでRGBチャンネルごとに色の位置をずらす加工 #JavaScript#Canvas タイトルわかりにく!! グリッチっぽいあれです。 元の画像 サンプル1: 赤を→2 サンプル2: 緑を←2, ↑2 サンプル3: 青を←4, ↓3 加工の流れは次の通りです。 全ピクセル (ImageData.data) をスキャンして、各座標の指定チャンネルの値を取得したあと、現在の値をゼロにします。 ふたたび全ピクセルをスキャンして、移動先座標の指定チャンネルに、取得しておいた値を加算します。 移動先座標を算出するので、2回目のスキャンはxyでやってます。xyの座標は、(y \* 幅 + x) * 4 で ImageData.data のインデックスに変換できます。 /** * 指定チャンネルの描画位置をずらす * @param {HTMLCanvasElement} canvas canvas要素 * @param {number} channel 0: 赤, 1: 緑, 2: 青 * @param {number} shiftX 右方向移動量 (px) * @param {number} shiftY 下方向移動量 (px) */ function shiftRGB(canvas, channel, shiftX, shiftY) { const ctx = canvas.getContext('2d'); const w = canvas.width; const h = canvas.height; const tmp = []; const imageData = ctx.getImageData(0, 0, w, h); for (let i = 0, len = imageData.data.length; i < len; i += 4) { tmp[i] = imageData.data[i + channel]; imageData.data[i + channel] = 0; } for (let y = 0; y < h; ++y) { for (let x = 0; x < w; ++x) { const dstX = x + shiftX; const dstY = y + shiftY; if (0 <= dstX && dstX < w && 0 <= dstY && dstY < h) { const i = (y * w + x) * 4; const dstI = (dstY * w + dstX) * 4; imageData.data[dstI + channel] = imageData.data[dstI + channel] + tmp[i]; } } } ctx.putImageData(imageData, 0, 0); }以下、ページ上部でやってるサンプルの例です。 HTML<figure> <img id="exsample-org" src="/assets/entry/20171118-rgb-channel-shifting/org.gif" /> <figcaption>元の画像</figcaption> </figure> <div style="display:flex; flex-wrap:wrap;"> <figure style="flex-grow:1;"> <canvas id="exsample-1"></canvas> <figcaption>サンプル1: 赤を→2</figcaption> </figure> <figure style="flex-grow:1;"> <canvas id="exsample-2"></canvas> <figcaption>サンプル2: 緑を←2, ↑2</figcaption> </figure> <figure style="flex-grow:1;"> <canvas id="exsample-3"></canvas> <figcaption>サンプル3: 青を←4, ↓3</figcaption> </figure> </div>JavaScriptdocument.getElementById('example-org').addEventListener("load", (event) => { /** * Canvasをコピー * @param {HTMLCanvasElement} src コピー元 * @param {HTMLCanvasElement} dst コピー先 */ function copyCanvas(src, dst) { dst.width = src.width; dst.height = src.height; const ctx = dst.getContext('2d'); ctx.drawImage(src, 0, 0, dst.width, dst.height); return dst; } const orgImage = event.currentTarget; const canvas1 = copyCanvas(orgImage, document.getElementById('example-1')); const canvas2 = copyCanvas(orgImage, document.getElementById('example-2')); const canvas3 = copyCanvas(orgImage, document.getElementById('example-3')); // サンプル1: 赤を→2 shiftRGB(canvas1, 0, 2, 0); // サンプル2: 緑を←2, ↑2 shiftRGB(canvas2, 1, -2, -2); // サンプル3: 青を←4, ↓3 shiftRGB(canvas3, 2, -4, 3); });