如何在.NET中使用大位图?我正在尝试编写一个轻量级的图像查看应用程序。但是,.NET有系统内存限制。尝试加载大位图(9000x9000像素或更大,24位)时,出现System.OutOfMemoryException。这是在具有2GBRAM(其中1.3GB已用完)的Windows2000PC上运行的。尝试加载文件也需要很长时间。以下代码会产生此错误:Imageimage=newBitmap(filename);使用(Graphicsgfx=this.CreateGraphics()){gfx.DrawImage(image,newPoint(0,0));这段代码也是如此:Streamstream=(Stream)File.OpenRead(filename);图片image=Image.FromStream(stream,false,false);使用(Graphicsgfx=this.CreateGraphics()){gfx.DrawImage(image,newRectangle(0,0,100,100),4000,4000,100,100,GraphicsUnit.Pixel);此外,这就足够了:Bitmapbitmap=newBitmap(filename);IntPtrhandle=bitmap.GetHbitmap();后面的代码旨在与GDI一起工作。在研究这个问题时,我发现它实际上是一个内存问题,.NET试图在单个内存块中分配两倍的内存。http://bytes.com/groups/net-c/279493-drawing-large-bitmaps我从其他应用程序(InternetExplorer、MSPaint等)了解到可以快速打开大图像。我的问题是,如何在.NET中使用大位图?无论如何要流式传输它们,或加载它们非内存?这是一个两部分的问题。第一个问题是如何在不耗尽内存的情况下加载大图像(1),第二个问题是提高加载性能(2)。(1)像Photoshop这样的Concider应用程序,你可以在文件系统上消耗千兆位和巨大的图像。在大多数系统(甚至8gbx64系统)上,不可能将整个图像保存在内存中,并且仍然有足够的空闲内存来执行操作(过滤器、图像处理等,甚至只是添加图层)。这就是为什么像这样的应用程序使用交换文件的概念。在内部,我假设photoshop使用专有文件格式,适合他们的应用程序设计,并构建为支持交换部分加载,允许他们将文件的一部分加载到内存中进行处理。(2)通过为每种文件格式编写自定义加载器,可以(大大)提高性能。这需要您阅读要使用的文件格式的文件头和结构。一旦掌握了它就不是****,但它不像进行方法调用那样微不足道。例如,您可以在谷歌上搜索FastBitmap以查看有关如何快速加载位图(BMP)文件的示例,其中包括解码位图标头。这涉及到pInvoke并让您了解您正在处理什么,您需要定义一个位图结构,例如[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructBITMAPFILEHEADER{publicInt16bfType;公共Int32bfSize;公共Int16bfReserved1;公共Int16bfReserved2;公共Int32bfOffBits;}[StructLayout(LayoutKind.Sequential)]publicstructBITMAPINFO{publicBITMAPINFOHEADERbmiHeader;公共RGBQUADbmiColors;}[StructLayout(LayoutKind.Sequential)]publicstructBITMAPINFOHEADER{publicuintbiSizepublicintbiWidth;公共诠释双高度;公共ushortbiPlanes;公共ushortbiBitCount;公共位图压缩双压缩;公共uintbiSizeImage;公共诠释biXPelsPerMeter;publicintbiYPelsPerMeter;/www.herdsoft.com/ti/davincie/imex3j8i.htm)与存储在位图中的数据的“反转”有关,您需要考虑到这一点,否则打开它时会看到镜像:-)现在这仅适用于位图。假设你想做PNG那么你需要做类似的事情,但是解码PNG标头,这在最简单的形式下并不难,但是如果你想要完整的PNG规范支持那么你正在经历一个有趣的旅程:-)PNG与位图不同,因为它使用基于块的格式,它有一个“标头”,您可以放置??它来查找不同的数据。我在播放格式时使用的一些块的示例是string[]chunks=newstring[]{"?PNG","IHDR","PLTE","IDAT","IEND","tRNS","cHRM""gAMA","iCCP","sBIT","sRGB","tEXt","zTXt","iTXt","bKGD","hIST","pHYs","sPLT","tIME"};您还必须了解PNG文件的Adler32校验和。因此,您想要处理的每种文件格式都会增加一组不同的挑战。我真的希望我能在回复中提供更完整的源代码示例,但这是一个复杂的话题,老实说我自己还没有实现交换,所以我不能给出太多可靠的建议。简短的回答是BCL中的图像处理能力不是那么高。中等答案是尝试找出是否有人编写了可以帮助您的图像库,长答案是挽起袖子并自己编写应用程序的核心。因为你在现实生活中认识我,所以你知道在哪里可以找到我;)要获得非常全面的答案,我会使用Reflector查看Paint.NET的源代码(http://www.getpaint.net/);用C#编写的高级图形编辑程序。(评论中指出,Paint.NET以前是开源的,现在是闭源的)。关于什么:Imageimage=newBitmap(filename);using(Graphicsgfx=Graphics.FromImage(image)){//Stuff}只是一个快速修复,我遇到了同样的问题,我创建了第二个位图实例并在构造函数中传递了位图。你能创建一个相同大小和颜色深度的新空白位图吗?如果是这种情况,您至少知道您的环境可以处理图像。然后问题出在图像加载子系统中,当然可能与您指示的链接有关。我想您可以编写自己的位图加载器,但是对于非平凡的格式来??说这需要大量工作,所以我不建议这样做。也许有可用的替换库来解决标准加载程序的这些问题?所以你是说导致内存不足的不是位图的加载,而是渲染?如果是这样,您可以使用Bitmap.LockBits获取像素并自己编写一个基本的图像缩放器吗?一件事对我来说很突出。您是在绘制整个图像而不仅仅是可见部分吗?您不应绘制比应用程序中显示的更大的图像部分,使用x、y、宽度和高度参数来限制绘图区域。以上是C#学习教程:如何在.NET中使用大位图?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
