DEV Community
Follow
Hitting an image size ceiling with Rust and WebAssembly
Many image tools offer a quality slider, but government mandates often require files under a specific size limit, which is a different problem. The relationship between quality and file size is complex, depending on various image properties and encoder settings. This project aimed to create a HEIC converter with the invariant that the output file size must be less than or equal to a target byte limit. The browser-based implementation uses Rust compiled to WebAssembly for efficiency. A key design choice was to decode the image only once, retaining a bounded image object to avoid redundant and expensive decoding operations for previews, rotations, and conversions.The system defines "precise size" as a ceiling, meaning files will be at or below the target size, not exactly a specific number of bytes. This avoids the ambiguity of KB measurements in the user interface by converting the target to bytes internally for all comparisons. For JPEG conversion, the algorithm employs a binary search for the optimal quality setting within a protected range. This search is optimized by first encoding at a minimum quality and, if too large, resizing and re-searching.If an initial JPEG encode is too large, the system estimates a new scale based on image area and applies a small margin before resizing using a high-quality filter. PNG conversion, being lossless, does not have a quality knob; instead, dimensions are adjusted. This involves an initial downscale for large photos, followed by encoding and comparison, and then potentially a "grow-back" phase to utilize more of the byte budget.Conversion to JPEG or lossless PNG is kept separate from compression to different byte targets, ensuring clear user intent. Color information, specifically ICC profiles, is preserved during conversion and compression whenever possible. The WebAssembly contract is designed to be simple, returning explicit metadata alongside the image bytes, keeping UI code separate from the compression logic. Finally, the system is tested with real HEIC files to ensure the invariant (output bytes <= target bytes), quality floors, dimensions, and other metrics are met, preventing data leaks from the page.