当前位置:  开发笔记 > 编程语言 > 正文

如何在.NET中使用大位图?

如何解决《如何在.NET中使用大位图?》经验,为你挑选了1个好方法。

我正在尝试编写一个轻量级图像查看应用程序.但是,.NET存在系统内存限制.

当尝试加载大位图(9000 x 9000 px或更大,24位)时,我得到一个System.OutOfMemoryException.这是在具有2GB RAM(其中1.3GB用完)的Windows 2000 PC上.尝试加载文件也需要很长时间.

以下代码生成此错误:

Image image = new Bitmap(filename);
using (Graphics gfx = this.CreateGraphics())
{
    gfx.DrawImage(image, new Point(0, 0));
}

这段代码也是如此:

Stream stream = (Stream)File.OpenRead(filename);
Image image = Image.FromStream(stream, false, false);
using (Graphics gfx = this.CreateGraphics())
{
    gfx.DrawImage(image, new Rectangle(0, 0, 100, 100), 4000, 4000, 100, 100, GraphicsUnit.Pixel);
}

此外,它就足以做到这一点:

Bitmap bitmap = new Bitmap(filename);
IntPtr handle = bitmap.GetHbitmap();

后一个代码旨在与G​​DI一起使用.在研究这个问题时,我发现这实际上是一个内存问题,.NET试图在单个内存块中分配两倍的内存.

http://bytes.com/groups/net-c/279493-drawing-large-bitmaps

我从其他应用程序(Internet Explorer,MS Paint等)了解到,可以打开大图像,而且很快.我的问题是,如何在.NET中使用大型位图?

无论如何流式传输它们,还是非内存加载它们?



1> TheCodeJunki..:

这是一个两部分问题.第一个问题是如何在不耗尽内存的情况下加载大型图像(1),第二个问题是提高加载性能(2).

(1)Concider像Photoshop一样的应用程序,你可以在文件系统上使用巨大的图像消耗gigabite.在大多数系统(甚至8gb x64系统)上,将整个图像保留在内存中并且仍然有足够的可用内存来执行操作(过滤器,图像处理等,甚至只是添加图层)是不可能的.

这就是为什么像这样的应用程序使用交换文件的概念.在内部我假设photoshop使用专有的文件格式,适合他们的应用程序设计并构建为支持来自交换的部分负载,使他们能够将文件的一部分加载到内存中来处理它.

(2)通过为每种文件格式编写自定义加载器,可以改进(非常多)Performande.这需要您阅读要使用的文件格式的文件头和结构.一旦你掌握了它,那就不是****,但它并不像做方法调用那样微不足道.

例如,您可以google for FastBitmap查看有关如何快速加载位图(BMP)文件的示例,其中包括解码位图标头.这涉及到pInvoke并且为了让你对你所遇到的内容有所了解,你将需要定义位图结构,例如

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct BITMAPFILEHEADER
        {
            public Int16 bfType;
            public Int32 bfSize;
            public Int16 bfReserved1;
            public Int16 bfReserved2;
            public Int32 bfOffBits;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFO
        {
            public BITMAPINFOHEADER bmiHeader;
            public RGBQUAD bmiColors;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFOHEADER
        {
            public uint biSize;
            public int biWidth;
            public int biHeight;
            public ushort biPlanes;
            public ushort biBitCount;
            public BitmapCompression biCompression;
            public uint biSizeImage;
            public int biXPelsPerMeter;
            public int biYPelsPerMeter;
            public uint biClrUsed;
            public uint biClrImportant;
        }

可能需要创建一个DIB(http://www.herdsoft.com/ti/davincie/imex3j8i.htm)和奇怪的数据,比如数据被"颠倒"存储在位图中,您需要考虑或者您会看到当你打开它时的镜像:-)

现在这只是针对位图.说你想做PNG然后你需要做类似的东西,但解码PNG标题,这是最简单的形式并不难,但如果你想得到完整的PNG规范支持,那么你是一个有趣的旅程: - )

PNG与位图不同,因为它使用基于块的格式,它具有"标题",您可以放置​​以查找不同的数据.我在播放格式时使用的一些块的示例是

    string[] chunks =  
new string[] {"?PNG", "IHDR","PLTE","IDAT","IEND","tRNS",
"cHRM","gAMA","iCCP","sBIT","sRGB","tEXt","zTXt","iTXt",
"bKGD","hIST","pHYs","sPLT","tIME"};

您还必须了解PNG文件的Adler32校验和.因此,您想要做的每种文件格式都会增加一系列不同的挑战.

我真的希望我能在回复中提供更完整的源代码示例,但这是一个复杂的主题,说实话我自己没有实现交换,所以我不能给出太多可靠的建议.

简短的回答是BCL中的图像处理能力并不高.中等答案是尝试找出是否有人编写了可以帮助您的图像库,而长期的答案就是拉起袖子并自己编写应用程序的核心.

既然你在现实生活中认识我,你就知道在哪里找到我;)

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有