Commit 211a94f5 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: PNG uploads now render correctly — remove pixelation from raster images

image-rendering:-webkit-optimize-contrast caused nearest-neighbor scaling on
PNGs making them blocky. Now only applied to SVGs. Also added cache-busting
timestamp so re-uploaded assets aren't served stale from browser cache.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent ae3a9a78
...@@ -32,9 +32,11 @@ All asset rendering MUST use: ...@@ -32,9 +32,11 @@ All asset rendering MUST use:
width: {exact}px; width: {exact}px;
height: {exact}px; height: {exact}px;
object-fit: contain; object-fit: contain;
image-rendering: -webkit-optimize-contrast;
``` ```
For SVGs only, add `image-rendering: -webkit-optimize-contrast;` for crisp edges.
For PNGs/JPEGs/WebP, do NOT apply this property — it causes pixelation on raster images.
Never use `width: 100%` or `auto` for themed assets — always explicit pixel dimensions. Never use `width: 100%` or `auto` for themed assets — always explicit pixel dimensions.
## Files That Control Theming ## Files That Control Theming
......
...@@ -92,7 +92,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['asset'])) { ...@@ -92,7 +92,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['asset'])) {
if ($httpCode >= 200 && $httpCode < 300) { if ($httpCode >= 200 && $httpCode < 300) {
// Public URL with anon key for browser access // Public URL with anon key for browser access
$anonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzM1Njg5NjAwLCJleHAiOjE4OTM0NTYwMDB9.31PF6PvP-pSrvRuQwLFptQoejR0W1A7o53lZhEbnz84'; $anonKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InN1cGFiYXNlIiwiaWF0IjoxNzM1Njg5NjAwLCJleHAiOjE4OTM0NTYwMDB9.31PF6PvP-pSrvRuQwLFptQoejR0W1A7o53lZhEbnz84';
$publicUrl = SUPABASE_URL . '/storage/v1/object/public/profile-images/' . $fileName . '?apikey=' . $anonKey; $publicUrl = SUPABASE_URL . '/storage/v1/object/public/profile-images/' . $fileName . '?apikey=' . $anonKey . '&v=' . time();
$theme['assets'][$slot] = $publicUrl; $theme['assets'][$slot] = $publicUrl;
// Save asset URL to Supabase platform_assets table // Save asset URL to Supabase platform_assets table
......
...@@ -98,7 +98,9 @@ function applyAnimations() { ...@@ -98,7 +98,9 @@ function applyAnimations() {
export function assetImg(slot, fallbackEmoji, width, height) { export function assetImg(slot, fallbackEmoji, width, height) {
const url = getAsset(slot); const url = getAsset(slot);
if (url) { if (url) {
return `<img src="${url}" alt="" style="width:${width}px;height:${height}px;object-fit:contain;image-rendering:-webkit-optimize-contrast;" draggable="false">`; const isSvg = url.includes('.svg');
const rendering = isSvg ? 'image-rendering:-webkit-optimize-contrast;' : '';
return `<img src="${url}" alt="" style="width:${width}px;height:${height}px;object-fit:contain;${rendering}" draggable="false">`;
} }
return `<span style="font-size:${Math.min(width, height) * 0.7}px;line-height:1;">${fallbackEmoji}</span>`; return `<span style="font-size:${Math.min(width, height) * 0.7}px;line-height:1;">${fallbackEmoji}</span>`;
} }
...@@ -106,7 +108,9 @@ export function assetImg(slot, fallbackEmoji, width, height) { ...@@ -106,7 +108,9 @@ export function assetImg(slot, fallbackEmoji, width, height) {
export function emoji(key, fallback, size = 20) { export function emoji(key, fallback, size = 20) {
const url = getAsset('emoji_' + key); const url = getAsset('emoji_' + key);
if (url) { if (url) {
return `<img src="${url}" alt="" style="width:${size}px;height:${size}px;object-fit:contain;vertical-align:middle;image-rendering:-webkit-optimize-contrast;" draggable="false">`; const isSvg = url.includes('.svg');
const rendering = isSvg ? 'image-rendering:-webkit-optimize-contrast;' : '';
return `<img src="${url}" alt="" style="width:${size}px;height:${size}px;object-fit:contain;vertical-align:middle;${rendering}" draggable="false">`;
} }
return fallback; return fallback;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment