Doubt in Graphics


#1

Hi Jules,
In many places you are using fillRect() method for drawing 1 pixel hotizontal or vertical line…
Is there any reason why you are not using drawline() method


#2

Yes - drawLine is for drawing anti-aliased lines which needn’t be exactly aligned to each pixel - e.g. if you drew a vertical line at a non-integer x postion, it’d actually be two pixels wide. fillRect is also probably a bit faster.


#3

:shock:

Strangely, I jumped on the forum just now to search for this exact issue.

So glad to have waited to today to look into this bug. Yes I am calling it a bug in the graphics API because the underlying behavior defies reasonable expectations.

Indeed, antialiasing should be optional, but that is another issue entirely.


#4

It’s certainly not a bug! I’m old enough to remember when you expected a ‘line’ to be an integer-aligned bresenham string of pixels, but these days they’re polygons!


#5

Yeah, I’ve got to agree completely with Jules here.

I’m not sure, in this day and age, under what normal[1] circumstances one would need to draw a line other than axials without anti-aliasing.

[1] Note, I’m saying this as someone who does need to draw lines without anti-aliasing, but I consider my needs specialized enough that I’m happy to provide equally specialized code of my own.


#6

[quote=“valley”]Yeah, I’ve got to agree completely with Jules here.

I’m not sure, in this day and age, under what normal[1] circumstances one would need to draw a line other than axials without anti-aliasing. [/quote]

I am specifically referring to axial lines. If I set a pixel width of 1 at a particular color, I should not get a 2 pixel line back with some unintended alpha value. Antialiasing is really not part of the discussion in this case.

But about anti-aliasing:

I fully understand the reaction against the “old days” and the preference for candy-coated UI basics, but IMO a general framework provides a switch for anti-aliasing. As the designer of such a framework, you should not assume to know the design requirements of each and every project that may benefit from the package in every other way. In other words, being dismissive of such requests is not really fair. I can accept that it’s a hassle and you simply would rather not be bothered, but that is not nor has it ever been your rebuttal AFAIK re. non-antialiased text and in this case, 1 pixel width axial lines. The ‘old way’ is just as valid a design choice as anything else. You’re dead wrong for thinking otherwise.

Sorry if I am coming off a little harsh on this. I mean no disrespect, I’m just strongly disagreeing with your stance.


#7

Well for axials, you can use the drawVerticalLine and drawHorizontalLine methods. These will always give what you expect.

I don’t recall with JUCE lines whether they’re centered at .5 or at 0, but if it’s the former, you’ll be getting a two pixel line if you call a line draw function with an integer value. I’m not in a position where I can easily check this, but it’s perhaps something you could try. To some degree, if this is the case, the same will hold true for non-axial lines, though obviously they’ll still be anti-aliased.


#8

Yep, they work for the special case rather than drawRect or fillRect… Less obtuse of a solution.

[quote=“valley”]
I don’t recall with JUCE lines whether they’re centered at .5 or at 0, but if it’s the former, you’ll be getting a two pixel line if you call a line draw function with an integer value. I’m not in a position where I can easily check this, but it’s perhaps something you could try. To some degree, if this is the case, the same will hold true for non-axial lines, though obviously they’ll still be anti-aliased.[/quote]

This is interesting. I always use integer coordinates, but subtracting off 0.5 from all values to drawLine yielded mostly 1px lines as expected. I guess this indicates that juce lines are centered at .5? Maybe it makes the most sense blur lines out in all directions rather than choose just one direction? shouldn’t the extrema be blurred out 1 pixel as well to maintain continuity when shapes are constructed out of lines? I don’t know enough about this stuff, but it seems really unintuitive to me. I never had these issues with Quartz or GDI+ (although thank goodness I don’t have to use those anymore!).

Take a look at this:

The line width is set to 1. The outer rectangle is made with drawRect, the inner is made with drawLine. Clearly the lines ‘bleed’ outward from the coordinates.

This one was made with drawHorizontalLine and drawVerticalLine:

I don’t know what’s up with the lower right corner. I know I’m not asking for that gap.

… sigh. This is more trouble than it’s worth. I’m going to stick with fillRect.


#9

[quote]
I guess this indicates that juce lines are centered at .5?[/quote]

No, the exact opposite is true. Think about it: when you get the 2-pixel wide blurred line, it’s because it’s straddling a pixel boundary.

To make it do what you want it to, the lines would need to be offset by .5. But that would mean that the coords you pass to drawLine would be inconsistent with the coords used by all the other vector drawing ops. And would you add or subtract 0.5…? It’s not as straightforward as it sounds!


#10

In this case, you’d add, surely? If you want a one pixel line at pixel co-ordinate zero, it’d need to be offset positively by 0.5 to ensure that the line exists within the area of pixel zero.

ObGrumble: I’m always somewhat surprised at how few graphics books raise the issue of how the complexities encountered when switching between discrete and floating space grids. It is, as you say, significantly more fiddly than it would seem at first blush. And don’t get me started on area calculations based on pixel counting that neglect to distinguish between four and eight connectivity. I’ve seen that in more than a few academic papers. :frowning: