Agg


#1

Has anyone here used AGG with Juce? For anyone that has not seen it, it is a C++ api free and open source for commercial and non-commercial things, sans the GPC it uses which only renders poly faster, not required as AGG implements an identical, but slower version, GPC is only free for non-commercial. AGG is a 2D rendering api that is explained well on its about page. I have not used it, but seen things that have, and it does work well. I am interested in if anyone has made a Graphic’s subclass that uses it, implementing the abilities it has that Graphic does not?

EDIT: Found the demo’s section on the site, this is actually quite a bit more impressive then I had seen used elsewhere. http://www.antigrain.com/demo/index.html
Did some quick tests, this thing renders dang fast…


#2

I had a look at that and it’s certainly interesting. Integrating it into juce would be tough as it’d require quite a bit of restructuring, but is definitely something I’d like to do. Ideally I want to make the graphics renderer interchangable - e.g. so it can be built to use either CoreGraphics, GDI+ or a software-renderer.


#3

That sounds like it would work well, pluggable things are always nice.


#4

that library is the most impressive piece of code that i’ve ever seen. it’s impressively fast, perfect looking and accurate, well written and extensible as hell. i’ve used it in some testing projects, just to play with the functionalities myself and see what can be done with it. is a really complex library that would take months of study to fully understand how to use it in depth and achieve the results you’re looking for. if you don’t have tried http://www.creativedocs.net/, just give it a look. you can see a real implementation of such a library.

just some words from the developer:

“Most of the graphic libraries have a single class like “Graphics” in GDI+, that has hundred or even thousands of functions… That’s simple and in some cases quite suitable, but always very restrictive. It works well only in simple cases, at least I haven’t seen a graphical library that would completely fit all my needs. Moreover, all that kinds of libraries or standards have a syndrome of giantism. Most of the functionality is never used, but some simple things are impossible to achieve…”

he’s 100% right imho :wink:

p.s. anyway:

juces, this is the most interesting thing you could end up for juce !

lou


#5

Well, thanks for convincing me. :slight_smile:


#6

if you want just to play with it. create an image with alpha channel then:

[code]if( image )
{
uint8* buffer = image->getPixelPointer(0,0);
agg::rendering_buffer rbuf( buffer, image->getWidth(),
image->getHeight(),
-image->getWidth() * 4);

typedef agg::pixfmt_bgra32 pixfmt_type;
typedef agg::renderer_base<pixfmt_type> renderer_base_type;

// here just use agg

g.drawImageAt(image,0,0);

}
[/code]

now just take a simple example and tweak this.
hope you find useful :wink:


#7

Well, that is certainly a simple setup, now I have no excuse short of time, thanks for that, probobly saved me a good half hour there. :slight_smile:


#8

of course is a simple setup :wink:
it’s just a starting point… then is up to you…
i can see what i can do next days to extend the basic


#9

Oh I should have fun with it, just no time to play until Friday.


#10

I’m looking into using JUCE for my projects, since it seems very well designed.

Anyone looked into AGG for JUCE lately? I noticed that an anti-aliased line doesn’t look too nice in comparison with AGG… (sorry Jules)

Regards,
/r


#11

RTFM, I saw the OversamplingLevel enum in EdgeTable, looks much better now… sorry Jules :slight_smile:

/r


#12

Yeah! I’m using AGG more than a year for my project. Honestly, I even helped Maxim the AGG author (Russian guy too) to adapt AGG image resizing algorithms from the C scratch source codes. The library is definitely awesome, but I did not dare to recommend it here for JUCE as it already has excellent draw implementations and moreover they are ASM optimized.


#13

I’ve also used AGG (http://www.antigrain.com) now for drawing envelope curves. But I’ve used the Agg2D wrapper which hides most (if not all) of the gorey details when working with AGG (http://www.novadsp.com/agg2d/agg2d-2.4.zip which works with the latest LGPL licensed AGG version)

Looking at LowLevelGraphicsContext vs. Agg2D, the interfaces seem to match reasonably with only blendImageWarped missing (at a first glance).

I did a performance comparison drawing a path (stroke) with 20 line segments in it, 1.5 px wide with both JUCE (at Oversampling_256times to be comparable to AGG) and AGG in release build, and AGG was a whopping 500 to 1000 times faster (yes you read correctly) with the same quality. Although this case might not be overall representative of the performance difference, it is interesting.

JUCE already kicks b*tt (I simply adore it!), but with AGG as rendering backend… well, use your imagination… :twisted:

/R


#14

500 to 1000?? That’s nuts (although juce will be very slow at 256x oversampling!) Could it be the rest of the juce rendering pipeline that’s slowing it down (i.e the graphics context clipping, etc)?


#15

I think it’s nuts too, but in both cases there is no clipping (other than that in the component client area). Not sure exactly what other stuff could slow it down. Additionally, when I use the default Oversampling_4times setting in JUCE, AGG is still up to 5 times faster (but then I tried 100 segments) with much better anti-alias quality.

Anyway, here’s the code I used so you can check if there’s something else I might have done wrong:

[code]Path path;
Agg2D agg(g, getWidth(), getHeight());
agg.lineColor(AggColourConverter(g.getCurrentColour()));
agg.lineWidth(1.5);
Random rnd(Time::currentTimeMillis());
for (int i = 0; i < 20; ++i)
{
double x1 = rnd.nextDouble() * getWidth()/2;
double x2 = x1 + getWidth()/2;
double y = rnd.nextDouble() * getHeight();
if (i == 0)
{
path.startNewSubPath(x1, y);
agg.moveTo(x2, y);
}
else
{
path.lineTo(x1, y);
agg.lineTo(x2, y);
}
}

int64 juceStart = Time::getHighResolutionTicks();
g.strokePath(path, PathStrokeType(1.5f));
int64 juceTime = Time::getHighResolutionTicks() - juceStart;

int64 aggStart = Time::getHighResolutionTicks();
agg.drawPath(Agg2D::StrokeOnly);
int64 aggTime = Time::getHighResolutionTicks() - aggStart;

Logger::outputDebugPrintf(JUCE_T(“Juce: %lf s, AGG: %lf s”), Time::highResolutionTicksToSeconds(juceTime), Time::highResolutionTicksToSeconds(aggTime));[/code]

Note that the path adding part is not timed, I figured it would be negligible. Also, I’ve patched Agg2D to take a Graphics object (and in it I create an Image, attach it to a AGG rendering buffer, then on destruction I draw the Image into the Graphics object).


#16

Very interesting…


#17

Jules, I just wanted to know if you were able to reproduce Robiwan conclusions, and if so, working on the performance ?


#18

Haven’t had time to try.

I have got some ideas about better ways of doing the path rendering though, which would speed things up and make it more suitable for eventually adding opengl acceleration.


#19

The way I use AGG now is that I create an Image to draw into, then draw that image into the Graphics object. This involves what I consider an unneccesary overhead and ideally I’d like to just attach the AGG rendering buffer directly to the Image used by the Graphics object internally (in LowLevelGraphicsSoftwareRenderer). However, since it is protected I can’t get hold of it. Is there any other way to get hold of it?

TIA
/R


#20

No, the whole point of that class is to keep its innards hidden. What would be cool would be to go into the rendering code and implement agg versions of all the methods in there, with some kind of JUCE_USE_AGG flag to compile them if people want to enable it. That’d make an interesting comparison…