鼠标指针文件格式解析

news2025/7/19 15:46:15

鼠标指针文件格式解析

文章目录

  • 鼠标指针文件格式解析
    • windows
      • ico文件格式分析
        • 文件头:
        • 图像数据头段:
        • 图像数据段:
      • Ani动态光标格式解析
        • 数据结构:
        • 'anih'
        • 'seq '
        • **'rate'**
        • 'LIST'
      • cur静态光标文件格式解析
    • macOS
    • Linux

windows

ico文件格式分析

是一种图标文件,文件后缀名一般位icon或者ico

文件格式:文件头,图像数据头,图像数据两部分

文件头:

6字节

type
 	ICONDIR = packed record					
    idReserved: SmallInt; // Reserved		保留位,必须为0
	idType: SmallInt; // Resource type		光标资源类型,作为ico时值为1,作为cur时值为2
	idCount: SmallInt; // Image Count		标记了文件中包含的图像数量
 end; // 6 bytes

图像数据头段:

紧接着文件头的就是图像数据头段了,它存放着文件中每个图像宽度、高度、颜色数量、数据段的偏移等信息,大小为16 * idCount。它是一个数组,每项数据16字节,定义如下:

type
  ICONDIRENTRY = packed record
    bWidth: Byte; // Width of the image										图像宽
    bHeight: Byte; // Height of the image (2 * Height)						图像高
    bColorCount: Byte; // Number of colors in image (0 when >= 8 bpp)		图像颜色数
    bReserved: Byte; // Reserved											保留位数
    wPlanes: SmallInt; // Color Planes   (-> xHotspot [Cursor])				X坐标热点,与Y同为0时代表左上角
    wBitCount: SmallInt; // Bits per pixel (-> yHotspot [Cursor])			Y坐标热点
    dwBytesInRes: Integer; // How many bytes in this resource?				数据大小
    dwImageOffset: Integer; // Where in the file is this image?				数据偏移量
  end; // 16 bytes

读取完图像数据头段后,就可以知道文件中每个图标的大小,颜色位数了,同时直接根据数据段的偏移,读取图像数据段。图像数据的偏移是从文件最开始算起的。

图像数据段:

图像数据为多个图像的DIB数据,根据数据头段的偏移来定位。定位后,读取BIH信息。从BIH信息中,判断颜色位数大于8位的,记取XOR调色盘数据(小于8位的不存在XOR调色盘,只包含有一个MASK调色盘)。读取完XOR调色盘后,初始化图像DIB头,然后在文件中读取DIB数据。

存疑,没懂,先放着

最后又变成分析bmp文件了,像素值是原始数据

Ani动态光标格式解析

Ani动态光标格式解析 - 孤影对酌 - 博客园 (cnblogs.com)

文件类型关系:

bmp ∈ (ico == cur ) ∈ ani

数据结构:

ani文件结构在010里并没有直接的模板,而是以RIFF为开头标志位的文件,因此也可以使用RIFF模板来分析

本文是在孤影对酌师傅的文章基础上进行了一些备注,以供自己学习和分析

Ani文件中的数据是按区段存放的,区段数据结构如下:

标识符(4字节ASCII),数据长度(一个DWORD),数据

按照此规则来看Ani文件,文件起始12字节(12字节指以下标识符、数据长度和ACON三个部分)可以理解为标准文件头,除数据长度外,其余两个字段不会改变:

0x0000    52 49 46 46    标识符'RIFF'
0x0004    40 4D 00 00    数据长度,指整个文件的大小
0x0008    41 43 4F 4E    'ACON'

标准头之后,就是各个区段了,在孤影对酌师傅的探索中共发现了:‘anih’, ‘rate’, 'seq ', 'LIST’4种区段('seq '区段标识最后一个字符是空格,共4个字符)。

‘anih’

此区段数据长度恒为36,每4字节为一组,另外,数据长度36加上块大小4和名称4共44,里面存储的是一个结构体:

struct _anih
{
    DWORD    dwHeaderSize;     //结构体大小,恒为36
    DWORD    dwNumFrames;      //图像帧数,代表转为gif有多少帧,且该数与LISTchunk数量相等
    DWORD    dwNumSteps;       //播放帧数,当'seq '存在时可能大于dwNumFrames
    DWORD    dwWidth;          //图像宽度
    DWORD    dwHeight;         //图像高度
    DWORD    dwBitCount;       //色彩位数
    DWORD    dwNumPlanes;      //设备平面数
    DWORD    dwDisplayRate;    //显示频率(Time Delay,单位为1/60秒)
    DWORD    dwFlags;          //标志
};

dwFlags的第0位为1时,表示图像帧数据格式为Icon或Cursor,为0表示图像帧数据为位图raw数据,使用_anih结构中的尺寸、色彩深度等信息。

第1位解释为bool型,表示文件是否含有’seq '段。

'seq ’

010显示顺序位**先rate后seq **

此区段为可选段(不一定存在),段内的数据为一个DWORD数组,长度为 “区段数据长度” / sizeof(DWORD)。

0x0000    73 65 71 20    标识符'seq '
0x0004    24 00 00 00    数据长度
0x0008    00 00 00 00    数组元素[0],值为0表示此处显示第0帧图像
0x000C    01 00 00 00    数组元素[1],值为1表示第一帧图像
0x0010    02 00 00 00    [2],第2帧
0x0014    03 00 00 00    [3],第3帧
0x0018    00 00 00 00    [4],第0帧
0x001C    04 00 00 00    ...
0x0020    05 00 00 00
0x0024    01 00 00 00
0x0028    00 00 00 00

此区段存储的是播放顺序,当Ani文件播放时,按照DWORD数组下标递增,依次从此数组中取出图像帧号,再到存储图像帧数据的’LIST’段中获取对应的图像帧进行显示。所以在一次播放中,同一个图像帧可以出现多次。_anih结构中的dwNumSteps即为播放起始数组下标。

此区段不存在时,'LIST’中图像帧的顺序即为播放顺序,_anih结构中的dwNumSteps为播放起始帧号。

‘rate’

此区段为可选段,段内数据为一个DWORD数组,长度为 “区段数据长度” / sizeof(DWORD)。

表示每一帧的播放速率,gif的每一帧都是匀速播放的,rate的存在代表这个播放的速率不一定相同

0x0000    72 61 74 65    标识符'rate'
0x0004    24 00 00 00    数据长度
0x0008    0F 00 00 00    x 1/60秒 = Time Delay
0x000C    0F 00 00 00
0x0010    0F 00 00 00
0x0014    0F 00 00 00
0x0018    46 00 00 00
0x001C    0F 00 00 00
0x0020    0F 00 00 00
0x0024    0F 00 00 00
0x0028    0F 00 00 00

此区段内存储的为播放频率(Time Delay),同样以1/60秒为单位,当’seq '存在时,按相同下标与’seq '中的每个元素相对应,数组大小与’seq '相等。当’seq '不存在时,与’LIST’中图像帧相对应,数组大小等于_anih结构中的dwNumFrames。

‘LIST’

同样拥有12字节“标准头”,探索中发现,此区段内存储的数据有两种可能:

1.Ani文件的名称、作者

2.图像帧数据

当存储名称、作者信息时,格式为:

0x0000    4C 49 53 54    标识符'LIST',前12字节为“标准头”
0x0004    26 00 00 00    数据长度
0x0008    49 4E 46 4F    标识符'INFO'表示此列表为信息列表

0x000C    49 4E 41 4D    标识符'INAM'表示名称
0x0010    0C 00 00 00    数据长度
0x0014    68 65 61 72 74 73 74 69 63 6B 31 00    字符串'heartstick1'

0x0020    49 41 52 54    标识符'IART'表示作者
0x0024    06 00 00 00    数据长度
0x0028    68 75 61 6C 69 00    字符串'huali'

当存储图像帧数据时,格式为:

0x0000    4C 49 53 54    标识符'LIST',前12字节为“标准头”
0x0004    90 11 00 00    数据长度
0x0008    66 72 61 6D    标识符'fram'表明此列表为图像数据帧列表

0x000C    69 63 6F 6E    标识符'icon'标识图像数据帧数据区段
0x0010    BE 08 00 00    数据长度
0x0014    00 00 02 00    图像数据
...       ...            多帧图像

至此,数据结构解析完毕。

此时有一个疑问,在icon的图像数据中,数据块的大小和图片的大小和像素有什么关系呢?

此时的这个图像数据是一个cur的文件格式

我们可以按照ico图标文件来进行分析

cur静态光标文件格式解析

很好,这次是彻底没有模板可以借助了

让我们从零开始分析一个文档吧

看了出题人写的文章,了解到cur文件也是和ico文件同属一宗,但唯一不同的是有一个标志位表明这是一个cur文件

这个标志位是全文档的第三个字节
在这里插入图片描述

唯二一篇可以参考的文章

从Windows动态指针到MacOS动态指针——ANI2GIF - 哔哩哔哩 (bilibili.com)

CURSOR 文件格式解析_jinhaijian的博客-CSDN博客

全称为CURSOR

因此,剩下的部分可以按照ico图标文件进行分析

macOS

从Windows动态指针到MacOS动态指针—— 在Windows上制作指针 - 哔哩哔哩 (bilibili.com)

是xml的形式,后缀名为cape文件

结构如下:

{
    'Author': '',
    'CapeName': '',
    'CapeVersion': 1.0,
    'Cloud': False,
    'Cursors': {
        'com.apple.coregraphics.Arrow': {
            'FrameCount': 1,
            'FrameDuration': 1.0,
            'HotSpotX': 0.0,
            'HotSpotY': 0.0,
            'PointsHigh': 32.0,
            'PointsWide': 32.0,
            'Representations': [b'']
        }
    },
    'HiDPI': False,
    'Identifier': 'local.error404.Unnamed.635739212.539397.A9D5CFB1-558B-46DD-95BB-3E8D6ED022D8.693110507.131993',
    'MinimumVersion': 2.0,
    'Version': 2.0
}

例子

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Author</key>
	<string>小蓝蓝</string>
	<key>CapeName</key>
	<string>蓝蓝的测试图标</string>
	<key>CapeVersion</key>
	<real>1.0</real>
	<key>Cloud</key>
	<false/>
	<key>Cursors</key>
	<dict>
		<key>com.apple.coregraphics.Arrow</key>
		<dict>
			<key>FrameCount</key>
			<integer>34</integer>					#代表帧数
			<key>FrameDuration</key>
			<real>0.1</real>
			<key>HotSpotX</key>						#代表生效的点的位置
			<real>0.0</real>
			<key>HotSpotY</key>
			<real>0.0</real>
			<key>PointsHigh</key>
			<real>32.0</real>						#代表图像大小,32*32
			<key>PointsWide</key>
			<real>32.0</real>
			<key>Representations</key>
			<array>
				<data>
                base64转图片,图片类型为tiff
				</data>
			</array>
		</dict>
		<key>com.apple.coregraphics.IBeam</key>
		<dict>
			<key>FrameCount</key>
			<integer>28</integer>
			<key>FrameDuration</key>
			<real>0.1</real>
			<key>HotSpotX</key>
			<real>0.0</real>
			<key>HotSpotY</key>
			<real>0.0</real>
			<key>PointsHigh</key>
			<real>32.0</real>
			<key>PointsWide</key>
			<real>32.0</real>
			<key>Representations</key>
			<array>
				<data>
                base64转图片,图片类型为tiff
				</data>
			</array>
		</dict>
		<key>com.apple.coregraphics.Move</key>
		<dict>
			<key>FrameCount</key>
			<integer>24</integer>
			<key>FrameDuration</key>
			<real>0.1</real>
			<key>HotSpotX</key>
			<real>0.0</real>
			<key>HotSpotY</key>
			<real>0.0</real>
			<key>PointsHigh</key>
			<real>32.0</real>
			<key>PointsWide</key>
			<real>32.0</real>
			<key>Representations</key>
			<array>
				<data>
                base64转图片,图片类型为tiff
				</data>
			</array>
		</dict>
		<key>com.apple.cursor.17</key>
		<dict>
			<key>FrameCount</key>
			<integer>52</integer>
			<key>FrameDuration</key>
			<real>0.1</real>
			<key>HotSpotX</key>
			<real>0.0</real>
			<key>HotSpotY</key>
			<real>0.0</real>
			<key>PointsHigh</key>
			<real>32.0</real>
			<key>PointsWide</key>
			<real>32.0</real>
			<key>Representations</key>
			<array>
				<data>
                base64转图片,图片类型为tiff
				</data>
			</array>
		</dict>
		<key>com.apple.cursor.18</key>
		<dict>
			<key>FrameCount</key>
			<integer>31</integer>
			<key>FrameDuration</key>
			<real>0.1</real>
			<key>HotSpotX</key>
			<real>0.0</real>
			<key>HotSpotY</key>
			<real>0.0</real>
			<key>PointsHigh</key>
			<real>32.0</real>
			<key>PointsWide</key>
			<real>32.0</real>
			<key>Representations</key>
			<array>
				<data>
                base64转图片,图片类型为tiff
				</data>
			</array>
		</dict>
	</dict>
	<key>HiDPI</key>
	<false/>
	<key>Identifier</key>
	<string>local.小蓝蓝.蓝蓝的测试图标.1673433937.428604.949CA744-8B80-4D9F-A8F6-7DA1877E517E.1673433937.428639</string>
	<key>MinimumVersion</key>
	<real>2.0</real>
	<key>Version</key>
	<real>2.0</real>
</dict>
</plist>

Linux

文档好像很复杂捏

挖巨坑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/361231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年PMP考试复习攻略

如何备考PMP呢&#xff1f; 这本书是PMP认证考试的官方教材&#xff0c;体系完善&#xff0c;可以迅速帮助入门者搭建项目管理知识体系&#xff0c;备考PMP考试的伙伴&#xff0c;这本书一定要读一遍&#xff01; 经验都是积累出来的&#xff0c;交流小队里有很多分享面试经验…

Vue3 中生命周期的使用

目录前言&#xff1a;一、什么是生命周期函数二、什么是 Keep-Alive 组件三、生命周期函数分为几种&#xff0c;分别有什么用&#xff1f;1. beforeCreate2. created3. beforeMount/onBeforeMount4. mounted/onMounted5. beforeUpdate/onBeforeUpdate6. updated/onUpdated7. be…

spring之事务概述

文章目录前言一、事务概述1、什么是事务2、事务的四个处理过程3、事务的四个特性二、引入事务场景1、引入依赖2、数据库创建3、建包4、spring.xml配置文件5、测试程序6、运行结果&#xff08;成功&#xff09;7、模拟异常三、Spring对事务的支持1、Spring实现事务的两种方式2、…

数值方法笔记4:插值、近似和拟合

1. 插值1.1 插值的一些概念1.1.1 插值的定义1.1.2 插值的存在性1.1.3 插值的误差分析1.2 拉格朗日插值(Lagrange Interpolation)1.2.1 拉格朗日插值误差分析1.3 Newton多项式插值1.3.1 Newton多项式插值误差分析1.4 Chebyshev多项式确定插值点1.4.1 Chebyshev多项式性质1.5 有理…

Green Hills Software(GHS)的安装

Green Hills Software(GHS)简介 Green Hills Software(GHS)是美国Green Hills软件公司提供的一种具有调试、编译器和闪存编程工具的集成开发环境,是汽车电子行业常用且重要的开发环境之一。它支持的功能包括:AUTOSAR感知、项目构建器、代码覆盖、运行时错误检查、MISRA C…

【HEC-RAS水动力】HEC-RAS 1D基本原理(恒定流及非恒定流)

一、数据说明 HEC-RAS模型主要由工程文件 (.prj) 文 件 、 河道地形数据文件 ( .g01)、运行文件(p01)、非恒定流文件 ( .u01) 等部分组成。 1. 一般数据 在创建并保存project文件(*.prj)后,其他data文件均会自动以同样的名字保存,但采用不同的后缀来区分各类文件。 &qu…

网络编程之IP 地址的介绍

IP 地址的介绍学习目标能够说出IP 地址的作用1. IP 地址的概念IP 地址就是标识网络中设备的一个地址&#xff0c;好比现实生活中的家庭地址。网络中的设备效果图:2. IP 地址的表现形式说明:IP 地址分为两类&#xff1a; IPv4 和 IPv6IPv4 是目前使用的ip地址IPv6 是未来使用的i…

Redis进阶-缓存问题

Redis 最常用的一个场景就是作为缓存&#xff0c;本文主要探讨Redis作为缓存&#xff0c;在实践中可能会有哪些问题&#xff1f;比如一致性、击穿、穿透、雪崩、污染等。 为什么要理解Redis缓存问题 在高并发业务场景下&#xff0c;数据库大多数情况都是用户并发访问最薄弱的…

计算机是怎么读懂C语言的?

文章目录前言程序环境翻译环境翻译环境分类编译预处理预处理符号预定义符号#define#undef命令行定义条件编译文件包含头文件包含查找规则嵌套文件包含其他预处理指令编译阶段汇编链接&#x1f389;welcome&#x1f389; ✒️博主介绍&#xff1a;博主大一智能制造在读&#xff…

Linux 目录操作命令

目录操作命令 进入目录 cd命令 cd 目录名 进入指定目录 cd / 进入根目录 cd … 返回上级目录 cd - 返回上一次所在的目录 cd ~ 进入当前用户的家目录 cd /usr 进入指定目录&#xff0c;绝对路径 创建目录 mkdir 目录名 在usr目录下创建dd目录 进入目录 cd 目录名 进入us…

TypeScript 学习笔记

最近在学 ts 顺便记录一下自己的学习进度&#xff0c;以及一些知识点的记录&#xff0c;可能不会太详细&#xff0c;主要是用来巩固和复习的&#xff0c;会持续更新 前言 想法 首先我自己想说一下自己在学ts之前&#xff0c;对ts的一个想法和印象&#xff0c;在我学习之前&a…

性能测试知多少?怎样开展性能测试

看到好多新手&#xff0c;在性能需求模糊的情况下&#xff0c;随便找一个性能测试工具&#xff0c;然后就开始进行性能测试了&#xff0c;在这种情况下得到的性能测试结果很难体现系统真实的能力&#xff0c;或者可能与系统真实的性能相距甚远。 与功能测试相比&#xff0c;性能…

适合打游戏用的蓝牙耳机有哪些?吃鸡无延迟的蓝牙耳机推荐

现在手游的兴起&#xff0c;让游戏市场变得更加火爆&#xff0c;各种可以提高玩家体验的外设也越来越多&#xff0c;除了提升操作的外置按键与手柄外&#xff0c;能带来更出色音质与舒心使用的游戏耳机&#xff0c;整体氛围感更好&#xff0c;让玩家在细节上占据优势&#xff0…

2023年2月中国数据库排行榜:OTO新格局持续三月,人大金仓、AnalyticDB排名创新高

玉兔迎春至&#xff0c;榜单焕新颜。 2023年2月&#xff0c;兔年开年的 墨天轮中国数据库流行度排行 火热出炉&#xff0c;本月共有259个数据库参与排名&#xff0c;排行榜样式去掉了较上月和半年前得分差的数据显示&#xff0c;更加聚焦各产品之间的排名变化以及当月的得分差距…

景区展馆客流量数据如何统计

客流统计系统是了解掌握景区客流量的小助手&#xff0c;只有知道每天景区来往客流的情况&#xff0c;才能对经营管理、员工分配等多方面要素进行合理布局安排。使用客流统计系统&#xff0c;利用大数据管理预测&#xff0c;以客流数据为基础&#xff0c;提高景区对突发事件的应…

【云原生】kubeadm部署k8s集群、Dashboard UI以及连接私有仓库

一、kubeadm 部署 K8S 集群架构 主机名IP地址安装组件master&#xff08;2C/4G&#xff0c;cpu核心数要求大于2&#xff09;192.168.2.66docker、kubeadm、kubelet、kubectl、flannelnode01&#xff08;2C/2G&#xff09;192.168.2.200docker、kubeadm、kubelet、kubectl、fla…

基本bash shell(浏览、管理、查看文件/目录)

基本bash shell使用shell启动shell$cat /etc/passwd文件存储用户账号列表和基本配置信息shell提示符默认&#xff1a;$表示&#xff1a;shell在等待用户输入bash手册man命令$man man表示&#xff1a;查看手册页内容$man -K terminal关键字搜索。表示&#xff1a;查找与终端相关…

弄懂 Websocket 你得知道的这 3 点

1. WebSocket原理 WebSocket同HTTP一样也是应用层的协议&#xff0c;但是它是一种双向通信协议&#xff0c;是建立在TCP之上的。 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简…

扬帆优配|联通港股创近两年新高!A股资源类股爆发,食品饮料领跌

今日上午&#xff0c;A股商场和港股商场均现较大起伏震动&#xff0c;临近上午收盘出现一波跳水&#xff0c;不过&#xff0c;到上午收盘&#xff0c;上证指数仍微涨0.10%&#xff0c;煤炭等资源类板块明显上涨。 港股商场上午走弱&#xff0c;科技股领跌。 沪指微涨0.10%资源…

进程间通信(二)/共享内存

⭐前言&#xff1a;在前面的博文中分析了什么的进程间通信和进程间通信的方式之一&#xff1a;管道&#xff08;匿名管道和命名管道&#xff09;。接下来分析第二种方式&#xff1a;共享内存。 要实现进程间通信&#xff0c;其前提是让不同进程之间看到同一份资源。所谓共享内存…