C++ 图片完整性校验

参考博客:https://blog.csdn.net/osmeteor/article/details/40299357
根据图片格式校验图片的完整性。支持png,bmp,jpg,gif
字节缓冲区管理,防止内存泄露

class CByteBuffer
{
public:
	CByteBuffer(size_t len)
	{
		m_length = len;
		m_byte = new byte[m_length];
		memset(m_byte, 0, m_length);
	}

	~CByteBuffer()
	{
		if (m_byte)
		{
			delete[]m_byte;
			m_byte = nullptr;
		}
	}
	byte* data(){ return m_byte; }
	byte operator[](size_t index){ return m_byte[index]; }
	size_t length(){ return m_length; }
private:
	size_t m_length;
	byte *m_byte;
};

涉及函数:int to hex

std::string toHex(int num)
{
	if (num == 0)
		return "0";

	std::string res = "";
	std::string hex[16] = { "0", "1", "2", "3", "4", "5", "6", "7",
		"8", "9", "a", "b", "c", "d", "e", "f" };

	unsigned int num2 = num;//无论正负,全部转换成无符号整型
	while (num2)
	{
		res = hex[num2 % 16] + res;//取余即是最低位
		num2 /= 16;
	}
	return res;
}

校验文件完整性

bool IsCompletedImage(std::string strFileName)
{
	struct _stat info;
	_stat(strFileName.c_str(), &info);
	FILE *fp = fopen(strFileName.c_str(), "r+b");
	if (fp == nullptr)
	{
		return false;
	}


	CByteBuffer buffer(info.st_size);
	size_t iread = fread(buffer.data(), 1, buffer.length(), fp);
	if (iread != buffer.length())
	{
		return false;
	}
	//jpg png图是根据最前面和最后面特殊字节确定. bmp根据文件长度确定
	//png检查
	if (buffer[0] == 137 && buffer[1] == 80 && buffer[2] == 78 && buffer[3] == 71 && buffer[4] == 13
		&& buffer[5] == 10 && buffer[6] == 26 && buffer[7] == 10)
	{
		if (buffer[buffer.length() - 5] == 68 && buffer[buffer.length() - 4] == 174 && buffer[buffer.length() - 3] == 66
			&& buffer[buffer.length() - 2] == 96 && buffer[buffer.length() - 1] == 130)
			return true;
		//有些情况最后多了些没用的字节
		for (int i = buffer.length() - 1; i > buffer.length() / 2; --i)
		{
			if (buffer[i - 5] == 68 && buffer[i - 4] == 174 && buffer[i - 3] == 66
				&& buffer[i - 2] == 96 && buffer[i - 1] == 130)
				return true;
		}
	}
	else if (buffer[0] == 66 && buffer[1] == 77)//bmp
	{
		//bmp长度
		//整数转成字符串拼接
		std::string str = toHex(buffer[5]) + toHex(buffer[4])
			+ toHex(buffer[3]) + toHex(buffer[2]);

		std::stringstream ss;
		ss << std::hex << str;
		int iLength = 0; //16进制数转成整数
		ss >> iLength;
		if (iLength <= buffer.length()) //有些图比实际要长
			return true;
	}
	else if (buffer[0] == 71 && buffer[1] == 73 && buffer[2] == 70 && buffer[3] == 56)//gif
	{
		//标准gif 检查00 3B
		if (buffer[buffer.length() - 2] == 0 && buffer[buffer.length() - 1] == 59)
			return true;
		//检查含00 3B
		for (int i = buffer.length() - 1; i > buffer.length() / 2; --i)
		{
			if (buffer[i] != 0)
			{
				if (buffer[i] == 59 && buffer[i - 1] == 0)
					return true;
			}
		}
	}
	else if (buffer[0] == 255 && buffer[1] == 216) //jpg
	{
		//标准jpeg最后出现ff d9
		if (buffer[buffer.length() - 2] == 255 && buffer[buffer.length() - 1] == 217)
			return true;
		else
		{
			//有好多jpg最后被人为补了些字符也能打得开, 算作完整jpg, ffd9出现在近末端
			//jpeg开始几个是特殊字节, 所以最后大于10就行了 从最后字符遍历
			//有些文件会出现两个ffd9 后半部分ffd9才行
			for (int i = buffer.length() - 2; i > buffer.length() / 2; --i)
			{
				//检查有没有ffd9连在一起的
				if (buffer[i] == 255 && buffer[i + 1] == 217)
					return true;
			}
		}
	}
	return false;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值