GDI +:绘制位图时出现未处理的异常

时间:2013-08-09 15:16:18

标签: c++ winapi gdi+

我正在做的是使用turbojpeg读取greyscale jpeg,使用其数据创建Gdiplus :: Bitmap并尝试使用Gdiplus :: Graphics绘制它。一切都很好,直到我尝试绘制图像 - 我得到Unhandled exception at 0x74123193 in program.exe: 0xC0000005: Access violation reading location 0x04ac7848.显然正确地创建了位图 - Bitmap::lastResult == Ok。我的代码如下所示:

// Initialize GDI+.
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// creating program window

Graphics = new Gdiplus::Graphics(GetDC(hwnd));
Graphics->SetCompositingMode( Gdiplus::CompositingModeSourceCopy );
Graphics->SetCompositingQuality( Gdiplus::CompositingQualityHighSpeed );
Graphics->SetPixelOffsetMode( Gdiplus::PixelOffsetModeNone );
Graphics->SetSmoothingMode( Gdiplus::SmoothingModeNone );
Graphics->SetInterpolationMode( Gdiplus::InterpolationModeDefault );

// loading jpeg using turbojpeg
std::vector<unsigned char> data;

int width, 
    height;

std::ifstream ifs(filename.c_str(), std::ios::in | std::ios::binary);

long begin,end;
begin = (long)ifs.tellg();
ifs.seekg (0, std::ios::end);
end = (long)ifs.tellg();
long size = end - begin;
ifs.seekg(0);

std::vector<char> jpegdata(size);
unsigned char* dataptr = reinterpret_cast<unsigned char*>(&jpegdata[0]);
ifs.read(&jpegdata[0], jpegdata.size());
tjhandle handle = tjInitDecompress();
tjDecompressHeader(handle, dataptr, jpegdata.size(), &width, &height);
data.resize(width * height);
tjDecompress2(handle, dataptr, jpegdata.size(), &data[0], width, width, height, TJPF_GRAY, 0);
tjDestroy(handle);

// creating Gdiplus::Bitmap
Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(width, 
                                height, 
                                width * 8, 
                                PixelFormat8bppIndexed, 
                                (BYTE*)&data[0]);

// drawing bitmap
Graphics->DrawImage(bitmap, 0, 0);

抛出异常
Graphics->DrawImage(bitmap, 0, 0);

这种行为的原因是什么?我做错了什么?

edit

设置正确的步幅为user1837009建议修复了异常。

有一个原因我使用这个特殊的构造函数 - 我需要尽可能使原始图像数据,灰度,每像素8位进行一些转换。而且我很确定在调用data之后我在tjDecompress2变量中的含义。不幸的是,似乎没有支持8位灰度像素格式,只有PixelFormat16bppGrayScale,这是16位。关于如何解决这个问题的任何想法?

2 个答案:

答案 0 :(得分:2)

这里有几个问题:

  1. Jpeg文件是包含压缩数据的复杂文件。您正在读取整个文件,并将其视为基本位图。这根本不可能奏效(它类似于将CD放在老式的乙烯基留声机上,并想知道为什么它没有发出任何/正确的声音)。
  2. 位图的步幅是一行像素与下一行像素之间的距离。
  3. 即使jpeg数据正确,我也不相信你的图片会有像素格式PixelFormat8bppIndexed
  4. 修复上述两点和三点非常简单(使用右侧步幅和右侧像素格式)。要修复点1意味着您必须以理智的方式读取JPEG图像。

    然而,当然有一个更简单的解决方案:使用Bitmap.Bitmap(const WCHAR*, BOOL),它将直接加载JPEG图像,而不必处理与“如何解码JPEG图像有关的任何事情。”

答案 1 :(得分:0)

读取:https://msdn.microsoft.com/en-us/library/windows/desktop/ms536315(v=vs.85).aspx

for stride param。

所以试试,

Gdiplus :: Bitmap bitmap = new Gdiplus :: Bitmap(width,                                 高度,                                 宽度,                                 PixelFormat8bppIndexed,                                 (BYTE )及数据[0]);