2013-04-10 65 views
3

可能noob問題。我希望使用CImg庫來進行一些圖像處理。他們中的一些可能是(8位)類型和其中一些(16位)。不幸的是,我不知道數據的類型,直到用戶不選擇文件來處理。當然,我可以這樣做:模板。沒有類型在編譯期間知道

... 
CImg <unsigned char> img_unisgned_char; 
CImg <unsigned short> img_unisgned_short; 
... 
if (user_pick_8bit) img_unisgned_char.load_raw(fname,img_size_x,img_size_y); 
if (user_pick_16bit) img_unisgned_short.load_raw(fname,img_size_x,img_size_y); 
... 

但CIMG方法99%,看起來完全爲「無符號的字符」,「詮釋」或「浮動」類型相同(如「load_raw」或「模糊」例如)。有什麼辦法可以做 - 我不知道 - 指針? - 因此,當用戶選擇文件我可以創造奇蹟,如:

if (user_pick_8_bit) img = img_unisgned_char; 
if (user_pick_16bit) img = img_unisgned_short; 
... 
//now no mother of what type is picked up by user I simply make: 
img.load_raw(...); 
+0

相關問題:[http://stackoverflow.com/q/608409/501250](http://stackoverflow.com/q/608409/501250)。如果您無法使用虛擬基類對CImg <>'進行翻新,則可能不適用您的情況。 – cdhowie 2013-04-10 19:47:05

+0

在我的網頁搜索期間,我找到了這個解決方案。但是我不明白我如何在我的情況下使用它。 (我對C++的瞭解甚至不足以改變CIMg庫中的任何東西......)。所以我唯一的選擇是爲每種類型創建單獨的代碼? – user2267612 2013-04-10 19:54:58

+0

不一定。你可以定義你自己的模板函數:'template void do_image_processing(/ * ... * /){CImg img; img.load_raw(/ * ... * /); }' – cdhowie 2013-04-10 19:56:38

回答

1

你當然可以這樣做,如果類模板CImg<T>有一個父類。但是您會發現,您可以在不知道像素類型的情況下執行的一組操作僅限於加載和保存等操作。爲了對圖像內容進行操作,您需要保留具體的圖像對象。

class CImgBase 
{ 
    // Functions that do not reference the pixel type can go here. 
    virtual void load_raw(...) = 0; // agnostic of pixel type 
}; 

// CImg implements CImgBase interface 
template<typename T> 
class CImg : public CImgBase 
{ 
    void load_raw(...); 
    T get_pixel(int x, int y); 
}; 
1

許多CImg類模板的方法取決於T參數,所以即使非相關的操作都抽象爲一個超類,使用該庫的代碼中的許多部分將取決於類型反正也結束了。界面的一個重要部分似乎使用了數據類型,因此可能有一種方法可以使一個suoerclass只有非依賴方法,這在某種程度上可以使用。

或許下面可以工作:

class SuperCimg { 
public: 
    // expose the non dependent methods as virtual pure 
    virtual Tfloat linear_atX(/* ... */) = 0; 
    // etc. 
}; 

template <typename T> 
class DependentCimg : public virtual SuperCimg, public virtual Cimg<T> { 
    // expose the needed constructors and methods 
    public: 
    Tfloat linear_atX(/* ... */) { 
     return Cimg<T>::linear_atX(/* ... */); 
    } 
}; 

但正如你所看到的,實施是乏味的,因爲它需要重新定義的所有接口。另外,每種方法最終都會變成虛擬的,這會在運行時產生影響(也許這就是實現者沒有成爲超類的原因)。

處理這個問題的另一種可能的方式是將你的應用程序的每個算法都作爲該類型的多態,並將最依賴的部分切分爲特定的類,這些類將用作模板參數給你的算法(有點像分配器,比較器和std庫模板的其他可配置部分作爲這些模板的參數)。

1

感謝「madcoder」和「didierc」。我發現你的答案很有用。我最終是這樣的:

#include <CImg.h> 
#include <conio.h> 
#include <stdio.h> 
#include <windows.h> 

using namespace cimg_library; 

class cimg_base 
{ 
public: 
virtual int load_bmp(const char *const filename) = 0; 
virtual int save_bmp (const char *const filename) = 0; 
virtual void blur (const float sigma) = 0; 
virtual void sharpen (const float amplitude) = 0; 
}; 

class cimg_unsigned_char : public cimg_base 
{ 
CImg <unsigned char> img; 
int load_bmp (const char *const filename) { img.load_bmp(filename); return 0;} 
int save_bmp (const char *const filename) { img.save_bmp(filename); return 0;} 
void blur (const float sigma) { img.blur(sigma); } 
void sharpen (const float amplitude) { img.sharpen(amplitude); }; 
}; 

class cimg_unsigned_short : public cimg_base 
{ 
CImg <unsigned short> img; 
int load_bmp (const char *const filename) { img.load_bmp(filename); return 0;} 
int save_bmp (const char *const filename) { img.save_bmp(filename); return 0;} 
void blur (const float sigma) { img.blur(sigma); } 
void sharpen (const float amplitude) { img.sharpen(amplitude); }; 
}; 


void main(void) 
{ 
cimg_base *data; 

LARGE_INTEGER lpFrequency; 
LARGE_INTEGER lpPerformanceCountStart, lpPerformanceCountEnd; 
double Frequency,Start,End; 

// no matter witch line is used - progrm work as expected 
data = new cimg_unsigned_char; 
//data = new cimg_unsigned_short; 

data->load_bmp("test.bmp"); 
//measure time with virtual 
QueryPerformanceFrequency(&lpFrequency); 
QueryPerformanceCounter(&lpPerformanceCountStart); 

data->blur(2.2f); 
data->sharpen(2.2f); 

QueryPerformanceCounter(&lpPerformanceCountEnd); 
Frequency = (double)lpFrequency.QuadPart; 
End = (double)lpPerformanceCountEnd.QuadPart; 
Start = (double)lpPerformanceCountStart.QuadPart; 
printf_s("Time (virtual):%lf ms\n",((End - Start)/Frequency)*1000); 
data->save_bmp("output_virt.bmp"); 

CImg <unsigned char> img; 
img.load_bmp("test.bmp"); 

QueryPerformanceCounter(&lpPerformanceCountStart); 

img.blur(2.2f); 
img.sharpen(2.2f); 

QueryPerformanceCounter(&lpPerformanceCountEnd); 
printf_s("Time (normal):%lf ms\n",((End - Start)/Frequency)*1000); 
img.save_bmp("output_normal.bmp"); 


_getch(); 
} 

,因爲這個程序的輸出是:

Time (virtual):93.705392 ms 
Time (normal):93.705392 ms 

我不覺得虛函數是我的性能問題(據我所知「didierc」這將是如果我會撥打大量電話,這個問題呢?)。這種解決方案有點「可以接受」嗎?或者出於某種原因,我現在不應該這樣做?