BMP colors in RGB order to BGR order Converter
Convert BMP image color channels from RGB to BGR order or BGR to RGB. Swap red and blue channels in 24-bit and 32-bit uncompressed bitmap files.
About
BMP files store pixel data in BGR order internally due to Windows GDI legacy conventions, yet external tools and APIs often expect RGB. Mismatched channel order produces images with inverted red-blue tones - skin appears cyan, skies turn orange. This converter performs direct byte-level swapping at offsets i and i+2 within each pixel triplet, preserving all other header data and metadata intact. The operation is lossless and reversible (applying twice restores the original).
Critical edge cases handled: row padding to 4-byte boundaries per BMP specification, negative height values indicating top-down scanline order, and 32-bit BMPs where the alpha channel at position 3 remains untouched. The tool rejects RLE-compressed BMPs (compression types 1 and 2) since channel swapping would corrupt the encoded data stream.
Formulas
The RGB↔BGR swap operates on the byte level within each pixel. For a 24-bit BMP, each pixel occupies 3 consecutive bytes. The swap exchanges bytes at relative positions 0 and 2:
temp ← data[i]
data[i] ← data[i + 2]
data[i + 2] ← temp
Row padding ensures each scanline aligns to a 4-byte boundary. The padding calculation prevents reading into adjacent row data:
padding = (4 − rowSize mod 4) mod 4
stride = rowSize + padding
Where bytesPerPixel = 3 for 24-bit or 4 for 32-bit BMPs. The stride represents the actual number of bytes per row including padding. Pixel data offset dataOffset is read from bytes 10-13 of the file header (little-endian 32-bit integer).
Reference Data
| BMP Format | Bits Per Pixel | Channels | Storage Order | Swap Operation | Supported |
|---|---|---|---|---|---|
| Monochrome | 1 | 1 | Indexed | N/A (palette) | No |
| 16 Color | 4 | 1 | Indexed | N/A (palette) | No |
| 256 Color | 8 | 1 | Indexed | N/A (palette) | No |
| High Color | 16 | 3 | RGB555/RGB565 | Bit masking | No |
| True Color | 24 | 3 | BGR | [0]↔[2] | Yes |
| True Color + Alpha | 32 | 4 | BGRA | [0]↔[2] | Yes |
| RLE-8 Compressed | 8 | 1 | Encoded | N/A | No |
| RLE-4 Compressed | 4 | 1 | Encoded | N/A | No |
| JPEG Compressed | Variable | 3 | Embedded | N/A | No |
| PNG Compressed | Variable | 3-4 | Embedded | N/A | No |
| Header Field | Offset (bytes) | Size (bytes) | Description | Typical Value |
|---|---|---|---|---|
| Signature | 0 | 2 | Magic bytes | 0x42 0x4D ("BM") |
| File Size | 2 | 4 | Total file size | Variable |
| Reserved | 6 | 4 | Application-specific | 0 |
| Data Offset | 10 | 4 | Pixel array start | 54 (no palette) |
| DIB Header Size | 14 | 4 | Header version | 40 (BITMAPINFOHEADER) |
| Width | 18 | 4 | Image width in pixels | Variable |
| Height | 22 | 4 | Image height (signed) | Positive = bottom-up |
| Color Planes | 26 | 2 | Must be 1 | 1 |
| Bits Per Pixel | 28 | 2 | Color depth | 24 or 32 |
| Compression | 30 | 4 | Compression method | 0 (BI_RGB) |
| Image Size | 34 | 4 | Pixel data size | 0 or calculated |
| X Pixels/Meter | 38 | 4 | Horizontal resolution | 2835 (72 DPI) |
| Y Pixels/Meter | 42 | 4 | Vertical resolution | 2835 (72 DPI) |
| Colors Used | 46 | 4 | Palette entries | 0 (full palette) |
| Important Colors | 50 | 4 | Significant colors | 0 (all) |