<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: biren001</title>
    <description>The latest articles on DEV Community by biren001 (@biren001).</description>
    <link>https://dev.to/biren001</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4138562%2Fbfe00531-fa93-47a3-8eb1-09dc01e0dc31.png</url>
      <title>DEV Community: biren001</title>
      <link>https://dev.to/biren001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/biren001"/>
    <language>en</language>
    <item>
      <title>I built an image compressor that cannot upload your photos</title>
      <dc:creator>biren001</dc:creator>
      <pubDate>Wed, 23 Sep 2026 11:38:44 +0000</pubDate>
      <link>https://dev.to/biren001/i-built-an-image-compressor-that-cannot-upload-your-photos-4d45</link>
      <guid>https://dev.to/biren001/i-built-an-image-compressor-that-cannot-upload-your-photos-4d45</guid>
      <description>&lt;p&gt;Every image compressor I tried makes the same promise: "your files are deleted after an hour." That is a policy, not a property. I could not verify it, and I was compressing photos I would rather not have on someone else's server.&lt;/p&gt;

&lt;p&gt;So I built one where the upload step does not exist. There is no server-side image code at all — decoding, resizing and re-encoding run in the browser through WebAssembly builds of MozJPEG, libheif for iPhone HEIC, and an AVIF encoder. If you block every network request after the page loads, it still works.&lt;/p&gt;

&lt;p&gt;"Your files are deleted after an hour" is a promise. This is a property: there is no endpoint in the codebase to delete files from.&lt;/p&gt;

&lt;p&gt;Two bugs I shipped before I measured anything&lt;br&gt;
Auto mode used to probe quality through the browser's native canvas. No browser encodes AVIF natively, so the canvas silently substituted another format, my probe reported a lossless pass, and the binary search settled on a quality that produced a 33 dB file while the page promised about 40 dB. The fix is not subtle: the probe has to use the same encoder as the final write.&lt;/p&gt;

&lt;p&gt;I published "WebP is 25-50% smaller than JPEG" for a while. When I measured it at equal PSNR against MozJPEG, WebP came out about 24% larger. That figure is not invented — it compares against baseline JPEG encoders, not an optimised one. I rewrote the page rather than keep the nicer-sounding number.&lt;/p&gt;

&lt;p&gt;What it actually does, measured&lt;br&gt;
Rather than copy figures from a comparison table, I built a small corpus of camera photos and measured each case:&lt;/p&gt;

&lt;p&gt;Camera JPEG to WebP, Auto mode: 24-54% smaller&lt;br&gt;
Camera JPEG to AVIF, Auto mode: 41-68% smaller&lt;br&gt;
An already-optimised photo: returned unchanged rather than re-compressed larger&lt;br&gt;
Auto mode aims at a 40 dB PSNR floor. That floor is the reason an already-optimised photo comes back unchanged: there is no quality left to give without dropping below it, and re-encoding to hit a number would make the file worse.&lt;/p&gt;

&lt;p&gt;EXIF and GPS are stripped, with camera orientation applied to the pixels first — removing metadata without applying the orientation flag hands you sideways photos. Batch processing, ZIP export on desktop (deliberately withheld on iOS, because the Files app will not unpack an archive into the photo library), and installable as a PWA.&lt;/p&gt;

&lt;p&gt;The honest limits&lt;br&gt;
Not "unlimited file size". The real ceiling is device memory, roughly 80 megapixels.&lt;br&gt;
Not "every HEIC". libheif handles standard HEIF; exotic variants can fail.&lt;br&gt;
Default Auto mode is lossy. PNG output is lossless.&lt;br&gt;
Free, no account, no watermark, no file-count limit. If you want to argue with my numbers, the measurement scripts are in the repo.&lt;/p&gt;

&lt;p&gt;Live: &lt;a href="https://localphototool.com" rel="noopener noreferrer"&gt;https://localphototool.com&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
