获取图片尺寸(Win32, C++)

47 篇文章 0 订阅

仅读取文件解析文件头获取图片宽高信息

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;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值