一个txt图像的灰度数据。C#如何快速读取并且画出图像

有时想起 2014-10-29 09:12:13
数据格式是这样的。
...全文
532 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_26685991 2017-04-12
  • 打赏
  • 举报
回复
楼主 我现在也遇到你的问题 我的灰度值已经在二维数组里存在内存上 我想通过C#的picturebox显示出内存里的这些灰度值形成的图像 具体怎么实行啊
有时想起 2014-11-01
  • 打赏
  • 举报
回复
引用 16 楼 github_22161131 的回复:
[quote=引用 15 楼 u011672494 的回复:] 嗯 不过代码这里有点小问题吧 Interlocked.Decrement(ref count);这句放到ptr += bmpData.Stride;后面 就行啦
那个是为了线程工作完成后计数器减一的,放外面就不对了,会导致unlockbits的时候工作线程可能还没有完全结束[/quote] 我这边试了 放里面 count的值始终是height。 因此一直在循环内 放在外面才是正常的!
winnowc 2014-11-01
  • 打赏
  • 举报
回复
引用 15 楼 u011672494 的回复:
嗯 不过代码这里有点小问题吧 Interlocked.Decrement(ref count);这句放到ptr += bmpData.Stride;后面 就行啦
那个是为了线程工作完成后计数器减一的,放外面就不对了,会导致unlockbits的时候工作线程可能还没有完全结束
有时想起 2014-11-01
  • 打赏
  • 举报
回复
引用 13 楼 github_22161131 的回复:
代码优化了下,用了并发,我这里是8s左右(数据是随机生成的6000*10000的csv,0.0-1.0间的浮点数)。而且因为边读边处理,内存占用小了很多。

int width = 6000, height = 10000;

// 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;

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++;
    }
}
嗯 不过代码这里有点小问题吧 Interlocked.Decrement(ref count);这句放到ptr += bmpData.Stride;后面 就行啦
有时想起 2014-10-31
  • 打赏
  • 举报
回复
引用 11 楼 github_22161131 的回复:
我感觉读取文件的地方还有优化的空间,那段代码release模式我这里(CPU 2.66GHz,内存1600MHz)执行的时间是5s左右。如果不包括生成数据,时间只需2.3s
/// <summary> /// 从指定的路径保存成一维数组 /// </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; } 这是我的数据读取方式
winnowc 2014-10-31
  • 打赏
  • 举报
回复
我感觉读取文件的地方还有优化的空间,那段代码release模式我这里(CPU 2.66GHz,内存1600MHz)执行的时间是5s左右。如果不包括生成数据,时间只需2.3s
有时想起 2014-10-31
  • 打赏
  • 举报
回复
引用 9 楼 github_22161131 的回复:
下面的代码是画了一个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");
很给力 之前数据是读出来以泛型的double二维数组形式 再将其setpixel 保存 时间大约1分半。用了您的方法 我数据读取后就以double[]数组保存,然后颜色映射过去,时间18s,(两者进行时电脑都不做其他事情 等待的状况下测试)
winnowc 2014-10-31
  • 打赏
  • 举报
回复
下面的代码是画了一个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");
卧_槽 2014-10-31
  • 打赏
  • 举报
回复
new FileStream(path, FileMode.Open, FileAccess.Read); 改为 File.OpenRead(path);
winnowc 2014-10-31
  • 打赏
  • 举报
回复
代码优化了下,用了并发,我这里是8s左右(数据是随机生成的6000*10000的csv,0.0-1.0间的浮点数)。而且因为边读边处理,内存占用小了很多。

int width = 6000, height = 10000;

// 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;

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++;
    }
}
卧_槽 2014-10-30
  • 打赏
  • 举报
回复
引用 5 楼 u011672494 的回复:
[quote=引用 4 楼 u011672494 的回复:] [quote=引用 3 楼 yuwenge 的回复:] 这数据变成图应该是什么样?
一副灰度图 像素点就是上面的数据啊[/quote] 但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了[/quote]换个64位的系统,内存就没问题了。另外换用bitmapdata操作。
有时想起 2014-10-30
  • 打赏
  • 举报
回复
不会溢出 溢出的原因是我画好后再对panel绘上这个图 这时候就溢出了。我想问setpixel速度太慢了 如何改善
比尔咔咔 2014-10-30
  • 打赏
  • 举报
回复
引用 5 楼 u011672494 的回复:
[quote=引用 4 楼 u011672494 的回复:] [quote=引用 3 楼 yuwenge 的回复:] 这数据变成图应该是什么样?
一副灰度图 像素点就是上面的数据啊[/quote] 但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了[/quote] 分批画 如10000个画一次,如果还溢出,则每10000个画完就保存本地磁盘,再重新打开画。(虽然我觉得直接画也不该溢出的)
feixuyue 2014-10-29
  • 打赏
  • 举报
回复
csv格式读取读成数组 lockbits移动块~
有时想起 2014-10-29
  • 打赏
  • 举报
回复
引用 4 楼 u011672494 的回复:
[quote=引用 3 楼 yuwenge 的回复:] 这数据变成图应该是什么样?
一副灰度图 像素点就是上面的数据啊[/quote] 但是其实我的数据有6000*10000个。。我试了用SetPixel画 直接outofmemory了
有时想起 2014-10-29
  • 打赏
  • 举报
回复
引用 3 楼 yuwenge 的回复:
这数据变成图应该是什么样?
一副灰度图 像素点就是上面的数据啊
卧_槽 2014-10-29
  • 打赏
  • 举报
回复
这数据变成图应该是什么样?
有时想起 2014-10-29
  • 打赏
  • 举报
回复
引用 1 楼 feixuyue 的回复:
csv格式读取读成数组 lockbits移动块~
数组已经读好了,后面那个移动块什么的 什么意思==

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧