JPG File Documentation


Summary

A JPEG Image (also written JPG) is a compressed photo, the most common picture format on the web, cameras, and phones. It uses lossy DCT compression: fine detail is discarded to keep files small, so every re-save loses a little quality. The extension is .jpg or .jpeg (the same format), and the MIME type is image/jpeg. Every operating system and browser opens one without extra software.

Technical details

FeatureValue
Full nameJPEG Image (Joint Photographic Experts Group)
File extension.jpg, .jpeg
MIME typeimage/jpeg
Format typeLossy-compressed raster bitmap (DCT-based)
DeveloperJoint Photographic Experts Group (ISO/IEC + ITU-T)
Introduced1992
StandardISO/IEC 10918-1; ITU-T T.81
Open standardYes — publicly published, royalty-free baseline
Container / wrapperJFIF (APP0) or Exif (APP1)
Colour modelYCbCr (converted from RGB before encoding)
Bit depth8 bits per channel, 24-bit colour (~16.7 million colours)
CompressionLossy, discrete cosine transform (DCT) on 8×8 blocks
Chroma subsampling4:4:4, 4:2:2, or 4:2:0 (2h2v)
Entropy codingHuffman (baseline); arithmetic coding optional in T.81
Encoding modesBaseline (SOF0) and progressive (SOF2)
TransparencyNone — no alpha channel
AnimationNone
Max dimensions65535 × 65535 pixels
Byte orderBig-endian (marker segments)
Magic numberFF D8 FF (SOI marker)
Related extensions.jpeg .jfif .heic .webp
Specificationw3.org/Graphics/JPEG/itu-t81.pdf
File signature (magic bytes)
FF D8 FF

Offset 0. The first two bytes FF D8 are the SOI marker (Start Of Image); the third byte FF opens the next marker segment. The fourth byte names the variant: E0 is a JFIF file (APP0), E1 is an Exif file (APP1, used by nearly every camera and phone). Every valid JPEG ends with the two-byte EOI marker FF D9.

What is a JPG file?

A JPG file holds a photograph compressed with the JPEG method. The name comes from the Joint Photographic Experts Group, the committee that published the standard in 1992 as ISO/IEC 10918-1, identical in content to the ITU-T recommendation T.81. That base standard defines only the compressed data stream. The rules for wrapping it in an actual file come from two interchange formats layered on top: JFIF (1992) for plain images, and Exif for camera and phone photos, which adds metadata such as date, exposure, and GPS.

The extensions .jpg and .jpeg name the same format; .jpg survives from the old DOS and Windows limit of three-letter extensions. A JPEG stores 24-bit colour (8 bits each for red, green, and blue), has no transparency and no animation, and its MIME type is image/jpeg. Everything below describes how the bytes are actually arranged, from the marker framing down to the 8×8 blocks where the compression happens.

Marker segments: how a JPEG stream is framed

A JPEG file is a sequence of marker segments. Every marker is two bytes: 0xFF followed by a non-zero code byte that identifies what comes next. Most markers introduce a segment whose next two bytes are a big-endian length (that length counts itself but not the leading marker), followed by that many bytes of payload. A few markers stand alone with no length and no payload, notably SOI and EOI.

FF D8                Start Of Image (SOI)           - standalone, no length
FF E0 <len> ...      APP0 segment  (JFIF metadata)   - or FF E1 for Exif
FF DB <len> ...      DQT   Define Quantization Table
FF C0 <len> ...      SOF0  Start Of Frame, baseline  (or FF C2 = SOF2 progressive)
FF C4 <len> ...      DHT   Define Huffman Table
FF DA <len> ...      SOS   Start Of Scan
   ... entropy-coded image data (not a segment; runs until next marker) ...
FF D9                End Of Image (EOI)             - standalone, no length

Because each segment carries its own length, a reader can walk the header and skip any segment it does not recognise: read the marker, read the length, jump that many bytes, repeat. The scan data after SOS is the exception. It has no length field and is read byte by byte until the next real marker (usually EOI) appears. The table below lists the markers you will meet in almost every file.

MarkerBytesMeaning
SOIFF D8Start of image; first two bytes of every JPEG
APP0FF E0JFIF segment (density, units, thumbnail)
APP1FF E1Exif segment (camera, date, GPS)
DQTFF DBDefine quantization table
SOF0FF C0Start of frame, baseline DCT
SOF2FF C2Start of frame, progressive DCT
DHTFF C4Define Huffman table
DRIFF DDDefine restart interval
SOSFF DAStart of scan; precedes the coded data
RST0–7FF D0FF D7Restart markers inside the scan
EOIFF D9End of image; last two bytes

The SOI and APP0/APP1 header, byte by byte

The first bytes decide whether a file is JFIF or Exif. After the SOI marker, a JFIF file opens an APP0 segment whose payload begins with the five ASCII bytes JFIF\0. An Exif file instead opens APP1 (FF E1) with the identifier Exif\0\0, after which sits a full TIFF header holding the metadata tags. Here is an annotated dump of a JFIF header:

Offset  Bytes            Meaning
0000    FF D8            SOI  - Start Of Image
0002    FF E0            APP0 marker
0004    00 10            segment length = 16 bytes
0006    4A 46 49 46 00   "JFIF\0" identifier
000B    01 02            JFIF version 1.02
000D    01               density units: 1 = pixels per inch
000E    00 48 00 48      X density 72, Y density 72
0012    00 00            thumbnail width 0, height 0 (no thumbnail)
0014    FF DB            DQT  - next segment: a quantization table

An Exif photo differs only from offset 0002: the marker is FF E1, and instead of JFIF\0 the payload starts 45 78 69 66 00 00 (“Exif\0\0”). Both variants keep the same SOI and the same downstream markers, which is why the three-byte signature FF D8 FF identifies a JPEG regardless of the wrapper, and the fourth byte (E0 versus E1) tells the two apart.

The 8×8 block DCT: turning pixels into frequencies

JPEG does not compress pixels directly. It first converts the image to the YCbCr colour space (one luma channel Y and two chroma channels Cb and Cr), then splits each channel into blocks of 8×8 samples. Every block is processed on its own. First each sample has 128 subtracted from it (a level shift that centres the 0–255 range on zero), then the block passes through a forward two-dimensional discrete cosine transform.

The DCT turns the 64 spatial samples into 64 frequency coefficients. The top-left coefficient is the DC term, the average brightness of the whole block. The other 63 are AC terms describing progressively finer detail, from slow gradients toward the top-left corner to sharp edges toward the bottom-right. The transform loses nothing by itself; it just reorganises the data so that most of a natural image’s energy piles into a handful of low-frequency coefficients while the high-frequency ones fall near zero. The 8×8 size is a compromise: large enough for the transform to find redundancy, small enough that the maths stays cheap and that detail does not smear across the whole image.

Quantization: the DQT table and where loss happens

The actual discarding of information happens in one step: quantization. Each of the 64 coefficients is divided by a matching entry in a quantization table and rounded to the nearest integer. Coefficients smaller than their divisor become zero and are gone for good. This is the lossy heart of JPEG, and the only place data is thrown away.

The table itself is stored in the DQT segment (FF DB), 64 values, usually one table for luma and a coarser one for chroma. The divisors are largest for high-frequency coefficients, because the human eye is far less sensitive to fine detail than to overall brightness, so those coefficients can be crushed hardest. The quality slider in an editor does not change the algorithm. It scales this table: a lower quality multiplies every divisor, zeroing more coefficients and shrinking the file, while a higher quality shrinks the divisors so more detail survives. Because the loss is baked into the stored coefficients, re-saving decodes and re-quantizes the image each time, and detail erodes with every generation.

Zig-zag ordering and run-length of AC zeros

After quantization most of the non-zero coefficients sit in the top-left of the block and most of the trailing ones are zero. To exploit that, the encoder reads the 8×8 block in a zig-zag order rather than row by row, walking diagonally from the DC term outward toward the highest frequency:

 0  1  5  6 14 15 27 28
 2  4  7 13 16 26 29 42
 3  8 12 17 25 30 41 43
 9 11 18 24 31 40 44 53
10 19 23 32 39 45 52 54
20 22 33 38 46 51 55 60
21 34 37 47 50 56 59 61
35 36 48 49 57 58 62 63

This ordering groups the surviving coefficients first and sweeps the long stretch of zeros to the end. The AC coefficients are then coded as (run, value) pairs, where run is the number of zeros preceding a non-zero value. A single end-of-block symbol says “every remaining coefficient is zero,” which for a smooth block can dismiss dozens of coefficients in one token. That is a large part of why photographs compress so well.

YCbCr and chroma subsampling: 4:4:4, 4:2:2, 4:2:0

Splitting colour into luma and chroma lets JPEG spend bits where the eye notices and save them where it does not. Because human vision resolves brightness far better than colour, the two chroma channels are commonly stored at reduced resolution, a step called chroma subsampling. The notation counts samples in a 4-pixel-wide reference block.

NotationChroma resolutionEffect
4:4:4Full, one chroma sample per pixelNo colour loss; largest files
4:2:2Halved horizontallyCommon in higher-quality photos
4:2:0 (2h2v)Halved horizontally and verticallyDefault for most cameras and the web

Subsampling forces a grouping unit larger than one 8×8 block. Under 4:2:0 a single 8×8 chroma block covers a 16×16 luma area, so the encoder processes a minimum coded unit (MCU) of four luma blocks plus one Cb and one Cr block together. The whole scan is a run of MCUs in raster order. This is also why JPEG is poor for text and line art: sharp coloured edges lose chroma resolution and the DCT rings around them, producing the smears and blocky halos that plague screenshots saved as JPG.

Huffman entropy coding and the DHT tables

The quantized, zig-zag-ordered coefficients are packed with Huffman coding, a lossless step that assigns short bit codes to common values and longer ones to rare values. The DC and AC coefficients are handled differently. The DC term of each block is coded as the difference from the previous block’s DC value, since neighbouring blocks usually have similar brightness. Each AC coefficient is coded from its (run, size) pair: the run of preceding zeros and the number of bits needed for the value, followed by the value bits themselves.

The code tables live in the DHT segments (FF C4). A baseline file carries up to four: a DC and an AC table for luma, and a DC and an AC table for chroma. Baseline JPEG uses Huffman coding; the T.81 standard also defines an arithmetic-coding option that compresses a little tighter but is rarely used because of historical patent caution and limited decoder support. One quirk follows from the marker rule: since 0xFF starts a marker, any 0xFF byte the entropy coder produces inside the scan is followed by a stuffed 0x00 (written FF 00), which the decoder strips so the value is never mistaken for a marker.

Baseline versus progressive: SOF0 and SOF2

The Start Of Frame marker sets the encoding mode. SOF0 (FF C0) is baseline: the image is coded in a single scan, top to bottom, and a decoder reconstructs it in one pass. SOF2 (FF C2) is progressive: the same coefficients are split across several scans, so the picture arrives as a blurry whole that sharpens as more data loads.

Progressive JPEG achieves this two ways, often combined. Spectral selection sends low-frequency coefficients (the coarse shapes) in early scans and high-frequency detail later. Successive approximation sends the most significant bits of each coefficient first and refines with lower bits in later scans. A file therefore contains multiple SOS segments, one per scan, each with its own coefficient range. Progressive files are usually a little smaller than baseline for the same quality and are friendlier on slow connections, at the cost of more decoding work. Whatever the SOF, the frame header also records image height and width (each 16-bit, capping dimensions at 65535×65535), the sample precision, and the component list with each channel’s subsampling factors.

Restart markers: DRI and RSTn

The entropy-coded scan is one long dependent bitstream: because DC values are differential and the Huffman bits are not byte-aligned, a single flipped bit corrupts everything after it. Restart markers limit that damage. A DRI segment (FF DD) sets a restart interval, a number of MCUs. After every interval the encoder inserts a restart marker, FF D0 through FF D7 cycling in order, resets the DC prediction to zero, and byte-aligns the stream.

Each interval is then independently decodable from its restart point, so a corrupt region only garbles until the next marker rather than the rest of the image. Restart markers also make it possible to decode intervals in parallel, since none depends on the previous one’s DC value. They are optional; many files omit them and carry the scan as one continuous run.

Frequently asked questions

Why does re-saving a JPG lose quality?

Each save runs the full lossy pipeline again: the file is decoded to pixels, re-transformed, and re-quantized against the quantization table. Rounding at the quantization step drops a little more detail every time, so repeated edit-and-save cycles accumulate block artefacts. This is called generation loss. Keep a lossless master (such as PNG or the camera raw) and export to JPG only as the final step.

What does the quality slider actually change?

It scales the DQT quantization table. A lower setting multiplies every divisor, so more coefficients round to zero: smaller file, coarser image. A higher setting uses smaller divisors, keeping more coefficients and more detail. The number (often 1–100) is just a scaling factor an application maps onto the table; it is not part of the JPEG standard, so the same “80” can differ between programs.

Why is JPG bad for text and line art?

The DCT and chroma subsampling both assume smooth, photographic content. A hard black-on-white edge contains strong high-frequency coefficients that quantization mangles, producing “ringing” halos, while 4:2:0 subsampling blurs coloured edges. For screenshots, logos, and text, a lossless format like PNG or WebP keeps edges crisp. Newer photo formats such as HEIC compress smaller than JPG but are not as universally readable.

References