▷ 图像格式简单解析(BMP,WebP,JPEG,PNG,GIF)

⌹ 365bet在线网投 ⏱️ 2026-01-28 14:43:22 👤 admin 👁️‍🗨️ 1484 ❤️ 528
图像格式简单解析(BMP,WebP,JPEG,PNG,GIF)

Bitmap位图

介绍

位图(Bitmap),又称栅格图或点阵图,是使用像素阵列来表示的图像。根据位深度,可将位图分为1、4、8、16、24及32位图像等。每个像素使用的信息位数越多,可用的颜色就越多,颜色表现就越逼真,相应的数据量越大。

BMP文件是微软公司所开发的一种交换和存储数据的方法。BMP格式的缺点是,要占用较大的存储空间,文件尺寸太大。

BMP文件结构

BMP文件存储结构的格式可以在Windows中的WINGDI.h文件中找到定义。

BMP文件总体上由4部分组成,分别是位图文件头、位图信息头、调色板和图像数据。

位图文件头

位图信息头

彩色表/调色板

位图数据

解析

BITMAPFILEHEADER文件头

用于描述 Windows 位图(Bitmap)文件的文件头信息,包含了图像类型、图像大小、图像数据存放地址和两个保留未使用的字段,其定义如下

typedef struct tagBITMAPFILEHEADER {

WORD bfType;

DWORD bfSize;

WORD bfReserved1;

WORD bfReserved2;

DWORD bfOffBits;

} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

bfType:这是一个 16 位无符号整数,用于标识文件类型。对于位图文件,这个值通常是0x4D42,其对应的 ASCII 码是BM。通过检查这个值,程序可以快速判断一个文件是否可能是位图文件

bfSize:这是一个 32 位无符号整数,表示位图文件的大小,单位是字节。这个值包含了文件头、信息头、颜色表(如果有)和像素数据的全部大小。例如,如果一个位图文件的bfSize值为1024字节,那么从文件开始到结束总共的数据量是 1024 字节。

bfOffBits:这是一个 32 位无符号整数,表示从文件头的起始位置到实际像素数据的偏移量,单位是字节。这个偏移量包括了文件头和信息头(以及可能存在的颜色表)的大小。

BITMAPINFOHEADER位图信息头

BITMAPINFOHEADER是 Windows 图形编程中用于描述位图(Bitmap)详细信息的一个关键结构体。它紧跟在BITMAPFILEHEADER之后,为程序提供了足够的信息来理解和处理位图的像素数据。

typedef struct tagBITMAPINFOHEADER{

DWORD biSize;

LONG biWidth;

LONG biHeight;

WORD biPlanes;

WORD biBitCount;

DWORD biCompression;

DWORD biSizeImage;

LONG biXPelsPerMeter;

LONG biYPelsPerMeter;

DWORD biClrUsed;

DWORD biClrImportant;

} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

字段名

大小(单位:字节)

描述

biSize

4

本结构的大小,在windows中,此字段的值总为28h字节=40字节

biWidth

4

BMP图像的宽度,单位像素

biHeight

4

biPlanes

2

总为0

biBitCount

2

BMP图像的色深,即一个像素用多少位表示,常见的有1、4、8、16、24和32,分别对应单色、16色、256色、16位高彩色、24位真彩色和32位增强型真彩色

biCompression

4

压缩方式,0表示不压缩,1表示RLE8压缩,2表示RLE4压缩,3表示每个像素值由指定的掩码决定

biSizeImage

4

BMP图像数据大小,必须是4的倍数,图像数据大小不是4的倍数时用0填充补足

biXPelsPerMeter

4

水平分辨率,单位像素/m

biYPelsPerMeter

4

垂直分辨率,单位像素/m

biClrUsed

4

BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为100h=256

biClrImportant

4

重要的颜色数,此值为0时所有颜色都重要,对于使用调色板的BMP图像来说,当显卡不能够显示所有颜色时,此值将辅助驱动程序显示颜色

彩色表/调色板(color table)

彩色表/调色板是是单色、16色和256色图像文件所特有的,相对应的调色板大小是2、16和256,调色板以4字节为单位,每4个字节存放一个颜色值,图像的数据是指向调色板的索引。

可以将调色板想象成一个数组,每个数组元素的大小为4字节,调色板的数据结构定义:

typedef struct tagRGBQUAD {

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD;

WebP

定义

WebP是由Google开发的一种现代图像格式,旨在提供更小的文件大小,同时保持较高的图像质量。它支持有损压缩和无损压缩,还支持透明背景(类似PNG)和动画(类似GIF)。

特点

压缩效率高

有损压缩比JPG文件小约25%~34%

无损压缩比PNG文件小约26%

支持透明背景(Alpha通道):无损和有损压缩都支持透明

支持动画:可以替代GIF格式

支持渐进加载(Progressive Decoding):提供更快的加载体验。

广泛支持:现代浏览器(如Chrome、Edge、Firefox、Safari等)都支持WebP

优点

高效压缩:相较JPG和PNG文件体积更小,节省带宽

多功能性:同时支持透明(类似PNG)、动画(类似GIF)和高质量压缩(类似JPG)。

提示网站性能:减少图像大小,提升页面加载速度。

下载链接

https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.4.0-windows-x64.zip

参考资料

https://developers.google.cn/speed/webp?hl=zh-cn

格式解析

RIFF文件格式

WebP文件格式基于RIFF(资源交换文件格式)文档格式

RIFF文件的基本元素是数据块。它由以下部分组成:

+++++++++++++++++++++

Chunk FourCC

+++++++++++++++++++++

Chunk Size

+++++++++++++++++++++

Chunk Payload

+++++++++++++++++++++

Chunk FourCC:32位

用于标识分块的四位ASCII代码

分块大小:32位

分块的大小,不包括此字段、区块标识符或填充

分块载荷:分块大小(字节)

数据载荷。如果Chunk Size(数据块大小)为奇数,则会添加一个填充字节(必须为0,以符合RIFF规范)。

注意:RIFF有一个惯例,即全大写的块FourCC是适用于任何RIFF文件格式的标准块,而特定于文件格式的FourCC全部采用小写形式。WebP不遵循此惯例。

WebP文件头

RIFF文件大小WEBP,统称为WebP文件头:WebP header,4个字节(RIFF),4个字节的文件大小,4个字节的标识(WEBP),总计12个字节。

https://developers.google.cn/speed/webp/docs/riff_container?hl=zh-cn

“RIFF”:32位

ASCII字符“R"”I"“F"”F"

文件大小:32位(uint32)

文件的大小(以字节为单位),从偏移量8开始。此字段的最大值为2^32减10字节,因此整个文件的大小不得超过4GiB减2字节。

“WEBP”:32位

ASCII字符“W"”E“”B""P"

WebP文件必须以包含FourCC"WEBP"的RIFF标头开头。标头中的文件大小是后续数据块的总大小加上“WEBP”FourCC的4字节。文件不应该在文件大小指定的数据后面包含任何数据。读取器可以解析此类文件,并忽略尾随数据。由于任何分块的大小都是偶数,因此RIFF标头给出的大小也是偶数。

JPEG

JPEG(Joint Photographic Experts Group)是同名专家小组开发的图像压缩技术标准,该标准由国际标准化组织(ISO)制订,是面向连续色调静止图像的一种压缩标准。JPEG格式是最常用的图像文件格式,后缀名为.jpg或.jpeg。其主要是采用预测编码(DPCM)、离散余弦变换(DCT)以及熵编码的联合编码方式,以去除冗余的图像和彩色数据,属于有损压缩格式,它能够将图像压缩在很小的存储空间,一定程度上会造成图像数据的损伤。

二进制文件

格式解析

JPEG文件头2字节 FF D8

FF D8标识JPEG文件头

APP0图像识别信息 FF E0

名称

字节数

值

说明

段标识

1

FF

段类型

1

E0

段长度

2

0010

如果有缩略图=16+3n

以下为段内容

交换格式

5

4A46494600

JFIF的ASCII码

主版本号

1

次版本号

1

密度单位

1

0=无单位;1=点数/英寸;2=点数/厘米

X像素密度

2

水平方向的密度

Y像素密码

2

垂直方向的密度

缩略图X像素

1

缩略图水平像素数目

缩略图Y像素

1

缩略图垂直像素数目

如果“缩略图X像素”和“缩略图Y像素”的值均>0,才有以下的数据

RGB缩略图

3xN

n=缩略图像素总数=缩略图X像素x缩略图Y像素

DQT定义量化表 FF DB

名称

字节数

值

说明

段标识

1

FF

段类型

1

DB

段长度

2

43

其值=3+n(当只有一个QT时)

以下为段内容

QT信息

1

0-3位

QT号

4-7位

QT精度(0=8bit,1字节;否则=16bit,2字节)

QT

n

n=64xQT精度的字节数

SOF0图像基本信息(帧图像起始块)FF C0

名称

字节数

值

说明

段标识

1

FF

段类型

1

C0

段长度

2

其值=8+组件数量x3

以下为段内容

样本精度

1

8

每个样本位数(大多数软件不支持12和16)

图片高度

2

图片宽度

2

组件数量

1

3

1=灰度图,3=YCbCr/YIQ彩色图,4=CMYK彩色图

组件ID

1

1=Y,2=Cb,3=Cr,4=I,5=Q

采样系数

1

0-3位:垂直采样系数4-7位:水平采样系数

量化表号

1

DHT定义huffman表 FF C4

名称

字节数

值

说明

段标识

1

FF

段类型

1

C4

段长度

2

其值=19+n(当只有一个HT表时)

HT信息

1

0-3位:HT号4位:HT类型,0=DC表,1=AC表 5-7位:必须=0

HT位表

16

这16个数的和应该<=256

HT值表

n

n=表头16个数的和

SOS扫描行开始 FF DA

名称

字节数

值

说明

段标识

1

FF

段类型

1

DA

段长度

2

000C

其值=6+2x扫描行内组件数量

扫描行内组件数量

1

3

必须>=1,<=4否则错误,通常=3

组件ID

1

1=Y,2=Cb,3=Cr,4=I,5=Q

Huffman表号

1

0-3位:AC表号(其值=0...3)4-7位:DC表号(其值=0...3)

剩余3个字节

3

忽略

EOI文件尾 FF D9

名称

字节数

值

段标识

1

FF

段类型

1

D9

PNG

PNG介绍

png是图像文件存储格式,其目的是试图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的“PNG‘s Not GIF",是一种位图文件存储格式。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可存储多到16位的α通道数据。PNG使用从LZ77派生的无损数据压缩算法。

PNG文件结构

PNG图像格式文件由一个8字节的PNG文件署名域和按照特定结构组织的3个以上的数据块(chunk)组成。

PNG定义了两种类型的数据块,一种是称为关键数据块(critical chunk),这是标准的数据块,另一种叫做辅助数据块(ancillary chunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。

PNG文件署名域

在PNG文件前8字节的PNG文件署名域用来识别该文件是不是PNG文件。该域的值是:

89 50 4e 47 0d 0a 1a 0a

PNG数据块

PNG文件中的每个数据块都由表1所示的4个域组成。

名称

字节数

说明

Length(长度)

4字节

指定数据块中数据域的长度

Chunk Type Code(数据块类型码)

4字节

数据块类型码由ASCII字母(A-Z和a-z)组成

Chunk Data(数据块数据)

可变长度

存储按照Chunk Type Code指定的数据

CRC(循环冗余检测)

4字节

存储用来检测是否有错误的循环冗余码

PNG文件中的关键数据块的4个标准数据块分别是文件数据块、调色板数据块、图像数据块、图像结束数据块。

数据块符号

数据块名称

多数据块

可选

位置限制

IHDR

文件头数据块

否

否

第一块

cHRM

基色和白色点数据块

否

是

在PLTE和IDAT之前

gAMA

图像Y数据块

否

是

在PLTE和IDAT之前

sBIT

样本有效位数据块

否

是

在PLTE和IDAT之前

PLTE

调色板数据块

否

是

在IDAT之前

bKGD

背景颜色数据块

否

是

在PLTE之后IDAT之前

hIST

图像直方图数据块

否

是

在PLTE之后IDAT之前

tRNS

图像透明数据块

否

是

在PLTE之后IDAT之前

oFFs

专用公共数据块

否

是

在IDAT之前

pHYs

物理像素尺寸数据块

否

是

在IDAT之前

sCAL

专用公共数据块

否

是

在IDAT之前

IDAT

图像数据块

是

否

与其他IDAT连续

tIME

图像最后修改时间数据块

否

是

无限制

tEXt

文本信息数据块

是

是

无限制

zTXt

压缩文本数据块

是

是

无限制

fRAc

专用公共数据块

是

是

无限制

glFg

专用公共数据块

是

是

无限制

glFt

专用公共数据块

是

是

无限制

glFx

专用公共数据块

是

是

无限制

IEND

图像结束数据

否

否

最后一个数据块

文件头数据块

文件头数据块的数据块类型码为IHDR,它包含有PNG文件中存储的图像数据的基本信息,并作为第一个数据块出现在PNG数据流中,而且一个PNG数据流中只能有一个文件头数据块。文件头数据块由13个字节组成,格式如下:

域的名称

字节数

说明

Width

4

图像宽度,以像素为单位

Height

4

图像高度,以像素为单位

Bit depth

1

图像深度:索引彩色图像:1,2,4或8灰度图像:1,2,4,8或16真彩色图像:8或16

ColorType

1

颜色类型:0:灰度图像2:真彩色图像3:索引彩色图像4:带α通道数据的灰度图像6:带α通道数据的真彩色图像

Compression method

1

压缩方法(LZ77派生算法)

Filter method

1

滤波器方法

Interlace method

1

隔行扫描方法:0:非隔行扫描1:Adam7

GIF

介绍

GIF的全称是Graphics Interchange Format,可译为图形交换格式,用于以超文本标志语言方式显示索引彩色图像。

文件格式

文件头是一个带有识别GIF格式数据流的数据块,用以区分早期版本和新版本

逻辑屏幕描述区定义了与图像数据相关的图像平面尺寸、彩色深度,并指明后面的调色板数据区属于全局调色板还是局部调色板。若使用的是全局调色板,则生成一个24bit的RGB全局调色板,其中一个基色占用一个字节。

调色板数据区。分通用调色板和局部调色板。其中通用调色板适用于文件中所有图像,局部调色板只适用于某一个图像。

图像数据区的内容有两类,一类是纯粹的图像数据,一类是用于特殊目的的数据块(包含专用应用程序代码和不可打印的注释信息)。在GIF89a格式的图像文件中,如果一个文件中包含多个图像,图像数据区将依次重复数据块序列。

结束标志区的作用主要是标记整个数据流的结束。

Header

在文件头中总包含着magic number数据,标识当前的文件类型,对于gif而言,它的前三个字节总是 0x47,0x49,0x46,而后三个字节标识当前gif的版本,可能是87a也可能是89a,这是header中包含的全部信息。

LogicScreenDescriptor

紧随Header之后的是LogicScreenDescriptor,这里包含了整个gif文件的全局信息,固定7个字节。

名称

字节个数

说明

宽

2

小端形式存储

高

2

同上

压缩字节

1

1位:全局颜色标识,如果存在则全局颜色表紧跟在LogicScreenDescriptor后面出现。2-4位:色表中每个颜色通道的位深,111即表示每个颜色通道允许的最大值为255,也就是7+1位所能表示的最大值。5位:排序标识,标识色表中的颜色是否经过排序,排序按颜色出现的次数从高至低,也就是说越重要的颜色排在更前面。6-8位:全局色表的个数,记为n,则颜色个数为2(n+1)

索引

1

背景色在全局表中的索引,全局色表存在时有效,当图像不能完全占满gif的实际大小时,应显示背景色

宽高比

1

一般不设置

Global Color Table

全局颜色表,只有当全局颜色标识为1时才存在;gif中颜色以rgb格式排序,也就是说每个颜色三字节,128个颜色则占用384字节。

Extension

在gif中还存在着很多扩展块,这些块的格式都是固定的。

[0x21][flag][info]?[subdata]?[0x00]

固定值[0x21]标识这是一个扩展块

[flag]标识当前扩展块的类型

[info]是可选的,携带了所需的额外信息,它的第一个字节表示后续有多少个字节的数据

[subdata]同样是可选的,这是携带的实际数据,它的第一个字节表示后续有多少个字节的数据,如果跳过这些字节后遇到的字节值不是0x00,那么这个字节表示的依然是后续的数据子块大小

固定值[0x00]标识块结束

Comment Extension

评论扩展,存储额外的文字数据。这些数据不能被感知,也就是与图像渲染无关,大部分解析器会跳过它。该扩展块以0x21,0xfe开始,其后跟数据子块(subdata);GIF只支持ASCII表中的字符,也就是一字节表示一字符,如果遇到不能打印的ASCII字符时,gif规范建议用空格(0x20)代替。

该扩展块建议始终在文件头或文件尾,不打扰到更重要的数据(图像或文本)的解析。

Graphic Control Extension

图形控制扩展,顾名思义包含了可以控制图形展示的信息,它的作用范围是此块出现后的第一个Image或Plain Text Extension,固定7字节,其中0x21,0xf9占用两个字节。

Image Descriptor

图像描述符,描述了当前图像的信息。遇到此块时则表示着一个Image的开始,固定10个字节,其中第一个字节始终是0x2c。

Local Color Table

本地色表,同全局色表,在本地色表标识为1时存在,如果不存在则使用全局色表。如果想要gif重现真彩色,可以利用本地色表的特性,将一个完整的图片切割的足够小,并对它们应用不同的色表,但这在大部分时候没有必要,因为这会增加整个gif的体积。

Image Data

图像数据紧跟在本地色表(不存在则跟随Image Descriptor)后,实际是经过压缩后的颜色索引。在gif编码中将图像中出现的所有颜色经过算法压缩至256色内,然后将每个颜色替换为在色表中最接近的颜色的索引,最后通过lzw算法将这些索引字节压缩。

Plain Text Extension

纯文本扩展,存放ASCII文本数据,这些文本需要被渲染到gif中,虽然大部分解析器都忽略它。此块包含15字节的固定信息,其后是可变长度的数据子块,用于存放文本数据。

Trailer

文件结尾,包含固定值0x3b

示例

获取图片宽高

#include

#include

#include "webp/decode.h"

//下载地址https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.4.0-windows-x64.zip

#pragma comment(lib, "libwebp.lib")

using namespace std;

struct LogicScreenDescriptor

{

short width;

short height;

UCHAR yasuo;

char index;

char widthAndHeight;

};

void printResolution(UINT32 width, UINT32 height)

{

cout << "分辨率为:" << width << "x" << height << endl;

}

void printResolutionLeve(UINT32 x, UINT32 y)

{

cout << "水平分辨率为:" << x << ";垂直分辨率为:" << y << endl;

}

void readGif(PCHAR buffer, size_t len)

{

cout << "当前是GIF文件" << endl;

LogicScreenDescriptor* lsd = (LogicScreenDescriptor*)buffer;

printResolution(lsd->width, lsd->height);

}

uint32_t bigToLittleEndian(uint32_t bigEndianValue) {

return ((bigEndianValue & 0xff) << 24) |

((bigEndianValue & 0xff00) << 8) |

((bigEndianValue & 0xff0000) >> 8) |

((bigEndianValue & 0xff000000) >> 24);

}

void readPNG(PCHAR buffer, size_t len)

{

cout << "当前是PNG文件" << endl;

uint32_t length = bigToLittleEndian(*(uint32_t*)buffer);

const char* chunkTypeCode = (const char*)(buffer + 4);

char* data = (char*)malloc(length);

if (data == nullptr)

return;

memcpy(data, buffer + 8, length);

uint32_t width = bigToLittleEndian(*(uint32_t*)data);

uint32_t height = bigToLittleEndian(*(uint32_t*)(data + 4));

printResolution(width, height);

free(data);

}

short swapEndian_short(short value) {

return ((value & 0xff) << 8) | ((value & 0xff00) >> 8);

}

void readJPG(PCHAR buffer, int len)

{

cout << "当前是JPG文件" << endl;

while (len > 0)

{

char seg[2] = {};

memcpy(seg, buffer, 2);

short length = swapEndian_short(*(short*)(buffer + 2));

char app0[] = { 0xFF, 0xE0 };

char sof0[] = { 0xff, 0xc0 };

if (memcmp(buffer, app0, 2) == 0)

{

short length = (*(short*)(buffer + 2));

const char* type = (const char*)(buffer + 4);

char* mversion = (buffer + 9);

char* sversion = (buffer + 10);

char* danwei = (buffer + 11);

short width = swapEndian_short((*(short*)(buffer + 12)));

short height = swapEndian_short((*(short*)(buffer + 14)));

printResolutionLeve(width, height);

}

else if (memcmp(buffer, sof0, 2) == 0)

{

short heigth = swapEndian_short((*(short*)(buffer + 5)));

short width = swapEndian_short((*(short*)(buffer + 7)));

printResolution(width, heigth);

}

len -= length;

buffer = buffer + length + 2;

}

}

void readBMP(PCHAR buffer, int len)

{

cout << "当前是BMP文件" << endl;

BITMAPFILEHEADER* bitmapFileHeader = (PBITMAPFILEHEADER)buffer;

PBITMAPINFOHEADER bitmapInfoHeader = (PBITMAPINFOHEADER)(buffer + sizeof(BITMAPFILEHEADER));

printResolution(bitmapInfoHeader->biWidth, bitmapInfoHeader->biHeight);

}

void readWebP(const uint8_t* buffer, int len)

{

cout << "当前是WebP文件" << endl;

int width, height;

WebPGetInfo(buffer, len, &width, &height);

printResolution(width, height);

}

int main()

{

std::string fileName = R"(C:\Users\stdio\AppData\Roaming\Tencent\WeMeet\Global\Data\DynamicResource\3e1fa3ae1923bb4bacdabc661bc53ec5\remote_control_privilege_elevate_guide\remote_control_privilege_elevate_guide_zh-cn.gif)";

fileName = R"(C:\Users\stdio\AppData\Roaming\kingsoft\office6\wpsassist\onlinetemplates\online\54b472eceb9de061adafdfa33b11780c_ds.png)";

fileName = R"(C:\Users\stdio\Documents\WXWork\1688854706571334\Cache\Image\2024-11\海报.png)";

fileName = R"(C:\Users\stdio\Documents\WXWork\1688854706571334\Cache\Image\2024-12\2.1每日一句 (1)(5).jpg)";

fileName = R"(C:\Users\stdio\Documents\WXWork\1688854706571334\Avator\2024-12\d8142a10d6690d8f96a979eee418051c.jpg)";

fileName = R"(C:\Users\stdio\AppData\Local\Packages\Microsoft.Windows.Search_cw5n1h2txyewy\AC\INetCache\LUF4768K\th0PBG8C9P.jpg)";

fileName = R"(C:\Users\stdio\AppData\Local\Packages\Microsoft.Windows.Search_cw5n1h2txyewy\AC\INetCache\DY0N0B04\thQOHNB4RX.jpg)";

fileName = R"(C:\Users\stdio\Documents\WXWork\1688854706571334\Cache\Image\2024-12\企业微信截图_17338795688595.jpg)";

fileName = R"(D:\Github\TrafficMonitor-master\TrafficMonitor\skins\皮肤06\background.bmp)";

fileName = R"(D:\Downloads\CppGuide-master\articles\imgs\zhyz7.webp)";

fileName = R"(D:\Downloads\CppGuide-master\articles\imgs\zhyz25.webp)";

FILE* file = nullptr;

fopen_s(&file, fileName.c_str(), "rb");

if (file)

{

cout << "当前文件:" << fileName << endl;

fseek(file, 0, SEEK_END);

long len = ftell(file);

fseek(file, 0, SEEK_SET);

PCHAR buffer = (PCHAR)malloc(len);

if (buffer == nullptr)

return 1;

size_t rlen = fread(buffer, 1, len, file);

fclose(file);

char gif89a[] = "GIF89a";

size_t gif89aCount = sizeof(gif89a);

char pngFileHead[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};

size_t pngFileHeadCount = sizeof(pngFileHead);

char jpgFileHead[] = { 0xff, 0xd8};

size_t jpgFileHeadCount = sizeof(jpgFileHead);

char bmpFileHead[] = { 0x42, 0x4d };

size_t bmpFileHeadCount = sizeof(bmpFileHead);

char webpFileHead[] = { 'R', 'I', 'F', 'F' };

size_t webpFileHeadCount = sizeof(webpFileHead);

if (memcmp(buffer, gif89a, gif89aCount) == 0)

{

readGif(buffer + gif89aCount, len - gif89aCount);

}

else if (memcmp(buffer, pngFileHead, pngFileHeadCount) == 0)

{

readPNG(buffer + pngFileHeadCount, len - pngFileHeadCount);

}

else if (memcmp(buffer, jpgFileHead, jpgFileHeadCount) == 0)

{

readJPG(buffer + jpgFileHeadCount, len - jpgFileHeadCount);

}

else if (memcmp(buffer, bmpFileHead, bmpFileHeadCount) == 0)

{

readBMP(buffer, len);

}

else if (memcmp(buffer, webpFileHead, webpFileHeadCount) == 0)

{

readWebP((const uint8_t*)buffer, len);

}

else

{

cout << "未知文件" << endl;

}

free(buffer);

}

}

◈ 相关文章

头茬韭菜什么人不能吃?营养专家为你解析
⌹ 365app最新版安卓下载

▷ 头茬韭菜什么人不能吃?营养专家为你解析

⏱️ 11-04 👁️‍🗨️ 7559
须奰的意思和含义解释
⌹ 365bet在线网投

▷ 须奰的意思和含义解释

⏱️ 07-22 👁️‍🗨️ 8309
阴阳师翅膀面具锥刀
⌹ 365bet足球网投

▷ 阴阳师翅膀面具锥刀

⏱️ 07-05 👁️‍🗨️ 922