1

目前正在使用 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”是一种输出参数。所以它给了我读取的字节数。

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

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

然后它给出了这个例外

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

请建议。

请告诉我是否错过了任何代码......包括在形成问题本身时。

谢谢。

4

2 回答 2

0

将 更改LPDWORD bytesread = 0DWORD 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。

但是,如果您想要一个更便携的解决方案,那么以下内容是否也适合您?

位图.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

位图.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();
}
于 2013-10-27T04:15:12.100 回答
0

问题在于您如何声明 bytesread。

它应该是:

DWORD bytesread = 0;

不是:

LPDWORD bytesread = 0;

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

DWORD *bytesread = 0;

当按值传递它时,你传递的是一个 NULL 指针,这会导致你的崩溃。

于 2013-10-27T04:28:10.600 回答