如何创建快速自定义像素格式

时间:2017-03-12 21:39:55

标签: c# performance image-processing pixel system.drawing

由于我要做的事情的要求,我需要有自己的像素自定义类。对于我有的每个像素:

byte red
byte green
byte blue
int brightness
int X
int Y

我需要坐标,所以我可以制作数组,它只包含我需要绘制的像素。例如,如果我有一条直线移动的线,我只想要一个像素的一维数组,我需要绘制;我不想扫描剩下的像素,所以我可以避免不必要的扫描。在我目前的情况下,我将有很多多边形,必须以特定的顺序和特定的方式应用于图像。这将是一个游戏引擎,所以我必须尽量避免扫描像素,这无论如何都不会被使用。

但是,像Pixel这样的数据,会让事情变得缓慢。真的很慢。可能比创建Bitmaps的默认像素格式慢几百倍。除此之外,对像素进行更改本身也非常缓慢。

如何在每个像素中存储颜色,亮度和坐标的所有信息的同时,如何加快像素的创建和操作? 一个附带问题:是否有一个地方可以解释System.Drawing中的像素格式是如何工作的?

2 个答案:

答案 0 :(得分:0)

您可以重载[]来访问单例的内部数组,而不是以跨步模式访问的许多类实例。因此pixels[n].X将访问“像素”对象的内部数组或结构数组,然后快速获取X.

在结构中包含所有像素属性。使用像素类的索引来访问该结构。将该结构放在结构数组中。

使用StructLayoutAttribute将struct打包到适当的大小(和对齐方式),以获得更好的访问性能。

重新排序struct中的字段,以便能够读取(可能)较少数量的内存操作中的所有数据。

如果在函数中使用所有属性,则可能很有用。

代替结构数组,您可以使用非托管内存区域(由游戏引擎的分配器给出)用于所有像素,并通过更大的块读取以消除转换开销。(可以在1或2个固有负载中读取整个结构)说明)。使用指针和不安全的上下文更新更大的块(或累积临时结果)。

int X
int Y
int brightness
byte red
byte green
byte blue
byte alpha

应该能够适合16字节的结构边界。

如果要与颜色分开使用坐标,或者总是不使用某些属性,则应将其分离并用作基元数组,以便为​​下一个像素迭代一个较少的步幅元素。如果你要在一些空间搜索算法中使用X和Y而不是颜色,你可以将X和Y重新组合在另一个数组(不仅仅是类)中,每个结构都有X和Y,因此颜色属性不会得到以你的方式表现。

访问X时,

public class MyPixel{
  public float X{
                get{ /* access an array or 
                        array of structs or 
                        unmanaged memory */} 
                set{ /* same */}
  }

  // for unrolled loops
  public static void BatchUpdateXY(float[] source,int pixelStart,int pixelEnd)
  { /* copy from source */}
}

即使setter getter的性能为%50,因此您可以尝试使用pixels.X[i]并拥有最大速度(使用数组或非托管内存)。

在上层解决方案中使用纯C ++数组添加新像素变得更难,因此您可能需要C ++方面的向量或类似容器。

答案 1 :(得分:0)

实际上,绘图功能正在以优化的方式进行(并且可能是硬件加速)。不确定为什么需要自己的绘图功能(即计算每个像素以形成对角线或多边形)。

也许,您可以只存储需要连接的点,而不是计算和存储每个像素,然后调用绘图函数来完成工作?

如果你真的需要自己做,可能最好的方法是创建一个大小宽度*高度的32位RGBA整数的数组或向量,这样处理起来要快得多。

而且..实际上是一个位图,所以你可以做的就是在内存中创建一个位图,使用标准绘图函数在该位图上绘制线条(这是一个带有RGBA点的数组)。一次遍历所有像素将比在一维数组中执行此操作要快得多,这需要进行搜索,保持排序和增长。

您甚至可以使用TransparentBlt()移动所有非零'像素一样到你的图像。