目前正致力于在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.
请建议。
请告诉我是否遗漏了任何代码....包括在形成问题时。
感谢。
答案 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指针,这会导致崩溃。