5

私はCImgライブラリを使用しており、統合と使用がいかに簡単であるかに満足しています。ただし、太い線(つまり、1ピクセル以上の太さ)を描画したいと思います。draw_line関数のAPIドキュメント(ここ)から、これをどのように行うことができるかは明らかではありません。関数の2番目のバージョン(ドキュメントの最初のバージョンのすぐ下)は、入力としてテクスチャを取りますが、幅はありません。このような包括的なライブラリにこの機能がないのは奇妙に思えます。おそらく、それはある種の変換を使用して行われることになっていますか?ポリゴン(つまり、線の法線を使用してポリゴンの角を計算する長方形)を使用してそれを実行できることは知っていますが、それが大幅に遅くなるのではないかと心配しています。

4

3 に答える 3

4

どうやら、「すぐに使える」ことはできませんが、CImgの「draw_line()」ルーチンを1回または2ピクセルシフトして複数回呼び出す独自のルーチンを作成すると、必要な結果が得られます。仕事いっぱい。

于 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_width20色と3色のベンチマーク。1回目はこの関数を使用し、2回目はを使用して1ピクセル幅の単一の線を描画し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 に答える