gemini_watermark_cleaner/js/core/blendModes.js

62 lines
2.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* 反向 Alpha 混合模块
* 实现去除水印的核心算法
*/
// 常量定义
const ALPHA_THRESHOLD = 0.002; // 忽略极小的 alpha 值(噪声)
const MAX_ALPHA = 0.99; // 避免除以接近零的值
const LOGO_VALUE = 255; // 白色水印的颜色值
/**
* 使用反向 alpha 混合移除水印
*
* 原理:
* Gemini 添加水印: watermarked = α × logo + (1 - α) × original
* 反向求解: original = (watermarked - α × logo) / (1 - α)
*
* @param {ImageData} imageData - 要处理的图像数据(会被原地修改)
* @param {Float32Array} alphaMap - Alpha 通道数据
* @param {Object} position - 水印位置 {x, y, width, height}
*/
export function removeWatermark(imageData, alphaMap, position) {
const { x, y, width, height } = position;
// 遍历水印区域的每个像素
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
// 计算在原图中的索引RGBA 格式,每个像素 4 个字节)
const imgIdx = ((y + row) * imageData.width + (x + col)) * 4;
// 计算在 alpha map 中的索引
const alphaIdx = row * width + col;
// 获取 alpha 值
let alpha = alphaMap[alphaIdx];
// 跳过极小的 alpha 值(噪声)
if (alpha < ALPHA_THRESHOLD) {
continue;
}
// 限制 alpha 值,避免除零
alpha = Math.min(alpha, MAX_ALPHA);
const oneMinusAlpha = 1.0 - alpha;
// 对 RGB 三个通道应用反向 alpha 混合公式
for (let c = 0; c < 3; c++) {
const watermarked = imageData.data[imgIdx + c];
// 反向 alpha 混合公式
const original = (watermarked - alpha * LOGO_VALUE) / oneMinusAlpha;
// 裁剪到 [0, 255] 范围
imageData.data[imgIdx + c] = Math.max(0, Math.min(255, Math.round(original)));
}
// Alpha 通道保持不变
// imageData.data[imgIdx + 3] 不需要修改
}
}
}