Image对象的内存占用问题。

前几天维护的程序发生了内存不足的问题,经查看,是由于用户一次加载了15张图片,每张图片的大小都接近1M,用户把图片修改后,程序可以正常处理了。

不过又想了一下,15张JPG图片的大小 加起来也不过是最大15M而已,也不至于内存不够呀!

于是检查代码:

 

FileStream fs = new FileStream(txtImageName.Text, FileMode.Open); BinaryReader br = new BinaryReader(fs); byte[] bytes = br.ReadBytes((int)fs.Length); //b_image fs.Close(); br.Close(); if (bytes == null) { return; } ArrayList result = new ArrayList(); Image orginalimg, originalIMG; using (Stream picStream = new MemoryStream(bytes)) { orginalimg = (Bitmap)Image.FromStream(picStream); } orginalimg.Dispose(); result.Add(originalIMG);//orginalimg result.Add(bytes); 

debug时发现只要执完 orginalimg = (Bitmap)Image.FromStream(picStream);  这一句,内存暴增100多M。然后图片的大小只有700多K,开始时,以为是Memorystream没有释放资源,弄了很久,也没有解决问题。

最后看到网上有人遇到类似的问题,有人提醒说有可能是Image的问题。

然后加上了orginalimg.Dispose()这句,发现果然,只要这一句一执行,点用的100多M内存就释放了。

可是由于后面还需要用到这个image,这时不能释放。因为界面会显示加载的所有图片的小图。

然后决定重点查了一下: 为什么一个700多K的JPG读到一个IMG对象后,会变成上白兆?

 

经过一翻Google后,发现在IMage的内存占用大小的计算方法如下:

Image在内存中占用的空间计算:

如果是32位,确实是Width   *   Height   *   4   
  实际上应该是Height   *(((Width   *   32)   +   31)   /   32)   *   4   
    
  如果是24位的化,就不一定是Width   *   Height   *   3了,   
  而是Height   *(((Width   *   24)   +   31)   /   32)   *   4   

 

Note: 上面的Height 和Weight是图片的原始大小。可以根据Image的这两个属性值来查看具体的大小。 

查看了一下我读入的图片的大小是:Height= 6800, Width = 4400. 代入上面的公式一算,果然是100M多(另上面公式算出来的是字节数,除以1024*1024可以得到多少M)

 

PS:所以我读的图片是JPG格式, jpg是压缩格式的位图,它本身不是真正的原始位图,进入内存后,要经过一定的算法的才能成为原始位图,也就是说,内存中的才是真正原始位图的大小,这时,它是未压缩的,并以纯二进制表示的,所以占用内存超出文件的大小。 

 

由于界面显示的是缩略图,所以我只需要把图片尺寸改小,就应该能正常显示了,

double scale = 0.1

originalIMG = orginalimg.GetThumbnailImage(Convert.ToInt32(orginalimg.Size.Width * scale), Convert.ToInt32(orginalimg.Size.Height * scale), null, IntPtr.Zero)

 

完成后再调用orginalimg.Dispose()释放那100M多内存。这样,当用户读一系列的图片进来时,就可以正常显示了。

 

(另:如果需要单独看某一张图片用原始尺寸,可以用一个变量把图片按字节读进来,然后单独显示时,再读到IMG,这样程序也可以正常显示,因为也就是100多M,而不是多个100M)。

 

你可能感兴趣的:(开发问题日志,.net,开发)