使用二进制确定图像文件的扩展名类型

时间:2014-10-13 23:10:34

标签: c++ image file visual-studio-2013 binary

我正在尝试编写一个函数来确定目录中的文件是否为gif / bmp / png / jpg扩展名。现在我想我已经正确编写了我的代码,直到列出目录中的文件并以二进制模式打开它们。

现在,我正在努力弄清楚如何确定图像的扩展名。现在我只专注于写我的“bool isGif();” function ...要确定文件是否是使用二进制文件的.gif扩展名,文件的前6个字节将包含GIF87a或GIF89a。那么,为此,我会将文件的前六个字节读入一个数组,然后将它们与包含“GIF87a”或“GIF89a”的数组进行比较,对吗?

以下是我尝试对此进行编码。它给了我2个警告,但没有错误,它在程序中运行正常,但它从不输出一个消息,该目录包含一个gif,我知道它确实如此,因为我把它放在那里......

getDir();

ifstream fin;

_finddata_t a_file;
intptr_t dir_handle;

dir_handle = _findfirst("*.*", &a_file);

//if (dir_handle == -1)
//{
    //return;
//}

while (_findnext(dir_handle, &a_file) == 0);
{
    fin.open(a_file.name, ios::in | ios::binary);

    if (!fin)
    {
        cout << endl << "Could not open the file."
            << " Attempting to open the next file." << endl;
        return false;
    }
    else
    {
        cout << "Files opened successfully."
            << " Processing through the directory." << endl;


            ifstream fl(a_file.name);
            fl.seekg(0, ios::end);
            size_t len = fl.tellg();
            char *ret = new char[len];
            fl.seekg(0, ios::beg);
            fl.read(ret, len);
            fl.close();

            char arr1[6] = { 'G', 'I', 'F', 8, 7, 'a' };
            char arr2[6] = { 'G', 'I', 'F', 8, 9, 'a' };

            if (ret == arr1 || arr2 )
            {
                cout << a_file.name << " has a .gif extension" << endl;
                return true;
            }


    }
}

好的,我想我现在已经接近了...这是对此问题很重要的更新/更改代码片段...我只是想尝试使用for循环来读取前6个字节到字符串,所以我可以比较这些位来确定它是否是一个gif,但我无法将字节输入字符串。

int i;
            int comp1, comp2;

            for (i = 0; i != 6; i++)
            {
                string gifStr;
                fin.read((char*)&a_file, i);

                gifStr(&a_file, i);
            }

            string gifStr1 = "GIF87a";
            string gifStr2 = "GIF89a";

            comp1 = strcmp( , gifStr1);

            if (comp1 == 0)
            {
                cout << a_file.name << " has a .gif extension" << endl;
            }

            comp2 = strcmp( , gifStr2);

            if (comp2 == 0)
            {
                cout << a_file.name << " has a .gif extension" << endl;
            }   

对不起,这个网站让我对这些回复和那些事情感到困惑......哈哈。

3 个答案:

答案 0 :(得分:1)

你可以查找你想要的每种图像类型的幻数。然后比较它们(类似),如下面的..它只有一些神奇的数字..我在C ++ 0x第一次出现时写了这个out ..可能有更好的方法,但下面应该给出一个粗略的想法..

int ValidImage(std::uint8_t* ImageBytes)
{
    const static std::vector<std::uint8_t> GIFBytesOne = { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 };
    const static std::vector<std::uint8_t> GIFBytesTwo = { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
    const static std::vector<std::uint8_t> PNGBytes = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
    const static std::vector<std::uint8_t> BMPBytes = { 0x42, 0x4D };
    const static std::vector<std::uint8_t> JPGBytes = { 0xFF, 0xD8, 0xFF };
    const static std::vector<std::uint8_t> JPEGBytes = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20 };
    const static std::vector<std::uint8_t> TIFFMonoChrome = { 0x0C, 0xED };
    const static std::vector<std::uint8_t> TIFFOne = { 0x49, 0x20, 0x49 };
    const static std::vector<std::uint8_t> TIFFTwo = { 0x49, 0x49, 0x2A, 0x00 };
    const static std::vector<std::uint8_t> TIFFThree = { 0x4D, 0x4D, 0x00, 0x2A };
    const static std::vector<std::uint8_t> TIFFFour = { 0x4D, 0x4D, 0x00, 0x2B };
    const static std::vector<std::uint8_t> CompressedTGA = {0x0, 0x0, 0xA, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
    const static std::vector<std::uint8_t> DeCompressedTGA = {0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

    const static std::array<std::vector<std::uint8_t>, 13> All = {
        GIFBytesOne, GIFBytesTwo, PNGBytes, BMPBytes,
        JPGBytes, JPEGBytes, TIFFMonoChrome, TIFFOne,
        TIFFTwo, TIFFThree, TIFFFour, CompressedTGA,
        DeCompressedTGA
    };

    int I = 0;
    for (const auto& it : All)
    {
        if (std::equal(it.begin(), it.end(), ImageBytes))
            return I;
        ++I;
    }
    return -1;
}

然后:

    std::fstream hFile(FilePath, std::ios::in | std::ios::binary);

    if (!hFile.is_open())
    {
        throw std::invalid_argument("File Not Found.");
    }

    std::uint8_t Header[18] = {0};
    hFile.read(reinterpret_cast<char*>(&Header), sizeof(Header));
    hFile.seekg(0, std::ios::beg);

    IMAGE_TYPE type = ValidImage(Header);

其中IMAGETYPE定义为:

enum IMAGE_TYPE {GIF = 0, PNG, BMP, JPG, JPEG, TIFF, TGA};

答案 1 :(得分:0)

罪魁祸首在这里:

if (ret == arr1 || arr2 )

你无法测试像这样的char数组是否相等。此外 - 测试本身是不正确的。首先 - 如果可以这样检查 - 您必须将其更改为:

if (ret == arr1 || ret == arr2 )

然而,仍然无法做到这一点,你必须做以下其中一项:

  • retarr1arr2转换为std::string
  • 使用strcmp
  • 一次测试数组1 char,循环

从您的评论和编辑到问题,您在这里可以做的最好的事情是阅读strings。甚至可以查看一些documentation

答案 2 :(得分:0)

以下代码的问题是它将整个文件加载到内存中,即使您只想检查几个字节。这很浪费,但留作练习。

ifstream fl(a_file.name);
fl.seekg(0, ios::end);
vector<char> ret(fl.tellg());
fl.seekg(0, ios::beg);
fl.read(&ret[0], ret.size());
fl.close();

static const vector<string> gif_ids = { "GIF87a", "GIF89a" };
bool is_gif = false;
for (const auto& id : gif_ids)
{
    // check size first because the file may contain less data than the id
    if (ret.size() >= id.size() && std::equal(id.begin(), id.end(), ret.begin()))
    {
        // it's a gif!
        is_gif = true;
        break;
    }
}
相关问题