Skip to content

Commit e0ac528

Browse files
committed
Refactor Pixel2CPP and packers.js to improve background color handling and packing logic. Updated background color state management to fill transparent areas correctly. Simplified packing functions by removing unnecessary alpha checks for pixel values, ensuring accurate color representation across different formats.
1 parent e426b08 commit e0ac528

File tree

2 files changed

+57
-43
lines changed

2 files changed

+57
-43
lines changed

src/Pixel2CPP.jsx

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ export default function Pixel2CPP() {
4747
const [primary, setPrimary] = useState(black());
4848
const [secondary, setSecondary] = useState(white());
4949
const [name, setName] = useState("sprite");
50-
const [backgroundColor, setBackgroundColor] = useState("black"); // black, white, transparent, custom
51-
const [customBackgroundColor, setCustomBackgroundColor] = useState("#000000");
50+
const [backgroundColor, setBackgroundColor] = useState("black"); // black, white, transparent
5251

5352
// UI state
5453
const [showCodeModal, setShowCodeModal] = useState(false);
@@ -91,6 +90,26 @@ export default function Pixel2CPP() {
9190
setRedo([]);
9291
}, [w, h]);
9392

93+
// Update background color when it changes
94+
useEffect(() => {
95+
setData((prev) => {
96+
const newData = [...prev];
97+
for (let i = 0; i < newData.length; i++) {
98+
if (newData[i].a === 0) { // Transparent pixels
99+
if (backgroundColor === "white") {
100+
newData[i] = white();
101+
} else if (backgroundColor === "black") {
102+
newData[i] = black();
103+
} else {
104+
// transparent - keep as transparent
105+
newData[i] = transparent();
106+
}
107+
}
108+
}
109+
return newData;
110+
});
111+
}, [backgroundColor]);
112+
94113
const idx = (x, y) => y * w + x;
95114

96115
// Drawing helpers
@@ -342,9 +361,9 @@ void setup(){
342361
}
343362
344363
void loop(){}`;
345-
} else if (drawMode === "HORIZONTAL_RGB565") {
346-
const words = packRGB565(data, w, h);
347-
const wordStr = words.map(hex565).join(", ");
364+
} else if (drawMode === "HORIZONTAL_RGB565") {
365+
const words = packRGB565(data, w, h);
366+
const wordStr = words.map(hex565).join(", ");
348367
return `// Generated by Pixel2CPP (RGB565 for TFT displays)
349368
#include <Adafruit_GFX.h>
350369
#include <Adafruit_ST7735.h> // Use ST7789, ILI9341, etc. for your display
@@ -401,9 +420,9 @@ void drawImagePixelByPixel(int16_t x0, int16_t y0) {
401420
}
402421
}
403422
*/`;
404-
} else if (drawMode === "HORIZONTAL_RGB888_24") {
405-
const bytes = packRGB24(data, w, h);
406-
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
423+
} else if (drawMode === "HORIZONTAL_RGB888_24") {
424+
const bytes = packRGB24(data, w, h);
425+
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
407426
return `// Generated by Pixel2CPP (RGB24 for ESP32/high-memory displays)
408427
#include <Adafruit_GFX.h>
409428
#include <Adafruit_ILI9341.h> // Use appropriate display library
@@ -452,9 +471,9 @@ void drawImage(int16_t x0, int16_t y0) {
452471
}
453472
}
454473
}`;
455-
} else if (drawMode === "HORIZONTAL_RGB332") {
456-
const bytes = packRGB332(data, w, h);
457-
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
474+
} else if (drawMode === "HORIZONTAL_RGB332") {
475+
const bytes = packRGB332(data, w, h);
476+
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
458477
return `// Generated by Pixel2CPP (RGB332 for low-memory/retro displays)
459478
#include <Adafruit_GFX.h>
460479
#include <Adafruit_SSD1331.h> // Or other 8-bit color displays
@@ -502,9 +521,9 @@ void drawImage(int16_t x0, int16_t y0) {
502521
- Green: 3 bits (0-7)
503522
- Blue: 2 bits (0-3)
504523
*/`;
505-
} else if (drawMode === "HORIZONTAL_GRAY4") {
506-
const bytes = packGray4(data, w, h);
507-
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
524+
} else if (drawMode === "HORIZONTAL_GRAY4") {
525+
const bytes = packGray4(data, w, h);
526+
const byteStr = bytes.map((b) => "0x" + b.toString(16).toUpperCase().padStart(2, "0")).join(", ");
508527
return `// Generated by Pixel2CPP (4-bit Grayscale for E-ink/EPD)
509528
#include <Adafruit_GFX.h>
510529
#include <Adafruit_EPD.h> // Use appropriate e-ink library
@@ -1423,12 +1442,12 @@ const GFXfont ${safeName} PROGMEM = {
14231442
</label>
14241443
))}
14251444
</div>
1426-
<div className="text-xs text-neutral-400 bg-neutral-800/50 p-2 rounded">
1427-
<div className="font-medium mb-1">Background affects display only:</div>
1428-
<div>• Black: White pixels = "on" (1)</div>
1429-
<div>• White: Black pixels = "on" (1)</div>
1430-
<div>• Transparent: Alpha &gt; 0 = "on" (1)</div>
1431-
</div>
1445+
<div className="text-xs text-neutral-400 bg-neutral-800/50 p-2 rounded">
1446+
<div className="font-medium mb-1">Background color fills transparent areas:</div>
1447+
<div>• Black: Transparent areas become black pixels</div>
1448+
<div>• White: Transparent areas become white pixels</div>
1449+
<div>• Transparent: Keeps transparent areas (alpha = 0)</div>
1450+
</div>
14321451
</div>
14331452
</>
14341453
)}
@@ -1502,18 +1521,17 @@ const GFXfont ${safeName} PROGMEM = {
15021521
<div className="space-y-4">
15031522
{/* Canvas Container */}
15041523
<div className="bg-neutral-900 rounded-2xl p-4 overflow-auto inline-block shadow-xl border border-neutral-700">
1505-
<PixelCanvas
1506-
width={w}
1507-
height={h}
1508-
zoom={zoom}
1509-
pixels={data}
1510-
backgroundColor={backgroundColor}
1511-
customBackgroundColor={customBackgroundColor}
1512-
cursor={tool === "eyedropper" ? "crosshair" : "pointer"}
1513-
onPointerDown={handleMouseDown}
1514-
onPointerMove={handleMouseMove}
1515-
onPointerUp={handleMouseUp}
1516-
/>
1524+
<PixelCanvas
1525+
width={w}
1526+
height={h}
1527+
zoom={zoom}
1528+
pixels={data}
1529+
backgroundColor={backgroundColor}
1530+
cursor={tool === "eyedropper" ? "crosshair" : "pointer"}
1531+
onPointerDown={handleMouseDown}
1532+
onPointerMove={handleMouseMove}
1533+
onPointerUp={handleMouseUp}
1534+
/>
15171535
</div>
15181536

15191537
{/* Canvas Info */}

src/lib/packers.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export function pack1bit(pixels, width, height, orientation = 'horizontal') {
3131
let cur = 0;
3232
for (let x = 0; x < width; x++) {
3333
const p = pixels[I(x, y)];
34-
const on = p.a > 0 && (p.r + p.g + p.b) > (255 * 3) / 2; // lighter pixel → 1 (white = on)
34+
const on = (p.r + p.g + p.b) > (255 * 3) / 2; // lighter pixel → 1 (white = on)
3535
if (on) cur |= 1 << bit;
3636
bit--;
3737
if (bit < 0) {
@@ -51,7 +51,7 @@ export function pack1bit(pixels, width, height, orientation = 'horizontal') {
5151
const y = yPage * 8 + (7 - bit);
5252
if (y < height) {
5353
const p = pixels[I(x, y)];
54-
const on = p.a > 0 && (p.r + p.g + p.b) > (255 * 3) / 2; // lighter pixel → 1 (white = on)
54+
const on = (p.r + p.g + p.b) > (255 * 3) / 2; // lighter pixel → 1 (white = on)
5555
if (on) cur |= 1 << bit;
5656
}
5757
}
@@ -91,7 +91,7 @@ export function pack1bitAlpha(pixels, width, height, orientation = 'horizontal')
9191
const y = yPage * 8 + bit;
9292
if (y < height) {
9393
const p = pixels[I(x, y)];
94-
const hasAlpha = p.a > 127;
94+
const hasAlpha = p.a > 127; // alpha threshold (opaque = on)
9595
if (hasAlpha) cur |= 1 << bit;
9696
}
9797
}
@@ -108,7 +108,7 @@ export function packRGB565(pixels, width, height) {
108108
for (let y = 0; y < height; y++) {
109109
for (let x = 0; x < width; x++) {
110110
const p = pixels[I(x, y)];
111-
out.push(p.a < 10 ? 0 : rgbTo565(p.r, p.g, p.b));
111+
out.push(rgbTo565(p.r, p.g, p.b));
112112
}
113113
}
114114
return out;
@@ -120,11 +120,7 @@ export function packRGB24(pixels, width, height) {
120120
for (let y = 0; y < height; y++) {
121121
for (let x = 0; x < width; x++) {
122122
const p = pixels[I(x, y)];
123-
if (p.a < 10) {
124-
out.push(0, 0, 0);
125-
} else {
126-
out.push(p.r, p.g, p.b);
127-
}
123+
out.push(p.r, p.g, p.b);
128124
}
129125
}
130126
return out;
@@ -143,7 +139,7 @@ export function packRGB332(pixels, width, height) {
143139
for (let y = 0; y < height; y++) {
144140
for (let x = 0; x < width; x++) {
145141
const p = pixels[I(x, y)];
146-
out.push(p.a < 10 ? 0 : rgbTo332(p.r, p.g, p.b));
142+
out.push(rgbTo332(p.r, p.g, p.b));
147143
}
148144
}
149145
return out;
@@ -157,7 +153,7 @@ export function packGray4(pixels, width, height) {
157153
let cur = 0;
158154
for (let x = 0; x < width; x++) {
159155
const p = pixels[I(x, y)];
160-
const luma = p.a < 10 ? 0 : Math.floor((0.2126 * p.r + 0.7152 * p.g + 0.0722 * p.b) / 16);
156+
const luma = Math.floor((0.2126 * p.r + 0.7152 * p.g + 0.0722 * p.b) / 16);
161157
const gray4 = Math.min(15, Math.max(0, luma)); // 0-15 range
162158

163159
if (nibble === 1) {

0 commit comments

Comments
 (0)