5

我一直在使用 CImg 库,并且对集成和使用的简单程度感到满意。然而,我现在想画粗线(即,超过一个像素的粗细)。draw_line从函数的 API 文档(here )中不清楚如何做到这一点。该函数的第二个版本(就在文档中第一个版本的下方)甚至将纹理作为输入,但同样没有宽度。这么全面的库居然没有这个功能,似乎很奇怪。也许应该使用某种转换来完成?我知道我可以使用多边形来做到这一点(即,一个矩形,我将使用直线的法线计算多边形的角),但我担心这会慢得多。

4

3 回答 3

4

显然,“开箱即用”是不可能的,但是创建自己的例程,多次调用 CImg 的“draw_line()”例程,一到两个像素移位应该会给你想要的结果,没有很多工作。

于 2011-04-15T08:31:20.080 回答
4

此功能可用于将粗线绘制为多边形。

void draw_line(cimg_library::CImg<uint8_t>& image,
    const int x1, const int y1,
    const int x2, const int y2,
    const uint8_t* const color,
    const unsigned int line_width)
{
    if (x1 == x2 && y1 == y2) {
        return;
    }
    // Convert line (p1, p2) to polygon (pa, pb, pc, pd)
    const double x_diff = std::abs(x1 - x2);
    const double y_diff = std::abs(y1 - y2);
    const double w_diff = line_width / 2.0;

    // Triangle between pa and p1: x_adj^2 + y_adj^2 = w_diff^2
    // Triangle between p1 and p2: x_diff^2 + y_diff^2 = length^2 
    // Similar triangles: y_adj / x_diff = x_adj / y_diff = w_diff / length
    // -> y_adj / x_diff = w_diff / sqrt(x_diff^2 + y_diff^2) 
    const int x_adj = y_diff * w_diff / std::sqrt(std::pow(x_diff, 2) + std::pow(y_diff, 2));
    const int y_adj = x_diff * w_diff / std::sqrt(std::pow(x_diff, 2) + std::pow(y_diff, 2));

    // Points are listed in clockwise order, starting from top-left
    cimg_library::CImg<int> points(4, 2);
    points(0, 0) = x1 - x_adj;
    points(0, 1) = y1 + y_adj;
    points(1, 0) = x1 + x_adj;
    points(1, 1) = y1 - y_adj;
    points(2, 0) = x2 + x_adj;
    points(2, 1) = y2 - y_adj;
    points(3, 0) = x2 - x_adj;
    points(3, 1) = y2 + y_adj;

    image.draw_polygon(points, color);
}

line_width具有20 和 3 种颜色的基准。第一次是使用这个功能,第二次是使用image.draw_line().

  • 1000,1000 至 2000,2000:216 µs / 123 µs
  • 2000,2000 到 8000,4000:588 µs / 151 µs
  • 3000,1000 至 3020,1000:21 µs / 5 µs
于 2018-06-04T07:35:35.493 回答
1

基本上,这段代码与@vll 的答案相同,但也处理了(x1-x2)/(y1-y2) < 0(我删除abs函数)时的情况。

void draw_line(cimg_library::CImg<uint8_t>& image,
      const int x1, const int y1,
      const int x2, const int y2,
      const uint8_t* const color,
      const uint8_t line_width,
      const double opacity=1.0)
   {
      if (x1 == x2 && y1 == y2) {
         return;
      }
      // Convert line (p1, p2) to polygon (pa, pb, pc, pd)
      const double x_diff = (x1 - x2);
      const double y_diff = (y1 - y2);
      const double w_diff = line_width / 2.0;

      // Triangle between pa and p1: x_adj^2 + y_adj^2 = w_diff^2
      // Triangle between p1 and p2: x_diff^2 + y_diff^2 = length^2 
      // Similar triangles: y_adj / x_diff = x_adj / y_diff = w_diff / length
      // -> y_adj / x_diff = w_diff / sqrt(x_diff^2 + y_diff^2) 
      const int x_adj = y_diff * w_diff / std::sqrt(std::pow(x_diff, 2) + std::pow(y_diff, 2));
      const int y_adj = x_diff * w_diff / std::sqrt(std::pow(x_diff, 2) + std::pow(y_diff, 2));

      // Points are listed in clockwise order, starting from top-left
      cimg_library::CImg<int> points(4, 2);
      points(0, 0) = x1 - x_adj;
      points(0, 1) = y1 + y_adj;
      points(1, 0) = x1 + x_adj;
      points(1, 1) = y1 - y_adj;
      points(2, 0) = x2 + x_adj;
      points(2, 1) = y2 - y_adj;
      points(3, 0) = x2 - x_adj;
      points(3, 1) = y2 + y_adj;

      image.draw_polygon(points, color, opacity);
   }
于 2022-01-30T04:36:06.420 回答