Board index » delphi » Re: AntiAliasing graphics library roundup for Delphi

Re: AntiAliasing graphics library roundup for Delphi


2006-11-29 07:11:06 PM
delphi49
Eric Grange writes:
Quote
>We have a Team Coherence repository (www.teamcoherence.com)

I don't have Team Coherence... I will wait for when it is bakc into
CVS/SVN. :)
I've found out that there's a new IDE plug-in for SVN. This could be a very
interesting alternative to TC.
Some screenshots can be found here:
tondrej.blogspot.com/2006/11/delphisvn-for-delphi-7.html
Mattias
 
 

Re: AntiAliasing graphics library roundup for Delphi

Hi Nils,
Nils Haeck writes:
Quote
>I'm not too sure how much pre-multiplying actually gains you in
>performance, but it may not be much (since you're often
>memory-bandwidth limited when blending a lot of pixels). All I know
>is that my MMX alphablending (non-pre-multiplied) is faster than
>Windows' pre-multiplied AlphaBlend, but that is not an
>apples-to-apples comparison.

It is much faster because you can skip a few "div 255" operations per
blend. Of course this can be implemented in a smart way, but for
instance G32 isn't pixel perfect when doing it with MMX. Especially
the cases where a value of 255 ends up as 254 is tricky, because then
"white" on the printer becomes "very light gray", and it will cause
ugly black dots once in a while on some printers.

I'll implement my library such that premul versus non-premul is an
option, but I certainly want to put it in.
There's an excellent article on this subject by Alvy Ray Smith:
<ftp.alvyray.com/Acrobat/4_Comp.pdf>
He argues that premultiplied alpha is both more efficient and leads to more
elegant formulas.
I think it would be interesting with some benchmark comparisons between
ordinary and premultiplied blending. Even though there are bandwidth
limitations, I think there may still be some increase in performance.
Also, while premultiplying will improve performance for blending, I think
the real advantage comes when using the merge operation.
Without premultiplying you need to compute this:
a_out = a1 + a2 - a1 * a2
c_out = (c1 * a1 + c2 * (1 - a1) * a2) / a_out
and with premultiplying this is simplified to:
a_out = a1 + a2 * (1 - a1)
c_out = c1 + c2 * (1 - a1)
Btw. deriving a formula for layer merging is an interesting numerical
exercise. I managed to do that using Bayesian probability theory.
Mattias
 

Re: AntiAliasing graphics library roundup for Delphi

Indeed, I read this article too about a year ago, so that is why I am
implementing it :)
The gain is to be found mostly in the simplified calculation of the alpha of
the result.
Nils
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
I've found out that there's a new IDE plug-in for SVN. This could be a very
interesting alternative to TC.
I've converted long ago to Tortoise and shell based VCS, I am not sure
I'll ever revert to using an IDE-based one willingly :)
Eric
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
There's an excellent article on this subject by Alvy Ray Smith:
That paper was written in 1995, that was more than ten years ago...
In 95, Everybody was still being impressed by 800x600 and 1027x768 @256
colors, let alone the "hicolor" 16bits per pixel modes, or the
"truecolor" at 24bits per pixel which was considered overkill by many... ^_^
Quote
He argues that premultiplied alpha is both more efficient and leads to more
elegant formulas.
However this surfaces an internal optimization at the library interface
level: color channels no longer hold actual color values, alpha and
color channels cannot be manipulated independently, etc.
That said, are there any plans for a GR128 library at some point?
I've got a couple of HDR processing that could use it, and some SSE code
I could contribute.
Eric
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
However this surfaces an internal optimization at the library interface
level: color channels no longer hold actual color values, alpha and color
channels cannot be manipulated independently, etc.
I don't agree, conceptually there's much to say for "pre-multiplied alpha"
(which is a wrong term anyway, the *colors* are premultiplied, not alpha).
In case of premultiplied color C' it means that it is reduced from the full
color C by a factor of alpha (0..100%):
C' = alpha * C
In this case, C' represents the "amount of color" present in that pixel,
e.g. if a pixel is 50% occluded, you can imagine this as "the bucket with
color for that pixel is also half-full".
If you want to be really precise conceptually you should even go a step
further than just alpha, and use a specific "cover" value next to the
"alpha", (so for RGB you'd have cover-alpha-R-G-B: 5 values). "cover"
represents the % visible of the pixel, and "alpha" represents the
transparency (as in glass).
There's a nice chapter in the PDF reference about this.
Esp when rendering shapes that just touch, instead of overlap, like often
seen in flash, the currently used "alpha" formulas in most graphics libs
fail miserably. The edges where two shapes meet often show a value of alpha
< 100%, while the pixel should actually be covered completely (albeit with 2
colors that mix).
This simply is the result of two consecutive blendings, e.g. for shapes that
touch and both cover 50% leading to an alpha of:
0.5 + (1 - 0.5) * 0.5 = 0.75,
where it should have been 1.0
Some libs try to offer a cloth for the bleeding with gamma correction but it
really does not help because the blending model is conceptually wrong.
My idea is to provide a special blending parameter when rendering layers,
that indicate whether a group of shapes are all on the same plane and when
sharing a border they should be rendered with a different model. Maybe this
is already done (I seem to recollect seeing some fairly recent posts in the
AGG group), but I haven't seen it yet in any Delphi library.
Nils
 

Re: AntiAliasing graphics library roundup for Delphi

Eric Grange writes:
Quote
>There's an excellent article on this subject by Alvy Ray Smith:

That paper was written in 1995, that was more than ten years ago...

In 95, Everybody was still being impressed by 800x600 and 1027x768
@256 colors, let alone the "hicolor" 16bits per pixel modes, or the
"truecolor" at 24bits per pixel which was considered overkill by
many... ^_^
Yeah, in ten years when we all have holographic displays, we will remember
this fuss about HDR... :)
Quote
>He argues that premultiplied alpha is both more efficient and leads
>to more elegant formulas.

However this surfaces an internal optimization at the library
interface level: color channels no longer hold actual color values,
alpha and color channels cannot be manipulated independently, etc.
I think you are right that this representation of color values can be
disadvantageous.
As an example: Assume that we have a tuple (A, C), where A is alpha and C is
the color value (premultiplied by A). Now, what if we want to change the
opacity to some new value B?
This would involve the following computations:
C := C * B/A;
A := B;
Without premultiplication, we would only need to update the alpha value.
Quote
That said, are there any plans for a GR128 library at some point?
I've got a couple of HDR processing that could use it, and some SSE
code I could contribute.
Well, it is definitely on the horizon. We are thinking about a generic
solution for custom bitmap formats.
This would require that each bitmap has its own signature that describes its
representation in memory.
I think the GDI BITMAPV4HEADER would be much too limited for this:
<msdn2.microsoft.com/en-us/library/ms532300.aspx>
We need something that will allow you to encode the color mode of each
plane. Perhaps we should also try to add support for non-interleaved data.
Once we have this worked out, we can start writing routines for converting
between various bitmap formats and we can add new optimized low-level
routines.
Anyhow, since this is an open source project, anyone is welcome to
contribute with source code and ideas.
If you want you could send the code to my e-mail (mattias at centaurix.com)
and then I will look into it later.
Mattias
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
In this case, C' represents the "amount of color" present in that pixel,
e.g. if a pixel is 50% occluded, you can imagine this as "the bucket with
color for that pixel is also half-full".
Where I disagree is that how much a pixel is occluded or occluding isn't
a property of the pixel, but of the blending operation, where alpha can
be factor, or not, can be used "directly", or not.
Premultiplied alpha (and consequences) is a bit like the old fixed
function pipeline in 3D graphics IMO: data and its processing are finely
intertwined, data is "built for" a specific processing, and processings
are "built for" a specific data.
The "fixed" nature of premultiplication becomes apparent if you consider
other operations you could be willing to apply to your pixels, like
color saturation, applying a gamma or colorization (just to name things
I commonly use in my UI, to generate "deactivated"/"hot" variants and
their transitions, or adapt to theme colors).
Eric
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
Yeah, in ten years when we all have holographic displays, we will remember
this fuss about HDR... :)
There was some hardware projecting 3D images in space (projection, not
holograms iirc) demonstrated some time ago in various fairs, the
remaining issue they had was their tech allowed only to add light, no
subtract it, so the visual quality was decent only in a dark room...
But we could be getting there soon :)
Quote
Without premultiplication, we would only need to update the alpha value.
IMO premultiplication is useful as a "compiled bitmap" format of sorts,
where you know alpha blendings are the operations that will mostly
occur, and where you know the same pixels will be blended multiple times
(to amorticize the premultiplication overhead).
But performance-wise, this has to be weighted against an approach that
would "premultiply on the spot", which can certainly be made quite more
efficient than a premultiplication pass (per pixel) because of the
reduced memory bandwidth needs, so you may need more quite a few
blendings before you can recoup the premultiplication cost.
There are also 3DNow! and SSE instructions that allow to compute fairly
quickly (division included), at floating point precision and with very
fast conversions to and from integers. So it is feasible to perform
everything in a mathematically "correct" fashion, something that wasn't
possible in 1995 (at interactive speeds anyway).
Quote
Well, it is definitely on the horizon. We are thinking about a generic
solution for custom bitmap formats. [...]
Anyhow, since this is an open source project, anyone is welcome to
contribute with source code and ideas.
I'll be hovering around the newsgroups then :)
It's something I had started for GLScene2 (to preprocess HDR textures,
and postprocess HDR output mainly), but couldn't find the time for
(itself or its usage).
Eric
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
Where I disagree is that how much a pixel is occluded or occluding isn't a
property of the pixel, but of the blending operation, where alpha can be
factor, or not, can be used "directly", or not.
That depends on how you interpret the alpha value. For full-color maps
you're right.. you see the alpha as transparency and it is nice to still
know what the color properties are in "full resolution", even if alpha is
very small.
However for intermediate blending operations, you can interpret alpha as the
cover. So if alpha=0, there is simply no shape in that pixel. How much sense
does it make to store color information then?
I think the best solution is to have a bitmap format that specifically knows
about premultiplication. The user or application will interact mostly with
the non-premultiplied bitmaps, but when rendering, the renderer will use
premultiplied bitmaps to speed things up.
There's hardly any extra costs involved, except from having to convert
full->pre before and pre->full after.
full->pre is relatively cheap, and a quick test for alpha=255 avoids doing
the multiplication.
pre->full costs more, but in almost all cases the user/app doesn't want the
result, it just wants the result displayed on a GDI device, and for that a
backdrop with alpha=255 is mostly used, so there won't be any alpha < 255
anyway.
Nils
 

Re: AntiAliasing graphics library roundup for Delphi

Eric Grange writes:
Quote
IMO premultiplication is useful as a "compiled bitmap" format of
sorts, where you know alpha blendings are the operations that will
mostly occur, and where you know the same pixels will be blended
multiple times (to amorticize the premultiplication overhead).
A similar question would be whether or not to support compressed bitmap
formats. I guess for RLE encoded bitmaps you could write quite efficient
blending routines. For instance, if you have a lot of fully transparent
pixels, then you can simply skip to the next non-transparent pixel. Also it
would probably give better memory performance.
Quote
There are also 3DNow! and SSE instructions that allow to compute
fairly quickly (division included), at floating point precision and
with very fast conversions to and from integers. So it is feasible to
perform everything in a mathematically "correct" fashion, something
that wasn't possible in 1995 (at interactive speeds anyway).
I think it would be really cool if we could replicate the current GR32
behaviour for HDR images. Although, another problem that springs to mind is
how to efficiently convert from HDR to DIBs (i.e. for blitting to the
screen). Would it make sense to use OpenGL for this rather than the GDI?
Quote
>Well, it is definitely on the horizon. We are thinking about a generic
>solution for custom bitmap formats. [...]
>Anyhow, since this is an open source project, anyone is welcome to
>contribute with source code and ideas.

I'll be hovering around the newsgroups then :)
Yep, sounds like a good idea...
Quote
It's something I had started for GLScene2 (to preprocess HDR textures,
and postprocess HDR output mainly), but couldn't find the time for
(itself or its usage).
Where can I find more info about the GLScene2 project?
Mattias
 

Re: AntiAliasing graphics library roundup for Delphi

On Fri, 1 Dec 2006 01:21:31 +0100, "Mattias Andersson"
<XXXX@XXXXX.COM>writes:
Quote
I think it would be really cool if we could replicate the current GR32
behaviour for HDR images
One thing I have found difficult with HDR is filtering. Filters with
negative values/lobes can produce very "unplesant" results.
Unfortunately that rules out most of the better filters :(
Still not sure how to best deal with it... I have tried some adaptive
approaches (ie use one filter for "normal range" and a positive-only
filter for pixels with "large range").
- Asbjørn
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
I've converted long ago to Tortoise and shell based VCS, I am not sure
I'll ever revert to using an IDE-based one willingly :)
Anyway, delphisvn is not a full-featured Subversion client (wasn't
intended to be) and can hardly be used as your only Subversion client.
All it aims to do is provide IDE integration to make some of the often
performed Subversion-related actions easier.
For example, I have installed and regularly use TortoiseSVN, svn.exe and
delphisvn. Tortoise is great, I love it. The command line client is
useful for automated builds (e.g. from specific revisions). I use
delphisvn mainly for quick checking for modifications and the integrated
history/diff view.
HTH
TOndrej
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
I'm currently in the process of evaluating anti-aliased 2D graphics
alternatives
under Delphi for the revamp of an internal library, below are those I
found, if
anyone knows one that isn't there, I'd be grateful for links :)

Keep in mind my comments below are for antialiased graphics only, with
software
rendering (no hardware acceleration):

* GDI super-sampling (draw on a larger bitmap then downsample it):
- low to medium speed, high memory usage
- low to high quality (but usually only "low" is practical)
- easy to maintain

* GDI+ :
- medium speed, some memory leaks to be avoided
- medium to low quality
- easy to maintain (some deployment issues to watch though)

* G32 : (www.g32.org)
- medium to high speed
- medium quality, but feature set somewhat limited
- easy to maintain

* AntiGrain : (www.aggpas.org)
- medium speed
- high quality, arguably the richest feature set
- complex to maintain

* DirectX/OpenGL :
- very slow speed when hardware not available (esp. for AA modes)
- medium quality, built-in 2D feature set limited (text output...)
- driver-specific quirks complicate maintainance

* Avalon/WPF :
- low to medium speed when hardware not available
- medium quality, rich feature set but with a retained mode renderer
- strong deployment issues for the foreseeable future

In conclusion, no definite winner yet IMO, a cross-over between AntiGrain's
features and G32 maintainability would be a godsend, and if it had the
potential
of becoming hardware accelerated one day like the last two options, this
would
be perfect... WPF is somewhat close, but dependencies and deployment
issues are
overwhelming, especially with the restrictions on pre-Vista OSes.
Any other options I'd have missed?

Eric

Hi Eric,
There is a AGG-dirived project called AggPlus which simulate GDI+
interface and implemented by AGG, however it is a C++ lib, I can't
tested... It would be great if anybody develop a lib like that but for
delphi :)
And I am currently develping a mind mapping software which using gr32 and
an extension from a Russian programmer, so far so that, except that I
don't know how to draw a spling with a arrow cap, could anybody give me a
hint? Thanks!
To Nils,
Sounds great! I like the pdf/svg import/expert, hope you to implemented to
allow little coding to output to the pdf/svg/emf, just like what GDI+
dose. and waiting for the first release to have a try!
To Mattias,
thanks very much for the greate graphics32 library! and I am very e{*word*277}d
to hear the info about the next release of gr32! Hope I can have a look on
it ASAP!
--------------
Edwin
Best Regards,
Mind Visualizer--Productive Mind Mapping Software
www.mindmapware.com
--- posted by geoForum on delphi.newswhat.com
 

Re: AntiAliasing graphics library roundup for Delphi

Quote
However for intermediate blending operations, you can interpret alpha as the
cover. So if alpha=0, there is simply no shape in that pixel. How much sense
does it make to store color information then?
Because a subsequent filtering or blending operation could be operating
on the alpha channel only, and result in a non null alpha?
Quote
How much sense does it make to store color information then?
Storing is a different issue IMO: when you set the color channels to
(0,0,0) because alpha is zero and premultiplication is used, you do not
avoid storing color information, you just "overwrote" the color
information with "black", or a darker shade of the color when alpha<255
Quote
I think the best solution is to have a bitmap format that specifically knows
about premultiplication. The user or application will interact mostly with
the non-premultiplied bitmaps, but when rendering, the renderer will use
premultiplied bitmaps to speed things up.
Yep, that is a form of "compilation", however for it to be beneficial you
have to have enough blending operations to recoup the cost of the
premultiplication, and be sure enough that the color precision lost
won't ever be needed.
Quote
There's hardly any extra costs involved, except from having to convert
full->pre before and pre->full after.
full->pre is relatively cheap, and a quick test for alpha=255
avoids doing the multiplication.
Well the conversion in itself isn't that cheap, as even if you neglect
processing cost, you will still have to read/write a lot of memory (which
will often not fit in cache), I wouldn't be surprised if it wasn't too
far in execution time from an alpha blending.
(the test for alpha can also be done in an alpha blending, so the
differential between the two will be on pixels with intermediate alphas)
Quote
pre->full costs more, but in almost all cases the user/app doesn't
want the result, it just wants the result displayed on a GDI device,
and for that a backdrop with alpha=255 is mostly used, so there won't
be any alpha < 255 anyway.
Though if the user/app ever wants a non-pre results with alpha, f.i. if
it is to be reused in another application/library, like as a texture for
3D rendering, there will be significant color artefacts on all areas
that had an alpha<255.
In the end, it is all about development time however:
If you have enough time to write and optimize both premultiplied and
non-premultiplied, then by all means you should! :)
Though if only one ought to be implemented (which is kinda what the
article suggested), premultiplication is a bit on the weak side IMO.
Eric