Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
483 views
in Technique[技术] by (71.8m points)

.net - Pixel behaviour of FillRectangle and DrawRectangle

nearly every time I use Graphics.DrawRectangle or Graphics.FillRectangle (the int versions) I seem to miss the pixels on the right and bottom border of the rectangle I want to draw.

What is the exact definition of which pixels get filled by

Graphics.FillRectangle(brush,x,y,width,height)

and

Graphics.DrawRectangle(pen,x,y,width,height) // pen is one pixel width, i.e. width=0f

and is there a logical explanation for it? (so I can finally remember the behaviour :) ...)

EDIT:

Using Oleg Zhuk's marvelous Try GDI+ application, I was able to find a curious difference between FillRectangle and DrawRectangle:

FillRectangle(brush,0,0,1,1) draws a single dot at (0,0) which is somehow understandable (it's a rectangle with width and height one after all).

DrawRectangle(pen,0,0,1,1) on the other hand draws a small 2 by 2 pixel rectangle.

The same behaviour is shown for other width/height combinations, DrawRectangle always extends one pixel more to the left and the bottom (which is a little annoying e.g. when using the ClientRectangle property to draw a frame around a control)

My first question solved (how to they behave...) there still remains the second one: Why do they behave this way?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

These methods work correctly, you just have to take into account effects of anti-aliasing and rounding.

First, turn on anti-aliasing to see everything (not only rounded result):

graphics.SmoothingMode = SmoothingMode.AntiAlias;

Now FillRectangle(10,10,10,10) will produce blurry result and DrawRectangle(10,10,10,10) will be sharp.

The blurry result means that you have pixel coordinates off-grid. If you need to call:

graphics.FillRectangle(9.5f, 9.5f, 10, 10);

to align top-left corner of the rectangle on grid.

The DrawRectangle is sharp because it uses Pen of width 1.0. So the line starts on the pixel center and goes 0.5 pixels in both directions, thus filling exactly 1 pixel.

Note that width and height are computed this way:

width = (right - left) = 19.5 - 9.5 = 10
height = (bottom - top) = ...

Notice that 19.5 is a right/bottom coordinate of the rectangle also aligned on the grid and the result is a whole number.

You can use different formula:

width2 = (right - left + 1)

But this applies on rounded coordinates only, since the smallest unit is 1 pixel. When working with GDI+ that uses anti-aliasing, be aware of the fact that the point has zero size and lies in the center of pixel (it is not the whole pixel).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...