如何将int16类型地形高度值转换回RGB格式并写入BMP文件?
Got it, let's break this down step by step—since your int16* heights array originated from an RGB BMP, we just need to reverse the original compression that turned 24-bit RGB into 16-bit values. The key here is figuring out how the original RGB-to-int16 conversion was done (the most common format is RGB565, so we'll start with that).
First, Confirm the Original Compression Format
Nearly all cases where 24-bit RGB is packed into 16 bits use the RGB565 standard:
- Red (8-bit) is compressed to 5 bits (uses the top 5 bits of the 16-bit value)
- Green (8-bit) is compressed to 6 bits (uses the middle 6 bits—since human eyes are more sensitive to green)
- Blue (8-bit) is compressed to 5 bits (uses the bottom 5 bits)
If your original conversion used RGB555 (15 bits for color, 1 unused bit), the logic is similar but each channel gets 5 bits. We'll cover both below.
Reverse Conversion Code (C/C++ Example)
Since you're working with int16*, we'll cast to unsigned 16-bit first to avoid sign issues, then extract each channel and expand it back to 8-bit.
For RGB565 (Most Common)
// Take a single int16 height value (which is the packed RGB565 value) int16_t height_val = heights[x + y * width]; uint16_t rgb565 = static_cast<uint16_t>(height_val); // Extract and expand each channel to 8-bit: // Red: Shift right 11 bits to get the 5 red bits, then shift left 3 to fill 8 bits uint8_t r = static_cast<uint8_t>((rgb565 >> 11) << 3); // Green: Mask out red and blue, shift right 5 bits, then shift left 2 to fill 8 bits uint8_t g = static_cast<uint8_t>(((rgb565 >> 5) & 0x3F) << 2); // Blue: Mask out red and green, shift left 3 to fill 8 bits uint8_t b = static_cast<uint8_t>((rgb565 & 0x1F) << 3);
Note: The expansion shifts (<<3 for red/blue, <<2 for green) scale the compressed 5/6-bit values back to the full 0-255 range. You won't get exact original 8-bit values (since we lost 3/2 bits during compression), but this is the standard lossless reverse of RGB565.
For RGB555
If your original data used 5 bits per channel (15 total, 1 unused bit):
uint16_t rgb555 = static_cast<uint16_t>(height_val); uint8_t r = static_cast<uint8_t>(((rgb555 >> 10) & 0x1F) << 3); uint8_t g = static_cast<uint8_t>(((rgb555 >> 5) & 0x1F) << 3); uint8_t b = static_cast<uint8_t>((rgb555 & 0x1F) << 3);
Critical Notes for Writing to BMP
- BMP uses BGR order: When writing pixels to the BMP file, write the
b,g,rvalues in that order (not RGB). If you mix this up, your colors will be inverted. - Row alignment: BMP requires each row of pixels to be a multiple of 4 bytes. After calculating the bytes per row (width * 3 for 24-bit RGB), add padding bytes (0s) at the end of each row if needed to reach the next multiple of 4.
- Verify with a test pixel: If you're unsure about the format, grab a known pixel from the original BMP (e.g., pure white (255,255,255) would be
0xFFFFin RGB565), check its correspondingint16value, and test the reverse conversion to confirm you get back ~255 for each channel.
内容的提问来源于stack exchange,提问作者Balan Narcis

