参考博客: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;
}