AGG第四十七課渲染抗鋸齒線的寬度問題探討

系統(tǒng)運維

代碼如下:

創(chuàng)新互聯長期為上千客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態(tài)環(huán)境。為商南企業(yè)提供專業(yè)的成都網站建設、成都網站制作,商南網站改版等技術服務。擁有十余年豐富建站經驗和眾多成功案例,為您定制開發(fā)。

agg::path_storage path;

for (int i = 100; i < 500; i=i+100)

{

path.move_to(i, 100);

path.line_to(i, 400);

}

for (int ii = 120; ii < 550; ii=ii+100)

{

path.move_to(ii+0.5, 100);

path.line_to(ii+0.5, 400);

}

agg::conv_stroke<agg::path_storage> stroke(path);

stroke.width(1.0);

ras.add_path(stroke);

agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(255,0,0));

分析:不知道你有沒有發(fā)現浮點坐標渲染的線段似乎更加細,然后似乎深些??梢岳^續(xù)替換

輪廓線寬為0.5,效果一樣。當然完全局限于當前的顯示屏的分辨率,這就是為什么需要專業(yè)

的電腦處理圖像的原因。如果線寬設置為1.5,目前暫時沒有發(fā)現什么不同。

從郵件中分析得出,為什么浮點型0.5渲染的線會顏色深些,這是由于像素實際上是在100和101之間,在這里我對于像素不做過多的定義,假設像素有50%在100點上,50%在101上,這個時候如果移動到100.5如果線寬剛好是1,實際上就是一個完整的像素點,一個完整的矩形,但是如果少了0.5實際上就是橫跨兩個像素點,這個情況下,實際上就引入了亞像素精度,將像素也就是坐標格子進行了劃分,對于坐標格子實際上采用了透明色的處理,之所以沒有鋸齒,不是因為不存在,而是因為被透明處理了,設置了一定的透明度,使得我們并沒有注意到,如果在高分辨率的顯示器,還是可以看出來的。

郵件中提及到了,如果渲染橫線或者豎線,實際上可以采用低級的渲染器,其中包括render_base,這種情況下,避免了引入亞像素精度,提高了性能,這種情況,在其他的章節(jié)會提及。

如下摘錄,相關的討論:

> Is the use of copy/blend hline/vline advised for efficiency or for

> better rendering?

Only for the sake of performance. And if you need subpixel positioning, you can

draw two adjacent horizontal/vertical lines calculating the intensity according

to the position (i.e, simulating the rasterizer for this simple case) - it will

be more efficient because of excluding some expensive operations.

Maxim> Actually, if you need to draw horizontal and vertical lines

Maxim> of exactly 1 pixel width, always aligned to pixels (say,

Maxim> coordinate grid), and if you are absolutely sure you won\'t

Maxim> need to transform them using AGG converters, it\'s better to

Maxim> use low level renderer_base::copy_hline(), copy_vline(),

Maxim> blend_hline(), blend_vline(), or, if you need to draw

Maxim> dashed/dotted lines, blend_solid_hspan(),

Maxim> blend_solid_vspan(). The latest require an array of

Maxim> covers, that can be 0 for gaps and 255 for

Maxim> dashes. Intermediate values will be drawn with respective

Maxim> opacity.

Actually, I don\'t know that they will be exactly 1 pixel wide (but I

am drawing a coordinate grid so would like to align them to pixels).

I missed that the pixels were aligned to the 0.5 point rather than the

integer point.

Is the use of copy/blend hline/vline advised for efficiency or for

better rendering?

> That\'s just what I needed to know.

Actually, if you need to draw horizontal and vertical lines of exactly 1 pixel

width, always aligned to pixels (say, coordinate grid), and if you are

absolutely sure you won\'t need to transform them using AGG converters, it\'s

better to use low level renderer_base::copy_hline(), copy_vline(),

blend_hline(), blend_vline(), or, if you need to draw dashed/dotted lines,

blend_solid_hspan(), blend_solid_vspan(). The latest require an array of

covers, that can be 0 for gaps and 255 for dashes. Intermediate values will

be drawn with respective opacity.

Pierre> Here you put the line centered exactly on the center of

Pierre> the pixels sitting between x=200 and x=201. When painting

Pierre> with 1.0 width, you will fill exactly one pixel (at

Pierre> x=200).

Pierre> So the matter here is not about AGG handling ints and

Pierre> floats in different ways, just that AGG accepts sub-pixel

Pierre> positioning, and its anti-aliasing machinery handles it

Pierre> quite well.

探討:嘗試修改浮點坐標為整型,+0.5替換為1,發(fā)現兩根線完全沒有什么分別

摘自:http://sourceforge.net/p/vector-agg/mailman/vector-agg-general/?viewmonth=200403

I am drawing some horizontal and vertical paths and notice that the

rasterized line width depends on whether I use an integer or float as

the x coordinate below. I know I can fix this by always passing and

integer (but this causes other complications), but am wondering if

this is the desired behavior, and if there is some bit of agg magic

that will display the lines with the same thickness even if the x

coords are sometimes integers, sometimes floats.

The critical bit is here (complete example below)

agg::path_storage path;

rb.clear(agg::rgba(1.0, 1.0, 1.0, 1.0));

path.move_to(100, 100);

path.line_to(100, 400);

path.move_to(200.5, 100);

path.line_to(200.5, 400);

agg::conv_stroke<agg::path_storage> stroke(path);

stroke.width(1.0);

ras.add_path(stroke);

And here is a complete example.

Thanks!

John Hunter

#include <fstream>

#include agg_path_storage.h

#include agg_pixfmt_rgb24.h

#include agg_pixfmt_rgba32.h

#include agg_rasterizer_scanline_aa.h

#include agg_renderer_scanline.h

#include agg_rendering_buffer.h

#include agg_scanline_bin.h

#include agg_scanline_p32.h

#include agg_conv_stroke.h

typedef agg::pixel_formats_rgba32<agg::order_rgba32> pixfmt;

typedef agg::renderer_base<pixfmt> renderer_base;

typedef agg::rasterizer_scanline_aa<> rasterizer;

// antialiased

//typedef agg::renderer_scanline_p_solid<renderer_base> renderer;

//typedef agg::scanline_p8 scanline;

// aliased

typedef agg::scanline_bin scanline;

typedef agg::renderer_scanline_bin_solid<renderer_base> renderer;

int main(int argc, char* argv[]) {

unsigned width(512), height(512);

unsigned stride(width*4);

size_t NUMBYTES(width*height*4);

agg::int8u buffer[NUMBYTES];

agg::rendering_buffer rbuf;

rbuf.attach(buffer, width, height, stride);

//draw_anti_aliased

pixfmt pixf(rbuf);

renderer_base rb(pixf);

renderer ren(rb);

rasterizer ras;

scanline sline;

agg::path_storage path;

rb.clear(agg::rgba(1.0, 1.0, 1.0, 1.0));

path.move_to(100, 100);

path.line_to(100, 400);

path.move_to(200.5, 100);

path.line_to(200.5, 400);

agg::conv_stroke<agg::path_storage> stroke(path);

//stroke.line_cap(cap);

//stroke.line_join(join);

stroke.width(1.0);

ras.add_path(stroke);

ren.color(agg::rgba(0.0, 0.0, 0.0, 1.0));

ras.render(sline, ren);

size_t i;

std::ofstream of2( line_aa.raw, std::ios::binary|std::ios::out);

for (i=0; i<NUMBYTES; ++i)

of2.write((char*)&buffer[i], sizeof(char));

}

摘自:http://permalink.gmane.org/gmane.comp.graphics.agg/1428

問題:

Is it possible to draw non-anti-aliased dashed lines using a Bresenham-type algorithm in Antigrain? For instance, I\'d like to draw a 45o dotted line, where every other pixel is solid.

I\'ve tried several approaches, including using agg::renderer_outline_p_w_picpath with an p_w_picpath that defines the dashes (http://permalink.gmane.org/gmane.comp.graphics.agg/972) and using agg::conv_dash and setting gamma_threshold(0.5) (http://permalink.gmane.org/gmane.comp.graphics.agg/1428), but I can\'t seem to get a clean drawing for the 45o dotted case.

2/ I would like to render aliased lines. After some tests, I\'m not able

> to render odd line width. If I try to render a line with a width = 3, I

> got a 4 pixel line. What do I need to do to ?

討論:

That\'s not easy. In short words, the visual width of the horizontal or vertical

lines depends not only on the stroke width you have set, but also on the

subpixel position of that line. A common way to draw everything aliased is to

set AA gamma:

ras.gamma(agg::gamma_threshold(0.5));

Here you can use scanline_bin and renderer_scanline_bin_solid that work faster.

But the problem still persists; I wrote about it here:http://antigrain.com/tips/line_alignment/line_alignment.agdoc.htmlNow imagine that you draw aliased lines, and set pixel if the coverage value

exceeds a certain threshold.

In other words you can easily draw aliased lines of exactly 1 pixel width

(Bresenham-like algorithm). Everything wider leads to problems. But even

reguilar jagged lines of 1 pixel width have different visual thickness

depending on the tangent. A line of 45 degree steep has visual thickness of

1/sqrt(2)=0.7 pixels.

文章名稱:AGG第四十七課渲染抗鋸齒線的寬度問題探討
URL分享:http://muchs.cn/article8/cgpjip.html

成都網站建設公司_創(chuàng)新互聯,為您提供企業(yè)建站、服務器托管、Google、用戶體驗、網站建設、營銷型網站建設

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

成都網站建設