Добрый день! Заранее извиняюсь за объем сообщения, сокращал как мог.
Возникла задача разработать библиотеку на языке C++ для обработки растровых изображений. Специфика задачи такова, что приходится иметь дело с различными цветовыми пространствами. Минимум — grayscale и binary, в дальнейшем, возможно, появится RGB.
Для примера смотрел на Qt4, System.Drawing из .Net и java.awt.Graphics.
Все фундаментальные свойства изображений я вынес в отдельный шаблон, который параметризуется типом, который хранит сведения об отдельном пикселе изображения.
template<class T>
class Image {
public:
// Тип данных, используемый для хранения сведений об отдельном пикселе
// изображения.
typedef T Pixel;
// Конструктор копирования и оператор присваивания.
Image(const Image &rhs);
Image<Pixel> &operator=(const Image &rhs);
// Возвращает true, если ширина и высота изображения равны 0.
bool isNull() const throw();
// Получить размеры изображения.
const Size &getSize() const throw();
int getWidth() const throw();
int getHeight() const throw();
// Получить пиксел с заданными координатами.
Pixel getPixel(const Point &point) const;
Pixel getPixel(int x, int y) const;
// Изменить пиксел с заданными координатами.
void setPixel(const Point &point, Pixel pixel);
void setPixel(int x, int y, Pixel pixel);
protected:
// Конструкторы.
Image() {}
explicit Image(const Size &size);
Image(int width, int height);
private:
Size size_;
std::vector<Pixel> pixels_;
};
От него наследуется класс для работы с полутоновыми изображениями:
// Класс "Полутоновое изображение".
class GrayImage : public Image<unsigned char> {
public:
// Конструкторы.
GrayImage() {}
explicit GrayImage(const Size &size) : Image<Pixel>(size) {}
GrayImage(int width, int height) : Image<Pixel>(width, height) {}
explicit GrayImage(const std::string &filename);
// Сохранить изображение в файл.
void save(const std::string &filename);
};
И почти то же самое делает для бинарных изображений — приводить код не буду, его и так уже много
Что касается классов Point и Size, то выглядят они так:
// Класс, описывающий координаты точки на плоскости.
class Point {
public:
// Конструкторы.
Point() throw() : x_(0), y_(0) {}
Point(int x, int y) throw() : x_(x), y_(y) {}
// Получить координаты точки.
int getX() const throw();
int getY() const throw();
// Изменить координаты точки.
void setX(int x) throw();
void setY(int y) throw();
void setXY(int x, int y) throw();
// Декрементировать координаты точки.
void decX() throw() { --x_; }
void decY() throw() { --y_; }
// Инкрементировать координаты точки.
void incX() throw() { ++x_; }
void incY() throw() { ++y_; }
private:
int x_;
int y_;
};
bool operator==(const Point &lhs, const Point &rhs) throw();
bool operator!=(const Point &lhs, const Point &rhs) throw();
// Класс, описывающий размеры двумерного объекта на плоскости (чаще всего -
// прямоугольника).
class Size {
public:
// Конструкторы.
Size() throw() : width_(0), height_(0) {}
Size(int width, int height) { setSize(width, height); }
// Возвращает true, если ширина и высота объекта равны 0.
bool isNull() const throw();
// Получить размер объекта.
int getWidth() const throw();
int getHeight() const throw();
// Изменить ширину объекта.
void setWidth(int width);
// Изменить высоту объекта.
void setHeight(int height);
// Изменить размер объекта.
void setSize(int width, int height);
private:
int width_;
int height_;
};
inline bool operator==(const Size &lhs, const Size &rhs) throw();
inline bool operator!=(const Size &lhs, const Size &rhs) throw();
Для тех, кто все-таки добрался до этого места, у меня есть ряд вопросов:
1. Какие есть минусы схемы с наследованием от Image<>? Мне пока ничего такого найти не удалось, поэтому и возникают некоторые сомнения — почему я такого больше нигде не видел?
2. Стоит ли овчинка выделки применительно к классам Point и Size? Может лучше отказаться от них, а при вызове методов Image<> отдельно указывать x и y (или width и height)?
3. Ну и вообще, как вам дизайн?
Заранее благодарю за ответы по существу.