|
try once more before you ask
|
|
|
|
|
Hello Keith,
first my congratulation for this article.
Now my question:
//Update transform for additional pixels
Matrix t = m.Clone();
t.Translate(-bounds.Left, -bounds.Top, MatrixOrder.Append);
t.Scale(4.0f, 4.0f, MatrixOrder.Append);
In web application I have not a matrix as method parameter? How can this custom antialiasing in web application used?
Thanks
Rene
www.drescher-hackel.de
|
|
|
|
|
Hello,
I download the attached file but not able to open it seems to be currepted. could you kindly send the attached file or upload it again.
Thanks,
Usman
|
|
|
|
|
It seems to be working now. I suspect that the codeproject website has been having some reliability issues. Hopefully that's been resolved.
Keith Rule
|
|
|
|
|
Great code, Can you please point to sources of information that document how to read a .ai? How did you convert the .ai files to code? I need to render some simple illustrator format graphics.
thanks in advance
|
|
|
|
|
I can't give you the source and I'm not aware of any open source efforts that can does this. However there are three approaches you might consider when building an .ai conversion tool.
1) Illustrator can output pdf files. Use an open source pdf reader (like XPDF) to read the pdf file and then create a GDI+ emitter. I've tried this and it works. Turning PDF into GDI+ code isn't too bad because GDI+ has a very close mapping to postscript. The issue I had with this approach was that I didn't have access to all of the information I needed to emit code good code. I realized pretty quickly that I was either going have to write my own pdf reader or I was going to have to do something different.
2) Instead I built an Illustrator plugin using the illustrator SDK that can be downloaded from www.adobe.com. The SDK gives you access to all of the graphic elements in the Illustrator file. This approach works well. However, be warned that the SDK documentation is missing a bunch of details that you will have to discover on your own. There is also very little information available on the web about writing Illustrator plug-ins. Luckly there are several very good example files included in the SDK that will get you started.
3) My backup plan (if the first two things didn't work) was to use SVG. Illustrator can emit SVG and I believe there is at least one open source implimentation of an SVG reader. However, I didn't have to use this method, because writing a plug-in worked well for me.
Sorry I couldn't offer more help. I hope this gets you started.
Keith Rule
|
|
|
|
|
The features you describe with the small lines can be attributed to the fact that you don't correct the pen widths that should also get bigger when you blow up your intermediate bitmap. So you draw with relatively thin pens after scaling back to the normal world.
Hence this is not just custom antialiasing, but you make the effective pen widths smaller.
Kind regards,
Wout
|
|
|
|
|
That's a good point. I will look into it further. If necessary, I will update the article to reflect this.
Thanks!
Keith
|
|
|
|
|
wout de zeeuw wrote:
The features you describe with the small lines can be attributed to the fact that you don't correct the pen widths that should also get bigger when you blow up your intermediate bitmap. So you draw with relatively thin pens after scaling back to the normal world.
Hence this is not just custom antialiasing, but you make the effective pen widths smaller.
Kind regards,
Wout
I've thought about this a bit more and I think I see your point. You are right, the fact that I'm enlarging the image does effect the custom antialiasing by providing additional information. But I believe the underlying pens are scaling correctly (meaning the pen widths scale with the rest of the image) and that the artifacts I'm showing are real GDI+ issues. If didn't understand your point, or I'm mistaken about the pen width scaling properly please let me know.
Thanks again for your comments.
Keith
|
|
|
|
|
Hi Keith,
If I draw a line with pen width 2 on a bitmap that's 4 x 4, and then scale the bitmap to be 2 x 2, then the effective pen width as rendered on screen will be twice smaller, hence 1.
Since you probably use pen width 1 on the big bitmap, it will get proportionally smaller depending how much you downscale the bitmap. Hence by choosing a initial bitmap size, you are effectively choosing a pen width.
Kind regards,
Wout
|
|
|
|
|
Hi Keith,
I must correct my statements! You indeed set the matrix transform, so the pen widths are scaled when drawing on the bigger bitmap.
I experimented a bit with setting other pen widths, since it's possible to set a float value to a pen width and I was wondering if it got similar results with pen widths smaller than 1f. GDI+ however doesn't react to widths smaller than 1f, so that's the minimum. And the whiskers of the cat are not draw with a pen, but drawn with a graphics path and then filled, so here pen width doesn't apply; it's a very thin path that is filled.
So indeed your approach does work. But application of it especially pays off when needing to draw features that are of subpixel size.
Kind regards,
Wout
|
|
|
|
|
wout de zeeuw wrote:
Hi Keith,
I must correct my statements! You indeed set the matrix transform, so the pen widths are scaled when drawing on the bigger bitmap.
I experimented a bit with setting other pen widths, since it's possible to set a float value to a pen width and I was wondering if it got similar results with pen widths smaller than 1f. GDI+ however doesn't react to widths smaller than 1f, so that's the minimum. And the whiskers of the cat are not draw with a pen, but drawn with a graphics path and then filled, so here pen width doesn't apply; it's a very thin path that is filled.
So indeed your approach does work. But application of it especially pays off when needing to draw features that are of subpixel size.
Kind regards,
Wout
When I said that lines don’t always antialias correctly, I was referring to strokes around paths, very small filled paths (like the one you just mentioned) and lines. In other words, anything that looks like a line. I probably should have been clearer about that in the article.
However, this example does show that an artist may choose a method for building a vector object that isn't necessarily the best approach when the image is scaled using GDI+ antialaising. I've found that communicating gnarly details like this to an artist can be challenging. With issues like this, I think our artists feel that we (programmers) make arbitrary rules that just get in their way. Maybe they're right about that.
Keith
|
|
|
|
|
It's 6 times slower.
On AMD XP2800+, with ATI AIW 9800
Aqua
GDI+ = 0.027, Custom = 0.158 (6 times slower)
Glass
GDI+ = 0.024 Custom = 0.278 (11 times slower)
|
|
|
|
|
Yes it can be. I think I pointed that out a few times in the article.
|
|
|
|
|
it can take even 2 or 3 seconds if you have a few buttons, the reason for being slow is C# in C++ this can be made at least 10 times faster.
|
|
|
|
|
Hmm, my personal experience is that C# is "nearly" as fast as C++ for most things. I had assumed that most of the speed issues I've seen here had to do with GDI+ and the fact that it does more than GDI without the help of hardware acceleration.
Another reason I believe that GDI+ is much of the issue here is that in an earlier version of the tool I used to output the C#/GDI+ code in this example, I emitted C++/GDI+ code and it was about the same speed as the C# version.
I suspect that to see a significant speed up (in C++ or C#) that I'd have to change the underlying graphic API. I tried using AGG and it was quite fast, but it didn't have all the features I needed and it only worked with C++.
Hopefully Avalon will resolve some of the speed issues. In the mean time I still need to produce vector based graphics code. So this will have to do.
BTW- my personal experience is that this techique produces very usable controls. I've not seen any significant problem with many controls built this way when used on a form.
|
|
|
|
|
don't compare Managed C++ which is C++ on top of C#, with plain C++ (if you know how to program in C++) you can get this at least 10 times faster! GDI+ itself is written in C++
when C# will not be a runtime language, then you can compare it with C++, until then C# runs on top of a C++ RTL/Framework.
|
|
|
|
|
Mario M. wrote:
don't compare Managed C++ which is C++ on top of C#, with plain C++ (if you know how to program in C++) you can get this at least 10 times faster! GDI+ itself is written in C++
when C# will not be a runtime language, then you can compare it with C++, until then C# runs on top of a C++ RTL/Framework.
I rarely use managed C++ (I normally use it just for gnarly interop). The experience I related was with an MFC based application compiled with code generation set to "blended" and managed extension off. So for the demo code I included, I don't believe the C# verses C++ discussion is relevant, because I believe that GDI+ calls are dominating the painting time.
I acknowledge there’s a lot about C++ and C# that I don’t know. And I certainly agree that managed code and JITing might not be as fast as straight C++ code in some cases (though Microsoft is claiming that Widbey is very near parity in most cases -- though I haven't checked that claim).
In this case, I believe that after the application is JITed (which takes about a half a second on my machine), that the performance issues we've talked about are dominated by GDI+ calls and not C#/managed code issues. Four of the top five profiled items (using TrueTime) are GDI+ calls. The AddBezier is a C# method which I’d guess is dealing with interop issues.
Method Name % in Method
GdipFillPath 10.7%
AddBezier (Interop??) 8.7%
GdipAddPathBezier 8.4%
GdipDrawPath 4.4%
GdipDrawImageRectRectI 3%
You bring up a good issue and I have no doubt that there are cases where C++ can beat C# hands down, I'm just skeptical that this is one of those cases.
Keith Rule
Keith
|
|
|
|
|
The performance issues are not because C# was used, nor because its a managed runtime. Just because C# runs in a managed runtime does not mean its interperated, which would in fact cause up to a 12 fold performance hit. C# code is compiled, just like C++, and when its compiled, it can be just as fast as pure C++.
The issue here is the difference between GDI and GDI+. The old GDI API has been around for a long time, and the whole thing is fully accelerated by graphics hardware. The GDI+ API, on the other hand, is relatively new, is only partially hardware accelerated (wherever GDI+ mirrors GDI's functionality, the same hardware acceleration can be used).
The neccesary functionality for implementing a custom AA routeen is one of those areas in GDI+ that is not hardware accelerated, so everything is done on the CPU. Sadly, for the moment, that means a performance hit. There are probably some optimizations that could be done to improve performance. The first time the AA code is called, there will be the small hit from the JIT doing its business, too. A more accurate comparison could probably be gained from comparing the time of the second custom AA rendering, rather than the first. The system namespaces, and thus the default GDI+ AA routeen, are precompiled when the .NET runtime is installed. They are always ready to do, and no JITting is required, which could be causing a skew in the performance comparisons.
|
|
|
|
|
you're completly wrong, C# is not compiled like C++, it's a runtime language like Visual Basic !, if you don't have the 30megabytes elephant .NET runtime, your C# app. is dead
I know that here on CP are a lot of people from M$ trying to convince people that C crap is better than C++, but real programmers will never switch to this non-portable beginner's language.
It's enough to see how slow a .NET framework is drawing when you start C# application, to realize that this is a big crap. If you write a simple server application in C# it will eat gigabytes of RAM.
I just wrote a newsletter mailer which uses our SQL user database and when it sends e-mails on 80 threads it takes 90MB of RAM, while our old C++ application needs only 6MB !!!
|
|
|
|
|
I'm sorry my friend, but you are gravely mistaken. Your somewhat of a fanatic, you seem to blindly beleive that C++ is the ultimate language, and that its the only compiled language. You seem to think that C# is insanely memory inefficient. I suggest you go educate yourself before you embarrase yourself further. If you wish to continue disprooving that C# (and .NET languages) are compiled, I suggest you first read http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconthecommonlanguageruntime.asp, and learn what .NET is truely all about.
C#, and in fact all .NET languages, are INDEED compiled. UNLIKE a Visual Basic 6.0 app, a .NET app is not interperated. The initial compile is stored as CIL, or MSIL, an intermediate compiled language. This language is not interperated, its byte code, similar to Java. Its portable, not compiled down to the level of any particular cpu-specific machine code. When you execute a .NET application, regardless of what language it was written in, the JIT, or just-in-time compiler, takes MSIL and converts it to machine code. The JIT only happens once per execution cycle, and once MSIL is JITted to machine code, the momentary chunk of cpu cycles used by the JIT compiling doesn't happen again until the next time the program is executed.
All .NET apps are indeed compiled. Its actually a two step process, but once the code is compiled, the difference between C++ and C#, or C# and VB.NET, etc. is negligable. I've been programming for 15 years. I've used C, C++, I've used the original Pascal language, long before Delphi. I've programmed in assembler, used MFC. Hell, I've even written a bulk mailing app, written in C++ for that matter.
It doesn't matter what language you use, performing a mass newsletter mailing, on a whopping 80 threads, is going to take more than 6 megs of memory. Not only that, forcing an application to use 80 threads is going to be detrimental to performance, due to the mass amounts of context switching that windows will be required to do. If you want to talk efficiency and performance, you should really educate yourself. Your last post showed your ignorance not only in the realm of .NET and how it works, but also what multi-threaded applications development intails, what the true differences between C and C++ are, etc. etc. I could go into your lack of understanding about GDI and GDI+, but I think you should get the picture now.
Irrationality like this only serves to display your ignorance to everyone. Pick up a book or find a web page and read about all these technologies. You might actually learn something, like whether a .NET app is compiled or not.
|
|
|
|
|
ok, thank you !, and happy C# sharp coding.
|
|
|
|
|
I've been writing programming tools with C# -- mostly code generator kinds of stuff. My experience is that generic .NET console apps run on Linux and Solaris without modification. All I have to do is install Mono on Linux or Solaris and bingo – the same binary runs on Windows, Linux or Solaris. If you stay away from interop and graphics, most stuff just works. I’d call that very portable.
Maybe it’s just me, but I thought running the same binaries on XP and Linux was pretty darn cool. Granted you have to install mono on your Linux distribution, but that’s not much different than installing a .Net runtime on Windows.
Mario, you sound like a person of strong convictions and opinions (just my kind of guy), but you also sound very young and inexperienced. Frankly I was skeptical too, especially after having worked with Java for awhile. But I must reluctantly admit that C# is a good language. It's not suited for everything, but neither is C/C++.
Try to have an open mind, and take a second look at .NET. I recommend starting at www.go-mono.com which is an open source C# and .NET runtime implimentation targeted for a variety of platforms.
Good Luck,
Keith Rule
|
|
|
|
|
I'm 28, and I write software in C++ since 1993 for DOS, Windows, Unix, and I am really open mind, when I first saw C# I wanted to switch completly to it, but after my first app. in c# I got really disapointed to see how hard is to maintain the sources in bigger projects, also disapointed to see that it's not a 100% compiled code, it's based on a redistributable runtime which is really huge, the code is slower, also the framework and it's memory hungry, and the worst it's full of bugs, my c# app crashed sometimes and I never found the problem, but after I have installed the .NET 1.1 it never crashed again. I have spent several hours to find out what's wrong and I end up with a m$ bug.
Then I have tried to write a PPC 2003 application in C#, again lots of bugs in .NET framework, and limitations in system classes, also the performance was horrible including memory utilization.
So I don't see any use for it, except small aplications which can be created faster with this RAD, maybe m$ will improve it in the future and will be much more useful, but it will not replace too soon C++
|
|
|
|
|
ok, thank you !, and happy C++ coding.
|
|
|
|
|