修改开机LOGO图片教程及注意事项/通过C++实现bmp图位深度从32位转换为8位
修改开机LOGO图片教程及注意事项
最近心血来潮想改一下开机LOGO图片,因为捡垃圾来的老主板开机LOGO实在是太丑了…
这部分链接:华南金牌X99修改开机LOGO的教程_哔哩哔哩_bilibili
不过由于主板过于老旧,不仅BIOS芯片相关信息找不到了,且原生的BIOS只有2MB大小,提取出的图片更是只有769KB
而我从铭瑄新主板BIOS中提取的LOGO有3MB,虽然通过通过工具写入时仅会提示该BIOS支持LOGO尺寸为800*600,但无论是否修改尺寸,修改完成后只会是黑屏一张
替换为一张低分辨率的bmp图后正常显示,这时该文件小于原文件
因此确定为文件过大,无法全部写入,文件大小需要小于等于原文件
通过C++实现bmp图位深度从32位转换为8位
似乎通过PS可以轻松实现,但目前电脑上没有PS
通过一番搜索,在各种复制抄袭之中,找到了一篇能用的(35条消息) C++ C语言 读取32位BMP图片转为8位灰度图_foreyes_1001的博客-CSDN博客_c++显示8位灰度图
点名一下抄袭的且没抄全:(35条消息) c语言32位变为灰度图,C++ C语言 读取32位BMP图片转为8位灰度图_等我想好名字先的博客-CSDN博客
原作者给出的代码是需要编译后通过命令提示行加参数运行的,且有一些小错误,这里我修改为了可以在Visual Studio中直接运行的版本:
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <windows.h>
#include <iostream>
using namespace std;
//设置内存对齐
#pragma pack(1)
typedef struct tag_color_32 {
BYTE Red;
BYTE Green;
BYTE Blue;
BYTE Alpha;
} color_32;
int main() {
// 定义一个文件指针
FILE* fp, * out;
// 定义一个 BMP 文件头的结构体
BITMAPFILEHEADER bmpFileHeader;
// 定义一个 BMP 文件信息结构体
BITMAPINFOHEADER bmpInfo;
// 8位bmp输出路径
out = fopen("G:\\Desktop\\001\\splash8.bmp", "wb");
// 32位原bmp读入路径
if ((fp = fopen("G:\\Desktop\\001\\splash32.bmp", "rb")) == NULL)
{
printf("Cann't open the file!\n");
return 0;
}
fseek(fp, 0, SEEK_SET);
fread(&bmpFileHeader, 14, 1, fp);
fread(&bmpInfo, sizeof(BITMAPINFOHEADER), 1, fp);
// 输出BMP文件的位图文件头的所有信息
printf("位图文件头主要是对位图文件的一些描述:BMPFileHeader\n\n");
printf("文件标识符 = 0X%X\n", bmpFileHeader.bfType);
printf("BMP 文件大小 = %d 字节\n", bmpFileHeader.bfSize);
printf("保留值1 = %d \n", bmpFileHeader.bfReserved1);
printf("保留值2 = %d \n", bmpFileHeader.bfReserved2);
printf("文件头到图像数据位开始的偏移量 = %d 字节\n", bmpFileHeader.bfOffBits);
// 输出BMP文件的位图信息头的所有信息
printf("\n\n位图信息头主要是对位图图像方面信息的描述:BMPInfo\n\n");
printf("信息头的大小 = %d 字节\n", bmpInfo.biSize);
printf("位图的高度 = %d \n", bmpInfo.biHeight);
printf("位图的宽度 = %d \n", bmpInfo.biWidth);
printf("图像的位面数(位面数是调色板的数量,默认为1个调色板) = %d \n", bmpInfo.biPlanes);
printf("每个像素的位数 = %d 位\n", bmpInfo.biBitCount);
printf("压缩类型 = %d \n", bmpInfo.biCompression);
printf("图像的大小 = %d 字节\n", bmpInfo.biSizeImage);
printf("水平分辨率 = %d \n", bmpInfo.biXPelsPerMeter);
printf("垂直分辨率 = %d \n", bmpInfo.biYPelsPerMeter);
printf("使用的色彩数 = %d \n", bmpInfo.biClrUsed);
printf("重要的色彩数 = %d \n", bmpInfo.biClrImportant);
printf("\n\n\n压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)");
//32位色图
if (bmpInfo.biBitCount == 32) {
int Height = bmpInfo.biHeight;
int Width = bmpInfo.biWidth;
bool reverse = false;
if (Height < 0) {
reverse = true;
Height *= -1;
}
color_32* pixels;
pixels = new color_32[Height * Width];
//fseek(fp,bmpFileHeader.bfOffBits,SEEK_SET);
for (int i = 0; i < Height * Width; i++)
fread(pixels + i, 4, 1, fp);
//设置文件头
bmpInfo.biBitCount = 8;
bmpInfo.biClrUsed = 256;
//灰度图颜色表
RGBQUAD pRGB[256];
for (int i = 0; i < 256; i++) {
pRGB[i].rgbRed = i;
pRGB[i].rgbGreen = i;
pRGB[i].rgbBlue = i;
pRGB[i].rgbReserved = 0;
}
bmpFileHeader.bfOffBits = 54 + 4 * 256;
//考虑对齐规则 计算每一行的字节数
int LineByte = ((bmpInfo.biBitCount / 8 * Width + 3) / 4) * 4;
bmpFileHeader.bfSize = 54 + 4 * 256 + Height * LineByte;
//写入新的文件
fseek(out, 0, SEEK_SET);
fwrite(&bmpFileHeader, 14, 1, out);
fwrite(&bmpInfo, 40, 1, out);
fwrite(&pRGB, 4 * 256, 1, out);
for (int i = 0; i < Height; i++) {
for (int j = 0; j < Width; j++) {
float pr = pixels[i * Width + j].Red;
float pg = pixels[i * Width + j].Green;
float pb = pixels[i * Width + j].Blue;
//提取灰度低的黑色部分
BYTE data = pr * 0.299 + pg * 0.587 + pb * 0.114;
if ((pr - pg) > 5 || (pr - pb) > 5) data = 255;
data = data < 25 ? 0 : 255;
fwrite(&data, 1, 1, out);
}
for (int j = Width; j < LineByte; j++) {
BYTE data = 0;
fwrite(&data, 1, 1, out);
}
}
}
fclose(out);
fclose(fp);
system("pause");
return 0;
}
原32位图:
8位图:
有一种像素的美…但能用…
对于这种纯黑LOGO来说,也可以直接等比裁剪…