import { BasePostProcess } from './base.js'; /** * 色相を変更するポストプロセス */ export class HuePostProcess extends BasePostProcess { constructor() { super(); this.name = 'hue'; this.label = '色相'; this.ui = { template: `
0°
` }; } /** * 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; } }