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