aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/gra/Bitmap.h
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
commitd5052f1c296dddf51b3e83d59bf3e3c1952cb2d0 (patch)
tree16f7920c5079e0aefcf9509d2dbab59c464d42bd /meowpp/gra/Bitmap.h
parentbd58f63900410ec4764031f2e6de2d75e91434b3 (diff)
downloadmeow-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.h411
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__