3.6 KiB
3.6 KiB
TrapMap Managed PNG Export Design
Goal
Replace System.Drawing.Common in TrapMap image export so Clumsy can save the full grid PNG without depending on platform-specific drawing assemblies.
Chosen approach
Use a small internal RGBA rasterizer for grid primitives and StbImageWriteSharp 1.16.7 for PNG encoding. Keep the public request/result API and the existing TrapMap call site unchanged.
Alternatives rejected:
- Copying
System.Drawing.Common.dllbeside the build output is unreliable because Clumsy performs its own dependency attachment and can load the incompatiblenetstandard2.0facade first. SkiaSharpadds native Windows assets and more deployment points.ImageSharphas a larger dependency/licensing surface and its current release does not target this project'snetstandard2.0runtime.
StbImageWriteSharp is selected because its package contains one managed netstandard2.0 implementation and declares no dependencies. It has no native assets or alternate platform facades for Clumsy to select incorrectly.
Rasterization
- Allocate an in-memory 32-bit RGBA pixel buffer after the existing 4000-pixel edge validation.
- Preserve the current canvas dimensions, 4 pixels per cell, colors, Y inversion, vehicle/workstation geometry, header height, and 50 MiB final-file limit.
- Draw filled rectangles, 1/2-pixel lines, circles, crosses, and vehicle polygons with deterministic integer raster operations.
- Render header and workstation text with a small embedded ASCII bitmap font. Non-ASCII metadata is sanitized to a printable fallback for the PNG header only; original messages remain unchanged in DLog/Console.
- Keep header lines non-overlapping and include bounds, resolution, rows/columns, occupied count/rate, obstacle count, tire status/message, and input source.
PNG encoding
- Pass the RGBA pixel buffer to
StbImageWriteSharp.ImageWriter.WritePng. - Insert a standard
pHYschunk immediately afterIHDR, with X/Y both 11,811 pixels per metre and unit1(300 DPI). - Calculate the inserted chunk's CRC-32 and write its integers in big-endian order.
- Validate the completed PNG before publication; encoding or metadata failures remain contained export failures.
- Preserve the current collision-safe temporary-file reservation, actual encoded-size check, atomic move, and best-effort cleanup behavior.
Project and deployment changes
- Remove the
System.Drawing.Commonpackage reference andDeployFrameworkDrawingRuntimetarget fromClumsyPilot.csproj. - Add
StbImageWriteSharpversion 1.16.7. No other new package is allowed. - The final build output must not require or deploy
System.Drawing.Common.dllfor TrapMap; it may deploy the single managedStbImageWriteSharp.dll. - Existing Clumsy references are not modified.
Verification
- TDD first proves the current exporter/package still depends on
System.Drawing.Common. - Reflection/source contracts assert the old package, build target,
using System.Drawing, and drawing types are absent, and the exact Stb package is present. - Decode the generated PNG in the test with a test-only decoder or framework reader and verify dimensions, 300 DPI metadata, representative colors, Y inversion, header separation, unique concurrent filenames, and no temporary files.
- Run source, build, grid, lifecycle, and image tests; require zero build errors and no new warnings.
Non-goals
- No changes to grid construction, obstacle/tire inputs, vehicle motion, Painter visualization, export switches, output directory, or file-size/pixel limits.
- No screenshot capture and no new general-purpose graphics framework.