WICBitmapSource.CopyPixels 到 GDI 位图 Scan0
我修改了 C# IWICBitmapSource .CopyPixels 接口允许数组封送和传递指针:
void CopyPixels(
WICRect prc,
uint cbStride,
uint cbBufferSize,
[Out]
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
byte[] pbBuffer
);
new void CopyPixels(
WICRect prc,
uint cbStride,
uint cbBufferSize,
IntPtr pbBuffer
);
我这样调用
public static Bitmap FromWic(IWICBitmapSource source) {
Guid format;
source.GetPixelFormat(out format);
PixelFormat gdiFormat = ConversionUtils.GetPixelFormat(format);
uint w, h;
source.GetSize(out w, out h);
Bitmap b = new Bitmap((int)w, (int)h, gdiFormat);
BitmapData bd = b.LockBits(new Rectangle(0, 0, (int)w, (int)h),
ImageLockMode.ReadWrite, b.PixelFormat);
try {
//Copy unmanaged-to-unmanaged
source.CopyPixels(
new WICRect { X = 0, Y = 0, Width = (int)w, Height = (int)h },
(uint)bd.Stride, (uint)(bd.Stride * bd.Height), bd.Scan0);
} finally {
b.UnlockBits(bd);
}
return b;
}
它代码执行没有错误,并且所有宽度,高度,步长和缓冲区大小值是正确的,但位图保持黑色,就好像 WIC 从未接触过它一样。
有什么想法为什么会发生这种情况吗? .NET 编组有问题吗?
I've modified the C# IWICBitmapSource.CopyPixels interface to allow both array marshaling and passing a pointer:
void CopyPixels(
WICRect prc,
uint cbStride,
uint cbBufferSize,
[Out]
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]
byte[] pbBuffer
);
new void CopyPixels(
WICRect prc,
uint cbStride,
uint cbBufferSize,
IntPtr pbBuffer
);
I'm calling it like this
public static Bitmap FromWic(IWICBitmapSource source) {
Guid format;
source.GetPixelFormat(out format);
PixelFormat gdiFormat = ConversionUtils.GetPixelFormat(format);
uint w, h;
source.GetSize(out w, out h);
Bitmap b = new Bitmap((int)w, (int)h, gdiFormat);
BitmapData bd = b.LockBits(new Rectangle(0, 0, (int)w, (int)h),
ImageLockMode.ReadWrite, b.PixelFormat);
try {
//Copy unmanaged-to-unmanaged
source.CopyPixels(
new WICRect { X = 0, Y = 0, Width = (int)w, Height = (int)h },
(uint)bd.Stride, (uint)(bd.Stride * bd.Height), bd.Scan0);
} finally {
b.UnlockBits(bd);
}
return b;
}
The code executes without errors, and all the width, height, stride, and buffer size values are correct, but the bitmap remains black, as if WIC never touched it.
Any ideas why this could be happening? Is there something wrong with the .NET marshalling?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来WPF使用代理方法将数据复制到非托管内存。基于此,我找到了解决方案。下面的代码可以工作并且应该非常高效。
请注意,我修改了 IWICBitmapSource_CopyPixels_Proxy dllimport 以使用 IWICBitmapSource 而不是 SafeMILHandle,并将 ref Int32Rect 修改为 IntPtr,以便我可以合法地传递 IntPtr.Zero (如果我传递一个要复制的矩形,我会收到 HRESULT 错误 - 而且我知道我的结构是值,我在其他 CopyPixels 调用中使用它。
It seems that WPF uses a proxy method to copy data to unmanaged memory. Based on that, I found a solution. The following code works and should be extremely efficient.
Note that I modified the IWICBitmapSource_CopyPixels_Proxy dllimport to use IWICBitmapSource instead of SafeMILHandle, and I modified ref Int32Rect to IntPtr, so that I could legally pass IntPtr.Zero (I get an HRESULT error if I pass in a rectangle to copy - and I know my stucture is value, I use it in other CopyPixels calls.