FreeToolio

BMP to JPG

Drop BMP files here and get JPG copies back in this tab. A BMP is a DIB header followed by rows of raw pixels, so this page reads the header first — header size, width, height, bit depth, row stride, palette, compression — and then decodes the file with its own reader. 1, 4, 8, 16, 24 and 32-bit pixels, RLE8 and RLE4, top-down rows, the 12-byte OS/2 header and a BMP that carries a JPEG or PNG inside are all read here. Nothing is uploaded.

Drop BMP images here

or choose files · .bmp · up to 12 at a time · batch or single

    BMP in, JPG out · up to 12 files, 200 MB each, 400 MB per batch · 60 megapixels per image · no upload · no account · no watermark

    BMP to JPG: The Header Knows the File Size Before a Pixel Is Read

    A 1,600 × 1,200 photograph saved as a 24-bit BMP measured 5,760,054 bytes. The same pixels saved as a 32-bit BMP measured 7,680,054. Both produced an 81,184-byte JPG at quality 90, and the two JPGs were byte-identical: the same SHA-256, 37e342cb…. The header, not the extension, decides how many bytes sit in each row. This page reads that header first, then converts the pixels in the tab.

    Diagram of two 24-bit BMP files of the same 1,600 by 1,200 pixels. The 1,600-pixel-wide file has a 4,800-byte row with no padding and totals 5,760,054 bytes. The 1,599-pixel-wide file has a 4,797-byte row plus 3 padding bytes, so each row is still 4,800 bytes and the file is also 5,760,054 bytes.
    A BMP row is padded to a multiple of four bytes. Cutting one column off a 1,600-pixel-wide 24-bit image leaves 4,797 bytes of pixels per row, and three padding bytes bring it back to 4,800. Across 1,200 rows that is 3,600 bytes of padding, and the file is the same 5,760,054 bytes as the wider one. The header holds width, height and bit depth, so the size is known before a row is decoded.

    A BMP is a header, a palette, and rows of pixels

    The first 14 bytes are a file header: BM, the file size, and the offset where pixel data begins. At byte 14 sits the DIB header, and its first four bytes are its own length. That length is not always 40. A BMP can carry a 12-byte OS/2 core header, a 40-byte BITMAPINFOHEADER, a 52- or 56-byte variant with colour masks, a 64-byte OS/2 2.x header, a 108-byte V4 header, or a 124-byte V5 header. The size decides which fields exist. A 12-byte header stores width and height as 16-bit integers and has no compression field at all. A 124-byte header adds an embedded ICC profile offset and length.

    The fields this page needs are present in all of them: width, height, planes, bits per pixel, compression, and the offset to the pixels. For paletted files there is also a palette between the header and the pixel data, one BGR0 entry per colour. A 1-bit file has two entries, a 4-bit file sixteen, an 8-bit file up to 256.

    Then come the rows. A BMP row is padded to a multiple of four bytes, so the stride is floor((width × bits + 31) / 32) × 4. For a 1,600-pixel-wide 24-bit image the row is 4,800 bytes: 5,760,000 bytes of pixels plus a 54-byte header gives 5,760,054.

    Cut one column off and the arithmetic gets more interesting. At 1,599 pixels wide, a 24-bit row holds 4,797 bytes of pixels. Three padding bytes bring it to 4,800. Across 1,200 rows that is 3,600 bytes of padding, and the file is still 5,760,054 bytes. Two images with different dimensions have exactly the same size on disk.

    The sign of the height sets which end is row zero

    A positive height means the first row in the file is the bottom row of the picture. A negative height means the first row is the top. Both are valid, and the second form is why a decoder cannot assume bottom-up. A file with the height field set to −1,200 and the rows written top-first contains the same picture as a bottom-up file with the rows reversed.

    The test pair made that concrete: 1,600 × 1,200, 24-bit, one bottom-up and one top-down. Both wrote an 81,184-byte JPG, and both hashes matched. If a decoder ignores the sign, the image arrives upside down, and a BMP has no orientation tag that can correct it later.

    Four containers, one picture

    The same 1,600 × 1,200 pixels in five BMP containers:

    Stored as File bytes JPG at quality 90
    24-bit, BI_RGB 5,760,054 81,184
    32-bit, BI_RGB 7,680,054 81,184, same SHA-256
    8-bit palette 1,921,078 87,626
    4-bit palette 960,118 61,078
    1-bit 240,062 66,626

    The 24-bit and 32-bit files produced the same JPG, byte for byte, because they held the same pixels; the 32-bit file was just one third larger on disk. The palette rows are a different picture in the strict sense: reducing the source to 256 or 16 colours changes the pixels. What they show is that the palette is storage, not image quality.

    The 8-bit file is less than a third of the 24-bit file on disk, and its JPG came out 8% larger: 87,626 against 81,184. Quantising a smooth gradient to 256 colours creates band edges, and JPEG spends bits on those edges. The 4-bit file produced a smaller JPG, 61,078 bytes, because sixteen colours leave flatter areas. The 1-bit file then went back up to 66,626 bytes: hard black-and-white edges are expensive for a transform built around smooth blocks.

    The compression code changes nothing about the result. RLE8 on the same indices produced the same 87,626 bytes as the uncompressed 8-bit file, and RLE4 produced the same 61,078 bytes as the uncompressed 4-bit file. RLE is a storage trick for runs of identical pixels, not a second image format.

    The fourth byte of a 32-bit BMP is usually reserved, not alpha

    A 32-bit BMP sounds like RGBA. In a plain BI_RGB file it is not. The fourth byte is reserved, and the usual value written by Windows tools is zero. A decoder that treats it as alpha will make the whole image disappear. This page ignores that byte unless the header declares an alpha mask: a V3, V4 or V5 header with a non-zero alpha mask, or BI_ALPHABITFIELDS.

    The 32-bit BI_RGB fixture had zero in every fourth byte and still produced the same 81,184-byte JPG as the 24-bit file. A second fixture used a 56-byte V3 header with a real 0xFF000000 alpha mask and a radial alpha channel: transparent corners, opaque centre. Its JPG was 47,710 bytes, and the corners read as (255,255,255), (0,0,0) and (254,0,0) on white, black and red mattes. That is the only case where the matte control does anything.

    The file also grew from 5,760,054 to 7,680,070 bytes for that extra channel, before the V3 header and masks. A JPG has nowhere to put it, so the page has to paint a background first.

    16 bits is not one format: 5-5-5 or 5-6-5

    A 16-bit BMP with BI_RGB uses five bits for red, five for green and five for blue. A BI_BITFIELDS file can use five, six and five instead, and the difference is visible on a gradient: 32 green levels become 64. The two test files were 3,840,054 and 3,840,066 bytes, the second carrying twelve bytes of colour masks.

    Expanding either to 8 bits introduces rounding. Against a desktop decoder, the 64 × 64 fixture differed on 3,643 of 4,096 pixels for 5-5-5 and 3,341 for 5-6-5, with a maximum channel difference of one level in both cases. At full size the JPGs were 98,256 and 94,957 bytes, larger than the 81,184 bytes from the 24-bit source, because the quantised levels create edges that JPEG then has to encode.

    If the 16-bit file is the master, keep it. The JPG is 8-bit per channel no matter what the BMP held.

    What the JPG cannot take with it

    What the BMP held Measured What came out
    palette, 256 / 16 / 2 colours 1,921,078 / 960,118 / 240,062 B full-colour JPG, palette gone
    16-bit channels 3,840,054 / 3,840,066 B 8-bit channels, max one level of rounding
    alpha mask, 32-bit 7,680,070 B flattened onto the matte
    embedded ICC, V5 header 588 B not written; a 456-byte sRGB profile is
    resolution fields 2,835 pixels per metre (72 dpi) not carried

    The quality setting does not change the channel count. All seven outputs from quality 30 to 100 were baseline SOF0, 8-bit, three components. At quality 90 the chroma is sampled 4:2:0; at 100 the encoder switches to 4:4:4 and writes a much larger file. It is still lossy: the quality-100 JPG was 623,367 bytes, its largest channel change was four levels, and 75.68% of pixels moved.

    The photo went from 5.76 MB to 81 KB

    The 1,600 × 1,200 24-bit photo at seven quality settings:

    Quality Bytes Change vs the BMP
    30 18,715 −99.68%
    50 21,560 −99.63%
    70 27,482 −99.52%
    80 39,119 −99.32%
    90 81,184 −98.59%
    95 148,757 −97.42%
    100 623,367 −89.18%

    At quality 90 the result measured 48.12 dB against the decoded BMP, with 83.0% of pixels changed and a largest channel difference of 20 levels. The last step from 95 to 100 added 474,610 bytes for a file that is still approximate. On this picture, 90 is the point where the size curve starts to steepen without a visible gain.

    A BMP can carry a JPEG or a PNG inside

    Compression codes 4 and 5 mean the pixel area is not raw pixels at all: it is a complete JPEG or PNG stream. The page hands that stream to the browser's own decoder and draws the result. An 800 × 600 BMP whose pixel area was a PNG measured 238,307 bytes and produced a 25,104-byte JPG, byte-identical to the JPG written from the uncompressed 24-bit version of the same image. The JPEG-inside variant measured 31,470 bytes and produced 27,431 bytes, since the stream had already been through one lossy encode.

    This is rare in the wild. It is also the cleanest proof that the extension is not the format: a file named .bmp can contain a PNG.

    What the page reads before it decodes

    Before allocating a pixel buffer, the page parses the file header and the DIB header and puts the useful fields on the card: header size, compression name, bits per pixel, palette size, padding bytes per row, row order, alpha, and the size of an embedded ICC profile. Those fields are also the refusal test.

    The reader handles 1, 4, 8, 16, 24 and 32-bit pixels, BI_RGB, BI_BITFIELDS, BI_ALPHABITFIELDS, RLE8, RLE4, top-down rows, the 12-byte OS/2 header, and embedded JPEG or PNG streams. It refuses unknown compression codes, pixel depths outside that set, a palette that ends before its last entry, and pixel data that ends before the last row. On a refusal the card names the field and writes nothing. A decoder that returns a zero-filled buffer would export a black page.

    The limits are 12 files at a time, 200 MB per file, 400 MB for the batch and 60 megapixels per image. They exist because the bytes stay in the tab: a 60-megapixel image needs about 240 MB for its RGBA buffer alone.

    How to convert BMP to JPG here

    1. Add .bmp files, or drop them on the box.
    2. Set the quality. Every file re-encodes when the number changes.
    3. Download each JPG, or one ZIP for the batch.

    What the controls do

    The quality slider runs from 30 to 100 and starts at 90. The number box and the slider stay in sync, and there is no run button. The matte selector only paints when a 32-bit header declares an alpha mask; on a plain BI_RGB file it changes nothing. Output keeps the source pixel dimensions. There is no resize and no watermark.

    Why this page doesn't upload your BMP

    The header parser, the pixel decoder, the canvas and the JPG encoder all run in the tab. To check, open the Network panel, add a BMP and convert it: no request carries the file. The stronger check is to load the page, convert one file, switch the network off and convert another. The same 5,760,054-byte photo produced the same 81,184 bytes and the same SHA-256 with the connection off, and the page's resource entry count did not change during either conversion.

    There is no decoder library to download. A BMP is a header and rows of pixels, so the reader is part of the page rather than a 100 KB dependency loaded on the first file.

    When to keep the BMP

    • It is a 1-bit mask or stencil. JPG adds grey halos around hard edges; the 240,062-byte BMP keeps them exact.
    • It is indexed pixel art and the palette indices matter to an editor.
    • An old Windows application or an industrial machine expects BMP input.
    • The BMP carries an embedded JPEG or PNG stream that is the real master.
    • You need a byte-exact archival copy. BMP has no compression layer to lose; JPG is lossy by design.
    • It carries a V5 ICC profile for colour-managed work. The canvas drops it.

    Questions that come up

    Why is the JPG from an 8-bit BMP bigger than the one from the 24-bit file? Because 256 colours turn a smooth gradient into bands, and JPEG spends bits on the edges between bands. The 8-bit file was 1,921,078 bytes on disk and produced an 87,626-byte JPG; the 24-bit file was 5,760,054 bytes and produced 81,184 bytes.

    Will my palette survive the conversion? No. A JPG is three-channel 8-bit; the palette is expanded into colours and the index table is gone. The output carries a 456-byte sRGB profile written by the encoder, not the BMP's palette.

    Is the fourth byte in a 32-bit BMP transparency? Usually not. In a plain BI_RGB file it is reserved and commonly zero. It is alpha only when the header declares an alpha mask. This page follows the header: no mask, no transparency, and the output is byte-identical to the 24-bit version.

    Can it read a BMP that has a JPEG or PNG inside? Yes. Compression code 4 or 5 means the pixel area is a complete stream; the page gives it to the browser decoder. A 238,307-byte BMP containing a PNG produced a 25,104-byte JPG here.

    Why did my 1-bit BMP get smaller instead of larger? Because BMP stores the bits raw. A 1,600 × 1,200 1-bit file is 240,062 bytes; the JPG was 66,626. The JPG is still the wrong choice for a mask, since its compression softens hard edges, but it is smaller.

    Is quality 100 a lossless copy? No. At 100 the encoder switches chroma from 4:2:0 to 4:4:4, but the transform is still lossy. The test photo came out at 623,367 bytes with a maximum channel change of four levels.

    What happens to a top-down BMP? The negative height is read as a row order, not as an error. A top-down 24-bit file and its bottom-up twin produced the same 81,184-byte JPG with the same SHA-256.