.icon 24 位位图读取

代码来源

读取格式来自:Icons | Microsoft Learn

rgb打印来自:位图(BMP)文件结构分析以及使用C++实现位图的读写与显示 - 简书 (jianshu.com)

位图转 icon 文件网站:

 w​​​​​​​在线生成透明ICO图标 - 在线工具 (toollist.net)

 

​​​​​​​Dev-C++ undefined reference to `_imp_SetPixel` 解决方法_为什么找不到标识符setpixel怎么解决-CSDN博客

#include <stdio.h>
#include <windows.h>
#pragma warning(disable : 4996)					// visual studio 宏定义,避免移植到Visual studio编译报错 

// 核心代码自 
//https://learn.microsoft.com/en-us/previous-versions/ms997538(v=msdn.10)


//掩码图,其中有 XOR AND 俩图片,都是用一个bit 0表示黑,1表示白,即一个字节对应八个像素
typedef struct
{
	BITMAPINFOHEADER   icHeader;      // DIB header
	RGBQUAD         icColors[1];   // Color table
	BYTE            icXOR[1];      // DIB bits for XOR mask
	BYTE            icAND[1];      // DIB bits for AND mask
} ICONIMAGE, *LPICONIMAGE;
// 一个ICON 文件有多个图片,是因为不同机器上识别不同格式图片,这里是紧随ICON文件头之后的图片信息结构体
typedef struct
{
	BYTE        bWidth;          // Width, in pixels, of the image
	BYTE        bHeight;         // Height, in pixels, of the image
	BYTE        bColorCount;     // Number of colors in image (0 if >=8bpp)
	BYTE        bReserved;       // Reserved ( must be 0)
	WORD        wPlanes;         // Color Planes
	WORD        wBitCount;       // Bits per pixel
	DWORD       dwBytesInRes;    // How many bytes in this resource?
	DWORD       dwImageOffset;   // Where in the file is this image?
} ICONDIRENTRY, *LPICONDIRENTRY;


// ICON 文件头
typedef struct
{
	WORD           idReserved;   // Reserved (must be 0)
	WORD           idType;       // Resource Type (1 for icons)
	WORD           idCount;      // How many images?
	ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
} ICONDIR, *LPICONDIR;


// 用于显示 Icon 的全部结构体数据 ,如果正常显示,说明微软的代码靠谱 
void showIcon(LPICONDIR pIconDir,LPICONDIRENTRY pIconDirEntry,LPICONIMAGE pIconImage)
{
	printf("pIconDir\n");
	printf("%0x\n",pIconDir->idReserved);
	printf("%0x\n",pIconDir->idType);
	printf("%0x\n",pIconDir->idCount);

	printf("pIconDirEntry\n");
	printf("bHeight = %d\n",pIconDirEntry->bHeight);
	printf("bWidth = %d\n",pIconDirEntry->bWidth);
	printf("%0x\n",pIconDirEntry->bColorCount);
	printf("%0x\n",pIconDirEntry->bReserved);
	printf("%0x\n",pIconDirEntry->wPlanes);
	printf("%0x\n",pIconDirEntry->wBitCount);
	printf("%ld\n",pIconDirEntry->dwBytesInRes);
	printf("%ld\n",pIconDirEntry->dwImageOffset);

	printf("pIconImage->icHeader\n");
//	https://zhuanlan.zhihu.com/p/339055549
//	https://blog.csdn.net/wangwenjing90/article/details/8537355
//	https://blog.csdn.net/weixin_44350503/article/details/90082061
	printf("%ld\n",pIconImage->icHeader.biSize);					// biSize = BMP头的info头部分的文件大小(以字节为单位)
//	icHeader 结构的 biHeight 成员表示 XOR 和 AND 掩码的组合高度。
	printf("icHeader.biHeight = %ld\n",pIconImage->icHeader.biHeight);
	printf("icHeader.biWidth =  %ld\n",pIconImage->icHeader.biWidth);

	printf("%d\n",pIconImage->icHeader.biPlanes);					// biPlanes 颜色平面数 https://blog.csdn.net/mmxida/article/details/122362449#:~:text=%E5%9C%A8%E4%B8%80%E4%B8%AA%E9%BB%98%E8%AE%A4%E7%9A%8416%E8%89%B2%E7%9A%84%E8%B0%83%E8%89%B2%E6%9D%BF%E4%B8%AD%EF%BC%8C%E9%A2%9C%E8%89%B2%E8%A2%AB%E7%B3%BB%E7%BB%9F%E6%8C%89%E7%85%A7%E4%B8%80%E5%AE%9A%E7%9A%84%E8%A7%84%E5%88%99%E8%BF%9B%E8%A1%8C%E5%88%86%E9%85%8D%EF%BC%8C%E4%BE%8B%E5%A6%82%E4%BD%8D0%E8%A1%A8%E7%A4%BA%E8%93%9D%E8%89%B2%E9%80%9A%E9%81%93%EF%BC%8C%E4%BD%8D1%E8%A1%A8%E7%A4%BA%E7%BB%BF%E8%89%B2%E9%80%9A%E9%81%93%EF%BC%8C%E4%BD%8D2%E8%A1%A8%E7%A4%BA%E7%BA%A2%E8%89%B2%E9%80%9A%E9%81%93%EF%BC%8C%E4%BD%8D4%E8%A1%A8%E7%A4%BA%E5%BC%BA%E5%BA%A6%E9%80%9A%E9%81%93%E3%80%82%20%E6%A0%B9%E6%8D%AE%E8%BF%99%E4%B8%AA%E8%A7%84%E5%88%99%EF%BC%8C%E8%BF%994%E4%B8%AA%E4%BD%8D%E5%8F%AF%E4%BB%A5%E8%A2%AB%E8%A7%A3%E9%87%8A%E4%B8%BA%EF%BC%9A%E5%BC%BA%E5%BA%A6%E5%B9%B3%E9%9D%A2%EF%BC%8C%E7%BA%A2%E8%89%B2%E5%B9%B3%E9%9D%A2%EF%BC%8C%E7%BB%BF%E8%89%B2%E5%B9%B3%E9%9D%A2%E5%92%8C%E8%93%9D%E8%89%B2%E5%B9%B3%E9%9D%A2%E3%80%82%20%E5%AF%B9%E4%BA%8E%E6%9C%80%E5%90%8E%E4%B8%89%E4%B8%AA%E5%B9%B3%E9%9D%A2%EF%BC%8C%E6%82%A8%E5%8F%AF%E4%BB%A5%E6%83%B3%E8%B1%A1%E6%AF%8F%E4%B8%AA%E5%B9%B3%E9%9D%A2%E9%83%BD%E4%BB%A3%E8%A1%A8%E4%BA%86%E5%A6%82%E6%9E%9C%E5%8F%AA%E6%9C%89%E7%9B%B8%E5%BA%94%E7%9A%84%E7%94%B5%E5%AD%90%E6%9E%AA%E5%9C%A8%E5%8F%91%E5%B0%84%E6%97%B6%E4%BD%A0%E7%9C%8B%E5%88%B0%E7%9A%84%E6%83%85%E5%86%B5%E3%80%82%20%E7%94%B1%E4%BA%8E%E8%BF%99%E6%98%AFEGA%E7%9A%84%E6%9C%AC%E6%9C%BA%E9%A2%9C%E8%89%B2%E6%A0%BC%E5%BC%8F%EF%BC%8C%E5%9B%A0%E6%AD%A4%E9%9C%80%E8%A6%81%E6%9C%89%E4%B8%80%E7%A7%8D%E6%96%B9%E6%B3%95%E5%9C%A8BITMAP%E7%BB%93%E6%9E%84%E4%B8%AD%E8%A1%A8%E8%BE%BE%E8%BF%99%E7%A7%8D%E9%A2%9C%E8%89%B2%E6%A0%BC%E5%BC%8F%EF%BC%8C%E4%BB%A5%E4%BE%BF,Windows%E5%8F%AF%E4%BB%A5%E8%A1%A8%E7%A4%BA%E4%B8%8E%E8%AE%BE%E5%A4%87%E7%9B%B8%E5%85%B3%E7%9A%84%E4%BD%8D%E5%9B%BE%E3%80%82%20%E5%9B%A0%E6%AD%A4%E8%AF%9E%E7%94%9F%E4%BA%86%E5%B9%B3%E9%9D%A2%E9%A2%9C%E8%89%B2%E6%A0%BC%E5%BC%8F%E3%80%82%20%E5%AF%B9%E4%BA%8E16%E8%89%B2%E5%B9%B3%E9%9D%A2%E7%9A%84%E4%BD%8D%E5%9B%BE%EF%BC%8C%E5%B9%B3%E9%9D%A2%E6%95%B0%E4%B8%BA%204%EF%BC%8C%E6%AF%8F%E4%B8%AA%E5%83%8F%E7%B4%A0%E7%9A%84%E4%BD%8D%E6%95%B0%E4%B8%BA%201%E3%80%82
	printf("%d\n",pIconImage->icHeader.biBitCount);					// biBitCount 每个像素的位数 图像位深度:1,4,8,16,24,32
	printf("%ld\n",pIconImage->icHeader.biCompression);				// biCompression 图像数据压缩类型:0(BI_RGB,不压缩),1(BI_RLE8,8比特游程编码),2(BI_RLE4,4比特游程编码),3(BI_BITFIELDS,比特域),4(BI_JPEG),5(BI_PNG)
	printf("%ld\n",pIconImage->icHeader.biSizeImage);				// biSizeImage 图像大小,用BI_RGB格式时,可设置为0.

//	https://blog.csdn.net/wangwenjing90/article/details/8537355
	printf("%ld\n",pIconImage->icHeader.biXPelsPerMeter);			// biXPelsPerMeter 水平分辨率,用于多图片存进 ICON时,在不同设备上像素密集程度不同,用于选取密集程度较接近当前设备的图片 ,但是一般不用管。
	printf("%ld\n",pIconImage->icHeader.biYPelsPerMeter);			// biYpelxPerMeter 垂直分辨率
	printf("%ld\n",pIconImage->icHeader.biClrUsed); 				// biCLrUsed 颜色索引数,查颜色表 https://blog.csdn.net/OrdinaryMatthew/article/details/114644916
	printf("%ld\n",pIconImage->icHeader.biClrImportant);			// biClrImortant 对图像显示有重要影响的颜色索引数,0表示都重要
	
	// 文件最顶上的微软教程链接中解释 is Colors 对应颜色表,因为 icHeader的 颜色索引不用了,isColors 成为了索引 
	printf("pIconImage->icColors[0]\n");							// icColors 成员是 RGBQUAD 的数组。此数组中的元素数是通过检查 icHeader 成员来确定的。
	printf("%d\n",pIconImage->icColors[0].rgbRed);
	printf("%d\n",pIconImage->icColors[0].rgbGreen);
	printf("%d\n",pIconImage->icColors[0].rgbBlue); 
	printf("%d\n",pIconImage->icColors[0].rgbReserved);
	

	printf("\n"); 
}
// 按名称复刻,发现isColor就是当前的像素数据
//代码来源  https://www.jianshu.com/p/1e4f302f43d0 
 void showBitmap(LPICONIMAGE pIconImage) {
    HWND hWindow;                                                //窗口句柄
    HDC hDc;                                                     //绘图设备环境句柄
    int yOffset = 150;                      
    hWindow = GetForegroundWindow();
    hDc = GetDC(hWindow);

    int posX, posY;
    for (int i = 0; i < pIconImage->icHeader.biWidth*pIconImage->icHeader.biHeight/2; i++){				// 除以二是因为 biHeight 计算的是掩码图 和色彩图的总数 
        char blue = pIconImage->icColors[i].rgbBlue;				// 读取一个字节的数据 刚好 char 就是一个字节,里面的 0 1 变成 0-255 
        char green = pIconImage->icColors[i].rgbGreen;
        char red = pIconImage->icColors[i].rgbRed;

        posX = i % pIconImage->icHeader.biWidth;
        posY = pIconImage->icHeader.biHeight - i / pIconImage->icHeader.biWidth + yOffset;
        SetPixel(hDc, posX, posY, RGB(red, green, blue));
    } 
    
  
}
int main()
{
	LPICONDIR pIconDir;							// 用于记录一个完整的ICON 数据头
//	https://blog.csdn.net/jeanphorn/article/details/44982273
	HANDLE hFile=  CreateFile("22.ico",GENERIC_READ,
	                          FILE_SHARE_READ,
	                          NULL,
	                          OPEN_EXISTING,        //打开已存在的文件
	                          FILE_ATTRIBUTE_NORMAL,
	                          NULL);
	DWORD dwBytesRead;								// 要读取的字节数,DROWD 就是 unsigned _long32 ctrl+鼠标左键可查
	// We need an ICONDIR to hold the data
	pIconDir = (LPICONDIR)malloc( sizeof( ICONDIR ) );
// Read the Reserved word
	dwBytesRead=1;
	ReadFile( hFile, &(pIconDir->idReserved), sizeof( WORD ), &dwBytesRead, NULL );
// Read the Type word - make sure it is 1 for icons
	dwBytesRead=1;
	ReadFile( hFile, &(pIconDir->idType), sizeof( WORD ), &dwBytesRead, NULL );
// Read the count - how many images in this file?
	dwBytesRead=1;						// deByteRead=1 是指读的 1个 WORD ,就是读取一个字,这里对应读取两个字节因为unsigned short是两个字节
	ReadFile( hFile, &(pIconDir->idCount), sizeof( WORD ), &dwBytesRead, NULL );
// Reallocate IconDir so that idEntries has enough room for idCount elements
	pIconDir = (LPICONDIR)realloc( pIconDir, ( sizeof( WORD ) * 3 ) +
	                               ( sizeof( ICONDIRENTRY ) * pIconDir->idCount ) );
// Read the ICONDIRENTRY elements
	ReadFile( hFile, pIconDir->idEntries, pIconDir->idCount * sizeof(ICONDIRENTRY),
	          &dwBytesRead, NULL );
// Loop through and read in each image
	int i;
	LPICONIMAGE pIconImage;
	for(i=0; i<pIconDir->idCount; i++)
	{
		// Allocate memory to hold the image
		pIconImage =(LPICONIMAGE) malloc( pIconDir->idEntries[i].dwBytesInRes );
		// Seek to the location in the file that has the image
		SetFilePointer( hFile, pIconDir->idEntries[i].dwImageOffset,
		                NULL, FILE_BEGIN );
		// Read the image data
		dwBytesRead=1; // 字节数已经在 dwBytesInRes 中给出了,所以 dwBytesRead 成为 1就是 只读取一次 
		ReadFile( hFile, pIconImage, pIconDir->idEntries[i].dwBytesInRes,
		          &dwBytesRead, NULL );
		// Here, pIconImage is an ICONIMAGE structure. Party on it :)

		//显示读取的数据信息
		showIcon(pIconDir,&pIconDir->idEntries[i],pIconImage);
		// Then, free the associated memory
		
		showBitmap(pIconImage); 
		
		Sleep(3000); 
		
		free( pIconImage );
	}
// Clean up the ICONDIR memory
	free( pIconDir );
	return 0; 
}


  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值