这是一个两部分的问题。第一个问题是如何在不耗尽内存的情况下加载大图像(1),第二个问题是提高加载性能(2)。
(1) 考虑一个像 Photoshop 这样的应用程序,您可以在其中处理在文件系统上消耗千兆位的巨大图像。在大多数系统(甚至 8gb x64 系统)上,将整个图像保存在内存中并且仍然有足够的空闲内存来执行操作(过滤器、图像处理等,甚至只是添加层)是不可能的。
这就是为什么像这样的应用程序使用交换文件的概念。在内部,我假设 Photoshop 使用专有文件格式,适用于他们的应用程序设计,并构建为支持从交换部分加载,使他们能够将文件的一部分加载到内存中进行处理。
(2) 通过为每种文件格式编写自定义加载器,可以提高性能(很多)。这需要您阅读要使用的文件格式的文件头和结构。一旦你掌握了它,它就不会那么难了,但它并不像调用方法那么简单。
例如,您可以搜索 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 中的图像处理能力并不那么热门。中等答案是尝试查找是否有人编写了可以帮助您的图像库,而长答案是卷起袖子自己编写应用程序的核心。
既然你在现实生活中认识我,你就知道在哪里可以找到我;)