3 回答
TA贡献2021条经验 获得超8个赞
关于你的问题4:在ImageLockMode.UserInputBuffer能给你可能被引用到的那些记忆大量的分配过程的控制BitmapData对象。
如果选择创建自己的BitmapData对象,则可以避免使用Marshall.Copy。然后,您将不得不将此标志与另一个标志结合使用ImageLockMode。
注意这是一项复杂的业务,特别是与Stride和PixelFormat有关。
这是一个示例,将一张照片中的24bbp缓冲区的内容放入一个BitMap中,然后另一张照片将其读回到另一个缓冲区中,并将其读入48bbp。
Size size = Image.Size;
Bitmap bitmap = Image;
// myPrewrittenBuff is allocated just like myReadingBuffer below (skipped for space sake)
// But with two differences: the buff would be byte [] (not ushort[]) and the Stride == 3 * size.Width (not 6 * ...) because we build a 24bpp not 48bpp
BitmapData writerBuff= bm.LockBits(new Rectangle(0, 0, size.Width, size.Height), ImageLockMode.UserInputBuffer | ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb, myPrewrittenBuff);
// note here writerBuff and myPrewrittenBuff are the same reference
bitmap.UnlockBits(writerBuff);
// done. bitmap updated , no marshal needed to copy myPrewrittenBuff
// Now lets read back the bitmap into another format...
BitmapData myReadingBuffer = new BitmapData();
ushort[] buff = new ushort[(3 * size.Width) * size.Height]; // ;Marshal.AllocHGlobal() if you want
GCHandle handle= GCHandle.Alloc(buff, GCHandleType.Pinned);
myReadingBuffer.Scan0 = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
myReadingBuffer.Height = size.Height;
myReadingBuffer.Width = size.Width;
myReadingBuffer.PixelFormat = PixelFormat.Format48bppRgb;
myReadingBuffer.Stride = 6 * size.Width;
// now read into that buff
BitmapData result = bitmap.LockBits(new Rectangle(0, 0, size.Width, size.Height), ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly, PixelFormat.Format48bppRgb, myReadingBuffer);
if (object.ReferenceEquals(result, myReadingBuffer)) {
// Note: we pass here
// and buff is filled
}
bitmap.UnlockBits(result);
handle.Free();
// use buff at will...
如果您使用ILSpy,则会看到此方法链接到GDI +,这些方法的帮助更加完整。
您可以通过使用自己的内存方案来提高性能,但是请注意,Stride可能需要进行一些调整才能获得最佳性能。
然后,您将可以例如分配巨大的虚拟内存映射的scan0并非常有效地blit它们。请注意,固定巨大的数组(尤其是少数数组)不会给GC造成负担,并且可以让您以完全安全的方式(或者如果您追求速度则不安全)来操纵字节/短路。
TA贡献2016条经验 获得超9个赞
我不确定您是否会按照自己的方式进行操作。也许有。似乎您走得太远了,所以您可能要尝试做一些比问题标题所暗示的要高级的事情...
但是,从字节数组创建位图的传统方法是:
using (MemoryStream stream = new MemoryStream(byteArray))
{
Bitmap bmp = new Bitmap(stream);
// use bmp here....
}
- 3 回答
- 0 关注
- 573 浏览
添加回答
举报