我需要将 vtkImageData
打印到打印机 CDC
。
在查看 this 之后,我想到了这样做和 this .
一种是使用vtk接口(interface),设置一个CImage
的像素,然后将CImage绘制到CDC
:
CImage c_image;
c_image.Create(dims[0], dims[1], 24);
for (int y=0; y<dims[1]; y++)
{
for (int x=0; x<dims[0]; x++)
{
float r = i_image->GetScalarComponentAsFloat(extent[0] + x, extent[2] + dims[1] - y - 1, 0, 0);
float g = i_image->GetScalarComponentAsFloat(extent[0] + x, extent[2] + dims[1] - y - 1, 0, 1);
float b = i_image->GetScalarComponentAsFloat(extent[0] + x, extent[2] + dims[1] - y - 1, 0, 2);
c_image.SetPixelRGB(x, y, r, g, b);
}
}
另一种方法是使用 CreateDIBSection()
然后将位图附加到 CImage
并将 CImage
绘制到 CDC
:
HBITMAP hBitmap = nullptr;
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = dims[0];
bmih.biHeight = dims[1];
bmih.biPlanes = 1;
bmih.biBitCount = i_image->GetNumberOfScalarComponents() * 8;
bmih.biCompression = BI_RGB ;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 10;
bmih.biYPelsPerMeter = 10;
bmih.biClrUsed =0;
bmih.biClrImportant =0;
BITMAPINFO dbmi;
ZeroMemory(&dbmi, sizeof(dbmi));
dbmi.bmiHeader = bmih;
dbmi.bmiColors->rgbBlue = 0;
dbmi.bmiColors->rgbGreen = 0;
dbmi.bmiColors->rgbRed = 0;
dbmi.bmiColors->rgbReserved = 0;
void* bits = nullptr;
// Create DIB
hBitmap = CreateDIBSection(i_printer_dc_ptr->GetSafeHdc(), &dbmi, DIB_RGB_COLORS, &bits, NULL, 0);
if (hBitmap == nullptr) {
::MessageBox(NULL, __T("Could not load the desired image image"), __T("Error"), MB_OK);
return;
}
::memcpy(bits, i_image->GetScalarPointer(), i_image->GetNumberOfScalarComponents() * dims[0] * dims[1]);
c_image.Attach(hBitmap);
两者都需要复制所有字节一次,然后打印到 CDC
。有没有办法避免这种中间复制,直接将字节打印到 CDC
?或者只是创建一个指向现有字节而不复制它们的 HBITMAP
?
最佳答案
是的,您可以使用 SetDIBitsToDevice()
将位直接复制到 DC 的函数。
注意关于对齐的限制:
The scan lines must be aligned on a DWORD except for RLE-compressed bitmaps.
一个常见的问题是生成的位图最终颠倒(因为位图在 Windows 中是自下而上的)。如果发生这种情况,请在 BITMAPINFO
结构中取反高度。
关于c++ - 有没有办法在不复制所有像素的情况下将现有的像素数组转换为 BITMAP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19302807/