Conversation
- Remove anti-aliased boundary artifacts from 5 sprite sheets - Affected assets: infrastructure, path_furniture, theme_classic, theme_modern, trees - Fixed ~355,000 boundary pixels with incorrect colors - Add fix-coaster-borders.mjs script for future use - Regenerated corresponding WebP files Co-authored-by: andrew <andrew@anysphere.co>
|
Cursor Agent can help with this pull request. Just |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Your pull request is now ready for review with Assert. Stop waiting for your code to break. Ship with confidence using Assert. |
Co-authored-by: andrew <andrew@anysphere.co>
| // Read image | ||
| const image = sharp(pngPath); | ||
| const metadata = await image.metadata(); | ||
| const { width, height, channels } = metadata; |
There was a problem hiding this comment.
Inconsistent channel source causes pixel stride mismatch
Low Severity · Potential Edge Case
The channels value used for pixel operations comes from metadata (line 92), but the raw buffer's actual layout is determined by info.channels from toBuffer() (line 158). All getPixel and setPixel calls use metadata.channels for stride calculation, but the buffer data follows info.channels. If these values differ, pixel index calculations become incorrect, causing the script to read/write wrong positions and corrupt the image data.
Additional Locations (1)
| // Create backup directory if needed | ||
| if (!existsSync(BACKUP_DIR)) { | ||
| const { mkdir } = await import('fs/promises'); | ||
| await mkdir(BACKUP_DIR, { recursive: true }); |
There was a problem hiding this comment.
Co-authored-by: andrew <andrew@anysphere.co>
Co-authored-by: andrew <andrew@anysphere.co>
| linePixelsCleared++; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Boundary clearing destroys all pixels unconditionally
Medium Severity · Logic Bug
The boundary clearing code at lines 178-200 unconditionally replaces all pixels within the boundary strips with background color, without checking if they are background-like first. This differs from the flood fill approach which correctly uses isBackgroundLike() to only modify background-like pixels. Any sprite content that extends to or within BOUNDARY_CLEAR_RADIUS pixels of grid boundaries will be destroyed and replaced with background red, potentially clipping sprites that have content near their cell edges.
|
|
||
| // Determine background similarity threshold from edge pixels | ||
| const edgeDiffs = []; | ||
| const edgeIsRedDominant = (r, g, b) => r > 120 && r >= g + 20 && r >= b + 20; |
There was a problem hiding this comment.
Duplicated red-dominant pixel check logic
Low Severity · Code Quality
The edgeIsRedDominant function at line 115 duplicates the exact same logic as redDominant on line 55 inside isBackgroundLike: r > 120 && r >= g + 20 && r >= b + 20. Extract this into a standalone isRedDominant(r, g, b) helper function and reuse it in both places.


Fixes visible grid line artifacts in coaster sprite sheets by correcting off-color boundary pixels.
Several coaster sprite sheets contained anti-aliased or artifact pixels at the boundaries between individual sprites. These pixels were not the pure red background color, leading to visible "skinny line borders" or grid lines when the sprites were rendered. This PR introduces a script to identify and replace these off-color boundary pixels with the correct background red.
Note
Low Risk
Low risk: adds a standalone asset-processing script that only modifies local image files when run, without affecting runtime code paths.
Overview
Adds
scripts/fix-coaster-borders.mjs, a CLI script that repairs coaster sprite-sheet “grid line” artifacts by sampling the red background color, flood-filling background-like edge regions to normalize color, then overwriting sprite boundary strips for configured sheet grids.The script backs up original PNG/WebP files, rewrites the fixed PNGs in place, and regenerates matching WebP outputs with consistent compression settings.
Written by Cursor Bugbot for commit 58e9644. This will update automatically on new commits. Configure here.