我目前面临的困境如下:
我有一个2550x3300 tiff。在我的tiff的某些(可变)点,我需要从tiff的其他地方插入一行像素。例如我需要在第500行和第501行之间的第100行中插入12个副本。
我一直在寻找不同的图像处理技术几天了,找不到其他人做这种事情让我相信我可能会以错误的方式解决这个问题。
或者,如果我正在做的事情非常缓慢而没有更好的方法,那么最快的方法是什么?使用GDI +我需要大约12秒才能添加1330行,如果我使用“不安全”需要7.7秒(我现在正在C#中完成所有这些),如果我使用FreeImage dll,我可以将其降低到大约2.5秒。
提前致谢。
答案 0 :(得分:1)
也许你会更好地看待数据结构。如果您只处理一个维度,那么B树将是一种非常有效的方式,可以随意插入对数成本。如果你需要插入列和行,你需要更复杂的东西,但如果你插入和删除行只有你的生活可以相对简单。
如果您可以将图像描述作为抽象数据类型,并且所有您想要执行的操作以及您希望成本的概念,那将会有所帮助。
如果您需要现成的解决方案,可以尝试将图像的行表示为数据库表中的条目。或者另一种方法是将您的像素行视为字符串,然后您可以尝试article by Boehm, Atkinson, and Plass中描述的“C cords”库。它描述了一种有效操作非常大的字符串的数据结构。
答案 1 :(得分:0)
除非这是一个使用性能问题,否则我会坚持使用GDI +,因为它被融入框架并保持依赖性。如果你真的需要性能,可以使用FreeImage库。
答案 2 :(得分:0)
在我看来,你可能已经尽可能地利用了FreeImage。
FreeImage源代码(http://freeimage.sourceforge.net/download.html,BitmapAccess.cpp :: FreeImage_AllocateT)似乎将malloc图像存储为一维数组:
unsigned dib_size = FreeImage_GetImageSize(width, height, bpp);
bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);
这里,dib_size是“设备无关位图大小”,bpp是“每像素位数”。
我假设您使用PixelAccess.cpp :: FreeImage_GetScanLine()来获取要复制的行:
BYTE * DLL_CALLCONV
FreeImage_GetScanLine(FIBITMAP *dib, int scanline) {
return (dib) ? CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline) : NULL;
}
调用
inline unsigned char *
CalculateScanLine(unsigned char *bits, unsigned pitch, int scanline) {
return (bits + (pitch * scanline));
}
对于基于数组的查找似乎是O(1)。
由于FreeImage内部使用静态一维数组存储,因此在生长图像时(例如,插入行副本时)如何获得比O(n)性能更好的效果似乎并不明显。在我看来,最好的FreeImage可以做的是内部malloc新存储足以增长图像,然后将图像数据从源复制到新图像。这似乎是O(n)。
使用新的数据结构(例如B-tree)需要花费一些精力,但会给你更好的插入时间特性(O(log(n))。但是,加速的权衡是增加存储空间 - - 你会将每个像素存储在更大的空间中。
由于GDI +似乎是闭源的,我不确定它是如何实现位图的,但考虑到性能特征,它似乎比FreeImage更差。