diff options
author | cathook <b01902109@csie.ntu.edu.tw> | 2014-06-01 13:56:57 +0800 |
---|---|---|
committer | cathook <b01902109@csie.ntu.edu.tw> | 2014-06-01 13:56:57 +0800 |
commit | d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0 (patch) | |
tree | 16f7920c5079e0aefcf9509d2dbab59c464d42bd /meowpp/gra/Bitmap.h | |
parent | bd58f63900410ec4764031f2e6de2d75e91434b3 (diff) | |
download | meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.gz meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.zst meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.zip |
big chnage
Diffstat (limited to 'meowpp/gra/Bitmap.h')
-rw-r--r-- | meowpp/gra/Bitmap.h | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/meowpp/gra/Bitmap.h b/meowpp/gra/Bitmap.h new file mode 100644 index 0000000..c4ed4e0 --- /dev/null +++ b/meowpp/gra/Bitmap.h @@ -0,0 +1,411 @@ +#ifndef gra_Bitmap_H__ +#define gra_Bitmap_H__ + + +#include "../Self.h" + +#include "../math/utility.h" +#include "../math/Matrix.h" + +#include "../oo/ObjBase.h" + +#include <vector> +#include <cmath> +#include <string> +#include <typeinfo> +#include <cstdlib> + +namespace meow{ + +/*! + * @brief 二維點陣資料 + * + * @author cat_leopard + */ +template<class Pixel> +class Bitmap: public ObjBase { +private: + Matrix<Pixel> matrix_; + // + static std::vector<double> gaussianFactor1(double sigma) { + double sigma2 = squ(sigma); + size_t width = std::max(ceil((double)(sigma * 2)), 0.0); + std::vector<double> factor(width + 1 + width); + for (size_t x = 0; x < width; x++) { + factor[width - x - 1] = exp(-(squ((double)x)) / (2.0 * sigma2)); + factor[width + x + 1] = exp(-(squ((double)x)) / (2.0 * sigma2)); + } + factor[width] = 1.0; + return factor; + } + static std::vector<double> gradianceFactor1(double sigma) { + double sigma2 = squ(sigma), ss = sigma * 2; + size_t width = std::max(ceil(ss), 1.0); + std::vector<double> factor(width + 1 + width); + for (size_t x = 0; x < width; x++) { + factor[width - x - 1] = (double)x * exp(-(squ((double)x))/(2.0*sigma2)); + factor[width + x + 1] = -(double)x * exp(-(squ((double)x))/(2.0*sigma2)); + } + factor[width] = 0.0; + return factor; + } + Bitmap xyBlur(std::vector<double> const& factor, + ssize_t dx, ssize_t dy) const { + Bitmap ret(*this); + if (factor.size() > 0) { + ssize_t w = factor.size() / 2; + for (size_t y = 0, Y = height(); y < Y; y++) { + for (size_t x = 0, X = width(); x < X; x++) { + Pixel sum(0); + double fsum(0); + for (ssize_t i = -w; i <= w; i++) { + ssize_t x2 = (ssize_t)x + dx * i; + ssize_t y2 = (ssize_t)y + dy * i; + if (0 <= x2 && x2 < (ssize_t)X && 0 <= y2 && y2 < (ssize_t)Y) { + sum = sum + pixel(y2, x2) * factor[i + w]; + fsum = fsum + fabs(factor[i + w]); + } + } + ret.pixel(y, x, sum / fsum); + } + } + } + return ret; + } +public: + /*! + * @brief constructor, 產生一個空的Bitmap + */ + Bitmap() { + } + + /*! + * @brief constructor, 複製一個bitmap + */ + Bitmap(Bitmap const& b): matrix_(b.matrix_) { + } + + /*! + * @brief constructor, 指定寬高, 預設\c Pixel + * + * @param [in] h 高 + * @param [in] w 寬 + * @param [in] p 預設pixel + */ + Bitmap(size_t h, size_t w, Pixel const& p): matrix_(h, w, p) { + } + + /*! + * @brief destructor + */ + ~Bitmap(){ + } + + /*! + * @brief 複製 + */ + Bitmap& copyFrom(Bitmap const& b) { + matrix_.copyFrom(b.matrix_); + return *this; + } + + /*! + * @brief reference + */ + Bitmap& referenceFrom(Bitmap const& b) { + matrix_.referenceFrom(b.matrix_); + return *this; + } + + /*! + * @brief 全部重設 + * + * @param [in] h 高 + * @param [in] w 寬 + * @param [in] p 預設pixel + * @return 無 + */ + void reset(size_t h, size_t w, Pixel const& p) { + matrix_.reset(h, w, p); + } + + /*! + * @brief 清除資料, 寬高階規零 + */ + void clear() { + matrix_.size(0, 0, Pixel(0)); + } + + /*! + * @brief 回傳高度 + */ + size_t height() const { + return matrix_.rows(); + } + + /*! + * @brief 回傳寬度 + */ + size_t width() const { + return matrix_.cols(); + } + + /*! + * @brief 回傳高度乘以寬度 + */ + size_t size() const { + return matrix_.size(); + } + + /*! + * @brief 修改高度 + * + * @param [in] h2 新的高 + * @param [in] p 如果高有變大, 則新長出來的地方用此 pixel填補 + * @return 新的高 + */ + size_t height(size_t h2, Pixel const& p) { + return matrix_.rows(h2, p); + } + + /*! + * @brief 修改寬度 + * + * @param [in] w2 新的寬 + * @param [in] p 如果寬有變大, 則新長出來的地方用此 pixel填補 + * @return 新的寬 + */ + size_t width(size_t w2, Pixel const& p) { + return matrix_.cols(w2, p); + } + + /*! + * @brief 修改寬高 + * + * @param [in] h2 新的高 + * @param [in] w2 新的寬 + * @param [in] p 如果寬or高有變大, 則新長出來的地方用此 pixel填補 + * @return 新的size + */ + size_t size(size_t h2, size_t w2, Pixel const& p) { + return matrix_.size(h2, w2, p); + } + + /*! + * @brief 取得 (y, x) 的pixel + * + * @param [in] y + * @param [in] x + * @return 該pixel 的 constant reference + */ + Pixel pixel(size_t y, size_t x) const { + return matrix_.entry(y, x); + } + + /*! + * @brief 修改 (y, x) 的pixel + * + * @param [in] y + * @param [in] x + * @param [in] p 指定的顏色 + * @return 該pixel 的 constant reference + */ + Pixel pixel(size_t y, size_t x, Pixel const& p) { + return matrix_.entry(y, x, p); + } + + /*! + * @brief 區塊修改 + * + * 一口氣將一個矩形區塊修改成指定的顏色 + * + * @param [in] yFirst y軸方向最小值(含) + * @param [in] yLast y軸方向最大值(含) + * @param [in] xFirst x軸方向最小值(含) + * @param [in] xLast x軸方向最大值(含) + * @param [in] p 指定的顏色 + * @return 無 + */ + void pixels(ssize_t yFirst, ssize_t yLast, + ssize_t xFirst, ssize_t xLast, + Pixel const& p) { + return matrix_.entries(yFirst, yLast, xFirst, xLast, p); + } + + /*! + * @brief 回傳高斯模糊 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return 一個\c Bitmap , 是自己被高斯模糊後的結果 + */ + Bitmap gaussian(double radiusY, double radiusX) const { + return (xyBlur(gaussianFactor1(radiusY), 1, 0). + xyBlur(gaussianFactor1(radiusX), 0, 1)); + } + + /*! + * @brief 把自己高斯模糊 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return *this + */ + Bitmap<Pixel>& gaussianed(double radiusY, double radiusX) { + copyFrom(gaussian(radiusY, radiusX)); + return *this; + } + + /*! + * @brief 回傳對x偏微分 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return 一個\c Bitmap , 是自己被偏微分後的結果 + */ + Bitmap<Pixel> gradianceX(double radiusY, double radiusX) const { + return (xyBlur(gaussianFactor1(radiusY), 1, 0). + xyBlur(gradianceFactor1(radiusX), 0, 1)); + } + + /*! + * @brief 把自己對x偏微分 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return *this + */ + Bitmap<Pixel>& gradiancedX(double radiusY, double radiusX) { + return copyFrom(gradianceX(radiusY, radiusX)); + } + + /*! + * @brief 回傳對y偏微分 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return 一個\c Bitmap , 是自己被偏微分後的結果 + */ + Bitmap<Pixel> gradianceY (double radiusY, double radiusX) const { + return (xyBlur(gaussianFactor1(radiusX), 0, 1). + xyBlur(gradianceFactor1(radiusY), 1, 0)); + } + + /*! + * @brief 把自己對y偏微分 + * + * @param [in] radiusY 高斯模糊的Y軸方向的sigma + * @param [in] radiusX 高斯模糊的X軸方向的sigma + * @return *this + */ + Bitmap<Pixel>& gradiancedY(double radiusY, double radiusX) { + return copyFrom(gradianceY(radiusY, radiusX)); + } + + /*! + * @brief same as \c copyFrom(b) + */ + Bitmap& operator=(Bitmap const& b) { + return copyFrom(b); + } + + /*! + * @brief same as \c pixel(y, x) + */ + Pixel operator()(size_t y, size_t x) const { + return pixel(y, x); + } + + /*! + * @brief same as \c pixel(y, x, p) + */ + Pixel const& operator()(size_t y, size_t x, Pixel const& p) const { + return pixel(y, x, p); + } + + /*! @brief 將資料寫入檔案 + * + * @note 未完成, 輸入參數 fg 無用 + */ + bool write(FILE* f, bool bin, unsigned int fg) const { + size_t w = width(), h = height(); + if (bin) { + if (fwrite(&h, sizeof(size_t), 1, f) < 1) return false; + if (fwrite(&w, sizeof(size_t), 1, f) < 1) return false; + } + else { + if (fprintf(f, "%lu %lu\n", h, w) < 2) return false; + } + if (fg) { + // TODO + return false; + } + return true; + //return propertyWrite(__f, __bin, __fg); + } + + /*! @brief 將資料讀入 + * + * @note 未完成, 輸入參數 fg 無用 + */ + bool read(FILE* f, bool bin, unsigned int fg) { + size_t w, h; + if (bin) { + if (fread(&h, sizeof(size_t), 1, f) < 1) return false; + if (fread(&w, sizeof(size_t), 1, f) < 1) return false; + } + else { + if (fscanf(f, "%lu %lu\n", &h, &w) < 2) return false; + } + if (fg) { + // TODO + return false; + } + else { + reset(h, w, Pixel(0)); + } + return true; + } + + /*! @brief new一個自己 + * + * @return 一個new出來的Bitmap<Pixel> + */ + ObjBase* create() const { + return new Bitmap(); + } + + /*! @brief 複製資料 + * + * 輸入型別是 \c ObjBase \c const* + * 這裡假設實體其實是 \c Bitmap. + * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom + * + * @param [in] b 資料來源 + * @return this + */ + ObjBase* copyFrom(ObjBase const* b) { + return &(copyFrom(*(Bitmap*)b)); + } + + /*! @brief 回傳class的type + * + * @return \c char \c const\c * 形式的typename + */ + char const* ctype() const{ + static char const* ptr = typeid(*this).name(); + return ptr; + } + + /*! @brief 回傳class的type + * + * @return \c std::string 形式的typename + */ + std::string type() const { + return std::string(ctype()); + } +}; + +} + +#endif // gra_Bitmap_H__ |