使用openCV VC ++读取文件I / O.

时间:2013-10-27 03:51:39

标签: c++ image visual-c++ image-processing

目前正致力于在VC ++中打开/读取图像。

我在互联网上遇到的一些例子使用了像ReadFile这样的Windows.h I / O例程......但是声明中似乎存在不一致。 (并不是说我在挑战Windows ......可能不是我的理解)

这就是我所拥有的。

//So i have this function to load file
BYTE* LoadFile ( int* width, int* height, long* size, LPCWSTR bmpfile )
{
  BITMAPFILEHEADER bmpheader;
  BITMAPINFOHEADER bmpinfo;
  DWORD bytesread = 0;
      HANDLE file = CreateFile ( bmpfile , GENERIC_READ, FILE_SHARE_READ,NULL, 
                              OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
  if ( NULL == file )
    return NULL;

  if ( ReadFile ( file, &bmpheader, sizeof ( BITMAPFILEHEADER ),&bytesread, 
                      NULL ) == false )
  {
    CloseHandle ( file );
    return NULL;
  } 
 .
 .
 .
 return appropriate value;
}

现在,ReadFile API函数在WinBase.h中声明如下

WINBASEAPI BOOL WINAPI ReadFile(
  _In_         HANDLE hFile,
  _Out_        LPVOID lpBuffer,
  _In_         DWORD nNumberOfBytesToRead,
  _Out_opt_    LPDWORD lpNumberOfBytesRead,
  _Inout_opt_  LPOVERLAPPED lpOverlapped
);

在MSDN示例中...... 他们这样称呼这个函数。

ReadFile(hFile, chBuffer, BUFSIZE, &dwBytesRead, NULL)

其中期望“bytesRead”是一种out参数。所以它给了我读取的字节数。

但是在我的代码中..它正在给出错误消息。     'ReadFile':无法将参数4从'LPDWORD *'转换为'LPDWORD'

所以我刚刚将bytesRead初始化为0并按值传递。(这是错误的......但只是检查它是否有效)。

然后它给出了这个例外

Unhandled exception at 0x774406ae in ImProc.exe: 0xC0000005: Access violation 
writing location 0x00000000.

请建议。

请告诉我是否遗漏了任何代码....包括在形成问题时。

感谢。

2 个答案:

答案 0 :(得分:0)

LPDWORD bytesread = 0更改为DWORD bytesread = 0

我使用以下代码运行您的代码:

#include <windows.h>
#include <cstdio>

BYTE* LoadFile(int* width, int* height, long* size, LPCWSTR bmpfile)
{
    DWORD bytesread = 0;
    BITMAPFILEHEADER bmpheader;
    BITMAPINFOHEADER bmpinfo;

    HANDLE file = CreateFile(bmpfile , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if (file == NULL)
        return NULL;

    if (ReadFile(file, &bmpheader, sizeof(BITMAPFILEHEADER), &bytesread, NULL) == FALSE)
    {
        CloseHandle(file);
        return NULL;
    }

    printf("Bytes Read: %d", bytesread);
    CloseHandle(file);
    return NULL;
}

int main()
{
    int width = 0;
    int height = 0;
    long size = 0;

    LoadFile(&width, &height, &size, L"C:/Users/Brandon/Desktop/Foo.bmp");
}

打印14。

但是,如果您想要一个更便携的解决方案,那么以下内容对您也有用吗?

Bitmap.h:

#ifndef BITMAP_H_INCLUDED
#define BITMAP_H_INCLUDED

#include <iostream>
#include <fstream>
#include <vector>
#include <stdexcept>

class Bitmap
{
    private:
        std::vector<std::uint8_t> Pixels;
        std::uint32_t width, height;
        std::uint16_t BitsPerPixel;

    public:
        Bitmap(const char* FilePath);
        void Save(const char* FilePath);
};
#endif // BITMAP_H_INCLUDED

Bitmap.cpp:

Bitmap::Bitmap(const char* FilePath) : Pixels(0), width(0), height(0), BitsPerPixel(0)
{
    std::fstream hFile(FilePath, std::ios::in | std::ios::binary);
    if (!hFile.is_open()) throw std::invalid_argument("Error: File Not Found.");

    hFile.seekg(0, std::ios::end);
    int Length = hFile.tellg();
    hFile.seekg(0, std::ios::beg);
    std::vector<std::uint8_t> FileInfo(Length);
    hFile.read(reinterpret_cast<char*>(FileInfo.data()), 54);

    if(FileInfo[0] != 'B' && FileInfo[1] != 'M')
    {
        hFile.close();
        throw std::invalid_argument("Error: Invalid File Format. Bitmap Required.");
    }

    if (FileInfo[28] != 24 || FileInfo[28] != 32)
    {
        hFile.close();
        throw std::invalid_argument("Error: Invalid File Format. 24 or 32 bit Image Required.");
    }

    BitsPerPixel = FileInfo[28];
    width = FileInfo[18] + (FileInfo[19] << 8);
    height = FileInfo[22] + (FileInfo[23] << 8);
    std::uint32_t PixelsOffset = FileInfo[10] + (FileInfo[11] << 8);
    std::uint32_t size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
    Pixels.resize(size);

    hFile.seekg (PixelsOffset, std::ios::beg);
    hFile.read(reinterpret_cast<char*>(Pixels.data()), size);
    hFile.close();
}

void Bitmap::Save(const char* FilePath)
{
    std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
    if (!hFile.is_open()) throw std::invalid_argument("Error: File not found.");

    std::uint32_t Trash = 0;
    std::uint16_t Planes = 1;
    std::uint32_t biSize = 40;
    std::uint16_t Type = 0x4D42;
    std::uint32_t compression = 0;
    std::uint32_t PixelsOffsetBits = 54;
    std::uint32_t size = ((width * BitsPerPixel + 31) / 32) * 4 * height;
    std::uint32_t bfSize = 54 + size;

    hFile.write(reinterpret_cast<char*>(&Type), sizeof(Type));
    hFile.write(reinterpret_cast<char*>(&bfSize), sizeof(bfSize));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(std::uint32_t));
    hFile.write(reinterpret_cast<char*>(&PixelsOffsetBits), sizeof(PixelsOffsetBits));
    hFile.write(reinterpret_cast<char*>(&biSize), sizeof(biSize));
    hFile.write(reinterpret_cast<char*>(&width), sizeof(width));
    hFile.write(reinterpret_cast<char*>(&height), sizeof(height));
    hFile.write(reinterpret_cast<char*>(&Planes), sizeof(Planes));
    hFile.write(reinterpret_cast<char*>(&BitsPerPixel), sizeof(BitsPerPixel));
    hFile.write(reinterpret_cast<char*>(&compression), sizeof(compression));
    hFile.write(reinterpret_cast<char*>(&size), sizeof(size));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(std::uint32_t));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(std::uint32_t));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(std::uint32_t));
    hFile.write(reinterpret_cast<char*>(&Trash), sizeof(std::uint32_t));
    hFile.write(reinterpret_cast<char*>(Pixels.data()), size);
    hFile.close();
}

答案 1 :(得分:0)

问题在于你如何声明bytesread。

应该是:

DWORD bytesread = 0;

LPDWORD bytesread = 0;

将其读作“(长)指向DWORD的指针”,相当于:

DWORD *bytesread = 0;

当按值传递时,您传入的是NULL指针,这会导致崩溃。