支持多种像素格式

时间:2010-09-09 13:15:18

标签: c++ image-processing image-manipulation

我需要编写一些代码,这些代码将以多种像素格式运行(例如A8R8G8B8,R8G8B8,R5G6B6,甚至可能是浮点格式)。

理想情况下,我不想为每种格式编写每个函数,因为这是大量几乎相同的代码。

我唯一能想到的是某种界面让它处理像素格式转换,例如:

class IBitmap
{
public:
    virtual unsigned getPixel(unsigned x, unsigned y)const=0;
    virtual void setPixel(unsigned x, unsigned y, unsigned argb)=0;
    virtual unsigned getWidth()const=0;
    virtual unsigned getHeight()const=0;
};

然而,为每个获取或设置像素操作调用虚函数几乎不快,因为不仅存在虚拟调用的额外开销,而且更重要的是防止内联仅仅是几个指令长。

是否还有其他选项可以让我有效地支持所有这些格式?一般来说,我的代码可能只在位图的一小部分上运行,并且在许多情况下需要读/写访问(混合)。

5 个答案:

答案 0 :(得分:1)

考虑使用模板。这将允许您在可能的情况下进行一般编写,并在编译时使用命中来专门化代码

有时称为静态多态。 http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern

答案 1 :(得分:0)

在现代处理器上,虚拟功能非常快,所以我不确定我会拒绝它们。运行一两个定时测试以确定。虚函数为您提供运行时多态性,允许您在编译时编写(或在编译时生成)较少的代码。模板表示的静态多态性可能会导致编译器生成您试图避免的大量代码。

答案 2 :(得分:0)

为了避免编写大量格式,编写总是存储特定格式的Color类或类似文件(例如A8R8G8B8或A32R32G32B32F),然后在该类上使用不同格式检索的方法,例如。 get(FORMAT_R5G6B6)或类似的。然后,您的所有方法都可以处理该类。只要有可能,只转换颜色一次(例如,绘制矩形时,将矩形颜色转换为目标格式,然后将其写入所有像素 - 不要为每个像素转换它!)。

完全避免使用SetPixel / GetPixel方法。它无法有效地完成,特别是如果您正在进行颜色转换,尤其是在优化程序决定不内联调用时。您最好直接公开内存缓冲区,并相信调用方将正确使用内存。这就是我之前使用过的所有其他API的方法。

答案 3 :(得分:0)

(这是我的新答案,因为经过广泛的研究,我得出结论,Adobe GIL不适用于此目的。)

我强烈推荐Windows Imaging Component的架构和界面设计。

我的意思是:

  • 他们的界面就是我推荐的。不是实施。
    • 每个人都可以实现类似的东西。实际上,Mono Project(Wine)包含WIC的部分实现。
  • WIC使用管道存储模型,而不是生产者 - 消费者模型。
    • 只读位图实现IWICBitmapSource接口
      • 只有5个成员方法。
    • 可写位图实现IWICBitmap接口,并提供对像素数据的直接内存读/写访问。
      • 在IWICBitmapSource之上只有3个额外的成员方法。
      • 作为“存储”类意味着在生成像素值时此类不依赖于任何其他位图实例。

答案 4 :(得分:0)

将所有内容转换为单一通用格式,然后在操作后转换回来的开销可能比您想象的要少。如果您可以限制一次转换的像素数,例如限制为单行,则中间结果可能会保留在整个操作的缓存中。我实际上已经看到使用这种方法的端到端时间更快的情况,尽管它涉及一位像素,当仍然打包时本身很难处理。

对于像素级函数调用持谨慎态度是正确的。我从未见过像素函数没有使处理速度慢得令人无法接受的情况。