• 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;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    涉及函数: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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    校验文件完整性

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
  • 相关阅读:
    Strongswan:gcrypt-ikev2/rw-cert测试浅析
    第八章:Springmvc中web.xml配置文件
    PaddlePaddle飞浆搭建和机器学习文字识别
    GUI-Guider软件使用
    电脑重装系统u盘文件被隐藏要怎么找出来
    【JAVASE】带你了解面向对象三大特性之一(继承)
    诊断DLL——周立功模板生成dll文件
    利用commit理解镜像构成
    正则表达式?: ?= ?! 的用法详解
    代码随想录阅读笔记-哈希表【两个数组的交集】
  • 原文地址:https://blog.csdn.net/CAir2/article/details/126726749