
ilovejpg exists because JPEG compression is everywhere: almost every photograph taken on a phone, attached to an email or published on a web page has passed through the same sequence of mathematical steps defined more than three decades ago. When you move the quality slider in a browser editor, you are adjusting one parameter of that pipeline. Understanding the rest of it explains why the slider behaves as it does, why some images compress far better than others, and why repeated saving gradually spoils a picture.
This article follows an image through the baseline JPEG encoder from start to finish. It covers the history of the standard, the colour conversion to YCbCr, chroma subsampling, the division into 8×8 blocks, the discrete cosine transform, quantisation and the quality scale, zigzag ordering, run-length and Huffman coding, and the difference between baseline and progressive files. It ends with the characteristic artefacts of JPEG, the problem of generation loss, and the formats designed to succeed it.
Where JPEG came from
JPEG takes its name from the Joint Photographic Experts Group, a committee formed in the mid-1980s by the International Organization for Standardization and the body then called the CCITT, now the telecommunication standardisation sector of the International Telecommunication Union. The word joint refers to that collaboration. The group's task was to define a method for compressing continuous-tone still images, photographs rather than line drawings, that would work across equipment from different manufacturers.
The result was approved as ITU-T Recommendation T.81 in 1992 and published as the identical international standard ISO/IEC 10918-1 in 1994. Strictly speaking, the standard defines a compression method and a code stream rather than a complete file format. The everyday .jpg file is usually wrapped in the JPEG File Interchange Format, JFIF, or in the Exif format used by digital cameras, which adds metadata such as exposure settings, timestamps and GPS coordinates. A freely available reference implementation from the Independent JPEG Group, first released in 1991, did a great deal to make the format universal.
JPEG's central insight is perceptual. Human vision is far more sensitive to changes in brightness than to changes in colour, and more sensitive to broad, gradual variation than to very fine detail. An encoder that discards mainly the information people are least likely to notice can achieve compression ratios of ten to one or more with little visible loss.
From RGB to YCbCr
A digital photograph normally starts as red, green and blue values for each pixel. These three channels are highly correlated: a bright area tends to be bright in all three. JPEG encoders conventionally convert RGB into YCbCr, which separates luminance, Y, from two colour-difference or chrominance components, Cb and Cr. Under JFIF, which uses full-range values from 0 to 255 and coefficients derived from ITU-R Recommendation BT.601, the conversion is a simple linear transform.
- Y = 0.299 R + 0.587 G + 0.114 B
- Cb = 128 − 0.168736 R − 0.331264 G + 0.5 B
- Cr = 128 + 0.5 R − 0.418688 G − 0.081312 B
The weights in the Y equation reflect the eye's differing sensitivity to the three primaries, with green contributing most to perceived brightness. Cb measures how blue the pixel is relative to its brightness, and Cr how red. The offset of 128 keeps both colour components within the same 0 to 255 range as luminance. The conversion itself loses almost nothing apart from rounding; its value lies in what it makes possible next.
Chroma subsampling
Because the eye resolves colour detail less finely than brightness detail, an encoder can store the Cb and Cr channels at reduced resolution. This is chroma subsampling, written as a ratio inherited from television engineering. The notation describes a reference region four pixels wide and two rows high: the first number is the width, the second the number of chroma samples in the top row, and the third the number of chroma samples in the bottom row.
| Scheme | Chroma resolution | Samples per pixel overall | Typical use |
|---|---|---|---|
| 4:4:4 | Full resolution in both directions | 3 | High-quality exports, graphics with fine coloured detail |
| 4:2:2 | Half horizontally, full vertically | 2 | Some cameras and video-derived images |
| 4:2:0 | Half horizontally and half vertically | 1.5 | The common default for photographs |
With 4:2:0, each chroma channel holds a quarter as many samples as luminance, so the total amount of data drops by half before any other compression takes place. For natural photographs the effect is essentially invisible. It becomes noticeable in images with sharp coloured edges, such as red text on a white background or saturated graphics, where colours bleed slightly beyond their boundaries. Many encoders automatically use 4:4:4 at very high quality settings for this reason.
If a screenshot or diagram with coloured text looks smeared after saving as JPEG, chroma subsampling is the likely cause. PNG is usually the better format for such images.
Blocks and the discrete cosine transform
Each component is then divided into blocks of 8×8 samples, and every block is processed independently. With 4:2:0 subsampling, a 16×16 pixel region forms a minimum coded unit containing four luminance blocks and one block each for Cb and Cr. Where image dimensions are not a multiple of the block size, the encoder pads the edges, and the decoder discards the padding.
Before transformation, each sample is level-shifted by subtracting 128, so values range from −128 to 127 and are centred on zero. The encoder then applies the two-dimensional discrete cosine transform, specifically the type-II DCT. It expresses the 64 sample values as a weighted sum of 64 fixed cosine patterns, called basis functions, which range from a completely flat block to a fine checkerboard.
In the form used by T.81, each coefficient F(u,v) equals one quarter of C(u) multiplied by C(v), multiplied by the sum over all x and y from 0 to 7 of the sample value f(x,y) multiplied by cos((2x+1)uπ/16) and by cos((2y+1)vπ/16). Here C(0) is 1 divided by the square root of 2, and C(k) is 1 for every other k. The coefficient at position (0,0) is called the DC coefficient and equals eight times the average value of the block. The remaining 63 are AC coefficients, representing progressively finer horizontal, vertical and diagonal variation.
The DCT does not by itself discard information; in exact arithmetic it is perfectly reversible. Its value is energy compaction. In a typical photograph, neighbouring pixels are similar, so most of a block's energy ends up in a few low-frequency coefficients near the top-left corner, while the high-frequency coefficients are small. That uneven distribution is what the next stage exploits.
The 8×8 block size was a compromise between compression efficiency and the computing power available around 1990. Larger blocks capture more correlation but are costlier to compute and produce worse artefacts when they fail.
Quantisation and the quality scale
Quantisation is where JPEG becomes lossy. Each of the 64 coefficients is divided by a corresponding value from an 8×8 quantisation table and rounded to the nearest integer. Large divisors reduce a coefficient to a small number or to zero; small divisors preserve it more precisely. On decoding, the integer is multiplied back by the same divisor, but the rounding error is permanent.
The tables are stored in the file, so encoders are free to choose their own. Annex K of the standard gives example tables derived from visibility experiments, and these became the de facto baseline. The example luminance table starts with 16, 11, 10, 16 along its top row and reaches values above 100 towards the bottom-right, reflecting the eye's lower sensitivity to high frequencies. The chrominance table is coarser still, with most entries set to 99.
What the quality number means
The quality setting familiar from software is not part of the standard. It is a convention for scaling the example tables. In the widely used Independent JPEG Group library, a quality q below 50 gives a scaling factor of 5000 divided by q, while a quality of 50 or above gives 200 minus twice q. Each table entry is multiplied by that percentage and clamped to a minimum of 1, and to 255 for baseline files. At quality 50 the Annex K tables are used unchanged; at quality 100 every divisor becomes 1, which minimises quantisation loss but does not make the file lossless, because colour conversion, subsampling and rounding still apply.
| Quality setting | Effect on divisors | Typical visual result |
|---|---|---|
| 95 to 100 | Divisors near 1 to 3 | Visually lossless; large files |
| 80 to 90 | Moderate divisors | Excellent for photographs; good balance of size and detail |
| 60 to 75 | Larger divisors | Good at normal viewing size; artefacts visible on close inspection |
| Below 50 | Divisors above the Annex K examples | Blocking, ringing and banding become obvious |
Different programs map their quality scales differently, so quality 80 in one application is not guaranteed to equal quality 80 in another. Browser encoders, such as the one ilovejpg uses when it exports from the canvas, accept a quality value and translate it into tables internally, which is why the live size estimate is a more reliable guide than the number alone.
Zigzag ordering, run-length and Huffman coding
After quantisation, a typical block contains a handful of non-zero values near the top-left and a large number of zeros elsewhere. The remaining stages compress this pattern without further loss.
Zigzag order
The 64 coefficients are read in a zigzag sequence that runs diagonally from the DC coefficient towards the highest frequencies in the bottom-right corner. This ordering places low-frequency values, which are most likely to be non-zero, at the start and gathers the zeros into long runs at the end.
DC prediction and run-length coding
Because the average brightness of neighbouring blocks is usually similar, the DC coefficient is coded as the difference from the previous block's DC value in the same component, a technique known as differential pulse-code modulation. The AC coefficients are coded as pairs describing how many zeros precede the next non-zero value and how many bits that value needs. Two special symbols handle the common cases: an end-of-block marker indicates that all remaining coefficients are zero, and a zero-run-length symbol stands for sixteen consecutive zeros.
Huffman coding
These symbols are then entropy-coded with Huffman codes, which assign shorter bit patterns to more frequent symbols. Each symbol's code is followed by extra bits giving the exact amplitude of the coefficient. Baseline JPEG allows up to two DC and two AC Huffman tables, conventionally one pair for luminance and one for chrominance. Encoders may use the example tables in the standard or compute optimised tables for each image, which typically saves a few percent. The standard also defines arithmetic coding, which compresses slightly better, but patent concerns limited its adoption for many years and support remains patchy.
- Zigzag ordering groups zeros together without changing any values.
- DC differences exploit similarity between neighbouring blocks.
- Run-length pairs and the end-of-block symbol describe long zero runs in a few bits.
- Huffman coding removes statistical redundancy from the symbol stream.
- None of these stages loses information; all loss occurs in subsampling and quantisation.
Baseline, progressive and the structure of a file
A baseline JPEG stores each block's complete data in a single scan from top to bottom, so a slowly loading image appears line by line. A progressive JPEG reorganises the same quantised coefficients into several scans. Spectral selection sends low-frequency coefficients before high-frequency ones, and successive approximation sends the most significant bits of each coefficient before the less significant ones. The image appears blurred at first and then sharpens. Because the coefficients are identical, a progressive file is visually equivalent to a baseline one at the same quality, and it is often slightly smaller, though it costs more memory and processing to decode.
The standard also defines a lossless mode based on prediction rather than the DCT, and a hierarchical mode that stores multiple resolutions. Neither is widely used in everyday files. Internally, a JPEG file is a sequence of segments introduced by two-byte markers.
| Marker | Name | Purpose |
|---|---|---|
| FFD8 | Start of image | Opens every JPEG stream |
| FFE0 | APP0 | JFIF header with version and pixel density |
| FFE1 | APP1 | Exif metadata, including camera data and GPS |
| FFDB | Define quantisation table | Stores the divisors used for each component |
| FFC0 or FFC2 | Start of frame | Baseline or progressive; gives dimensions and sampling factors |
| FFC4 | Define Huffman table | Stores the entropy coding tables |
| FFDA | Start of scan | Begins the compressed image data |
| FFD9 | End of image | Closes the stream |
Removing the APP1 segment strips Exif data without touching the image itself. Re-encoding through a canvas, as ilovejpg does, produces a new file in which that segment is simply never written.
Artefacts and generation loss
Each JPEG artefact can be traced to a specific stage of the pipeline. Recognising them helps you choose the right remedy.
- Blocking: visible 8×8 squares, most obvious in smooth areas such as sky, caused by heavy quantisation that leaves each block described by little more than its average value, so neighbouring blocks no longer join smoothly.
- Ringing, often called mosquito noise: faint halos and shimmering near sharp edges and text, caused by discarding high-frequency coefficients that are needed to represent an abrupt transition, an effect related to the Gibbs phenomenon.
- Banding: smooth gradients broken into visible steps, caused by coarse quantisation of low-frequency coefficients combined with the limited precision of 8-bit samples.
- Colour bleeding: colours spreading across sharp boundaries, caused by chroma subsampling rather than by quantisation.
Generation loss describes the cumulative damage from decoding and re-encoding a JPEG repeatedly. Each cycle repeats colour conversion, rounding and quantisation, and errors accumulate. The damage is worst when settings change between generations, when an image is resized, or when it is cropped by an amount that is not a multiple of the block size, so that block boundaries shift and every block is quantised afresh. Re-saving at identical settings without other changes tends to stabilise after a few generations, but there is no general guarantee.
Some operations can be performed losslessly on the compressed coefficients. Rotation by 90 degrees and flipping can be achieved by rearranging and transposing coefficients, and cropping can be lossless when it follows block boundaries. Specialised tools exist for this purpose. General editors, including browser editors that work through a canvas, decode and re-encode, so the practical defence against generation loss is to keep an untouched original, perform all changes in one session and export once.
Successors to JPEG
Several formats have been designed to improve on JPEG, with varying success. Understanding them puts the old standard's longevity in context.
| Format | Standard | Core technique | Notable strengths |
|---|---|---|---|
| JPEG 2000 | ISO/IEC 15444, first part published in 2000 | Discrete wavelet transform | No block artefacts, scalable resolution; used in digital cinema and medical imaging |
| JPEG XL | ISO/IEC 18181, core coding system published in 2022 | Variable-size DCT and modular modes | Lossless and lossy modes, high bit depth, and lossless recompression of existing JPEG files |
| WebP | Developed by Google, released in 2010 | Based on VP8 video intra-frame coding | Smaller files than JPEG at similar quality; broad browser support |
| AVIF | Alliance for Open Media, based on AV1 | AV1 intra-frame coding | Strong compression at low bit rates; supports high dynamic range |
JPEG 2000 replaced the block DCT with a wavelet transform, avoiding block artefacts and allowing an image to be decoded at several resolutions from one file. It found lasting niches in digital cinema distribution, archives and medical imaging, but never displaced JPEG on the web. JPEG XL, standardised more recently, offers efficient lossy and lossless coding and can repack an existing JPEG into a smaller file, typically around 20 percent smaller, from which the original JPEG can be reconstructed bit for bit. Browser support for JPEG XL remains uneven.
Despite these alternatives, JPEG endures because of universal compatibility, fast decoding, hardware support in every camera and phone, and decades of encoder refinement. For photographs that must open anywhere, it remains the default choice.
Frequently Asked Questions
Is JPEG compression always lossy?
Almost always in practice. The standard does define a separate lossless mode based on prediction, but it is rarely supported or used. Ordinary JPEG files lose information during chroma subsampling, quantisation and the rounding involved in colour conversion. Even quality 100 does not produce a lossless file, although the remaining differences from the original are normally far too small to see.
Why are JPEG blocks 8×8 pixels?
The size was a compromise reached when the standard was developed around 1990. Larger blocks capture more correlation between pixels and can compress better, but they need more computation and produce more noticeable artefacts when quantisation is heavy. Smaller blocks compress less efficiently. Eight by eight gave good compression with processing that hardware and software of the time could manage comfortably.
Does quality 80 mean the same thing in every program?
No. The quality number is not defined by the JPEG standard. It is a convention each encoder uses to scale its quantisation tables, and different applications use different formulas and different base tables. Quality 80 in one program may produce a larger or smaller file than quality 80 in another. Judging by visual results and actual file size is more reliable than comparing numbers.
Why does a JPEG get worse each time I save it?
Each save decodes the image and encodes it again, repeating colour conversion, rounding and quantisation. Small errors accumulate across generations, especially if the quality setting changes, the image is resized, or a crop shifts the 8×8 block grid. Keeping an untouched original, making all edits in one session and exporting once is the most effective way to avoid this cumulative loss.
Is a progressive JPEG better than a baseline one?
Visually they are equivalent at the same quality, because both store the same quantised coefficients. A progressive file arranges the data in several scans so that a blurred preview appears quickly and then sharpens, which can feel faster on slow connections. Progressive files are often slightly smaller, but they need more memory and processing to decode, which matters little on modern devices.
Should I switch from JPEG to a newer format?
For web pages, WebP and AVIF usually deliver smaller files at similar quality and are widely supported by current browsers. JPEG XL offers excellent features but uneven browser support. For email attachments, upload forms and sharing with people whose software you do not control, JPEG remains the safest choice. Many sites serve a modern format with JPEG kept as a fallback.
Conclusion
JPEG compression is a chain of carefully chosen steps. Converting to YCbCr separates brightness from colour; chroma subsampling discards colour resolution the eye barely notices; the 8×8 DCT concentrates each block's energy into a few coefficients; quantisation, governed by the quality setting, removes the fine detail that matters least; and zigzag ordering, run-length coding and Huffman coding pack what remains into a compact stream. Only subsampling and quantisation are deliberately lossy, which is why the quality setting has such a direct effect on both appearance and size.
That understanding has practical consequences. Use moderate quality settings rather than extremes, choose PNG for sharp-edged graphics, avoid repeated re-saving, and resize before compressing. When you adjust quality in ilovejpg and watch the live size estimate change, you are watching quantisation tables being scaled in real time, the same mechanism defined in ITU-T T.81 in 1992 and still at work in billions of images today.