• 实区域种子填充算法


    本文给出三个实区域填充算法的c++实现。三个填充算法分别为边界填充算法、泛洪填充算法、扫描线种子填充算法,相关的理论与算法描述这里不涉及。

    边界填充算法

    st int direction[] = { 1, 0, -1, 0, 0, 1, 0, -1,  1, 1, 1, -1, -1, 1, -1, -1 };
    
    void BoundaryFill4(HDC hdc, int x, int y, COLORREF fill_color, COLORREF boundary_color)
    {
      COLORREF cur_color = GetPixel(hdc, x, y);
      if ((cur_color != boundary_color) && (cur_color != fill_color)) {
        SetPixel(hdc, x, y, fill_color);
        for (int i = 0; i < sizeof(direction) / sizeof(direction[0]) / 2; i += 2) {
          BoundaryFill4(hdc, x + direction[i], y + direction[i + 1], fill_color, boundary_color);
        }
      }
    }
    
    void BoundaryFill8(HDC hdc, int x, int y, COLORREF fill_color, COLORREF boundary_color)
    {
      COLORREF cur_color = GetPixel(hdc, x, y);
      if ((cur_color != boundary_color) && (cur_color != fill_color)) {
        SetPixel(hdc, x, y, fill_color);
        for (int i = 0; i < sizeof(direction) / sizeof(direction[0]); i += 2) {
          BoundaryFill8(hdc, x + direction[i], y + direction[i + 1], fill_color, boundary_color);
        }
      }
    }
    

    泛洪填充算法

    void FloodFill4(HDC hdc, int x, int y, int fill_color, int old_color)
    {
      COLORREF cur_color = GetPixel(hdc, x, y);
      if (cur_color == old_color) {
        SetPixel(hdc, x, y, fill_color);
        int z = sizeof(direction) / sizeof(direction[0]) / 2;
        for (int i = 0; i < sizeof(direction) / sizeof(direction[0]) / 2; i += 2) {
          FloodFill4(hdc, x + direction[i], y + direction[i + 1], fill_color, old_color);
        }
      }
    }
    
    void FloodFill8(HDC hdc, int x, int y, int fill_color, int old_color)
    {
      COLORREF cur_color = GetPixel(hdc, x, y);
      if (cur_color == old_color) {
        SetPixel(hdc, x, y, fill_color);
        for (int i = 0; i < sizeof(direction) / sizeof(direction[0]); i += 2) {
          FloodFill4(hdc, x + direction[i], y + direction[i + 1], fill_color, old_color);
        }
      }
    }
    

    扫描线种子填充算法

    void ScanLineSeedFill(HDC hdc, RECT re, int x, int y, int fill_color, int boundary_color)
    {
      if (x < re.left || x > re.right || y < re.top || y > re.bottom) return;
    
      std::stack<POINT> point_stack;
      
      point_stack.push(POINT{ x, y });
      while (!point_stack.empty()) {
        POINT point = point_stack.top();
        point_stack.pop();
    
        int x = point.x, y = point.y;
        if ((GetPixel(hdc, x, y) & 0xFFFFFF) == boundary_color)
          continue;
        std::tuple<int, int> interval = FindInterval(hdc, re, x, y, fill_color, boundary_color);
        std::vector<int> top_seeds = FindSeeds(hdc, std::get<0>(interval), std::get<1>(interval),
                                               y - 1, fill_color, boundary_color);
        std::vector<int> bottom_seeds = FindSeeds(hdc, std::get<0>(interval), std::get<1>(interval),
                                                  y + 1, fill_color, boundary_color);
        std::for_each(std::begin(top_seeds), std::end(top_seeds), [&point_stack, y](int x) { point_stack.push(POINT{ x, y - 1 }); });
        std::for_each(std::begin(bottom_seeds), std::end(bottom_seeds), [&point_stack, y](int x) { point_stack.push(POINT{ x, y + 1 }); });
      }
    }
    
    
    std::tuple<int, int> FindInterval(HDC hdc, RECT re, int x, int y, int fill_color, int boundary_color)
    {
      int left = x, right = x, tmp_x = x;
    
      if ((GetPixel(hdc, x, y) & 0xFFFFFF) != boundary_color)
        SetPixel(hdc, x, y, fill_color);
      for (tmp_x = x; --tmp_x >= re.left;) {
        if ((GetPixel(hdc, tmp_x, y) & 0xFFFFFF) == boundary_color)
          break;
        SetPixel(hdc, tmp_x, y, fill_color);
      }
      left = tmp_x + 1;
      for (tmp_x = x; ++tmp_x < re.right;) {
        if ((GetPixel(hdc, tmp_x, y) & 0xFFFFFF) == boundary_color)
          break;
        SetPixel(hdc, tmp_x, y, fill_color);
      }
      right = tmp_x - 1;
      return std::make_tuple(left, right);
    }
    
    
    std::vector<int> FindSeeds(HDC hdc, int x_left, int x_right, int y, int fill_color, int bounary_color)
    {
      std::vector<int> right_most;
      bool in_fill_area = false;
    
      for (int i = x_left; i <= x_right; ++i) {
        int cur_color = GetPixel(hdc, i, y) & 0xFFFFFF;
        if (!in_fill_area && cur_color != fill_color && cur_color != bounary_color) {
          in_fill_area = true;
        } else if (in_fill_area && (cur_color == fill_color || cur_color == bounary_color)) {
          in_fill_area = false;
          right_most.push_back(i - 1);
        }
        if (i == x_right && in_fill_area)
          right_most.push_back(i);
      }
      return right_most;
    }
    

    这里给出种子扫描线算法的填充结果:

  • 相关阅读:
    知名网站的技术发展历程
    自己的代码仓库源码
    重构着讲解设计原则与模式——从DIP中“倒置”的含义说接口的正确使用
    jQuery Colorbox插件
    测试是否支持DOMAttrModified
    python(贪吃蛇)
    界面简洁,无广告,无插件,无网络却功能强播放器
    Asp.Net MVC 4 Web API
    理解MVC底层运行机制
    BS单点登陆(SSO)实现代码展示
  • 原文地址:https://www.cnblogs.com/tallisHe/p/5408369.html
Copyright © 2020-2023  润新知