精华内容
下载资源
问答
  • ICOWindows图标文件格式)_百度百科
    2021-07-26 02:06:55

    ICO

    (Windows的图标文件格式)

    语音

    编辑

    锁定

    讨论

    上传视频

    ICO是Windows的图标文件格式,图标文件可以存储单个图案、多尺寸、多色板的图标文件。一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域。

    中文名

    图标外文名

    ICOn

    外国语缩写

    ICO

    ICO格式详解

    编辑

    语音

    它是Windows的图标文件格式的一种,可以存储单个图案、多尺寸、多色板的图标文件。

    图标是具有明确指代含义的计算机图形。其中桌面图标是软件标识,界面中的图标是功能标识。

    图标有一套标准的大小和属性格式,且通常是小尺寸的。每个图标都含有多张相同显示内容的图片,每一张图片具有不同的尺寸和发色数。一个图标就是一套相似的图片,每一张图片有不同的格式,从这一点上说图标是三维的。图标还有另一个特性:它含有透明区域,在透明区域内可以透出图标下的桌面背景。在结构上图标其实和麦当劳的巨无霸汉堡差不多。

    一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域。因为计算机操作系统和显示设备的多样性,导致了图标的大小需要有多种格式。

    操作系统在显示一个图标时,会按照一定的标准选择图标中最适合当前显示环境和状态的图像。如果你用的是Windows98操作系统,显示环境是800x600分辨率,32位色深,你在桌面上看到的每个图标的图像格式就是256色32x32像素大小。如果在相同的显示环境下,Windows XP操作系统中,这些图标的图像格式就是:真彩色(32位色深)、32x32像素大小。

    下面就是Windows各个操作系统中的标准图标格式:(单位:大小—颜色)

    Windows 98 SE/ME/2000

    48 x 48 - 256 32 x 32 - 256 16 x 16 - 256

    48 x 48 - 16 32 x 32 - 16 16 x 16 - 16

    Windows XP

    48 x 48 - 32bit 32 x 32 - 32bit 24 x 24 - 32bit * 16 x 16 - 32bit

    (32位真彩色支持多通道透明。)

    48 x 48 - 256 32 x 32 - 256 24 x 24 - 256 * 16 x 16 - 256

    48 x 48 - 16 32 x 32 - 16 24 x 24 - 16 * 16 x 16 - 16

    * 这种格式在XP图标中并不是必须的。

    在Vista系统下最大可以支持256 x 256

    同时,非标准的ico格式文件也支持不规则尺寸的存储。

    注意:Windows98/2000对24 x 24格式的图标不兼容。你可以在相关应用软件中打开含有这种图像格式的图标,但操作系统却认为是无效的。你必须确保你所设计的图标中至少含有以上所列的图像格式来获得良好的显示效果。如果操作系统在图标中找不到特定的图象格式,它总是采用最接近的图象格式来显示,比如把大小为48 x 48的图标缩小为24 x 24像素大小。当然,效果就差些了。

    图标的文件格式

    在Windows操作系统中,单个图标的文件名后缀是.ICO。这种格式的图标可以在Windows操作系统中直接浏览;后缀名是.ICL的代表图标库,它是多个图标的集合,一般操作系统不直接支持这种格式的文件,需要借助第三方软件才能浏览。

    在图形用户界面中,系统中的所有资源分别由三种类型的图标所表示:应用程序图标(指向具体完成某一功能的可执行程序)、文件夹图标(指向用于存放其他应用程序、文档或子文件夹的“容器”)和文档图标(指向由某个应用程序所创建的信息)。

    在Windows系统中,左下角带有弧形箭头的图标代表快捷方式。快捷方式是一种特殊的文件类型,它提供了对系统中一些资源对象的快速简便访问,快捷方式图标是原对象的“替身”图标。

    快捷方式图标十分有用,它是定制桌面,进行快速访问经常使用的应用程序和文档的最主要的方法。

    ICO应用途径

    编辑

    语音

    ico可以作为浏览器首段图标显示,还可以在收藏夹内收藏内容的前段显示小图标

    ico还可以应用于windows软件

    ico也可以应用于个性化磁盘驱动器图标

    词条图册

    更多图册

    更多相关内容
  • win10超多图标.ico文件

    2020-10-15 17:05:37
    win10系统的几百个自定义.ico文件,包括网上找的和几个自己做的,可以替换系统自定义图标,基本上都是纯白色的。直接用.ico文件替换原本系统的图标便可以更改,方便好用颜值高
  • windows安装包 默认图标 打包 软件 图标 安装包图标.ico格式文件
  • Windows+ICO图标大全

    2013-11-26 14:36:59
    Windows+ICO图标大全,很全的Windows ICO图标,要做开发和写软件的拿去用吧
  • Go语言处理Windows系统的图标ICO文件(上) Go语言处理Windows系统的图标ICO文件(下)… 编写中 提取ICO文件中的所有图标图像 在上一篇文章中,我们了解了ico文件的结构,在这一篇文章中,我们首先来看看如何将多icon...

    ICO文件格式

    存放在github.com上的源代码链接
    Go语言处理Windows系统的图标ICO文件(上)
    Go语言处理Windows系统的图标ICO文件(下)


    提取ICO文件中的所有图标图像

    在上一篇文章中,我们了解了ico文件的结构,在这一篇文章中,我们首先来看看如何将多icon资源的ico文件中的图标图像提取出来。
    ico文件结构
    从我选中的部分,我们已经知道了,该ico文件有25个ico图像(png和bmp),从开头的22个字节后,每16字节为一个ico文件的header,直到第一个header中的偏移量为止(19-22字节所描述的偏移量)。

    那么将我们的理解转换为代码如下:
    1、通过22个字节的header中,最后4个字节,我们获取icon图标头结构偏移量0x960100,即:‘406bytes offset’。
    2、我们获取的0-406的内容就是我们第一个ico文件中所有icon图标的structure header
    3、根据icon数量来循环处理22个字节后的其他icon文件的header
    声明与定义一个读取ico文件的函数:

    func LoadIconFile(rd io.Reader) (icon *WinIcon, err error)
    

    如果我们完成了读取,则返回一个*WinIcon对象的指针,如果失败则返回错误对象。
    那么我们的错误应该有哪些呢?
    1、非法的文件(非法的ico文件)
    a、文件的长度连22个字节都没(说明根本就不是一个ico文件,只是扩展名是.ico)
    b、文件的长度的确超过了22字节,但是这22字节的内容却和ico的header结构不匹配
    c、可能传入的读取像不是一个*os.File,亦或则不是一个文件呢…可能需要做些基本判断
    d、在读取数据中,会不会出现越界的情况呢?
    先暂时想到这里。
    这里我定义了一些错误信息对象:

    // 定义变量
    var (
    	// 错误信息
    	ErrIcoInvalid  = errors.New("ico: Invalid icon file")                  // 无效的ico文件
    	ErrIcoReaders  = errors.New("ico: Reader type is not os.File pointer") // LoadIconFile的io.Reader参数不是文件指针
    	ErrIcoFileType = errors.New("ico: Reader is directory, not file")      // io.Reader的文件指针是目录,不是文件
    	ErrIconsIndex  = errors.New("ico: Slice out of bounds")                // 读取ico文件时,可能出现的切片越界错误
    )
    

    定义两个常量:

    // 定义常量
    const (
    	fileHeaderSize = 6  // 文件头的大小
    	headerSize     = 16 // icon图标的头结构大小
    )
    

    所以我们还需要一个函数来判断是否是ico文件:

    func getIconHeader(b []byte) (wih *winIconHeader, err error)
    

    在这个函数中,我们判断文件合法性,如果非法,则返回err,如果合法,则提取icon的结构。
    如果是单icon图标的ico文件,那么结构中的文件数量则为1,如果是多icon图标的ico文件,则文件数量为n,我们可以根据这个n来循环。或则为1则直接读取icon图标数据。

    文件头只有6个字节,只是做一个简单判断,即3个部分,保留字段、是否是ico的marker,icon图标的数量
    

    getIconHeader的代码实现:

    if len(b) != fileHeaderSize {
    	return nil, ErrIcoInvalid
    }
    reserved := binary.LittleEndian.Uint16(b[0:2])
    filetype := binary.LittleEndian.Uint16(b[2:4])
    imagecount := binary.LittleEndian.Uint16(b[4:6])
    if reserved != 0 || filetype != 1 || imagecount == 0 {
    	return nil, ErrIcoInvalid
    }
    header := &winIconFileHeader{
    	ReservedA:  reserved,
    	FileType:   filetype,
    	ImageCount: imagecount,
    }
    return header, nil
    

    我们获取到了文件的头结构后,也就获得了icon图标的数量,根据数量我们可以控制循环的次数。
    这里是部分LoadIconFile函数的代码:

    // 创建一个 winIconStruct 数组切片
    icos := make([]winIconStruct, int(icoHeader.ImageCount))
    // 根据文件头中表示的icon图标文件的数量进行循环
    structOffset := fileHeaderSize
    // 这里的icoHeader就是文件头,ImageCount就是我们获取的ico图标数量 
    for i := 0; i < int(icoHeader.ImageCount); i++ {
    	// data 是怎个文件的[]byte数据
    	wis := getIconStruct(data, structOffset, headerSize)
    	structOffset += headerSize
    	icos[i] = *wis
    } 
    // 这个循环的意义在于,我们将ico图标的头结构全部拿到,拿到这个就可以
    // 根据ico图标的头结构信息来获取偏移量,从而获取图标图像的数据
    
    // 创建 WinIcon 对象
    ico = &WinIcon{
    	fileHeader: icoHeader,
    	icos:       icos,
    	data:       data,
    }
    return ico, nil
    

    获取所有数据:

    func getFileAll(rd *bufio.Reader, size int64) (fb []byte, err error)
    

    实现:

    data := make([]byte, size)
    // 丢弃1-6字节内容(文件头)
    // if _, err := rd.Discard(fileHeaderSize); err != nil {
    // 	return nil, err
    // }
    // size = size - fileHeaderSize
    for i := int64(0); i < size; i++ {
    	b, err := rd.ReadByte()
    	if err != nil {
    		return nil, err
    	}
    	data[i] = b
    }
    return data, nil
    

    当我们有了文件的所有数据,以及icon图标的所有头结构后,我们就可以获取图标数据了:

    func (wi *WinIcon) GetImageData(index int) (d []byte, err error)
    func (wi *WinIcon) getImageData(data []byte, offset, datasize int) []byte
    

    getImageData是包内的private:成员函数,GetImageData是包外public:成员函数

    从参数上看GetImageData仅需要传递索引即可,getImageData需要传递的内容是所有数据data,以及ico文件在所有数据中的偏移量,以及数据大小(length长度),最后返回ico的图像数据:[]byte类型。

    getImageData代码实现:

    var d = make([]byte, datasize) // 不建议 data[offset:length] 采用复制数据会相对安全些
    for i, j := offset, 0; i < datasize+offset; i++ {
    	d[j] = data[i]
    	j++
    }
    return d
    

    GetImageData 代码实现:

    if index >= wi.getIconsHeaderCount() || index < 0 {
    	return nil, ErrIconsIndex
    }
    wis := wi.icos[index]
    db := wi.getImageData(wi.data, int(wis.ImageOffset), int(wis.ImageDataSize))
    return db, nil
    

    wi.getIconsHeaderCount获取我们已经的得到的icon图标头结构的数量。

    基本上而言,以上代码就是读取数据的主要内容。完整代码请见页面中的github.com的链接。

    好了,当我们实现了ico文件的读取/解析功能后,我们就可以实现提取数据的功能了。
    函数签名:

    func (wis winIconStruct) generateFileNameFormat(prefix string, width, height, bit int) string
    func (wis winIconStruct) IconToFile(path string, data []byte) error
    func (wi *WinIcon) ExtractIconToFile(filePrefix, filePath string) error
    func (wi *WinIcon) IconToFile(filePath string, index int) error
    

    这里顺便提一下,关于WinIconwinIconStruct,在之前的结构体定义的时候,WinIcon 是首字母大写的,意思就是它是包级的,包外可以访问,而winIconStruct是包内的,包外是隐藏,我们包内实现,包内使用。
    所以generateFileNameFormatIconToFile 并不是提供给调用ico包的角色使用的。

    这里就贴一下(wi *WinIcon) ExtractIconToFile ,我们可以使用该函数将ico文件中所有的icon图标全部提取出来,并保存到磁盘,而(wis winIconStruct) generateFileNameFormat 就是自动生成文件名前缀的函数。生成后效果如下:
    ico文件中的所有icon图标提取后的效果
    favicon_all.ico 这个文件就是多icon图标结构的ico文件,使用了30天试用版的某IconWorkshop软件生成(我不是美术,所以花钱买,貌似辱没了Gopher呀,而且买了,我就没必要写这个教程了?,我的win10三套都是正版,office正版,Xmind正版…,基本上我很少用盗版,嗯…不好意思,跑题了??),2-4个ico文件,分辨率为0x0,是因为图标的width和height数据段使用1byte,前面说了,1byte的最大正整数为255,而256这个数字则会被储存为0x00,高位丢失。所以在ico文件中如果icon头结构中的w,h字段值为0,那么如果没有出错的话,分辨率则为256x256pixel。

    func (wi *WinIcon) ExtractIconToFile(filePrefix, filePath string) error
    

    ExtractIconToFile 的实现:

    for _, v := range wi.icos {
    	fileName := v.generateFileNameFormat(filePrefix,
    		int(v.Width),
    		int(v.Height),
    		int(v.BitsPerPixel))
    	fp := filepath.Join(filePath, fileName)
    	d := wi.getImageData(wi.data, int(v.ImageOffset), int(v.ImageDataSize))
    	if err := v.IconToFile(fp, d); err != nil {
    		return err
    	}
    }
    return nil
    

    这里我贴出package的测试ico_test.go

    package ico
    
    import (
    	"log"
    	"os"
    	"path/filepath"
    	"testing"
    )
    
    func TestLoadIconFile(t *testing.T) {
    	var fs *os.File
    	defer func() {
    		if fs != nil {
    			fs.Close()
    		}
    		if err := recover(); err != nil {
    			log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
    			log.Printf("LoadIconFile() = Error:%v\r\n", err)
    			os.Exit(1)
    		}
    	}()
    	path := "../testico/"
    	file := "favicon_all.ico"
    	filePath := filepath.Join(path, file)
    	fs, err := os.Open(filePath)
    	if err != nil {
    		panic(err)
    	}
    	wi, err := LoadIconFile(fs)
    	if err != nil {
    		panic(err)
    	}
    	// if err := wi.ExtractIconToFile("test", "../testdata/", 0); err != nil {
    	// 	panic(err)
    	// }
    	// for _, v := range wi.icos {
    	// 	fmt.Printf("image width:%v, height:%v\r\n", v.Width, v.Height)
    	// 	fmt.Printf("image offset:%v, datesize:%v\r\n", v.ImageOffset, v.ImageDataSize)
    	// 	d := wi.getImageData(wi.data, int(v.ImageOffset), int(v.ImageDataSize))
    	// 	fn := fmt.Sprintf("../testico/%vx%v@%v.ico", v.Width, v.Height, v.BitsPerPixel)
    	// 	err := ioutil.WriteFile(fn, d, 0)
    	// 	if err != nil {
    	// 		fmt.Println(err)
    	// 	}
    	// }
    	if err := wi.ExtractIconToFile("test", "../testico/"); err != nil {
    		panic(err)
    	}
    }
    

    我们使用go语言封装的时候,没必要写main package和main函数来跑代码,golang给我们自带了UT,善加利用,即可提高效率和质量。

    提取后的png文件头部:
    png图像文件的开头部分内容
    提取后的dib(bitmap)文件头部:
    bmp图像文件的dib头

    我们需要实现对png或bmp的数据检测函数。
    以下是具有像素格式RGB24的2×2像素,24位位图(Windows DIB标题BITMAPINFOHEADER)的示例:
    放大显示的效果
    bmp的文件结构
    以下是具有像素格式ARGB32的alpha通道(Windows DIB标题BITMAPV4HEADER)中具有不透明度值的4×2像素,32位位图的示例:
    放大显示的效果
    ARGB32位图的结构
    PNG文件头结构:
    PNG File Headericon全部提取与单个提取
    关于提取的*.ico文件数据,实际上还需要进一步处理,bitmap需要写一个bmp头,因为ico文件中的bitmap icon图标是没有BMP header,只有DIB header的。而png没有这个问题,我们需要识别一下后,bmp的保存为 *.bmp,png的保存为*.png。有了提取,我们还需要实现根据命令行参数将多个bmp或png文件打包为ico文件结构并输出ico文件的功能。而这些内容,我们将在下一集教程中讲解。

    下面是读取ico文件,实现了全部提取及单独提取及单独提取并保存为单icon图标的ico文件的功能:
    打包功能还没有写,下一章教程实现。

    /*
       _____       __   __             _  __
      ╱ ____|     |  ╲/   |           | |/ /
     | |  __  ___ |  ╲ /  | __  _ _ __| ' /
     | | |_ |/ _ ╲| |╲ /| |/ _`  | '__|  <
     | |__| |  __/| |   | (  _|  | |  | . ╲
      ╲_____|╲___ |_|   |_|╲__,_ |_|  |_|╲_╲
     可爱飞行猪❤: golang83@outlook.com  ???
     Author Name: GeMarK.VK.Chow奥迪哥  ???
     Creaet Time: 2019/05/25 - 07:51:34
     ProgramFile: ico.go
     Description:
    			  Windows系统的ico文件工具包
    */
    
    package ico
    
    import (
    	"bufio"
    	"bytes"
    	"encoding/binary"
    	"errors"
    	"fmt"
    	"io"
    	"io/ioutil"
    	"os"
    	"path/filepath"
    	"runtime"
    )
    
    // 定义常量
    const (
    	typeUKN          = iota // unknow type
    	typeBMP                 // bmp ico
    	typePNG                 // png ico
    	fileHeaderSize   = 6    // 文件头的大小
    	headerSize       = 16   // icon图标的头结构大小
    	bitmapHeaderSize = 14   // 位图文件头
    	dibHeaderSize    = 40   // dib结构头
    )
    
    // 定义变量
    var (
    	// 错误信息
    	ErrIcoInvalid  = errors.New("ico: Invalid icon file")                  // 无效的ico文件
    	ErrIcoReaders  = errors.New("ico: Reader type is not os.File pointer") // LoadIconFile的io.Reader参数不是文件指针
    	ErrIcoFileType = errors.New("ico: Reader is directory, not file")      // io.Reader的文件指针是目录,不是文件
    	ErrIconsIndex  = errors.New("ico: Slice out of bounds")                // 读取ico文件时,可能出现的切片越界错误
    )
    
    // 类型定义
    // 定义icon图标数据的存放
    type (
    	ICONTYPE      int
    	WinIconData   [][]byte
    	WinIconStruct []winIconStruct
    )
    
    // 定义 Windows 系统的 Ico 文件结构
    type WinIcon struct {
    	fileHeader *winIconFileHeader // 文件头
    	icos       WinIconStruct      // icon 头结构
    	icod       WinIconData        // 单独的icon图标的数据
    	data       []byte             // 所有ico文件数据
    }
    
    type winIconFileHeader struct {
    	ReservedA  uint16 // 保留字段,始终为 '0x0000'
    	FileType   uint16 // 图像类型:'0x0100' 为 ico,'0x0200' 为 cur
    	ImageCount uint16 // 图像数量:至少为 '0x0100' 即 1个图标
    }
    
    type winIconStruct struct {
    	Width         uint8  // 图像宽度
    	Height        uint8  // 图像高度
    	Palette       uint8  // 调色板颜色数,不使用调色版为 '0x00'
    	ReservedB     uint8  // 保留字段,始终为 '0x00'
    	ColorPlanes   uint16 // 在ico中,指定颜色平面,'0x0000' 或则 '0x0100'
    	BitsPerPixel  uint16 // 在ico中,指定每像素的位数,如:'0x2000' 32bit
    	ImageDataSize uint32 // 图像数据的大小,单位字节
    	ImageOffset   uint32 // 图像数据的偏移量
    }
    
    type dibHeader struct {
    	dibSize        uint32 // 4bytes
    	bitmapWidth    uint32 // 4bytes
    	bitmapHeight   uint32 // 4bytes
    	colorPlanes    uint16 // 2bytes
    	BitsPerPixel   uint16 // 2bytes
    	markerBI_RGB   uint32 // 4bytes
    	originalSize   uint32 // 4bytes
    	printResH      uint32 // 4bytes
    	printResV      uint32 // 4bytes
    	Palette        uint32 // 4bytes
    	importantColor uint32 // 4bytes
    }
    
    type bitmapHeader struct {
    	bitmapID         uint16
    	fileSize         uint32
    	unusedA          uint16
    	unusedB          uint16
    	bitmapDataOffset uint32
    }
    
    // createBitmapHeader 创建位图文件头结构
    func createBitmapHeader(datasize int) *bitmapHeader {
    	return &bitmapHeader{
    		bitmapID:         binary.LittleEndian.Uint16([]byte{0x42, 0x4d}),
    		fileSize:         uint32(datasize + bitmapHeaderSize),
    		unusedA:          0,
    		unusedB:          0,
    		bitmapDataOffset: uint32(bitmapHeaderSize + dibHeaderSize),
    	}
    }
    
    // GetIconType 获取icon的数据类型
    func GetIconType(d []byte) ICONTYPE {
    	if checkDIBHeader(d) {
    		return typeBMP
    	}
    	if checkPNGHeader(d) {
    		return typePNG
    	} else {
    		return typeUKN
    	}
    }
    
    // checkPNGHeader 检测是否是png ico数据
    func checkPNGHeader(d []byte) bool {
    	if len(d) < 8 {
    		return false
    	}
    	if bytes.Compare(d[0:8], []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}) != 0 {
    		return false
    	}
    	return true
    }
    
    // headerToBytes 将bitmapHeader位图头结构转换为字节切片
    func (bmh *bitmapHeader) headerToBytes() []byte {
    	d := make([]byte, bitmapHeaderSize)
    	binary.LittleEndian.PutUint16(d[0:2], bmh.bitmapID)
    	binary.LittleEndian.PutUint32(d[2:6], bmh.fileSize)
    	binary.LittleEndian.PutUint16(d[6:8], bmh.unusedA)
    	binary.LittleEndian.PutUint16(d[8:10], bmh.unusedB)
    	binary.LittleEndian.PutUint32(d[10:14], bmh.bitmapDataOffset)
    	return d
    }
    
    // JoinHeader 将bitmapfileheader链接到含有dib头的位图数据前
    func (bmh *bitmapHeader) JoinHeader(d []byte) []byte {
    	h := bmh.headerToBytes()
    	j := [][]byte{h, d}
    	return bytes.Join(j, nil)
    }
    
    // checkDIBHeader 检测是否是bmp ico数据
    func checkDIBHeader(d []byte) bool {
    	if len(d) < 40 {
    		return false
    	}
    	a := d[0:4]
    	b := []byte{0x28, 0, 0, 0}
    	if bytes.Compare(a, b) != 0 {
    		return false
    	}
    	return true
    }
    
    // 将ico文件的数据载入到内存
    func LoadIconFile(rd io.Reader) (icon *WinIcon, err error) {
    	// 类型断言
    	v, t := rd.(*os.File)
    	if !t {
    		return nil, ErrIcoReaders
    	}
    	// 声明与定义变量
    	var (
    		fileSize int64
    		ico      *WinIcon
    	)
    
    	// 获取文件信息及判断是否是文件,而不是目录
    	fi, err := v.Stat()
    	if err != nil {
    		return nil, err
    	}
    	if fi.IsDir() {
    		return nil, ErrIcoFileType
    	}
    	fileSize = fi.Size()
    
    	// 创建缓冲IO的Reader对象窥视6个字节的文件头
    	reader := bufio.NewReader(rd)
    	p, err := reader.Peek(fileHeaderSize)
    	if err != nil {
    		return nil, err
    	}
    
    	// 检测文件头及获取头结构
    	icoHeader, err := getIconFileHeader(p)
    	if err != nil {
    		return nil, err
    	}
    
    	// 获取ico文件的所有数据
    	data, err := getFileAll(reader, fileSize)
    	if err != nil {
    		return nil, err
    	}
    
    	// 创建一个 winIconStruct 数组切片
    	icos := make(WinIconStruct, int(icoHeader.ImageCount))
    	icod := make(WinIconData, int(icoHeader.ImageCount))
    	// 根据文件头中表示的icon图标文件的数量进行循环
    	structOffset := fileHeaderSize
    	for i := 0; i < int(icoHeader.ImageCount); i++ {
    		wis := getIconStruct(data, structOffset, headerSize)
    		icodata := wis.getImageData(data, wis.getIconOffset(), wis.getIconLength())
    		structOffset += headerSize
    		icos[i] = *wis
    		icod[i] = icodata
    	}
    
    	// 创建 WinIcon 对象
    	ico = &WinIcon{
    		fileHeader: icoHeader,
    		icos:       icos,
    		icod:       icod,
    		data:       data,
    	}
    	return ico, nil
    }
    
    // getFileAll 获取ico文件所有数据(不包括文件头的6个字节)
    // rd *bufio.Reader: 对象
    // size int64: 文件大小(我们需要读取的总数量)
    // fb []byte: 文件的所有数据,如果成功读取的话
    // err error: 如果读取出现错误,返回错误
    func getFileAll(rd *bufio.Reader, size int64) (fb []byte, err error) {
    	data := make([]byte, size)
    	for i := int64(0); i < size; i++ {
    		b, err := rd.ReadByte()
    		if err != nil {
    			return nil, err
    		}
    		data[i] = b
    	}
    	return data, nil
    }
    
    // getIconFileHeader 获取文件头结构
    // b []byte: 读取的数据来自这个字节切片
    // wih *winIconFileHeader: 如果获取成功返回 winIconFileHeader对象指针
    // err error: 如果读取发生错误,则返回错误信息
    func getIconFileHeader(b []byte) (wih *winIconFileHeader, err error) {
    	if len(b) != fileHeaderSize {
    		return nil, ErrIcoInvalid
    	}
    	reserved := binary.LittleEndian.Uint16(b[0:2])
    	filetype := binary.LittleEndian.Uint16(b[2:4])
    	imagecount := binary.LittleEndian.Uint16(b[4:6])
    	if reserved != 0 || filetype != 1 || imagecount == 0 {
    		return nil, ErrIcoInvalid
    	}
    	header := &winIconFileHeader{
    		ReservedA:  reserved,
    		FileType:   filetype,
    		ImageCount: imagecount,
    	}
    	return header, nil
    }
    
    // getIconStruct 根据 offset, length 来获取icon图标结构
    // b []byte: 文件数据的字节切片
    // offset int: 偏移量
    // length int: 数据长度
    func getIconStruct(b []byte, offset, length int) (wis *winIconStruct) {
    	var std []byte
    	//std = b[offset:length]
    	std = make([]byte, headerSize)
    	j := 0
    	for i := offset; i < length+offset; i++ {
    		std[j] = b[i]
    		j++
    	}
    	is := &winIconStruct{
    		Width:         std[0],
    		Height:        std[1],
    		Palette:       std[2],
    		ReservedB:     std[3],
    		ColorPlanes:   binary.LittleEndian.Uint16(std[4:6]),
    		BitsPerPixel:  binary.LittleEndian.Uint16(std[6:8]),
    		ImageDataSize: binary.LittleEndian.Uint32(std[8:12]),
    		ImageOffset:   binary.LittleEndian.Uint32(std[12:]),
    	}
    	return is
    }
    
    // getImageData 根据 offset, length 参数获取图标图像数据
    // data []byte: 图像数据的字节切片
    // offset int: 图像数据的偏移量
    // length int: 图像数据的长度
    // return []byte: 返回获取的数据字节切片
    func (wi *WinIcon) getImageData(data []byte, offset, datasize int) []byte {
    	var d = make([]byte, datasize) //data[offset:length]
    	for i, j := offset, 0; i < datasize+offset; i++ {
    		d[j] = data[i]
    		j++
    	}
    	return d
    }
    
    func (wis winIconStruct) getImageData(data []byte, offset, ds int) []byte {
    	var d = make([]byte, ds)
    	for i, j := offset, 0; i < ds+offset; i++ {
    		d[j] = data[i]
    		j++
    	}
    	return d
    }
    
    // ExtractIconToFile 提取 ico 数据到文件
    // filePrefix string: 为前缀,如果传如空字符串,则没有前缀,使用数字和分辨率作为文件名
    // filePath string: 提取的数据写入的路径,空字符串则将文件保存到当前目录
    // 舍弃:--count int: 提取文件的数量,0: 为所有,> 0 则根据已保存的map对象来提取对应数量内容,指定数量超出实际数量则全部提取--
    // 该函数不检测路径的有效性,使用者自己把控,如果路径有问题,会返回error对象
    func (wi *WinIcon) ExtractIconToFile(filePrefix, filePath string) error {
    	var ext string
    	for i, v := range wi.icos {
    		w := v.getIconWidth()
    		h := v.getIconHeight()
    		b := v.getIconBitsPerPixel()
    		d, _ := wi.GetImageData(i)
    		if GetIconType(d) == typeBMP {
    			ext = "bmp"
    		} else {
    			ext = "png"
    			if w == 0 && h == 0 {
    				w = 256
    				h = 256
    			}
    		}
    		fn := v.generateFileNameFormat(filePrefix, ext, w, h, b)
    		if err := wi.IconToFile(filePath, fn, i); err != nil {
    			return err
    		}
    	}
    	return nil
    }
    
    // GetImageData 获取ico图标的图像数据
    // index int: 下标索引,0序
    // 如果越界或读取数据错误,返回 error 对象
    func (wi *WinIcon) GetImageData(index int) (d []byte, err error) {
    	if index >= wi.getIconsHeaderCount() || index < 0 {
    		return nil, ErrIconsIndex
    	}
    	wis := wi.icos[index]
    	offset := wis.getIconOffset()
    	datasize := wis.getIconLength()
    	data := wi.getImageData(wi.data, offset, datasize)
    	return data, nil
    }
    
    // IconToFile 将图标写入文件
    // path string: 文件写入的路径
    // name string: 文件名
    // error 如果写入发生错误,则返回错误信息
    // IconToFile 并不会检测路径是否有效
    func (wi *WinIcon) IconToFile(path, name string, index int) error {
    	if index >= wi.getIconsHeaderCount() || index < 0 {
    		return ErrIconsIndex
    	}
    	wis := wi.icos[index]
    	p := filepath.Join(path, name)
    	d, e := wi.GetImageData(index)
    	if e != nil {
    		return e
    	}
    	// 处理bitmap头结构
    	if GetIconType(d) == typeBMP {
    		w := wis.getIconWidth()
    		h := wis.getIconHeight()
    		b := wis.getIconBitsPerPixel()
    		s := len(d) - dibHeaderSize
    		dib := createDIBHeader(w, h, b, s, 0, 0)
    		err := dib.EditDIBHeader(d)
    		if err != nil {
    			return err
    		}
    		bmh := createBitmapHeader(len(d))
    		d = bmh.JoinHeader(d)
    	}
    	if e := wis.IconToFile(p, d); e != nil {
    		return e
    	} else {
    		return nil
    	}
    }
    
    // IconToIcoFile 将ico文件中的指定icon图标数据写入ico文件
    // path string: 路径(不检查合法性)
    // index int: icon图标的索引
    // error: 如果发生错误返回error对象
    func (wi *WinIcon) IconToIcoFile(path string, index int) error {
    	if index < 0 || index >= len(wi.icos) {
    		return ErrIconsIndex
    	}
    	d := wi.icod[index]
    	wis := wi.icos[index]
    	wis.ImageOffset = fileHeaderSize + headerSize
    	wis.ImageDataSize = uint32(len(d))
    	d = wis.joinHeader(d)
    	if e := ioutil.WriteFile(path, d, getPerm()); e != nil {
    		return e
    	}
    	return nil
    }
    
    // getIconsHeaderCount 获取 icons 图标的结构数量-可能和头结构的ico数量不一致,只是可能
    // 返回值为数量,类型 int
    func (wi *WinIcon) getIconsHeaderCount() int {
    	return len(wi.icos)
    }
    
    // generateFileNameFormat 产生文件名
    func (wis winIconStruct) generateFileNameFormat(prefix, ext string, width, height, bit int) string {
    	return fmt.Sprintf("%s_icon%dx%d@%dbit.%s", prefix, width, height, bit, ext)
    }
    
    // iconToFile 将ico图像数据写入磁盘文件
    func (wis winIconStruct) IconToFile(path string, data []byte) error {
    	if err := ioutil.WriteFile(path, data, getPerm()); err != nil {
    		return err
    	}
    	return nil
    }
    
    func (wis winIconStruct) headerToBytes() []byte {
    	d := make([]byte, fileHeaderSize+headerSize)
    	binary.LittleEndian.PutUint16(d[0:2], 0)
    	binary.LittleEndian.PutUint16(d[2:4], 1)
    	binary.LittleEndian.PutUint16(d[4:6], 1)
    	d[6] = uint8(wis.getIconWidth())
    	d[7] = uint8(wis.getIconHeight())
    	d[8] = wis.Palette
    	d[9] = wis.ReservedB
    	binary.LittleEndian.PutUint16(d[10:12], wis.ColorPlanes)
    	binary.LittleEndian.PutUint16(d[12:14], wis.BitsPerPixel)
    	binary.LittleEndian.PutUint32(d[14:18], wis.ImageDataSize)
    	binary.LittleEndian.PutUint32(d[18:22], wis.ImageOffset)
    	return d
    }
    
    func (wis winIconStruct) joinHeader(d []byte) []byte {
    	h := wis.headerToBytes()
    	j := [][]byte{h, d}
    	return bytes.Join(j, nil)
    }
    
    // getIconOffset 获取icon图像数据的偏移量
    // 返回偏移量数据
    func (wis winIconStruct) getIconOffset() int {
    	return int(wis.ImageOffset)
    }
    
    // getIconLength 获取icon图像数据的长度
    // 返回长度数据
    func (wis winIconStruct) getIconLength() int {
    	return int(wis.ImageDataSize)
    }
    
    // getIconWidth 获取icon图像数据的宽度
    func (wis winIconStruct) getIconWidth() int {
    	return int(wis.Width)
    }
    
    // getIconHeight 获取icon图像数据的高度
    func (wis winIconStruct) getIconHeight() int {
    	return int(wis.Height)
    }
    
    // getIconBitsPerPixel 获取icon图像数据的颜色位数
    func (wis winIconStruct) getIconBitsPerPixel() int {
    	return int(wis.BitsPerPixel)
    }
    
    // createDIBHeader创建DIB头结构
    func createDIBHeader(width, height, bit, size, p, i int) *dibHeader {
    	return &dibHeader{
    		dibSize:        40,             // uint32
    		bitmapWidth:    uint32(width),  // uint32
    		bitmapHeight:   uint32(height), // uint32
    		colorPlanes:    1,              // uint16
    		BitsPerPixel:   uint16(bit),    // uint16
    		markerBI_RGB:   0,              // uint32
    		originalSize:   uint32(size),   // uint32
    		printResH:      2835,           // uint32
    		printResV:      2835,           // uint32
    		Palette:        uint32(p),      // uint32
    		importantColor: uint32(i),      // uint32
    	}
    }
    
    // HeaderToBytes 将DIB的头结构转换为字节切片
    func (dh *dibHeader) HeaderToBytes() []byte {
    	d := make([]byte, dibHeaderSize)
    	binary.LittleEndian.PutUint32(d[0:4], dh.dibSize)
    	binary.LittleEndian.PutUint32(d[4:8], dh.bitmapWidth)
    	binary.LittleEndian.PutUint32(d[8:12], dh.bitmapHeight)
    	binary.LittleEndian.PutUint16(d[12:14], dh.colorPlanes)
    	binary.LittleEndian.PutUint16(d[14:16], dh.BitsPerPixel)
    	binary.LittleEndian.PutUint32(d[16:20], dh.markerBI_RGB)
    	binary.LittleEndian.PutUint32(d[20:24], dh.originalSize)
    	binary.LittleEndian.PutUint32(d[24:28], dh.printResH)
    	binary.LittleEndian.PutUint32(d[28:32], dh.printResV)
    	binary.LittleEndian.PutUint32(d[32:36], dh.Palette)
    	binary.LittleEndian.PutUint32(d[36:40], dh.importantColor)
    	return d
    }
    
    // EditDIBHeader 修改DIB头
    func (dh *dibHeader) EditDIBHeader(b []byte) error {
    	if len(b) <= 40 {
    		return ErrIconsIndex
    	}
    	h := dh.HeaderToBytes()
    	for i := 0; i < 40; i++ {
    		b[i] = h[i]
    	}
    	return nil
    }
    
    func CreateWinIcon(b [][]byte) (*WinIcon, error) {
    
    	return nil, nil
    }
    
    func getPerm() os.FileMode {
    	if runtime.GOOS == "windows" {
    		return 0
    	} else {
    		return 0666
    	}
    }
    
    
    展开全文
  • windows图标大全

    2021-02-14 10:08:59
    windows图标大全
  • 多年收集的精美的图标,通用性强,非常适合作为应用程序的图标和按钮图标
  • Windows 空白图标资源,blank.icowindows系统资源,通过修改注册表,去除windows图标箭头
  • 常用windows文件图标

    2008-06-21 21:36:12
    常用的windows文件图标ico格式,方便网页设计
  • Win10系统图标ico文件全套
  • win10原版ico、dll 含win10资源管理器原版图标,可替换q-dir图标 及系统全部默认图标dll供大家使用 希望对大家有帮助,推荐一款文件资源管理器——q-dir
  • Mico 是一个命令行工具,用于从多个图像创建 Windows 图标。 Sico 是一个命令行工具,用于将图标拆分回单独的图像。
  • 最新最全Windows10系统图标,包含各种硬件图标、磁盘管理所用图标、音频设备图标、网络和共享中心图标和各种传感器图标
  • Go语言处理Windows系统的图标ICO文件(中)… 编写中 Go语言处理Windows系统的图标ICO文件(下)… 编写中 概述 我们在编写一个程序后,如果是windows系统中的程序,我们希望它有一个图标,这个时候,我们可以使用一些...

    ICO 文件格式

    存放在github.com上的源代码链接
    Go语言处理Windows系统的图标ICO文件(中)
    Go语言处理Windows系统的图标ICO文件(下)


    概述

    我们在编写一个程序后,如果是windows系统中的程序,我们希望它有一个图标,这个时候,我们可以使用一些软件来完成图标,嗯…但是好的Icon制作软件要收费,例如Axialis IconWorkshop,可以制作Windows以及MacOS等系统的图标。网络上基于Web页面的在线转转换工具也是有的,但是我看了下,貌似只是单Image(jpg or png or bmp)转单icon格式,而一个Windows应用程序实际上用到的ico文件,应该是多icon图标的,即一个ico文件内,包含了多个icon图标图像数据。例如下图:
    通过PE软件查看exe中的icon
    我们可以通过PE Explorer 看到一个Windows的应用程序中,包含图标有多个不同分辨率及不同颜色数量的icon,从Windows Vista开始,windows可以支持的图标分辨率可以达到256x256@32bit的图标资源,既然我们的口号是I am a Gopher!,那么我们无论是从学习角度,还是从Go Code角度,我们完全可以自己实现一个我们自己的Icon工具。


    单个icon文件分析

    单个icon文件的意思是:我们要分析的ico文件只包含了一个图标,实际上ico文件是一种目录结构的文件,即文件内的数据格式结构是可以存放多文件(多个ico图标),为了将理解流程简化,所以我们先观察只在文件结构中存放了一张图标的ico文件。

    我这里首先来分析一个16x16pixel@24bit 的ico文件:
    一个16x16像素的单icon文件
    资源管理器中显示的2KB大小是一个大概的值,我们鼠标右键菜单,点击属性查看实际大小:
    ico文件实际大小
    我们看到是1.12KB,实际大小为1150字节。(1150 / 1024 = 1.123046875 round 1.12KB)

    我们再查看文件的HEX(Binary二进制文件,通常我们用16进制查看器来阅读)
    ico文件16进制显示数据
    我框选的部分有22个字节,这22个字节就是我们这个ico文件的header部分,我们通常称之为文件头(用于描述文件结构的概念)
    然后我们通过下面这张图来充分理解,每个字节的含义:
    ico的文件头
    首先根据Windows系统下ico文件格式的标准,存储的数据采用的是little-endian即“小端序”。
    什么是小端序,我们可以理解为:数据的低位在前,高位在后,即个十百千-> 1024 -> 4201
    在16进制查看器中,例如:

    var data uint32 = 255
    

    那么小端序存储在内存或磁盘的方式为:

    FF 00 00 00
     |-  255的16进制
    
    var data uint32 = 256
    

    那么一个字节能够表示的最大正整数为255,这里256,超出了1位:

    00 01 00 00
     |----|- 进位了,256的16进制为100
    

    关于小端序的数据转换,这里先说一下代码:

    var data = []byte{0x00, 0x01, 0x00, 0x00}
    Int32Data := binary.LittleEndian.Uint32(data[0:])
    t.Logf("%v", Int32Data)
    

    输出结果:

    === RUN   Test_LittleEndian
    --- PASS: Test_LittleEndian (0.00s)
        main_test.go:144: 256 // 这里是结果
    PASS
    ok      ICOFormat 0.187s
    

    现在我们将概念的理解转换为代码:

    type winIcon struct {
    	reservedA     uint16 // 保留字段,始终为 '0x0000'
    	fileType      uint16 // 图像类型:'0x0100' 为 ico,'0x0200' 为 cur
    	imageCount    uint16 // 图像数量:至少为 '0x0100' 即 1个图标
    	width         uint8  // 图像宽度
    	height        uint8  // 图像高度
    	palette       uint8  // 调色板颜色数,不使用调色版为 '0x00'
    	reservedB     uint8  // 保留字段,始终为 '0x00'
    	colorPlanes   uint16 // 在ico中,指定颜色平面,'0x0000' 或则 '0x0100'
    	bitsPerPixel  uint16 // 在ico中,指定每像素的位数,如:'0x2000' 32bit
    	imageDataSize uint16 // 图像数据的大小,单位字节
    	imageOffset   uint32 // 图像数据的偏移量
    }
    

    等一等,这似乎只是单图标文件的结构描述,我们前面说了,ico文件内部应该是以目录结构描述的。
    而且图像的数据可以是bmp(Bitmap位图),也可以是png(Portable Network Graphics便携式网络图形)格式。


    多个ico图标结构分析

    所以我们再来看一个多icon图标文件的ico文件结构:
    多icon图标的ico文件结构
    上图中橘黄色的框中为BMP或PNG的数据偏移量,0x960100 -> 小端转换后为:406字节
    那么后面的数据段应该是啥样的呢?我们看看从头偏移406字节的内容:
    多icon图标的ico文件头结构
    从第一个字节开始偏移406字节的内容选中后,即便我不用不同颜色的框标明一下,都会觉得感觉每一行的结构都好特么的像。再用不同颜色的框一画,聪明的同学肯定感觉一切尽在掌握。哈哈哈。刚好25个…
    换句话说,那个BMP或PNG的偏移量表示的就是偏移过后,就是图像数据。而偏移量前的就是我们的ico文件中的头结构。

    那么我们可以这样理解ico文件的头结构:
    1-6字节:ico文件头,表明ico文件中包含多少个icon图标
    7-22字节:ico文件结构头,主要说明图像数据的偏移量
    而19至22字节的偏移量则是我们整个单或多ico图标ico文件的头结构。

    那么我们来将理解转换代码:

    type WinIcon struct {
    	fileHeader *winIconFileHeader // 文件头
    	icos       []winIconStruct    // icon 头结构
    	data       []byte             // 所有ico文件数据
    }
    
    type winIconHeader struct {
    	ReservedA  uint16 // 保留字段,始终为 '0x0000'
    	FileType   uint16 // 图像类型:'0x0100' 为 ico,'0x0200' 为 cur
    	ImageCount uint16 // 图像数量:至少为 '0x0100' 即 1个图标
    }
    
    type winIconStruct struct {
    	Width         uint8  // 图像宽度
    	Height        uint8  // 图像高度
    	Palette       uint8  // 调色板颜色数,不使用调色版为 '0x00'
    	ReservedB     uint8  // 保留字段,始终为 '0x00'
    	ColorPlanes   uint16 // 在ico中,指定颜色平面,'0x0000' 或则 '0x0100'
    	BitsPerPixel  uint16 // 在ico中,指定每像素的位数,如:'0x2000' 32bit
    	ImageDataSize uint16 // 图像数据的大小,单位字节
    	ImageOffset   uint32 // 图像数据的偏移量
    }
    

    下一节文章会讲到如何读取ico文件

    展开全文
  • 自己提取的Windows98和XP下的经典图标,做一些APP的时候如果需要复古风可以采用,里面还附加了ico图标裁剪工具,可以根据需要裁剪图标大小。
  • 之前在前端设计实现了一个生成ico图标的功能,然而后来经过用户的反馈才发现,之前生成的ico图标的编码格式,其实只能在网站等地方使用,如果在windows桌面上使用,就会提示找不到ico图标文件,错误提示如下所示。...

    之前在前端设计实现了一个生成ico图标的功能,然而后来经过用户的反馈才发现,之前生成的ico图标的编码格式,其实只能在网站等地方使用,如果在windows桌面上使用,就会提示找不到ico图标文件,错误提示如下所示。

     这个错误确实是百思不得其解,我以为只要图片的后缀是ico的,windows系统就能够认可,然而事实是,windows的桌面ico对它内部的编码格式是有很严格要求的。也就是说,windows桌面图标使用的ico文件,不是从png或者jpg直接演化而来的。

    因此从网上找到了一个思路,也就是先将任何图像变成bmp格式的,因为bmp格式保存的就是实际的像素值和每个像素的内容。然后再将bmp格式后缀改成ico就能够被windows系统所识别了。所以我们可以将普通图像显示在canvas中,然后getimagedata获取到图像的每个像素内容,然后通过代码,以bmp格式的形式,来将每个像素放入到规定的编码格式中,并且附加上数据头等等一些指示符,就可以自己拼接出一个完整的bmp编码文件,然后变成ico后缀就搞定了。大概的思路就是这样,因为实际上自己拼接出图像文件的编码并不是太简单,当然也不难,开源的资源也很多。

    在线ICO图标制作生成,图片转换ICO图标Pro版icon-default.png?t=LA92https://www.butterpig.top/icopro

     所以这个工具现在可以选择是将图片转换成普通网站使用的ico图标,还是windows专用的标准ico图标格式。并且因为windows桌面图标是通过bmp演化而来,所以实际上这个ico的文件大小,其实居然是和他的宽高尺寸完全相关的,大家可以自己去这个工具体验一下。

    展开全文
  • vc提取EXE或DLL中的资源,比如 图标
  • 苹果桌面图标ico全集

    2012-04-09 13:55:40
    涵盖苹果电脑系统所有ico图标 windows系统可以直接更换
  • win11 图标 icon

    2022-04-18 07:50:20
    windows11 中的所有图标,icon
  • Mico是用于从多个图像创建Windows图标的命令行工具。 Sico是用于将图标拆分回单独图像的命令行工具。
  • 适用于 Windows 10 的 Git 图标 Windows 10 文件夹图标风格的 Git 存储库图标。 我最终还可能包含 Windows 7 和 8 以及 Mac OS X 的图标。 安装 下载 git.ico 将 git.ico 放在不会被删除的位置。 我推荐在 C:/...
  • windows图标文件打包

    2021-08-24 17:59:23
    .ico 酷炫图标文件打包带走
  • 给你400个.ico图标文件.zip 图标各类有 windows 互联网 交通 其它 体育 办公 动物 卡通人物 太空 娱乐 建筑物 杂项 电脑 电子产品 水果 生活用品 游戏人物 绘图 水果 电视节目 音乐 食品 饮料..
  • IconMod从Windows可执行文件添加和删除图标组(.ico文件)。
  • ICOWindows图标文件格式,图标文件可以存储单个图案、多尺寸、多色板的图标文件。一个图标实际上是多张不同格式的图片的集合体,并且还包含了一定的透明区域。下面来看看具体的介绍吧。ico图标格式它是Windows的...
  • Go语言处理Windows系统的图标ICO文件(上) Go语言处理Windows系统的图标ICO文件(中) 将PNG或BMP转换为ICO文件 在前面的两章中,我们初探了ico文件的结构,并且完成了将ico文件中的bmp和png数据提取出来的功能,在本...
  • 最近搞前端web开发,需要展示常用相关文件图标以及点击下载,自己扣了一些win10常用图标,可用于html素材, 分享一下...图标样本请看 https://blog.csdn.net/tianbbs2008/article/details/120314073
  • WIndows 下所有ICon图标集合,包含48*48 32*32 16*16
  • 准备一个ico图标文件放在工程目录A,命名demo.ico 在目录A下新建一个文件,demo.rc,内容如下,注意前面加id,否则会报语法错误 id ICON "demo.ico" 用cmd或powershell进入目录A,执行: windres -i "demo.rc" -o...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,651
精华内容 5,860
关键字:

windows文件图标ico