Compressing an image to an exact file size, in the browser
"Make this photo under 100 KB" is one of the most common things people need from an image tool, and one of the few things almost no image editor exposes directly. Photoshop gives you a quality slider. cwebp gives you -q . The canvas API gives you a float between 0 and 1. None of them takes bytes. The reason is that the mapping you want does not exist in the encoder. You ask for a file size; the…
Creating an image with a specific file size in the browser can be challenging, as most image editing tools do not offer direct control over file size. Photoshop, cwebp, and the canvas API provide options like quality sliders, -q flags, or floats between 0 and 1, but none of these directly translate to file size measurements. The issue arises because the mapping from quality settings to file sizes is not inherently present in the encoder.
To address this, the code needs to search for the appropriate quality setting that results in the desired file size.
The initial approach, a naive loop that gradually decreases the quality until the target file size is reached, is inefficient. This method can take up to 18 encodes for a 12 MP phone photo, consuming significant computational resources. Moreover, it is biased and may stop at a quality level that yields a file size far below the target, contradicting the user's intention.
A more effective solution involves binary search over the quality space. The goal is to find the highest quality that results in a file size under the target. By assuming monotonicity (higher quality equates to larger file size) and performing binary search, the process can be completed in a maximum of eight iterations, regardless of the initial quality range. This approach ensures the best fitting quality is found rather than merely the first one encountered.
However, this assumption does not hold for PNG images, which utilize a different compression strategy. PNG compression is lossless, relying on palette reduction to decrease file size. To achieve a more targeted compression, the palette size must be adjusted. The search space transitions from quality values to palette sizes, ranging from 2 to 256, with a perceptual cost associated with inaccurately adjusting the palette size.
Implementing this binary search within a browser-only image tool requires additional considerations. The encoding process must be performed asynchronously to prevent blocking the main thread, which could lead to a frozen tab. This necessitates the use of Web Workers, allowing the encoding logic to be executed in a separate thread.
Consequently, the code is split between components handling canvas operations on the main thread and the pure encoding logic running in a Web Worker. This separation ensures a smoother user experience, avoiding the pitfalls of a frozen and unresponsive interface.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.