c语言将24位的bmp图片转为8位的bmp图片
时间: 2023-10-08 18:08:40 浏览: 100
下面是一个将24位bmp图片转为8位bmp图片的C语言代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(2) // 结构体按2字节对齐
// BMP文件头
typedef struct {
char bfType[2]; // 文件类型,必须为BM
int bfSize; // 文件大小,包括文件头、位图信息头、调色板和位图数据
short bfReserved1; // 保留字段,必须为0
short bfReserved2; // 保留字段,必须为0
int bfOffBits; // 从文件头到位图数据的偏移量,单位为字节
} BMPFileHeader;
// BMP位图信息头
typedef struct {
int biSize; // 结构体大小,必须为40
int biWidth; // 图像宽度,单位为像素
int biHeight; // 图像高度,单位为像素
short biPlanes; // 必须为1
short biBitCount; // 每个像素所需位数,必须为8
int biCompression; // 压缩类型,必须为0
int biSizeImage; // 位图数据大小,单位为字节
int biXPelsPerMeter; // 水平分辨率,单位为像素/米
int biYPelsPerMeter; // 垂直分辨率,单位为像素/米
int biClrUsed; // 实际使用的颜色表中的颜色数,0表示使用全部颜色
int biClrImportant; // 对图象显示有重要影响的颜色数,0表示都重要
} BMPInfoHeader;
// BMP调色板
typedef struct {
unsigned char rgbBlue; // 蓝色分量
unsigned char rgbGreen; // 绿色分量
unsigned char rgbRed; // 红色分量
unsigned char rgbReserved; // 保留字段,必须为0
} RGBQuad;
int main()
{
FILE *fpIn, *fpOut;
BMPFileHeader fileHeader;
BMPInfoHeader infoHeader;
RGBQuad *palette = NULL;
unsigned char *pixelData24 = NULL, *pixelData8 = NULL;
int rowSize24, rowSize8, padding24, padding8;
int width, height, i, j, k;
// 读取24位bmp图片文件
fpIn = fopen("input.bmp", "rb");
if (fpIn == NULL) {
printf("Open file failed!\n");
return -1;
}
fread(&fileHeader, sizeof(BMPFileHeader), 1, fpIn);
fread(&infoHeader, sizeof(BMPInfoHeader), 1, fpIn);
// 获取图片宽度、高度、每行像素所占字节数、调色板大小
width = infoHeader.biWidth;
height = infoHeader.biHeight;
rowSize24 = width * 3;
padding24 = (rowSize24 % 4) ? (4 - rowSize24 % 4) : 0;
// 分配内存,读取调色板和像素数据
palette = (RGBQuad*)malloc(sizeof(RGBQuad) * 256);
pixelData24 = (unsigned char*)malloc(sizeof(unsigned char) * (rowSize24 + padding24) * height);
pixelData8 = (unsigned char*)malloc(sizeof(unsigned char) * width * height);
if (palette == NULL || pixelData24 == NULL || pixelData8 == NULL) {
printf("Memory allocation failed!\n");
return -1;
}
fread(palette, sizeof(RGBQuad), 256, fpIn);
fread(pixelData24, sizeof(unsigned char), (rowSize24 + padding24) * height, fpIn);
fclose(fpIn);
// 计算8位bmp图片的每行像素所占字节数和调色板大小
rowSize8 = ((width + 3) / 4) * 4;
padding8 = rowSize8 - width;
// 将24位像素转换为8位像素
for (i = 0; i < height; i++) {
for (j = 0, k = 0; j < rowSize24; j += 3, k++) {
int gray = (int)(0.299 * pixelData24[i * (rowSize24 + padding24) + j + 2] +
0.587 * pixelData24[i * (rowSize24 + padding24) + j + 1] +
0.114 * pixelData24[i * (rowSize24 + padding24) + j]);
pixelData8[i * rowSize8 + k] = (unsigned char)gray;
}
// 填充空白字节
for (j = 0; j < padding8; j++) {
pixelData8[i * rowSize8 + k + j] = 0;
}
}
// 写入8位bmp图片文件
fpOut = fopen("output.bmp", "wb");
if (fpOut == NULL) {
printf("Create file failed!\n");
return -1;
}
fwrite(&fileHeader, sizeof(BMPFileHeader), 1, fpOut);
fwrite(&infoHeader, sizeof(BMPInfoHeader), 1, fpOut);
fwrite(palette, sizeof(RGBQuad), 256, fpOut);
fwrite(pixelData8, sizeof(unsigned char), rowSize8 * height, fpOut);
fclose(fpOut);
// 释放内存
free(palette);
free(pixelData24);
free(pixelData8);
return 0;
}
```
该程序先读取24位bmp图片文件的文件头、位图信息头、调色板和像素数据,然后将24位像素转换为8位像素,并写入8位bmp图片文件的文件头、位图信息头、调色板和像素数据。注意,这里使用了灰度化公式将RGB三个通道的亮度值加权平均,然后取整得到灰度值。同时还需要考虑到调色板等其他因素。
阅读全文
相关推荐
















