仅读取文件解析文件头获取图片宽高信息
CimageSizeUtils.h
#pragma once
#include <windows.h>
//图片类型
enum CImageType
{
CImage_unknown = 0,
CImage_bmp = 1,
CImage_gif = 2,
CImage_jpg = 3,
CImage_png = 4,
CImage_max = 5
};
//图片尺寸
typedef struct _IMAGE_SIZE
{
DWORD dwWidth;
DWORD dwHeight;
CImageType imageType;
_IMAGE_SIZE() :dwWidth(0), dwHeight(0), imageType(CImage_unknown) {};
}IMAGE_SIZE;
class CimageSizeUtils
{
public:
static CImageType GetImageType(LPCTSTR lpFilePath);
static bool GetImageSize(LPCTSTR lpFilePath, IMAGE_SIZE& size);
private:
static bool GetJpgSize(HANDLE hFile, IMAGE_SIZE& size);
static bool GetPngSize(HANDLE hFile, IMAGE_SIZE& size);
static bool GetGifSize(HANDLE hFile, IMAGE_SIZE& size);
static bool GetBmpSize(HANDLE hFile, IMAGE_SIZE& size);
};
CimageSizeUtils.cpp
#include "CimageSizeUtils.h"
#define MAKEDWORD(_0, _1, _2, _3) (((DWORD)((BYTE)(_3)) << 24) | ((DWORD)((BYTE)(_2)) << 16) | ((DWORD)((BYTE)(_1)) << 8) | ((DWORD)((BYTE)(_0))))
//PNG图片使用
#pragma pack (1)
typedef struct _PNG_IHDR
{
struct {
BYTE data3;
BYTE data2;
BYTE data1;
BYTE data0;
}Width; //图像宽度(大头字节序),以像素为单位
struct {
BYTE data3;
BYTE data2;
BYTE data1;
BYTE data0;
}Height; //图像高度(大头字节序),以像素为单位
BYTE Depth; //图像深度:
//索引彩色图像:1,2,4或8
//灰度图像:1,2,4,8或16
//真彩色图像:8或16
BYTE ColorType; // 颜色类型:
//0:灰度图像, 1,2,4,8或16
//2:真彩色图像,8或16
//3:索引彩色图像,1,2,4或8
//4:带α通道数据的灰度图像,8或16
//6:带α通道数据的真彩色图像,8或16
BYTE CompressionMethod;
BYTE FilterMethod;
BYTE InterlaceMethod; //隔行扫描方法: 0:非隔行扫描 1: Adam7(由Adam M.Costello开发的7遍隔行扫描方法)
_PNG_IHDR()
{
ZeroMemory(this, sizeof(_PNG_IHDR));
}
}PNG_IHDR, * PPNG_IHDR;
#pragma pack()
//GIF图片使用
#pragma pack (1)
typedef struct _IMAGE_GIF
{
BYTE Magic[3]; //文件头标识
BYTE Version[3]; //版本号
WORD Width; //宽度
WORD Height; //高度
BYTE Background; //背景色
BYTE aspect; //宽高比
BYTE ColorIndex[0x10][3];
_IMAGE_GIF()
{
ZeroMemory(this, sizeof(_IMAGE_GIF));
}
}IMAGE_GIF, * PIMAGE_GIF;
#pragma pack()
//JPG图片使用
#pragma pack (1)
typedef struct _IMAGE_JPG
{
BYTE Type[2]; //start of frame
struct {
BYTE data1;
BYTE data0;
}Length; //长度(大头字节序)
BYTE Precision; //精度, 每像素多少位
struct {
BYTE data1;
BYTE data0;
}Height; //图像高度(大头字节序),以像素为单位
struct {
BYTE data1;
BYTE data0;
}Width; //图像宽度(大头字节序),以像素为单位
BYTE ComponentsIndex; //组件数量(应为 1 或 3)
BYTE Components[3][3];
_IMAGE_JPG()
{
ZeroMemory(this, sizeof(_IMAGE_JPG));
}
}IMAGE_JPG, * PIMAGE_JPG;
#pragma pack()
//BMP图片使用
#pragma pack (1)
typedef struct _IMAGE_BMP
{
BYTE bfType[2];
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
struct BITMAP_INFO
{
DWORD biSize;
DWORD biWidth;
DWORD biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImages;
DWORD biXPelsPerMeter;
DWORD biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
}bitmapInfo;
_IMAGE_BMP()
{
ZeroMemory(this, sizeof(_IMAGE_BMP));
}
}IMAGE_BMP, * PIMAGE_BMP;
#pragma pack()
CImageType CimageSizeUtils::GetImageType(LPCTSTR lpFilePath)
{
CHAR szFileBuf[1024] = { 0 };
DWORD dwNumberOfBytesRead = 0;
HANDLE hFile = INVALID_HANDLE_VALUE;
const CHAR HEAD_BMP[2] = { 0x42, 0x4D };
const CHAR HEAD_JPG[2] = { 0xFF, 0xD8 };
const CHAR HEAD_GIF[3] = { 0x47, 0x49, 0x46 };
const CHAR HEAD_PNG[4] = { 0x89, 0x50, 0x4E, 0x47 };
hFile = CreateFile(
lpFilePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
return CImageType::CImage_unknown;
}
do
{
//检查是不是JPG
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_JPG), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_JPG, sizeof(HEAD_JPG)))
{
return CImageType::CImage_jpg;
}
//检查是不是GIF
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_GIF), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_GIF, sizeof(HEAD_GIF)))
{
return CImageType::CImage_gif;
}
//检查是不是BMP
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_GIF), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_BMP, sizeof(HEAD_BMP)))
{
return CImageType::CImage_bmp;
}
//检查是不是PNG
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_PNG), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_PNG, sizeof(HEAD_PNG)))
{
return CImageType::CImage_png;
}
} while (FALSE);
if (INVALID_HANDLE_VALUE != hFile)
{
::CloseHandle(hFile);
}
return CImageType::CImage_unknown;
}
bool CimageSizeUtils::GetImageSize(LPCTSTR lpFilePath, IMAGE_SIZE& size)
{
CHAR szFileBuf[1024] = { 0 };
DWORD dwNumberOfBytesRead = 0;
HANDLE hFile = INVALID_HANDLE_VALUE;
bool bResult = false;
const CHAR HEAD_BMP[2] = { 0x42, 0x4D };
const CHAR HEAD_JPG[2] = { 0xFF, 0xD8 };
const CHAR HEAD_GIF[3] = { 0x47, 0x49, 0x46 };
const CHAR HEAD_PNG[4] = { 0x89, 0x50, 0x4E, 0x47 };
hFile = CreateFile(
lpFilePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
return false;
}
do
{
//检查是不是JPG
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_JPG), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_JPG, sizeof(HEAD_JPG)))
{
size.imageType = CImageType::CImage_jpg;
return GetJpgSize(hFile, size);
}
//检查是不是GIF
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_GIF), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_GIF, sizeof(HEAD_GIF)))
{
size.imageType = CImageType::CImage_gif;
return GetGifSize(hFile, size);
}
//检查是不是BMP
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_GIF), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_BMP, sizeof(HEAD_BMP)))
{
size.imageType = CImageType::CImage_bmp;
return GetBmpSize(hFile, size);
}
//检查是不是PNG
::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN);
if (!::ReadFile(hFile, szFileBuf, sizeof(HEAD_PNG), &dwNumberOfBytesRead, NULL))
{
break;
}
if (0 == memcmp(szFileBuf, HEAD_PNG, sizeof(HEAD_PNG)))
{
size.imageType = CImageType::CImage_png;
return GetPngSize(hFile, size);
}
} while (FALSE);
if (INVALID_HANDLE_VALUE != hFile)
{
::CloseHandle(hFile);
}
return bResult;
}
bool CimageSizeUtils::GetJpgSize(HANDLE hFile, IMAGE_SIZE& size)
{
IMAGE_JPG jpgTag;
DWORD dwNumberOfBytesRead = 0;
DWORD dwFilePointer = 0;
DWORD dwFileSize = ::SetFilePointer(hFile, 0x00, NULL, FILE_END);
if (2 != ::SetFilePointer(hFile, 0x02, NULL, FILE_BEGIN))
{
return false;
}
while (dwFilePointer < dwFileSize)
{
//读书数据标签头
if (!::ReadFile(hFile, &jpgTag, 4, &dwNumberOfBytesRead, NULL))
{
break;
}
//得到数据标签长度
WORD wLength = MAKEWORD(jpgTag.Length.data0, jpgTag.Length.data1);
WORD wReadSize = wLength - 2;
//遇到SOF0 帧开始, 读取数据信息解析
if (0xFF == jpgTag.Type[0] && 0xC0 == jpgTag.Type[1])
{
//防止缓冲区读入溢出(万一有人篡改数据)
DWORD njpgTagSize = sizeof(jpgTag);
if (wReadSize > njpgTagSize - 4)
{
wReadSize = njpgTagSize - 4;
}
if (!::ReadFile(hFile, ((LPBYTE)&jpgTag) + 4, wReadSize, &dwNumberOfBytesRead, NULL))
{
break;
}
size.dwWidth = MAKEWORD(jpgTag.Width.data0, jpgTag.Width.data1);
size.dwHeight = MAKEWORD(jpgTag.Height.data0, jpgTag.Height.data1);
return true;
break;
}
//遇到SOS开始扫描则结束
if (0xFF == jpgTag.Type[0] && 0xDA == jpgTag.Type[1])
{
break;
}
else
{
dwFilePointer = ::SetFilePointer(hFile, wReadSize, NULL, FILE_CURRENT);
}
}
return true;
}
bool CimageSizeUtils::GetPngSize(HANDLE hFile, IMAGE_SIZE& size)
{
CHAR szFileBuf[1024] = { 0 };
DWORD dwNumberOfBytesRead = 0;
if (0x10 != ::SetFilePointer(hFile, 0x10, NULL, FILE_BEGIN))
{
return false;
}
if (::ReadFile(hFile, &szFileBuf, sizeof(PNG_IHDR), &dwNumberOfBytesRead, NULL))
{
PPNG_IHDR pData = (PPNG_IHDR)szFileBuf;
size.dwWidth = MAKEDWORD(pData->Width.data0, pData->Width.data1, pData->Width.data2, pData->Width.data3);
size.dwHeight = MAKEDWORD(pData->Height.data0, pData->Height.data1, pData->Height.data2, pData->Height.data3);
return true;
}
return false;
}
bool CimageSizeUtils::GetGifSize(HANDLE hFile, IMAGE_SIZE& size)
{
CHAR szFileBuf[1024] = { 0 };
DWORD dwNumberOfBytesRead = 0;
if (0 != ::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN))
{
return false;
}
if (::ReadFile(hFile, &szFileBuf, sizeof(IMAGE_GIF), &dwNumberOfBytesRead, NULL))
{
PIMAGE_GIF pData = (PIMAGE_GIF)szFileBuf;
size.dwWidth = pData->Width;
size.dwHeight = pData->Height;
return true;
}
return false;
}
bool CimageSizeUtils::GetBmpSize(HANDLE hFile, IMAGE_SIZE& size)
{
CHAR szFileBuf[1024] = { 0 };
DWORD dwNumberOfBytesRead = 0;
if (0 != ::SetFilePointer(hFile, 0x00, NULL, FILE_BEGIN))
{
return false;
}
if (::ReadFile(hFile, &szFileBuf, sizeof(IMAGE_BMP), &dwNumberOfBytesRead, NULL))
{
PIMAGE_BMP pData = (PIMAGE_BMP)szFileBuf;
size.dwWidth = pData->bitmapInfo.biWidth;
size.dwHeight = pData->bitmapInfo.biHeight;
return true;
}
return false;
}
main.cpp
#include "CimageSizeUtils.h"
#include <iostream>
int main()
{
IMAGE_SIZE imageSize;
CimageSizeUtils::GetImageSize(LR"(C:\Users\FlameCyclone\Downloads\logo.png)", imageSize);
return 0;
}