SenY's picture
postprocess
79a900a
raw
history blame
4.06 kB
import { BasePostProcess } from './base.js';
/**
* 色相を変更するポストプロセス
*/
export class HuePostProcess extends BasePostProcess {
constructor() {
super();
this.name = 'hue';
this.label = '色相';
this.ui = {
template: `
<div class="mb-2">
<label class="form-label">色相の変更</label>
<input type="range" class="form-range" min="0" max="359" value="0" id="hueRotate">
<div class="range-value"><span id="hueRotateValue">0</span>°</div>
</div>
`
};
}
/**
* RGBからHSLに変換
* @private
*/
rgbToHsl(r, g, b) {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [h * 360, s * 100, l * 100];
}
/**
* HSLからRGBに変換
* @private
*/
hslToRgb(h, s, l) {
h /= 360;
s /= 100;
l /= 100;
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
/**
* 色相を変更する処理を適用
* @param {HTMLCanvasElement} canvas - 処理対象のcanvas
* @returns {HTMLCanvasElement} - 処理後のcanvas
*/
async apply(canvas) {
// 色相の値を取得
const hueRotate = parseInt(document.getElementById('hueRotate').value);
if (hueRotate === 0) return canvas;
// 新しいcanvasを作成
const newCanvas = document.createElement('canvas');
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;
const ctx = newCanvas.getContext('2d');
// 元のcanvasを描画
ctx.drawImage(canvas, 0, 0);
// ピクセルデータを取得
const imageData = ctx.getImageData(0, 0, newCanvas.width, newCanvas.height);
const data = imageData.data;
// 各ピクセルの色相を変更
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
// アルファ値が0の場合はスキップ
if (a === 0) continue;
// RGBからHSLに変換
let [h, s, l] = this.rgbToHsl(r, g, b);
// 色相を回転
h = (h + hueRotate) % 360;
if (h < 0) h += 360;
// HSLからRGBに変換
const [newR, newG, newB] = this.hslToRgb(h, s, l);
// 新しい色を設定
data[i] = newR;
data[i + 1] = newG;
data[i + 2] = newB;
}
// 変更した画像データを描画
ctx.putImageData(imageData, 0, 0);
return newCanvas;
}
}