栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

C#

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C#

立即可用的代码

public class DirectBitmap : IDisposable{    public Bitmap Bitmap { get; private set; }    public Int32[] Bits { get; private set; }    public bool Disposed { get; private set; }    public int Height { get; private set; }    public int Width { get; private set; }    protected GCHandle BitsHandle { get; private set; }    public DirectBitmap(int width, int height)    {        Width = width;        Height = height;        Bits = new Int32[width * height];        BitsHandle = GCHandle.Alloc(Bits, GCHandleType.Pinned);        Bitmap = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, BitsHandle.AddrOfPinnedObject());    }    public void SetPixel(int x, int y, Color colour)    {        int index = x + (y * Width);        int col = colour.ToArgb();        Bits[index] = col;    }    public Color GetPixel(int x, int y)    {        int index = x + (y * Width);        int col = Bits[index];        Color result = Color.FromArgb(col);        return result;    }    public void Dispose()    {        if (Disposed) return;        Disposed = true;        Bitmap.Dispose();        BitsHandle.Free();    }}

不需要

LockBits
SetPixel
。使用上述类可直接访问位图数据。

使用此类,可以将原始位图数据设置为32位数据。请注意,它是PARGB,它是预乘alpha。有关如何工作的更多信息,请参见Wikipedia上的Alpha合成,有关BLENDFUNCTION的MSDN文章上的示例,请参阅示例以了解如何正确计算Alpha。

如果预乘可能会使事情复杂化,请

PixelFormat.Format32bppArgb
改用。绘制时会发生性能下降的情况,因为它是在内部转换为的
PixelFormat.Format32bppPArgb
。如果在绘制之前不必更改图像,则可以在预乘之前完成工作,将其绘制到
PixelFormat.Format32bppArgb
缓冲区中,然后从那里进一步使用。

Bitmap
通过
Bitmap
属性公开访问标准成员。使用该
Bits
属性可以直接访问位图数据。

使用
byte
代替
int
原始像素数据

将的两个实例都更改

Int32
byte
,然后更改此行:

Bits = new Int32[width * height];

对此:

Bits = new byte[width * height * 4];

使用字节时,格式为Alpha / Red / Green /
Blue。每个像素占用4个字节的数据,每个通道一个。GetPixel和SetPixel函数将需要进行相应的重新设计或删除。

使用上述课程的好处

  • 仅用于处理数据的内存分配是不必要的;对原始数据所做的更改将立即应用于位图。
  • 没有其他要管理的对象。
    IDisposable
    就像一样实现
    Bitmap
  • 它不需要
    unsafe
    块。

注意事项

  • 固定的内存无法移动。为了使这种内存访问起作用,这是必需的副作用。这降低了垃圾收集器的效率(MSDN文章)。仅对需要性能的位图执行此操作,并
    Dispose
    在完成操作后确保对位图进行操作,以便可以取消固定内存。

通过
Graphics
对象访问

因为该

Bitmap
属性实际上是.NET
Bitmap
对象,所以使用
Graphics
该类执行操作很简单。

var dbm = new DirectBitmap(200, 200);using (var g = Graphics.FromImage(dbm.Bitmap)){    g.DrawRectangle(Pens.Black, new Rectangle(50, 50, 100, 100));}

性能比较

该问题询问性能,因此下面的表格应显示答案中提出的三种不同方法之间的相对性能。这是使用基于.NET Standard 2的应用程序和NUnit完成的。

* Time to fill the entire bitmap with red pixels *- Not including the time to create and dispose the bitmap- Best out of 100 runs taken- Lower is better- Time is measured in Stopwatch ticks to emphasize magnitude rather than actual time elapsed- Tests were performed on an Intel Core i7-4790 based workstation   Bitmap sizeMethod        4x4   16x16   64x64   256x256   1024x1024   4096x4096DirectBitmap  <1    2       28      668       8219        178639LockBits      2     3       33      670       9612        197115SetPixel      45    371     5920    97477     1563171     25811013* Test details *- LockBits test: Bitmap.LockBits is only called once and the benchmark      includes Bitmap.UnlockBits. It is expected that this      is the absolute best case, adding more lock/unlock calls      will increase the time required to complete the operation.


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/373372.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号