修改开机LOGO图片教程及注意事项/通过C++实现bmp图位深度从32位转换为8位


文章目录

  • 修改开机LOGO图片教程及注意事项/通过C++实现bmp图位深度从32位转换为8位
  • 修改开机LOGO图片教程及注意事项
  • 通过C++实现bmp图位深度从32位转换为8位


修改开机LOGO图片教程及注意事项

最近心血来潮想改一下开机LOGO图片,因为捡垃圾来的老主板开机LOGO实在是太丑了…

技嘉主板更改BIOS开机图片 技嘉bios修改开机画面_技嘉主板更改BIOS开机图片

不过由于主板过于老旧,不仅BIOS芯片相关信息找不到了,且原生的BIOS只有2MB大小,提取出的图片更是只有769KB

而我从铭瑄新主板BIOS中提取的LOGO有3MB,虽然通过通过工具写入时仅会提示该BIOS支持LOGO尺寸为800*600,但无论是否修改尺寸,修改完成后只会是黑屏一张

替换为一张低分辨率的bmp图后正常显示,这时该文件小于原文件

因此确定为文件过大,无法全部写入,文件大小需要小于等于原文件

通过C++实现bmp图位深度从32位转换为8位

原作者给出的代码是需要编译后通过命令提示行加参数运行的,且有一些小错误,这里我修改为了可以在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位图:

技嘉主板更改BIOS开机图片 技嘉bios修改开机画面_技嘉主板更改BIOS开机图片_02

8位图:

技嘉主板更改BIOS开机图片 技嘉bios修改开机画面_位图_03

有一种像素的美…但能用…
对于这种纯黑LOGO来说,也可以直接等比裁剪…