GDI+ Image EXTREMELY faster than C# Image - c#

I decided to benchmark reading an image in C#, and in C++, to decide which language to use in a project i'm thinking about making for myself.
I expected the benchmarks to be extremely close with C++ maybe pushing ahead slightly.
The C# code takes about 300ms each run (I ran each test 100 times), where the C++ code takes about 1.5ms.
So is my C# code wrong? Am I benchmarking it badly? Or is it really just this much slower?
Here's the c# code I used:
Stopwatch watch = new Stopwatch();
watch.Start();
Image image = Image.FromFile(imagePath);
watch.Stop();
Console.WriteLine("DEBUG: {0}", watch.ElapsedMilliseconds);
And the C++ code pretty much boiled down to this:
QueryPerformanceCounter(&start);
Image * img = Image::FromFile(imagePath);
QueryPerformanceCounter(&stop);
delete img;
return (stop.QuadPart - start.QuadPart) * 1000.0 / freq.QuadPart;
Regardless of which language, they need to end up in an Image object, as it provides the functionality i'm going to need.
=======================================================================
As xanatos pointed out in the comments, the Image.FromFile does do checking.
More specifically, this:
num = SafeNativeMethods.Gdip.GdipImageForceValidation(new HandleRef(null, zero));
if (num != 0)
{
SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(null, zero));
throw SafeNativeMethods.Gdip.StatusException(num);
}
Using Image.FromStream() instead, you can avoid this.
What i'm wondering is, if you do avoid this and try to load an invalid image file it throws an OutOfMemory exception.
And in C++, you don't do checking like this. So how important is this checking? Can anyone give me a situation where it would be bad to avoid this?

Yes, your benchmark is flawed. The problem is that you forgot to actually do something with the bitmap. Like paint it.
GDI+ heavily optimizes the loading of an image. Very similar to the way .NET optimizes loading an assembly. It does the bare things necessary, it reads the header of the file to retrieve essential properties. Format, Width, Height, Dpi. Then it creates a memory-mapped file to create a mapping to the pixel data in the file. But doesn't actually read the pixel data.
Now the difference comes into play. System.Drawing.Image next actually reads the pixel data. That causes page faults, the operating system now reads the file and copies the pixel data into RAM. Highly desirable, if there's anything wrong with the file then you'll get an exception at the FromFile() call instead of some time later, typically when your program draws the image and is buried in framework code you didn't write. Your bench mark for the C# code times the creation of the mmf plus the reading of the pixel data.
The C++ program is always going to have to pay for reading the pixel data too. But you didn't measure that, you only measured the cost of creating the MMF.

Few Points which I know
There is a thing called as CLR. If the said c++ framework(It seems Qt) used The system calls which not depends on .net framework, then obviously it will run fast.
Regarding c# => It is possible to load that assembly before you call it in your code. If you do so,then You can find it's fastness in good scale.
If you use windows platform, then MS wont reduce the execution speed of its own language unless otherwise there is some necessity.

Related

How can I free the memory taken up by Bitmap in .NET?

I am working on some image related projects on .NET.
When I do:
while(true)
{
Bitmap m = new Bitmap(100,100);
m.Dispose();
}
The memory usage keeps going up. Why Dispose did not free all the memory used by Bitmap, and how can I actually free that piece of memory?
In my real work case, I can not reuse the exist Bitmap, because it might be in a different size every time it runs.
I also can not warp it with using, because Bitmap creation happens inside a methold and the result Bitmap is returned for further process.
EDIT:
It's strange I tried this exact same while true code but the memory usage seems to stop increasing fast. I just can not reproduce the situation(that it keept going up and up slowly and never fall back, at least in a few minutes)
Thanks for all your answers and I will pick the only answer I can pick as the solution.
You cant. .NET Runtime will do it for you when it "needs / wants" to.
If you'd like to have a "control" over the allocated memory, you're supposed to use unmanaged structures with pointers / unsafe.
Anyway, if you don't have any performance issues regarding to the code eg. insufficient memory - you should leave it as it is - runtime is going to free that memory in convenient time.
If you want to learn more about GarbageCollector and how memory is managed in .NET i can recommend you a book https://www.amazon.com/Pro-NET-Memory-Management-Performance/dp/148424026X

How to convert large image files in c#

I have several large image files that I need to convert to different image formats. I am using the following code to do this:
using (Image img =new Bitmap(inputImageName))
{
img.Save(outputImageName, imageFormat);
}
It do the conversation, but also since the images are big, it generate outofmemory exception. I read several articles about how to overcome fragmentation of LOH, but I cannot use any of them in this case.
What Can I do?
The images are around 100MByte and it happens after opening 3 or 4 images.
The question you need to ask here is "Do I have to do this in .NET and / or C#"
While I can see why that to many folks a flexible language like C# may be the answer to performing many tasks, I also have to say that "When All you have is a hammer, every problem looks like a Nail"
If this is a one time conversion, and you only need to use them for one project, then my advice to you is to use a stand alone tool better suited for the Job.
There are tons out there ranging from paid applications like:
AcdSee Photo Manager
http://www.acdsee.com/
to free tools such as
Ifran View and it's image conversion functions
http://www.bleepingcomputer.com/forums/topic50519.html
If command line scripting is your game, then use a tool set such as ImageMagik:
http://www.imagemagick.org/script/index.php
Iamage Magik also has .NET bindings so it's functionality can be used from within .NET projects as well as many others if your project requires that you convert these on the fly in your program code.
http://www.imagemagick.org/script/api.php
For scenarios like this one there really is no reason to re-invent the wheel, this problem has been solved so many times before that it really is not a decision you should have to make.
Have a look at WPF image manipulation classes, which do not use GDI, according to this article. The following source code is a good starting point :
public static void Resize(string input, string output)
{
using (var inputStream = File.OpenRead(input))
{
var photoDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
var frame = photoDecoder.Frames[0];
using (var ouputStream = File.Create(output))
{
var targetEncoder = new PngBitmapEncoder();
targetEncoder.Frames.Add(frame);
targetEncoder.Save(ouputStream);
}
}
}
It doesn't have anything to do with the Large Object Heap. The Bitmap class is a managed wrapper for GDI+ and GDI+ is a big chunk of unmanaged code. It allocates pixel data buffers in unmanaged memory. The amount of managed memory your code uses is very small.
A 100 megabyte image file doesn't say much about how much unmanaged memory is required. In all likelihood it is a compressed image format, like JPEG or PNG. Which does require a great deal more unmanaged memory after it is uncompressed. So you could easily end up needing hundreds of megabytes.
And that's a problem when you run your code on a 32-bit operating system or you've selected the x86 as your EXE's platform target setting (the default on VS2010 and up). Your program allocates virtual memory from the holes that are available between the chunks of code and data that are already loaded. GDI+ requires a contiguous chunk of memory to load the pixel data and that can be hard to come by when your program has lots of available virtual memory but it is spread among many holes. An additional problem is address space fragmentation, loading a DLL or allocating memory could cut the size of a large hole in two.
There's a simple fix available for this problem, run your code on a 64-bit operating system. It has gobs of virtual memory available, big holes. The odds that you can do anything about your current problem on a 32-bit operating system are slim to none. You have no direct control over the memory manager.

C# - Multithreaded Processing of a single Image (Webcam Frames)

I have made a programm which is able to capture webcam frames and display them after running different per pixel algorithms - for example making the image gray scale.
At the moment I am using the FastBitmap class (can't find the link atm) which uses pointers to set and get a pixel within a bitmap.
However, I wanted to make my programm multithreaded so that multiple threads are working on the same image. For that I split the image into several sections via its BitmapData (one section per thread) and let the different threads work on their given section BitmapData. In the end a "manager" waits until all threads are done (join) and hands in the resulting image.
That's the theory, but in real this isn't working for me.
When I run this programm I get some strange errors, telling me that I have to release the LHC before reusing it, that I am accessing illegal memory, external exceptions etc. ... Everytime another and I can't understand why but I think the BitmapData sections are the main problem but I don't want to use the slower Mashal copy!
So my questions are the following:
Is it possible to have sectioned multithreaded image processing in C# with unsafe pointer methods?
If yes - how?
As for image processing libraries:
I don't need filters or some default image processing algorithms but I need my own "per pixel" algorithm - I even thought about adding a pixel shader to my program. xD
As my programm is based around the converting of frames of a webcam I need the fastest algorithm possible.
I've read all forum posts and tutorials etc. which I could just find and still have no idea how to do this with unsafe code correctly until I've made this account to finally ask this question here.
Robbepop
Of course it is possible :)
Take a look at:
https://github.com/dajuric/accord-net-extensions
This library contains exactly want you want:
parallel processor which is used to execute parallel operations on an image (e.g. color conversion) and yes those functions which operate on an image are unsafe (use pointers):
NuGet packages ready.

Image resizing efficiency in C# and .NET 3.5

I have written a web service to resize user uploaded images and all works correctly from a functional point of view, but it causes CPU usage to spike every time it is used. It is running on Windows Server 2008 64 bit. I have tried compiling to 32 and 64 bit and get about the same results.
The heart of the service is this function:
private Image CreateReducedImage(Image imgOrig, Size NewSize)
{
var newBM = new Bitmap(NewSize.Width, NewSize.Height);
using (var newGrapics = Graphics.FromImage(newBM))
{
newGrapics.CompositingQuality = CompositingQuality.HighSpeed;
newGrapics.SmoothingMode = SmoothingMode.HighSpeed;
newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic;
newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, NewSize.Width, NewSize.Height));
}
return newBM;
}
I put a profiler on the service and it seemed to indicate the vast majority of the time is spent in the GDI+ library itself and there is not much to be gained in my code.
Questions:
Am I doing something glaringly inefficient in my code here? It seems to conform to the example I have seen.
Are there gains to be had in using libraries other than GDI+? The benchmarks I have seen seem to indicate that GDI+ does well compare to other libraries but I didn't find enough of these to be confident.
Are there gains to be had by using "unsafe code" blocks?
Please let me know if I have not included enough of the code...I am happy to put as much up as requested but don't want to be obnoxious in the post.
Image processing is usually an expensive operation. You have to remember that a 32 bit color image is expanded in memory into 4 * pixel width * pixel height before your app even starts any kind of processing. A spike is definitely to be expected especially when doing any kind of pixel processing.
That being said, the only place i could see you in being able to speed up the process or lowering the impact on your processor is to try a lower quality interpolation mode.
You could try
newGrapics.InterpolationMode = InterpolationMode.Low;
as HighQualityBicubic will be the most processor-intensive of the resampling operations, but of course you will then lose image quality.
Apart from that, I can't really see anything that can be done to speed up your code. GDI+ will almost certainly be the fastest on a Windows machine (no code written in C# is going to surpass a pure C library), and using other image libraries carries the potential risk of unsafe and/or buggy code.
The bottom line is, resizing an image is an expensive operation no matter what you do. The simplest solution is your case might simply be to replace your server's CPU with a faster model.
I know that the DirectX being released with Windows 7 is said to provide 2D hardware acceleration. Whether this implies it will beat out GDI+ on this kind of operation, I don't know. MS has a pretty unflattering description of GDI here which implies it is slower than it should be, among other things.
If you really want to try to do this kind of stuff yourself, there is a great GDI Tutorial that shows it. The author makes use of both SetPixel and "unsafe blocks," in different parts of his tutorials.
As an aside, multi-threading will probably help you here, assuming your server has more than one CPU. That is, you can process more than one image at once and probably get faster results.
When you write
I have written a web service to resize
user uploaded images
It sounds to mee that the user uploads an image to a (web?) server, and the server then calls a web service to do the scaling?
If that is the case, I would simply move the scaling directly to the server. Imho, scaling an image doesn't justify it's own web service. And you get quite a bit unnecessary traffic going from the server to the web service, and back. In particular because the image is probably base64 encoded, which makes the data traffic even bigger.
But I'm just guessing here.
p.s. Unsafe blocks in itself doesn't give any gain, they just allow unsafe code to be compiled. So unless you write your own scaling routing, an unsafe block isn't going to help.
You may want to try ImageMagick. It's free, and there is also a .NET wrapper: click here. Or here.
Or you can send a command to a DOS Shell.
We have used ImageMagick on Windows Servers now and then, for batch processing and sometimes for a more flexible image conversion.
Of course, there are commercial components as well, like those by Leadtools and Atalasoft. We have never tried those.
I suspect the spike is because you have the interpolation mode cranked right up. All interpolation modes work per pixel and BiCubic High Quality is about as high as you can go with GDI+ so I suspect the per pixel calculations are chewing up your CPU.
As a test try dropping the interpolation mode down to InterpolationModeNearestNeighbor and see if the CPU spike drops - if so then that's your culprit.
If so then do some trial and error for cost vs quality, chances are you might not need High Quality BiCubic to get decent results

GDI+ System.Drawing.Bitmap gives error Parameter is not valid intermittently

I have some C# code in an ASP.Net application that does this:
Bitmap bmp = new Bitmap(1184, 1900);
And occasionally it throws an exception "Parameter is not valid". Now i've been googling around and apparently GDI+ is infamous for throwing random exceptions, and lots of people have had this problem, but nobody has a solution to it! I've checked the system and it has plenty of both RAM and swap space.
Now in the past if i do an 'iisreset' then the problem goes away, but it comes back in a few days. But i'm not convinced i've caused a memory leak, because as i say above there is plenty of ram+swap free.
Anyone have any solutions?
Stop using GDI+ and start using the WPF Imaging classes (.NET 3.0). These are a major cleanup of the GDI+ classes and tuned for performance. Additionally, it sets up a "bitmap chain" that allows you to easily perform multiple actions on the bitmap in an efficient manner.
Find more by reading about BitmapSource
Here's an example of starting with a blank bitmap just waiting to receive some pixels:
using System.Windows.Media.Imaging;
class Program {
public static void Main(string[] args) {
var bmp = new WriteableBitmap(1184, 1900, 96.0, 96.0, PixelFormat.Bgr32, null);
}
}
For anyone who's interested, the solution i'm going to use is the Mono.Cairo libraries from the mono C# distribution instead of using system.drawing. If i simply drag the mono.cairo.dll, libcairo-2.dll, libpng13.dll and zlib1.dll files from the windows version of mono into the same folder as my executable, then i can develop in windows using visual studio 2005 and it all works nicely.
Update - i've done the above, and stress tested the application and it all seems to run smoothly now, and uses up to 200mb less ram to boot. Very happy.
Everything I've seen to date in my context is related to memory leaks / handle leaks. I recommend you get a fresh pair of eyes to investigate your code.
What actually happens is that the image is disposed at a random point in the future, even if you've created it on the previous line of code. This may be because of a memory/handle leak (cleaning some out of my code appears to improve but not completely resolve this problem).
Because this error happens after the application has been in use for a while, sometimes using lots of memory, sometimes not, I feel the garbage collector doesn't obey the rules because of some special tweaks related to services and that is why Microsoft washes their hands of this problem.
http://blog.lavablast.com/post/2007/11/The-Mysterious-Parameter-Is-Not-Valid-Exception.aspx
You not only need enough memory, it needs to be contiguous. Over time memory becomes fragmented and it becomes harder to find big blocks. There aren't a lot of good solutions to this, aside from building up images from smaller bitmaps.
new Bitmap(x, y) pretty much just needs to allocate memory -- assuming that your program isn't corrupted in some way (is there any unsafe code that could corrupt the heap), then I would start with this allocation failing. Needing a contiguous block is how a seemingly small allocation could fail. Fragmentation of the heap is something that is usually solved with a custom allocator -- I don't think this is a good idea in IIS (or possible).
To see what error you get on out of memory, try just allocation a gigantic Bitmap as a test -- see what error it throws.
One strategy I've seen is to pre-allocate some large blocks of memory (in your case Bitmaps) and treat them as a pool (get and return them to the pool). If you only need them for a short period of time, you might be able to get away with just keeping a few in memory and sharing them.
I just got a reply from microsoft support. Apparently if you look here:
http://msdn.microsoft.com/en-us/library/system.drawing.aspx
You can see it says "Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions."
So they're basically washing their hands of the issue.
It appears that they're admitting that this section of the .Net framework is unreliable. I'm a bit disappointed.
Next up - can anyone recommend a similar library to open a gif file, superimpose some text, and save it again?
Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service
For a supported alternative, see Windows Imaging Components (msdn), a native library which ironically System.Drawing is based on.

Categories