下面的代码是画了一个6000*10000的随机灰度图,你可以参考 // 初始化6000*10000个0-99的数字 int width = 6000, height = 10000; var max = 100; var rnd = new Random(); var data = Enumerable.Range(0, width * height).Select(_ => rnd.Next(max)).ToArray();// 8bit索引方式位图,设置灰度调色板 var fmt = PixelFormat.Format8bppIndexed; var bmp = new Bitmap(width, height, fmt); var palette = bmp.Palette; for (var i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } bmp.Palette = palette;// 把数据映射到256灰度,unsafe填充到位图 var step = 255f / (max - 1); var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, fmt); unsafe { var p = (byte*)bmpData.Scan0; for (var i = 0; i < data.Length; i++) { *p = (byte)(step * data[i]); p++; } } bmp.UnlockBits(bmpData); bmp.Save(@"e:\x.png");
lockbits移动块~
但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了
但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了换个64位的系统,内存就没问题了。另外换用bitmapdata操作。
但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了分批画 如10000个画一次,如果还溢出,则每10000个画完就保存本地磁盘,再重新打开画。(虽然我觉得直接画也不该溢出的)
// 初始化6000*10000个0-99的数字
int width = 6000, height = 10000;
var max = 100;
var rnd = new Random();
var data = Enumerable.Range(0, width * height).Select(_ => rnd.Next(max)).ToArray();// 8bit索引方式位图,设置灰度调色板
var fmt = PixelFormat.Format8bppIndexed;
var bmp = new Bitmap(width, height, fmt);
var palette = bmp.Palette;
for (var i = 0; i < 256; i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = palette;// 把数据映射到256灰度,unsafe填充到位图
var step = 255f / (max - 1);
var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, fmt);
unsafe
{
var p = (byte*)bmpData.Scan0;
for (var i = 0; i < data.Length; i++)
{
*p = (byte)(step * data[i]);
p++;
}
}
bmp.UnlockBits(bmpData);
bmp.Save(@"e:\x.png");
/// 从指定的路径保存成一维数组
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private double[] Read(string path)
{
double[] arrary = new double[bmpHeight * bmpWidth];
int row = 0;//行
int col = 0;//lie FileStream fs;
fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader sr;
sr = new StreamReader(fs);
while (!sr.EndOfStream)
{
string[] arr = sr.ReadLine().Split(',');
col = arr.Length;
for (int x = 0; x < col - 1; x++)
{
if (arr[x] != "")
{
arrary[row*bmpWidth+x] = Convert.ToDouble(arr[x]);
}
}
row++;
}
sr.Close();
fs.Close(); return arrary;
}
这是我的数据读取方式
var fmt = PixelFormat.Format8bppIndexed;
var bmp = new Bitmap(width, height, fmt);
var palette = bmp.Palette;
for (var i = 0; i < 256; i++)
{
palette.Entries[i] = Color.FromArgb(i, i, i);
}
bmp.Palette = palette;var step = 255f;
var count = height; // 任务计数器
var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, fmt);
using (var sr = new StreamReader(@"e:\data.txt"))
{
var ptr = bmpData.Scan0;
while (!sr.EndOfStream)
{
// 每次读一行数据,在其它线程执行SetData,之后计数器减一
var line = sr.ReadLine();
var p = ptr;
Task.Factory.StartNew(() => {
SetData(p, step, line); Interlocked.Decrement(ref count);
});
ptr += bmpData.Stride;
}
}// 等待所有任务完成(计数器清零)
while (count > 0) { Thread.Sleep(20); }bmp.UnlockBits(bmpData);
bmp.Save(@"e:\x.png");// 处理一行数据,把数据映射到256灰度,unsafe填充到位图
private unsafe void SetData(IntPtr ptr, float step, string line)
{
var p = (byte*)ptr;
var data = line.Split(',');
for (var i = 0; i < data.Length; i++)
{
*p = (byte)(step * float.Parse(data[i]));
p++;
}
}
改为 File.OpenRead(path);
嗯 不过代码这里有点小问题吧
Interlocked.Decrement(ref count);这句放到ptr += bmpData.Stride;后面 就行啦