How BMP, PNG, and JPEG Store Pixel Data at the Binary Level
In my years working with image processing and file recovery, the first thing I look at when analyzing a binary image file is its magic number. Every image file format begins with a specific sequence of bytes that identifies the format. For JPEG, the magic number is FF D8 FF. For PNG, it is 89 50 4E 47 0D 0A 1A 0A (which includes "PNG" in ASCII). For BMP, it is 42 4D ("BM" in ASCII, short for "BitMap"). These signatures are critical for file type identification when extensions are misleading or missing. I've used them countless times to recover images from corrupted drives.
Try this: Take any image file and open it in a hex editor. Look at the first 8 bytes — you will see the magic number of the format. For PNG, you can literally read "PNG" in the binary data.
The BMP format, short for Windows Bitmap, is the simplest binary image format to understand. A BMP file begins with the magic number 42 4D (hexadecimal for "BM", the ASCII characters "B" and "M"). This two-byte signature is immediately followed by a 14-byte BITMAPFILEHEADER containing the file size, reserved fields, and the offset where pixel data starts. The signature 0x424D in binary is 01000010 01001101. In my experience working with low-level image data, BMP is the best teaching format because every byte in the file directly maps to something meaningful. There's no compression, no complex encoding — just headers and raw pixel data.
After the 14-byte file header comes the DIB (Device Independent Bitmap) header. The most common version is BITMAPINFOHEADER, which is exactly 40 bytes. It contains the image width (4 bytes), height (4 bytes), color planes (2 bytes, always 1), bits per pixel (2 bytes), compression method (4 bytes), and several other fields. For a BMP with 24 bits per pixel, the pixel data starts right after the headers at byte offset 54. The pixel array is stored bottom-up — the first row of pixel data in the file is the bottom row of the image. Each pixel occupies 3 bytes in BGR order (Blue, Green, Red), not RGB. I've debugged many BMP reading issues caused by forgetting that BGR byte order.
PNG (Portable Network Graphics) uses a much more sophisticated binary structure than BMP. The file starts with an 8-byte signature: 89 50 4E 47 0D 0A 1A 0A. The byte 89 (binary 10001001) sets the high bit to ensure the file is treated as binary, not text. The next three bytes are the ASCII characters "PNG". The remaining bytes detect common file transfer problems. After the signature, the file is a sequence of chunks. Each chunk has a 4-byte length field, a 4-byte chunk type (ASCII, like "IHDR", "IDAT", "IEND"), the chunk data itself, and a 4-byte CRC32 checksum. I've worked extensively with PNG at the binary level, and the chunk-based architecture makes it highly extensible — readers can safely skip unknown chunk types.
The three essential PNG chunks are IHDR (image header), IDAT (image data), and IEND (image end). The IHDR chunk is always first and contains the image width (4 bytes), height (4 bytes), bit depth (1 byte), color type (1 byte), compression method (1 byte), filter method (1 byte), and interlace method (1 byte). The IDAT chunk contains the compressed pixel data, which has been filtered (using Sub, Up, Average, or Paeth filters) and then compressed with DEFLATE. Multiple IDAT chunks can appear in sequence and must be concatenated. The IEND chunk is always last and has no data (length = 0). In binary, the IEND chunk literally reads 00 00 00 00 49 45 4E 44 AE 42 60 82 — zero length, the type "IEND", and the CRC32 checksum.
Key insight: PNG achieves lossless compression by applying a filter to each scanline that subtracts predicted pixel values, reducing data entropy. The filtered data is then compressed with DEFLATE, the same algorithm used by ZIP files.
JPEG uses a marker-based binary structure entirely different from BMP and PNG. Every marker starts with byte FF followed by a marker type byte. The file begins with SOI (Start of Image): FF D8. Then comes a sequence of marker segments: APP0 (FF E0) contains the JFIF header with version, density, and thumbnail; DQT (FF DB) contains quantization tables; SOF0 (FF C0) contains the image dimensions and number of components; DHT (FF C4) contains Huffman tables; SOS (FF DA) marks the start of the compressed scan data. The file ends with EOI (End of Image): FF D9. In my experience debugging corrupt JPEG files, these markers are lifesavers — you can find where data starts and ends even if parts are damaged.
The JPEG compression magic happens after the SOS marker. The image is divided into 8 × 8 pixel blocks, and each block is transformed using the Discrete Cosine Transform (DCT). The resulting frequency coefficients are divided by values from the quantization table (stored in the DQT marker segment) and rounded to integers. High-frequency coefficients (fine detail) get divided by larger numbers, often becoming zero. The quantized coefficients are then run-length encoded and Huffman coded using the tables from the DHT marker segment. At quality setting 75, many coefficients become zero, and the bitstream efficiently stores runs of zeros. The JPEG binary stream is a continuous sequence of Huffman-coded bits with no byte alignment until the EOI marker. This is why JPEG is not a format where you can easily inspect pixel values in a hex editor — the data is highly transformed and compressed.
Here's how a 1920 × 1080 image differs at the binary level across formats:
I've used this comparison in presentations many times. Understanding the binary structure helps me choose the right format for every project. BMP for teaching and direct pixel access, PNG for lossless web graphics and screenshots, JPEG for photographs where file size matters more than pixel-perfect accuracy.
When I encounter an unknown file, these are the binary signatures I check first:
FF D8 FF at offset 0 = JPEG89 50 4E 47 at offset 0 = PNG42 4D at offset 0 = BMP ("BM")49 49 2A 00 or 4D 4D 00 2A = TIFF (little-endian or big-endian)47 49 46 38 at offset 0 = GIF ("GIF8")Knowing these first 2-4 bytes of the most common image formats is enough to identify almost any image file you encounter. The binary signatures work regardless of file extension, making them essential for digital forensics, data recovery, and file validation.
Open the Binary Code Decoder in a new tab and enter some binary patterns to see the results instantly. All conversions happen in your browser — no data is sent to any server.