From a13ef22b9258764397547d3f7eb7b1825daaee94 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Tue, 26 May 2026 10:33:44 -0400 Subject: [PATCH] =?UTF-8?q?Add=20image=20=E2=86=92=20pixelize=20(Phase=20D?= =?UTF-8?q?)=20and=20move=20it=20into=20the=20pixel=20editor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new "From image…" button in the pixel editor toolbar opens a file picker and then a pixelize modal. The modal previews source and pixelized output side by side, with live updates as the user changes: - W / H (4–128, matching the editor's resize cap; default = the editor's current dims so Apply lands as a drop-in replacement) - Colors (2–64; index 0 reserved as transparent) - Fit mode — Cover / Fit / Stretch Algorithm: - _pixelDownsampleImage draws the image onto an off-screen canvas with imageSmoothingEnabled=false; fit-mode math computes source and dest rects so Cover crops edges, Fit letterboxes with transparent, Stretch ignores aspect. - _pixelMedianCut quantizes the downscaled pixels: collect opaque samples, recursively split the bucket with the widest single- channel range until N buckets, average each bucket → palette entry. Pixels with alpha < 128 become transparent (index 0). - _pixelNearestPaletteIdx maps each opaque pixel to the nearest palette entry by squared RGB distance. Apply replaces the editor's current pixel art — frames, palette, and dims all get swapped to match the pixelized output. One pixelSnapshot before mutating, so Ctrl+Z restores everything. Standalone mode commits immediately. Drive-bys in this commit: - Move the From image entry out of the vector-canvas ▦ popup and into the pixel editor toolbar (per request — the editor is where the workflow lives). - Fix the modal show bug: .modal CSS rule sets display:none, so the modal must be opened with style.display = 'flex' (matching the publish-confirm modal). The previous '' didn't override the rule. - Drop the long hint paragraph under the colour picker — the SV square + hue strip + Add button are self-explanatory and the eyedropper has its own tooltip. Co-Authored-By: Claude Opus 4.7 --- src/index.html | 327 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 326 insertions(+), 1 deletion(-) diff --git a/src/index.html b/src/index.html index abffb6c..4ad42cd 100644 --- a/src/index.html +++ b/src/index.html @@ -2209,6 +2209,30 @@ border-radius: 6px; cursor: pointer; font-family: inherit; } .pixelToolMenu button:hover { background: rgba(127,127,127,.14); } + .pixelizePreviewRow { display: flex; gap: 12px; margin: 0 0 10px; } + .pixelizePreviewBox { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; } + .pixelizePreviewLabel { font-size: .72rem; color: #64748b; font-weight: 600; } + .pixelizePreviewArea { + width: 100%; aspect-ratio: 1; + background: repeating-conic-gradient(#e2e8f0 0% 25%, #f8fafc 0% 50%) 0 0 / 14px 14px; + border: 1px solid var(--line); border-radius: 6px; + display: flex; align-items: center; justify-content: center; + overflow: hidden; + } + .pixelizePreviewArea img, .pixelizePreviewArea canvas { + max-width: 100%; max-height: 100%; display: block; + image-rendering: pixelated; image-rendering: crisp-edges; + } + .pixelizeRow { display: flex; gap: 10px; align-items: center; margin: 0 0 8px; } + .pixelizeField { + display: flex; align-items: center; gap: 6px; + font-size: .82rem; flex: 1; + } + .pixelizeField input { + width: 60px; padding: 4px 6px; + border: 1px solid var(--line); border-radius: 6px; + font-family: inherit; + } .toolOptions { grid-area: options; display: flex; @@ -3542,6 +3566,8 @@ + +
@@ -3611,7 +3637,6 @@
-

Drag on the gradient square + rainbow strip above to pick a colour, then click + Add to push it into the palette. The ⊙ eyedropper tool in the toolbar samples colours already on your sprite.

@@ -4022,6 +4047,42 @@ + +