feat: auto-extract color from logo + PHP extension check

Added extractDominantColor() JS function that picks the dominant
color from uploaded logo and suggests it as theme color.
Updated gdcheck.php to show all needed extensions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 17:19:08 +02:00
parent 9797fda7b7
commit d2ca790e32
2 changed files with 87 additions and 6 deletions

View File

@@ -1,6 +1,15 @@
<?php
echo "GD: " . (extension_loaded('gd') ? 'KYLLÄ' : 'EI') . "\n";
echo "Imagick: " . (extension_loaded('imagick') ? 'KYLLÄ' : 'EI') . "\n";
if (extension_loaded('gd')) {
echo "GD info: " . json_encode(gd_info()) . "\n";
echo "PHP " . PHP_VERSION . " (" . php_sapi_name() . ")\n";
echo "php.ini: " . php_ini_loaded_file() . "\n\n";
$check = ['pdo', 'pdo_mysql', 'gd', 'imagick', 'fileinfo', 'mbstring', 'curl', 'openssl', 'json', 'session', 'mysqli', 'imap', 'zip', 'xml', 'dom', 'simplexml'];
echo "=== Tarvittavat laajennukset ===\n";
foreach ($check as $ext) {
echo ($ext . ': ' . str_pad('', 15 - strlen($ext)) . (extension_loaded($ext) ? '✅ KYLLÄ' : '❌ EI')) . "\n";
}
echo "\n=== Kaikki ladatut ===\n";
echo implode(', ', get_loaded_extensions()) . "\n";
echo "\n=== Lisätietojen ini-polut ===\n";
$scanDir = php_ini_scanned_files();
echo $scanDir ?: "(ei skannattu lisä-ini-tiedostoja)\n";

View File

@@ -1884,11 +1884,69 @@ document.getElementById('company-edit-color-text').addEventListener('input', fun
}
});
// Logo-upload
// Poimi hallitseva väri kuvasta (canvas)
function extractDominantColor(file) {
return new Promise((resolve) => {
const img = new Image();
const url = URL.createObjectURL(file);
img.onload = () => {
const canvas = document.createElement('canvas');
const size = 50; // Pieni koko nopeuttaa
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, size, size);
const pixels = ctx.getImageData(0, 0, size, size).data;
URL.revokeObjectURL(url);
// Laske värien esiintymät (ryhmiteltynä 32-askeleen tarkkuudella)
const colorCounts = {};
for (let i = 0; i < pixels.length; i += 4) {
const r = pixels[i], g = pixels[i+1], b = pixels[i+2], a = pixels[i+3];
if (a < 128) continue; // Ohita läpinäkyvät
// Ohita lähes valkoiset, mustat ja harmaat
const max = Math.max(r, g, b), min = Math.min(r, g, b);
const saturation = max === 0 ? 0 : (max - min) / max;
if (max > 230 && min > 200) continue; // Valkoinen
if (max < 30) continue; // Musta
if (saturation < 0.15 && max > 60) continue; // Harmaa
// Ryhmittele
const qr = Math.round(r / 32) * 32;
const qg = Math.round(g / 32) * 32;
const qb = Math.round(b / 32) * 32;
const key = `${qr},${qg},${qb}`;
colorCounts[key] = (colorCounts[key] || 0) + 1;
}
// Etsi yleisin
let bestKey = null, bestCount = 0;
for (const [key, count] of Object.entries(colorCounts)) {
if (count > bestCount) { bestCount = count; bestKey = key; }
}
if (bestKey) {
const [r, g, b] = bestKey.split(',').map(Number);
const hex = '#' + [r, g, b].map(v => Math.min(255, v).toString(16).padStart(2, '0')).join('');
resolve(hex);
} else {
resolve(null); // Ei löytynyt selkeää väriä
}
};
img.onerror = () => { URL.revokeObjectURL(url); resolve(null); };
img.src = url;
});
}
// Logo-upload — poimi väri automaattisesti
document.getElementById('company-logo-upload').addEventListener('change', async function() {
if (!this.files[0] || !currentCompanyDetail) return;
const file = this.files[0];
// Poimi väri logosta ennen uploadia
const dominantColor = await extractDominantColor(file);
const formData = new FormData();
formData.append('logo', this.files[0]);
formData.append('logo', file);
formData.append('company_id', currentCompanyDetail);
try {
const res = await fetch('api.php?action=company_logo_upload', { method: 'POST', body: formData, credentials: 'include' });
@@ -1901,6 +1959,20 @@ document.getElementById('company-logo-upload').addEventListener('change', async
// Päivitä paikallinen data
const comp = companiesTabData.find(c => c.id === currentCompanyDetail);
if (comp) comp.logo_file = data.logo_file;
// Aseta logosta poimittu väri teemaväriksi
if (dominantColor) {
const colorInput = document.getElementById('company-edit-color');
if (colorInput) {
colorInput.value = dominantColor;
// Näytä ilmoitus
const msg = document.createElement('span');
msg.textContent = ` Väri ${dominantColor} poimittu logosta`;
msg.style.cssText = 'color:#27ae60;font-size:0.85rem;margin-left:8px;';
colorInput.parentElement.appendChild(msg);
setTimeout(() => msg.remove(), 4000);
}
}
} catch (e) { alert(e.message); }
this.value = ''; // Reset file input
});