将一幅24位色的、不压缩的、BMP真彩色图像,编程实现两种灰度图像,一幅是24位的不压缩的BMP图像,一幅是具有调色板的不压缩的BMP图像。不借用任何的第三方的类图像函数,只用fread和fwrite
时间: 2024-11-09 12:21:45 浏览: 4
bmp24位彩色图像转8位灰度图像(纯C++)
将24位颜色的BMP图像转换成灰度图像,可以按照以下步骤操作,这里假设原始图片数据存储在二进制文件中:
1. **读取原始BMP图像**:
使用`fread`从文件中逐字节读取原始BMP文件的内容。BMP文件通常包含位图头信息(如宽度、高度、位深度等),然后是像素数据。
```c
int width, height, bpp; // 宽度、高度和位深度
unsigned char* pixels; // 存储像素数据的指针
// 读取BMP头部信息
fread(&header, sizeof(BITMAPFILEHEADER), 1, file);
fread(&dibheader, sizeof(BITMAPINFOHEADER), 1, file);
width = dibheader.biWidth;
height = dibheader.biHeight;
bpp = dibheader.biBitCount; // 由于是真彩,初始值为24
pixels = (unsigned char*)malloc(width * height * bpp);
fread(pixels, width * height * bpp, 1, file); // 读取像素数据
```
2. **将RGB转灰度**:
对于每个像素点,根据灰度公式(例如平均红绿蓝三原色的值)计算出灰度值。如果是真彩色(BGR),需要先调整到RGB模式再处理。
```c
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int r = pixels[(y * width + x) * 3]; // 红分量
int g = pixels[(y * width + x) * 3 + 1]; // 绿分量
int b = pixels[(y * width + x) * 3 + 2]; // 蓝分量
int gray = (r + g + b) / 3; // 计算灰度值
// 将灰度值存入新的像素数组
pixels[(y * width + x) * 3] = gray;
pixels[(y * width + x) * 3 + 1] = gray;
pixels[(y * width + x) * 3 + 2] = gray;
}
}
```
3. **保存灰度BMP图像**:
创建一个新的BMP文件头,并保存修改后的像素数据。由于灰度图像的位深度只有8位(1 byte),所以需要调整BMP头的信息。
```c
BITMAPINFOHEADER biHeaderGray;
biHeaderGray.biSize = sizeof(BITMAPINFOHEADER);
biHeaderGray.biWidth = width;
biHeaderGray.biHeight = -height; // BMP头高度为负
biHeaderGray.biPlanes = 1;
biHeaderGray.biBitCount = 8;
biHeaderGray.biCompression = BI_RGB;
// 释放原始像素内存
free(pixels);
// 写入新的灰度BMP头和像素数据
fseek(file, 0, SEEK_SET);
fwrite(&biHeaderGray, sizeof(BITMAPINFOHEADER), 1, file);
fwrite(gray_pixels, width * height, 1, file); // gray_pixels是新的灰度像素数组
```
4. **创建调色板的BMP图像**:
如果需要一个带调色板的BMP,首先需要创建一个调色板(PALETTEENTRY结构体数组),然后修改BMP头信息。在这种情况下,每个像素索引指向调色板中的颜色。
```c
// 创建调色板
const int colorPaletteSize = 256; // 最大256种颜色
PALETTEENTRY palette[colorPaletteSize];
for (int i = 0; i < colorPaletteSize; i++) {
palette[i].peRed = i;
palette[i].peGreen = i;
palette[i].peBlue = i;
}
// 修改BMP头信息
biHeaderGray.biClrUsed = colorPaletteSize;
biHeaderGray.biClrImportant = colorPaletteSize;
// 保存调色板和像素数据
fseek(file, sizeof(BITMAPFILEHEADER), SEEK_SET);
fwrite(&palette, sizeof(PALETTEENTRY), biHeaderGray.biClrUsed, file);
fwrite(gray_palette, width * height, sizeof(PALETTEENTRY), file); // gray_palette是索引为调色板颜色的新像素数组
```
完成上述步骤后,你可以分别通过`fwrite`函数将两个灰度BMP图像写回到新文件中。
阅读全文