<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14" -->

---
title: Regressive JPEGs: (Maurycy's blog) | daily.dev
description: Progressive JPEG files store image data in multiple scans ordered from low to high frequency, allowing partial rendering during download. By exploiting the...
canonical: https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Regressive JPEGs: (Maurycy's blog) | daily.dev
og:description: Progressive JPEG files store image data in multiple scans ordered from low to high frequency, allowing partial rendering during download. By exploiting the...
og:url: https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14
og:image: https://api.daily.dev/og/posts/SR9GxAz14.png
og:image:alt: Regressive JPEGs: (Maurycy's blog)
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Regressive JPEGs: (Maurycy's blog)

**[Hacker News](https://daily.dev/sources/hn)** · 5 min read · 2 upvotes · 0 comments

## Summary

Progressive JPEG files store image data in multiple scans ordered from low to high frequency, allowing partial rendering during download. By exploiting the fact that each scan explicitly sets its spectral range, it's possible to concatenate multiple JPEG images into a single file where successive scans overwrite previously rendered data — effectively encoding a video inside a single JPEG. The key trick is using DC-only scans (1/16th resolution frames) to maximize the number of frames before browsers stop processing scans, achieving around 90 frames in Chrome. Since DC-only progressive JPEGs are standards-compliant, they can be generated with jpegtran. The result has no practical use since there's no timing control — playback depends entirely on network delay — but enables unconventional animations and interactive applications with no CSS or JavaScript.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://maurycyz.com/projects/bad_jpeg>

## Questions this post answers

### How does progressive JPEG scan structure allow multiple images to be hidden in a single file?

Progressive JPEG files store image data across multiple scans, each with its own header specifying channels and DCT bin range. By concatenating several same-resolution JPEGs and stripping their start-of-image, start-of-frame, and end-of-image markers, the scans from different source images can be merged into one file, causing decoders to render different images as more scans arrive over a slow connection.

_daily.dev surfaces deep format internals like this for developers exploring unconventional JPEG encoding tricks._

### Why do most browsers stop decoding a JPEG after only a few scans?

Most decoders cap the number of scans they will process, likely to prevent zip-bomb style resource exhaustion attacks. Chrome renders around 90 frames of a specially crafted DC-only scan JPEG before giving up, while Firefox tolerates more scans, but neither will process an arbitrarily large number of progressive scans.

_following practical browser rendering limits like this helps developers building unconventional file-based tricks on daily.dev._

### How can jpegtran be used to create a JPEG with only a single DC scan?

A custom scan script fed to jpegtran's -scans option can define a scan containing only channels 0, 1, and 2 with DCT bin range 0-0, producing a DC-only scan with no AC refinement. This yields a standards-compliant image at 1/16th resolution per 16x16 DCT block, useful for minimizing scan count when packing many frames into one file.

_developers experimenting with jpegtran scan scripts can track niche encoding techniques like this on daily.dev._

## Similar posts on daily.dev

- [Exploring Hidden JPEG Features](https://daily.dev/posts/exploring-hidden-jpeg-features-qyt63xgek) · Hackaday · 0 upvotes · 0 comments
- [The present and potential future of progressive image rendering](https://daily.dev/posts/the-present-and-potential-future-of-progressive-image-rendering-x30vnz4xu) · Jake Archibald · 2 upvotes · 0 comments
- [Issue \#624 – CSS Weekly](https://daily.dev/posts/issue-624-css-weekly-zs3kdhkbd) · CSS Weekly · 3 upvotes · 0 comments
- [Shipping JPEG XL in Chrome](https://daily.dev/posts/shipping-jpeg-xl-in-chrome-sqxidsuck) · Lobsters · 4 upvotes · 1 comments
- [Why Tiny JPEGs Look Different in Chrome](https://daily.dev/posts/why-tiny-jpegs-look-different-in-chrome-68fy1ywqj) · Hacker News · 2 upvotes · 1 comments

---

[View this post on daily.dev](https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Regressive JPEGs: (Maurycy's blog)","url":"https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14"},"datePublished":"2026-07-18T07:16:50.170Z","dateModified":"2026-09-13T20:41:41.925Z","description":"Progressive JPEG files store image data in multiple scans ordered from low to high frequency, allowing partial rendering during download. By exploiting the...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/59d6638523ccf53d0906ce43568cda79?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/59d6638523ccf53d0906ce43568cda79?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":2},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"","timeRequired":"PT5M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Regressive JPEGs: (Maurycy's blog)"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/regressive-jpegs-maurycy-s-blog--sr9gxaz14#faq","mainEntity":[{"@type":"Question","name":"How does progressive JPEG scan structure allow multiple images to be hidden in a single file?","acceptedAnswer":{"@type":"Answer","text":"Progressive JPEG files store image data across multiple scans, each with its own header specifying channels and DCT bin range. By concatenating several same-resolution JPEGs and stripping their start-of-image, start-of-frame, and end-of-image markers, the scans from different source images can be merged into one file, causing decoders to render different images as more scans arrive over a slow connection. daily.dev surfaces deep format internals like this for developers exploring unconventional JPEG encoding tricks."}},{"@type":"Question","name":"Why do most browsers stop decoding a JPEG after only a few scans?","acceptedAnswer":{"@type":"Answer","text":"Most decoders cap the number of scans they will process, likely to prevent zip-bomb style resource exhaustion attacks. Chrome renders around 90 frames of a specially crafted DC-only scan JPEG before giving up, while Firefox tolerates more scans, but neither will process an arbitrarily large number of progressive scans. following practical browser rendering limits like this helps developers building unconventional file-based tricks on daily.dev."}},{"@type":"Question","name":"How can jpegtran be used to create a JPEG with only a single DC scan?","acceptedAnswer":{"@type":"Answer","text":"A custom scan script fed to jpegtran's -scans option can define a scan containing only channels 0, 1, and 2 with DCT bin range 0-0, producing a DC-only scan with no AC refinement. This yields a standards-compliant image at 1/16th resolution per 16x16 DCT block, useful for minimizing scan count when packing many frames into one file. developers experimenting with jpegtran scan scripts can track niche encoding techniques like this on daily.dev."}}]}
```

