• Windows C++ 判断文件是否是图片格式的方法。


    一、通过后缀名去判断。

    bool IsImageByTail(const std::wstring &path)
    {
        std::wstring file_exten;
        size_t pos = path.rfind(L'.');
        if (pos == std::wstring::npos)
            return false;
        file_exten = path.substr(pos, std::wstring::npos);
        //把file_exten转小写
        for (size_t u = 0; u < file_exten.length();u++)
        {
            if (file_exten[u] >= L'A' && file_exten[u]<='Z')
            {
                file_exten[u] += L'a' - L'A';
            }
        }
        if (file_exten == L".jpg" || file_exten == L".tif"
            || file_exten == L".png" || file_exten == L".bmp"
            || file_exten == L".gif" || file_exten == L".ico")
            return true;
        return false;
    }

                优点:效率快,不用读取整个文件,无依赖,理解简单。

                缺点:不准确,用户可以通过修改后缀名蒙混过关。 

                 

    二、通过文件头判断

               我们知道,图片文件的文件头带有图片标记信息,常见的如下:

               JPEG (jpg),文件头:FFD8FF

               PNG (png),文件头:89504E47

               GIF (gif),文件头:47494638

               TIFF (tif),文件头:49492A00

               Windows Bitmap (bmp),文件头:424D

    bool IsImageByHead(const std::wstring &path)
    {
        //读取文件首部4个字节
        HANDLE hFile = CreateFile(path.c_str(), FILE_GENERIC_READ,      //  打开文件,获得文件读句柄
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,     //  共享方式打开,避免其他地方需要读写此文件
            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
        if (INVALID_HANDLE_VALUE == hFile)                              //  文件打开失败,返回错误值
            return false;
        BYTE data[4] = { 0 };
        DWORD readSize;
        bool ok=false;
        if(ReadFile(hFile, data, 4, &readSize, NULL))
        {
            if (readSize == 4)
            {
                if (data[0] == 0xFF && data[1]==0xD8 && data[2]==0xFF)
                {
                    ok = true;
                }
                else if (data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47)
                {
                    ok = true;
                }
                else if (data[0] == 0x47 && data[1] == 0x49 && data[2] == 0x46 && data[3] == 0x38)
                {
                    ok = true;
                }
                else if (data[0] == 0x49 && data[1] == 0x49 && data[2] == 0x2A && data[3] == 0x00)
                {
                    ok = true;
                }
                else if (data[0] == 0x42 && data[1] == 0x4D)
                {
                    ok = true;
                }
            }
        }
        CloseHandle(hFile);                                             //  关闭文件句柄,避免句柄泄露
        return ok;
    }

                优点:只需要文件读取函数,实现逻辑较简单。

                缺点:不准确,图片可能不完整,头部可能被伪造。

             

    三、严格的读取文件头,匹配内部的长度、宽度与文件大小,校验值等。

              这个算法偏复杂,需要对各类图片格式了如指掌,解析到位。

              这里不实现了。

                

              优点:准确无误。

              缺点:实现难度复杂,需要对各类图片了如指掌。

    四、通过GDI+来解析图片,判断图片的有效性

              感谢GDI+,帮助我们做了解析图片的格式与内容。并提供Image类统一管理。

              

    #include <gdiplus.h>
    #pragma comment(lib,"gdiplus.lib")
    bool IsImageByGDI(const std::wstring &path)
    {
        Gdiplus::Image image_src(path.c_str());
        Gdiplus::Status status = image_src.GetLastStatus();
        if (status != Gdiplus::Ok)
        {
            return false;
        }
        GUID guid;
        if (image_src.GetRawFormat(&guid) != Gdiplus::Ok)
        {
            return false;
        }
        if (guid == Gdiplus::ImageFormatGIF || guid == Gdiplus::ImageFormatJPEG || guid == Gdiplus::ImageFormatPNG
            || guid == Gdiplus::ImageFormatBMP || guid == Gdiplus::ImageFormatIcon || guid == Gdiplus::ImageFormatTIFF)
        {
            return true;
        }
        return false;
    }

             优点:准确无误、实现简单。

             缺点:需要依赖GDI+库,效率比较低。

             当然,如果我们不需要准确的判断的话。上述函数可以结合使用。

             如:bool isPic  =  IsImageByTail  ||   IsImageByHead。可以解决无后缀的图片的判断,并且依赖较低。

                    bool isPic  =  IsImageByTail  ||   IsImageByGDI 。可以通过后缀名提前过滤一遍,加快效率。

            另外:上述函数稍微修改下,也可以返回具体的图片类型(到底是jpg呢还是png呢)。

            另外:GDI+真的是不错的东西!

            本来想更新一个GDI+系列的,感觉关注的人不多,动力不足。

            从零开始学习GDI+ (一)我的第一个GDI+程序

             

                 

                

  • 相关阅读:
    App调试的几个命令实践【转】
    解决sdk更新时候报错 http://dl-ssl.google.com/android上不去,链接拒绝
    fastjson序列化排序问题
    Java中的四种引用
    equal&==&hashcode
    ThreadPool线程池的关注点
    JVM的本地方法栈
    JVM的堆分配
    JVM的类装载子系统
    JVM的数据类型
  • 原文地址:https://www.cnblogs.com/xuhuajie/p/11721912.html
Copyright © 2020-2023  润新知