[英]C# draw bitmap from integer
我必須從整數值繪制圖像。 它們存儲在List<int>[]
。 該列表包含5081個數組,每個數組具有2048個值。 每個值都在0-1000之間,並且int是一個像素的顏色,因此它是灰度。
我知道如何用setpixel做到這一點,但這太慢了。
for (int y = 0; y < channelId.Length; y++) {
for (int x = 0; x < channelId[y].Count; x++) {
int myColor = (channelId[y].ElementAt(x) * 255) / 1000;
if (myColor > 255) {
myColor = 255;
} else if (myColor < 0) {
myColor = 0;
}
bmp.SetPixel(x, y, Color.FromArgb(myColor, myColor, myColor));
}
}
我知道這里也有類似的問題,如何更快地繪制位圖,但是它們已經有了位圖。 我必須從我的價值觀中得出印象。
如果您不想不安全地進行操作,則可以這樣做(假設32bppArgb
):
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var bmpData = bmp.LockBits(rect, ImageLockMode.WriteOnly, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
for (var y = 0; y < channelId.Length; y++)
{
var scanLineSize = channelId[y].Count*4;
var rgb = new byte[scanLineSize];
int idx = 0;
// Convert the whole scanline
foreach (var id in channelId[y])
{
rgb[idx] = rgb[idx+1] = rgb[idx+2] = (byte)(id*255/1000);
rgb[idx+3] = 255;
idx += 4;
}
// And copy it in one pass
System.Runtime.InteropServices.Marshal.Copy(rgb, 0, ptr, scanLineSize);
ptr += bmpData.Stride;
}
bmp.UnlockBits(bmpData);
如果不夠快,則可以在內存中完成位圖的整個轉換,並一次性復制整個數組。 但是,這在內存方面的效率不是很高,並且對於要移動的數據量來說應該“足夠快”。
只是為了好玩,一口氣:
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var bmpData = bmp.LockBits(rect, ImageLockMode.WriteOnly, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int idx = 0;
var rgb = new byte[channelId[0].Count * 4 * channelId.Length];
foreach (var id in channelId.SelectMany(t => t))
{
rgb[idx] = rgb[idx+1] = rgb[idx+2] = (byte)(id*255/1000);
rgb[idx+3] = 255;
idx += 4;
}
System.Runtime.InteropServices.Marshal.Copy(rgb, 0, ptr, rgb.Length);
bmp.UnlockBits(bmpData);
除了提高內存效率,您還需要確保數組中的所有List<int>
包含相同數量的元素,並且位圖的Stride
與width*4
相同。 它應該用於2048個元素,但您永遠不會知道。
BitmapData bitmapData = bmp.LockBits(
new Rectangle(0, 0, channelId[0].Count, channelId.Length),
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb
);
unsafe{
ColorARGB* startingPosition = (ColorARGB*) bitmapData.Scan0;
for (int y = 0; y < channelId.Length; y++) {
for (int x = 0; x < channelId[y].Count; x++) {
int myColor = (channelId[y].ElementAt(x) * 255) / 1000;
if (myColor > 255) {
myColor = 255;
} else if (myColor < 0) {
myColor = 0;
}
ColorARGB* position = startingPosition + j + i * channelId[0].Count;
position->A = 255;
position->R = myColor;
position->G = myColor;
position->B = myColor;
}
}
bmp.UnlockBits(bitmapData);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.