mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 11:00:47 +02:00
Feature/adjust colors contrast tool (#4544)
# Description of Changes - Addition of the "Adjust Colors/Contrast" tool --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { AdjustContrastParameters } from '../../../hooks/tools/adjustContrast/useAdjustContrastParameters';
|
||||
|
||||
export function applyAdjustmentsToCanvas(src: HTMLCanvasElement, params: AdjustContrastParameters): HTMLCanvasElement {
|
||||
const out = document.createElement('canvas');
|
||||
out.width = src.width;
|
||||
out.height = src.height;
|
||||
const ctx = out.getContext('2d');
|
||||
if (!ctx) return src;
|
||||
ctx.drawImage(src, 0, 0);
|
||||
|
||||
const imageData = ctx.getImageData(0, 0, out.width, out.height);
|
||||
const data = imageData.data;
|
||||
|
||||
const contrast = params.contrast / 100; // 0..2
|
||||
const brightness = params.brightness / 100; // 0..2
|
||||
const saturation = params.saturation / 100; // 0..2
|
||||
const redMul = params.red / 100; // 0..2
|
||||
const greenMul = params.green / 100; // 0..2
|
||||
const blueMul = params.blue / 100; // 0..2
|
||||
|
||||
const clamp = (v: number) => Math.min(255, Math.max(0, v));
|
||||
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
let r = data[i] * redMul;
|
||||
let g = data[i + 1] * greenMul;
|
||||
let b = data[i + 2] * blueMul;
|
||||
|
||||
// Contrast (centered at 128)
|
||||
r = clamp((r - 128) * contrast + 128);
|
||||
g = clamp((g - 128) * contrast + 128);
|
||||
b = clamp((b - 128) * contrast + 128);
|
||||
|
||||
// Brightness
|
||||
r = clamp(r * brightness);
|
||||
g = clamp(g * brightness);
|
||||
b = clamp(b * brightness);
|
||||
|
||||
// Saturation via HSL
|
||||
const rn = r / 255, gn = g / 255, bn = b / 255;
|
||||
const max = Math.max(rn, gn, bn); const min = Math.min(rn, gn, bn);
|
||||
let h = 0, s = 0;
|
||||
const l = (max + min) / 2;
|
||||
if (max !== min) {
|
||||
const d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
switch (max) {
|
||||
case rn: h = (gn - bn) / d + (gn < bn ? 6 : 0); break;
|
||||
case gn: h = (bn - rn) / d + 2; break;
|
||||
default: h = (rn - gn) / d + 4; break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
s = Math.min(1, Math.max(0, s * saturation));
|
||||
const hue2rgb = (p: number, q: number, t: number) => {
|
||||
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;
|
||||
};
|
||||
let r2: number, g2: number, b2: number;
|
||||
if (s === 0) { r2 = g2 = b2 = l; }
|
||||
else {
|
||||
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||
const p = 2 * l - q;
|
||||
r2 = hue2rgb(p, q, h + 1/3);
|
||||
g2 = hue2rgb(p, q, h);
|
||||
b2 = hue2rgb(p, q, h - 1/3);
|
||||
}
|
||||
data[i] = clamp(Math.round(r2 * 255));
|
||||
data[i + 1] = clamp(Math.round(g2 * 255));
|
||||
data[i + 2] = clamp(Math.round(b2 * 255));
|
||||
}
|
||||
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user