0

我正在做的是使用 turbojpeg 读取灰度 jpeg,使用其数据创建 Gdiplus::Bitmap 并尝试使用 Gdiplus::Graphics 绘制它。一切都很好,直到我尝试绘制图像 - 我得到Unhandled exception at 0x74123193 in program.exe: 0xC0000005: Access violation reading location 0x04ac7848.Bitmap 显然是正确创建的 - 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 位。关于如何解决这个问题的任何想法?

4

2 回答 2

2

这里有几个问题:

  1. Jpeg 文件是包含压缩数据的复杂文件。您正在读取整个文件,并将其视为基本位图。这根本不可能工作(这类似于将 CD 放在老式黑胶留声机上,然后想知道为什么它没有发出任何/正确的声音)。
  2. 位图的步幅是一行像素和下一行像素之间的字节距离。
  3. 我不相信,即使 jpeg 数据是正确的,你的图像也会有 pixelformat PixelFormat8bppIndexed

修复上述第 2 点和第 3 点非常简单(使用正确的步幅和正确的像素格式)。修复第 1 点意味着您必须以理智的方式读取 JPEG 图像。

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

于 2013-08-09T15:47:33.047 回答
0

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

对于步幅参数。

所以试试,

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

于 2015-01-29T13:44:24.097 回答