🚧 wip: chekkupointo

This commit is contained in:
2026-02-19 23:47:28 +01:00
parent fff2e56467
commit 336105eee8
17 changed files with 611 additions and 120 deletions
+216
View File
@@ -0,0 +1,216 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Color Arg Test</title>
<style>
body {
display: flex;
font-family: sans-serif;
}
.left-panel {
flex: 1;
padding: 20px;
border-right: 1px solid #ccc;
}
.right-panel {
flex: 1;
padding: 20px;
}
#image-preview {
max-width: 100%;
max-height: 500px;
margin-top: 10px;
display: none;
}
.control-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
}
#color-box {
width: 100px;
height: 100px;
border: 1px solid #000;
margin-top: 20px;
background-color: #ccc;
}
</style>
</head>
<body>
<div class="left-panel">
<input type="file" id="image-upload" accept="image/*" />
<br />
<img id="image-preview" alt="Image Preview" />
</div>
<div class="right-panel">
<div class="control-group">
<label for="saturation-power">Saturation Power: <span id="sat-val">1.0</span></label>
<input type="range" id="saturation-power" min="1" max="5" step="0.1" value="1" />
</div>
<div class="control-group">
<label for="lightness-power">Lightness Power: <span id="light-val">1.0</span></label>
<input type="range" id="lightness-power" min="1" max="5" step="0.1" value="1" />
</div>
<div id="color-box"></div>
</div>
<canvas id="hidden-canvas" style="display: none"></canvas>
<script>
const imageUpload = document.getElementById('image-upload');
const imagePreview = document.getElementById('image-preview');
const hiddenCanvas = document.getElementById('hidden-canvas');
const ctx = hiddenCanvas.getContext('2d');
const satSlider = document.getElementById('saturation-power');
const lightSlider = document.getElementById('lightness-power');
const satValDisplay = document.getElementById('sat-val');
const lightValDisplay = document.getElementById('light-val');
const colorBox = document.getElementById('color-box');
let currentPixelBuffer = null;
function 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 * 255, l * 255];
}
function foobar(rgbaBuffer, satPower, lightPower) {
const numBins = 36;
const bins = Array.from({ length: numBins }, () => ({
totalWeight: 0,
sumR: 0,
sumG: 0,
sumB: 0,
}));
for (let i = 0; i < rgbaBuffer.length; i += 4) {
const r = rgbaBuffer[i];
const g = rgbaBuffer[i + 1];
const b = rgbaBuffer[i + 2];
const a = rgbaBuffer[i + 3];
if (a < 5) continue;
const [h, s, l] = rgbToHsl(r, g, b);
if (s === 0) continue;
const sNorm = s / 255.0;
const wS = Math.pow(sNorm, satPower);
const dist = Math.abs(l - 128.0) / 128.0;
const lNorm = 1.0 - dist;
const wL = Math.pow(lNorm, lightPower);
const weight = wS * wL;
if (weight < 0.05) continue;
const binIndex = Math.floor(h / 10) % numBins;
bins[binIndex].totalWeight += weight;
bins[binIndex].sumR += r * weight;
bins[binIndex].sumG += g * weight;
bins[binIndex].sumB += b * weight;
}
let maxBinIndex = -1;
let maxWeight = 0;
for (let i = 0; i < numBins; i++) {
if (bins[i].totalWeight > maxWeight) {
maxWeight = bins[i].totalWeight;
maxBinIndex = i;
}
}
if (maxBinIndex === -1 || maxWeight <= 0) {
return `rgb(128, 128, 128)`;
}
const winningBin = bins[maxBinIndex];
const finalR = Math.round(winningBin.sumR / winningBin.totalWeight);
const finalG = Math.round(winningBin.sumG / winningBin.totalWeight);
const finalB = Math.round(winningBin.sumB / winningBin.totalWeight);
return `rgb(${finalR}, ${finalG}, ${finalB})`;
}
function updateColor() {
if (!currentPixelBuffer) return;
const satPower = parseFloat(satSlider.value);
const lightPower = parseFloat(lightSlider.value);
satValDisplay.textContent = satPower.toFixed(1);
lightValDisplay.textContent = lightPower.toFixed(1);
const color = foobar(currentPixelBuffer, satPower, lightPower);
colorBox.style.backgroundColor = color;
}
imageUpload.addEventListener('change', function (e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function (event) {
const img = new Image();
img.onload = function () {
imagePreview.src = event.target.result;
imagePreview.style.display = 'block';
hiddenCanvas.width = img.width;
hiddenCanvas.height = img.height;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, img.width, img.height);
currentPixelBuffer = imageData.data;
updateColor();
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
});
satSlider.addEventListener('input', updateColor);
lightSlider.addEventListener('input', updateColor);
</script>
</body>
</html>