Images
Choosing an image format: PNG, JPG, WebP, AVIF, GIF and more
Every image format is a bundle of trade-offs: lossy or lossless compression, whether transparency survives, how many colors a pixel can hold, whether it can animate, and whether a browser will draw it at all. This guide settles which format fits which job and shows what goes wrong when a file is converted to the wrong one. The examples are byte-level output from the same BMP, GIF and ICO writers that sit behind the converters on this site.
By the MaffeiTools team · Updated · 7 min read
Two questions that decide most choices
The first question is whether the image is a photograph or a drawing. Photographs and other continuous-tone images tolerate lossy compression because the discarded detail is hard to see. Screenshots, diagrams, logos and line art do not: MDN's format guide points out that blurring and colored fringes around text and sharp edges are very visible in lossy output, so those want lossless encoding or a vector format.
The second question is whether any pixel has to be partly see-through. JPEG has no alpha channel at all, so a logo with a soft shadow cannot live in a JPEG. Once those two answers are in hand, the rest is refinement: does it animate, how many colors does it really contain, and will every browser that matters decode it.
What each format is for, and what it cannot do
Format capabilities below follow MDN's image format guide, and the percentages are MDN's averages; a single file can land well outside them. The remarks about photographs and re-saving describe how lossless and lossy coding behave in general.
- PNG: lossless, with indexed color, greyscale and truecolor modes, optional full alpha, and 8 or 16 bits per component in truecolor. The default for screenshots, diagrams and anything with transparency. Photographs compress poorly because lossless coding cannot discard noise.
- JPEG: lossy, based on the discrete cosine transform, 8 bits per component, no alpha, no indexed mode. Supported everywhere, which is its main virtue. Each re-save quantizes again, so repeated edits and saves accumulate artifacts.
- WebP: lossy (VP8 based) and lossless, with alpha and animation. MDN puts lossy WebP at roughly 25 to 35 percent smaller than JPEG at similar visual quality, and lossless WebP about 26 percent smaller than PNG. Lossy WebP stores 8-bit YUV 4:2:0. On macOS, Safari needs version 14 and macOS Big Sur.
- AVIF: AV1 video coding inside a HEIF container. Lossy and lossless, alpha, animation, HDR, and 8, 10 or 12 bits per component. Support arrived in Chrome 85, Firefox 93, Safari 16.1 and Edge 121. It has no progressive rendering, so the whole file must download before anything appears. Canvas in Chrome, Edge and Firefox does not encode AVIF, so the AVIF converters here run libavif compiled to WebAssembly instead.
- GIF: LZW compression of 8-bit indexed color, so at most 256 colors per frame, plus a single transparent index and simple animation. MDN's advice is to prefer PNG for still images and consider WebP, AVIF or APNG for animation.
- BMP: normally uncompressed, so file size depends only on dimensions. MDN says to avoid it for web content.
- ICO: a container that holds one or more images at different sizes, used for favicons and Windows icons. It is not a compression format.
- SVG: XML text describing shapes, so it stays sharp at any size. Right for icons, logos and diagrams; wrong for photographs.
- HEIC: HEVC-coded images in a HEIF container. Good compression, but it is not something Chrome or Firefox will display, as covered below.
The exact size of a BMP, byte by byte
A 24-bit BMP starts with a 14-byte file header and a 40-byte info header, the layout Microsoft documents for the Windows bitmap format. The pixels follow uncompressed, bottom row first, three bytes each in blue, green, red order. The rule that surprises people is that every row is padded with zero bytes to a multiple of four bytes, as MDN notes.
That gives a closed formula: row bytes = ceil(width x bits / 32) x 4, and file bytes = 54 + row bytes x height. Below is the header the site's BMP writer produces for a 3 by 2 test image, followed by the sizes it reports for other dimensions.
3x2, 24-bit: 78 bytes
header: 42 4d 4e 00 00 00 00 00 00 00 36 00 00 00 28 00 00 00
03 00 00 00 02 00 00 00 01 00 18 00 00 00 00 00 18 00 00 00
13 0b 00 00 13 0b 00 00 00 00 00 00 00 00 00 00
first row written (the bottom row of the image):
32 64 00 | 32 64 64 | 32 64 c8 | 00 00 00 <- 3 pad bytes
1000x1000, 24-bit: 3000054 bytes
1001x1000, 24-bit: 3004054 bytes
4000x3000, 24-bit: 36000054 bytesWorth knowing. Reading the header: 42 4d is the ASCII letters BM, 4e 00 00 00 is the file size 78, 36 is the pixel offset 54, 28 is the info header size 40, then width 3, height 2, one plane, 0x18 = 24 bits per pixel, and no compression. Nine bytes of pixels per row are padded to 12, so 2 rows x 12 + 54 = 78.
What a 256-color palette does to a photograph
A GIF file begins with six ASCII bytes, GIF89a: the signature GIF followed by version 89a, the July 1989 revision, an extension of version 87a that defines the Graphic Control Extension carrying the transparent color index. Every pixel is then an index into a palette of at most 256 entries, so any image with more distinct colors has to be quantized first.
The site's GIF writer does this in two passes. It first counts exact colors; if there are 256 or fewer (255 when transparency needs one slot) the palette is exact and nothing is lost, which is why icons and flat art survive. Otherwise it runs median-cut quantization and maps every pixel to the nearest palette color. It does not dither, so smooth gradients turn into visible bands.
2x2, black and white checker, opaque: 36 bytes 47 49 46 38 39 61 | 02 00 02 00 f0 00 00 | 00 00 00 ff ff ff | 2c 00 00 00 00 02 00 02 00 00 | 02 03 44 02 05 00 | 3b (GIF89a | width 2, height 2, packed f0 | palette | image descriptor | LZW data | trailer) 64x64 gradient, distinct colors in the source: 4096 palette entries after quantizing: 256
Worth knowing. The packed byte f0 means a global color table is present, 8 bits per color channel, and a table of 2 entries. The trailer 3b ends the file. The 4096 distinct colors of the gradient end up represented by 256 palette entries.
Where transparency goes when you convert
A conversion to a format without full alpha has to decide what a see-through pixel becomes. The converters on this site make these choices, and knowing them explains most surprises:
- JPEG: the canvas is filled with white before the image is drawn, so transparent areas become solid white. On a dark page that shows as a white box.
- BMP: the writer produces 24-bit files, which have no alpha, so each pixel is blended onto white. The writer can emit 32-bit BMP with an alpha byte, but the converters use 24-bit.
- GIF: alpha is thresholded at 128. Pixels below it become fully transparent and the rest fully opaque, so anti-aliased edges turn jagged and soft shadows vanish or turn solid.
- ICO: each image is stored as a PNG inside the container, so alpha is preserved.
- PNG, WebP and AVIF: alpha is preserved.
24-bit BMP, file size 58 bytes: pixel = 7f 7f ff 00 (B G R + 1 pad byte) 32-bit BMP, file size 58 bytes: pixel = 00 00 ff 80 (B G R A)
Worth knowing. In the 24-bit file, half-transparent red blended onto white becomes RGB 255, 127, 127 and the transparency is gone. Converting a JPEG to PNG later cannot bring back either the detail or the transparency; PNG just stores the already-degraded pixels losslessly, usually in a larger file.
ICO is a container, and the payload is a PNG
An ICO file is a 6-byte directory header (reserved zero, type 1 for icons, image count), then one 16-byte entry per image giving width, height, bit depth, payload size and offset, then the payloads. The payload may be a complete PNG file, a form ICO has allowed since Windows Vista, and that is what the site's ICO writer stores. Because the width and height fields are one byte each, a 256-pixel side is written as 0.
total 232 bytes = 6 + 2 x 16 + 84 + 110 00 00 01 00 02 00 10 10 00 00 01 00 20 00 54 00 00 00 26 00 00 00 16x16, 32 bpp, 84 bytes at offset 38 20 20 00 00 01 00 20 00 6e 00 00 00 7a 00 00 00 32x32, 32 bpp, 110 bytes at offset 122
HEIC opens on the phone and fails in the browser tab
The caniuse data for HEIF and HEIC shows no support in Chrome or Firefox, and support in Safari from version 17. The reason given there is that HEIC rests on the HEVC video codec, which is complex and expensive to license, and that AVIF and JPEG XL were designed to replace it. Practically, a HEIC file dropped into a web page or an upload preview will often show as a broken image.
The HEIC converters decode the file with libheif compiled to WebAssembly, produce a PNG in memory, and then run the ordinary pipeline, which is why HEIC to JPG, WebP, AVIF, BMP and ICO all work. For sharing, JPEG is the safe target; choose WebP or AVIF only when the destination is known to display them. The pixels pass through a canvas, so camera metadata such as location is not carried into the output file.
File signatures decide what a file is, not its name
Renaming a file does not change its format. The processing tools here (compressor, resizer, crop and EXIF reader) read the first bytes of an upload and match them against known signatures: FF D8 FF for JPEG, 89 50 4E 47 0D 0A 1A 0A for PNG, the text GIF8 for GIF, 42 4D (BM) for BMP, and RIFF at byte 0 with WEBP at byte 8 for WebP. They accept only those five, and refuse SVG outright, with the message that SVG is not supported for security reasons; AVIF, HEIC and ICO files go through the converters first.
photo.jpg (bytes are a BMP) -> image/bmp logo.png (bytes are a GIF) -> image/gif notes.txt (bytes are text) -> Unsupported or unrecognized image format.
The rules in order
Apply these top to bottom and stop at the first that matches:
- Drawn with shapes and must stay sharp at every size: SVG, with a PNG or WebP fallback where SVG is not accepted.
- Needs transparency: PNG, or lossless or lossy WebP or AVIF when the size matters and browsers you target support them.
- Photograph: JPEG for compatibility, WebP or AVIF for smaller files with a JPEG fallback in a picture element.
- Screenshot or text-heavy graphic: PNG or lossless WebP, never a low-quality JPEG.
- Animation: prefer animated WebP, AVIF or APNG over GIF; use GIF only for compatibility, and expect the 256-color limit.
- Received as HEIC: convert to JPEG before it goes anywhere a browser has to display it.
- BMP: only when a specific program asks for it.