我正在尝试为此设计一个更好的方案!
考虑到我们有一个继承自模板矩阵库(在这种情况下是Eigen,但它可以是任何东西)的模板Image类。
template <typename T>
class Image : public Eigen::Matrix <T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
现在考虑一个情况,我们希望编写一个函数来处理从文件中读取图像。当然,图像可以是不同的类型,如无符号字符、uint16_t、浮点数,甚至具有不同的通道,如灰度、RGB或RGBA。
因此,我们可以使用模板类来轻松处理这些。比如:
Image<RGB<unisgned char>> or Image<RGBA<float>>
当我们知道图像的类型,比如单色8位,处理起来就变得简单了。
Image<unisgned char> image = ReadImage(const char* const filename);
或者它甚至可以是
Image<unisgned char> image;
bool b = ReadImage(const char* const filename, Image<unisgned char>& image)
然而,当读取图像文件时,我们无法事先知道其类型。例如,Tiff和png都支持8位和16位,而tiff甚至支持float。在这种情况下,使用上述任何函数都是不可能的。然而,我们可以使用一个模板工厂类来解决这个问题。为此,我们首先需要引入一个BaseImage类。
class BaseImage
{
public:
inline BaseImage() {};
virtual inline ~BaseImage() {};
virtual inline int Width() const = 0;
virtual inline int Height() const = 0;
virtual inline int Depth() const = 0;
etc...
};
template <typename T>
class Image : public BaseImage, public Eigen::Matrix <T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
然后我们可以有一个工厂类(factory class),在其中传递我们的unsigned char*,float*等数据类型,并让它处理创建过程。
class ImageFactory
{
typename <T>
static BaseImage* createImage(const T* const src, const int& width, const int& height, const int& depth)
{
if (depth == 1)
{
return new Image<T>();
}
else if (depth == 3)
{
return new Image<RGB<T>>();
}
etc...
}
}
当然,这迫使我使用动态分配和继承。
我想我可以通过将其隐藏在一个负责处理它的类中来避免动态分配。 在构造函数中,工厂类将被调用。
class Image2
{
public:
Image2(const char* const path)
{
// where ReadImage and external function that will call ImageFactory
pBaseImage = ReadImage(path);
}
~Image2();
private:
BaseImage* pBaseImage;
};
无论哪种情况,我的 BaseImage 类都必须公开我需要从矩阵库中使用的所有功能,这有点违背了继承的目的。
问题是,是否存在更好的设计方案,因为现在变得相当麻烦。
float
适用于单色图像。 - polkovnikov.ph