How to load and manage images more efficiently? - c#

I have a front-end program for PND's running Windows CE (both 5.0 and 6.0) It user a high quantity of images (currently in png format) as buttons or for decoration purposes. The images are loaded from the SD Card via the new Bitmap(path);
I'm currently using v3.5 of the framework.
Upon loading, OS + my application have consumed 75 to 80% of the device's memory.
Wich good ways are there to optimize all that files?

The only ways that come to my mind to optimise these picture would be to resize them to the real size they are needed (like most icons will be used in a 16x16 size) and if you store also as bitmap no your card you can also set the used color palette to a size that matches the exact needs of the given picture (e.g. a picture of 16x16 has 256 pixels. So you need a maximum palette of 256 colors, but maybe also a self-defined 16 color palette is enough, cause in your picture are only 16 different colors.)
As a second approach you could also check if you maybe have the same picture multiple times loaded. In this case you should load it only once and use it multiple times.
A last one, that came to my mind belongs to background pictures. If you have a solid background you don't need a fully sized image of it. Just take a 1x1 bitmap and stretch it to the needed size. The same counts for gradient backgrounds, but in this case you have a 1x2 bitmap which will be stretched. And last but not least if you have a regular pattern, just take the smallest unique brick out of it and use some tile mechanism.

If you create the OS, is it possible to store the images as part of the OS?
In case it is possible, and the image is loaded fully to RAM, you can load the images only on a need to display basis and unload them when not needed. This will eliminate some loading time as well since accessing RAM is faster than accessing the SD card.
Another trick in with the same concept would be to copy all the images to a RAM based FS and load them only on a need basis - the down side is that this needs to be done after every reboot.

Related

losing quality when resizing with ImageResizer

I'm using the ImageResizer .net library. It works as expected, but one image messes around.
I've uploaded the image below. I've already tried some things like format=jpg&quality=100, only width=220, also different sizes, but it always adds this blurry border around the image.
The original image is a png.
This one is the original image:
This one is resized by the ImageResizer:
And this one is resized with photoshop:
EDIT:
If you're running into the same issue. Try to set up the SpeedOrQuality Plugin. I've set it to speed=3 and the image is sharp again.
Vector graphics require different resampling algorithms than photographs.
ImageResizer V4 includes higher quality image resampling options under the FastScaling plugin.
For graphics (non-photographic images), I suggest playing with &f.sharpen=0..100, &down.preserve=-5..5, and &down.filter=Robidoux. Make sure &fastscale=true and FastScaling is installed.
You can certainly find a good configuration for your rasterized vector art and set up a preset for it. FastScaling is capable of much better resampling than Photoshop - on par with Lightroom, in fact.
Enabling fastscaling alone helps substantially (?width=200&fastscale=true):
Adding sharpening gives a very clear result: (?width=220&fastscale=true&f.sharpen=100):
Visibly crisper than Photoshop:
Each time you save a jpeg, you loose quality (the image is reencoded).
I would recommend using the same quality as the original image was save against, it should give the best results.
Using a higher quality is not recommended as it will artificially try to improve quality, mistaking approximations done by previous encoding for details, resulting in things like the blurry border.
Aside that, usually, one should not use a quality over 95 for jpeg encoding.

BitmapImage DecodePixelWidth odd behavior

I was experiencing some performance issues when displaying a large number of images, I discovered the issue was that the full resolution image was being used when I really only needed an image less than 1/4 of the size. So I added a line in between BeginInit and EndInit to set the DecodePixelWidth to 200 which is the max width I will need in my layout. My performance was no longer an issue but some of the images are really small, definitely nowhere close to 200 pixels wide. Most of the images seemed to display correctly, and there doesn't seem to be any rhyme or reason to which are too small and which work correctly. I thought it might be due to differences in the original dimensions of the images but there was no pattern to the results. I tried bumping the width up to 600 which then allowed the offending images to display at the correct width of 200 but the performance then suffers.
At this point I am not even sure where to start looking, and would be really grateful for a kick in the right direction.
EDIT: Some more information below about the images and how I am using them.
Most of the images are around 1000X1500 although some have odd dimensions like 1000x1513. All of the images are JPEG. Currently each image is placed in a custom user control that I designed, nothing too fancy just a background around it with some text. Each user control is then placed in a grid, in its own row/column. The grid is inside a scrollviewer so the user can scroll through the list. This might not be the best way to accomplish what I am looking for but its what I came up with quickly and it works for the most part. Id be happy to switch to another method of display if it would accomplish what i want in an easier or more concise way.
The intended result is for a movie browsing app. There will be a scrollable list of movies, each represented as its own tile complete with title, movie poster, genre info, rating, and description. This list will be sortable on various items. The information about the movies is stored in a sql database on another machine. The images are originally stored on another machine but are copied locally to improve performance.
EDIT: I have been able to solve the issue by not using DecodePixelWidth and instead saving a copy of the image at the desired size, this has improved performance. Youngjae's recommendation of not using DecodePixelWidth along with his mention of using a virtualized list led me to the following set of articles on creating a Virtualized Wrap Panel which should solve any other performance issues. The article is for silverlight but from what I understand silverlight is basically a watered down version of wpf, if it works in silverlight it should work in wpf. It shouldn't be too difficult to convert it for my use.
Part 1 - MeasureOverride
Part 2 - ArrangeOverride
Part 3 - Animation
Part 4 - Virtualization
In MSDN link, you can find words as below.
The JPEG and Portable Network Graphics (PNG) codecs natively decode the image to the specified size; other codecs decode the image at its original size and scale the image to the desired size.
And, I recommend you NOT to use DecodePixelWidth for resizing purpose because of the above reason.
I don't know your original image sizes and formats, but isn't it enough to use with virtualized list and <Image Width="200" Stretch="Uniform">?

C# fast pixel rendering

I'm developing depth processing (Xbox Kinect, Asus Xtion, etc) applications using OpenNI.
I need a really simple and fast way of drawing on a Windows form when new depth data is available from the sensor (30 or 60 fps depending on resolution).
Currently I'm invalidating a double-buffered panel from a seperate thread when the data becomes available, and then setting pixels of a bitmap in the panel's paint method, yielding a predictably awful 5fps.
System.Drawing.Graphics seems to lack a fast way to set individual pixels, unless anyone can instruct otherwise.
I literally just need to set pixel colours, so would like to avoid using third party high speed rendering APIs if possible, and ideally use something as native as possible.
Does anyone have any suggestions?
If you're using Bitmaps, then you should use LockBits and UnlockBits to access the data directly in memory. In C#, you can get some extra performance by using unsafe code blocks and pointers.
See this link for more information: http://web.archive.org/web/20150227183132/http://bobpowell.net/lockingbits.aspx
image.SetPixel() is very slow when you are replacing many pixels per frame and you need many frames per second.
It will be a lot faster when you use a WriteableBitmap and call CopyPixels
This way you can fill the array with pixel data using multiple threads and simply blit the array to the image in a single call.
EDIT
Note that WriteableBitmap is a WPF class. If you are bound to WinForms you might need to create your own implementation. WPF/WinForms/GDI interop: converting a WriteableBitmap to a System.Drawing.Image?
You could try my LINQ image processing library to work with your "buffer-bitmaps". It uses an accessible LINQ syntax but is very performant for large bitmaps. It is available on Nuget as a single file include in your project.
Hope that helps!

Zooming an extremely large image

Is there any predefined control in WPF or VS2010 to implement the Image Zooming functionality (like Googlemaps) for a bitmap displayed over a panel using C#? My bitmap will be minimum 8GB in Size.
Thanks in advance
Murali
There is DeepZoom for Silvelight. There is no such thing in WPF. It was planned for WPF4, but removed before RTM.
Update:
Loading images of this size is pretty uncommon. You should consider tiling as others suggested. Also consider if you really need load all data at once. If the image has size of for example 30000x30000 then the user do not really need/can't to see all this data. Use tiling and appropriate image format (jpg etc) for each zoom level.
Relevant links:
Single objects still limited to 2 GB in size in CLR 4.0?
Pushing the Limits of Windows: Physical Memory

Large bitmap maniuplation in WPF

Is WPF be able to manipulate large bitmaps where GDI+ cannot due to memory limitations?
I have bitmaps that are 10,000x10,000 easily, and could even be much larger than that. Worst case I think I can break the single bitmap into large tiles and work with that I guess.
I basically need to do four things
Take an set of tiled images
Put all of those tiles into a single bitmap
Convert the bitmap to black and white
Scan the bitmap looking for changes from black to white
I know how to do these things in GDI+, but the problem I am running into is that the size of my bitmap is too large for the machine I am using, and it causes the program to crash, and I cannot make the image any smaller, so I am hoping that WPF will be able to succeed where GDI+ has failed me.
I don't think WPF will be able to help you here.
Why do you want to use bitmap object? You may as well work with an two-dimensional array of bytes or doubles (or any other type, depending oh what accuracy and range do you need), especially if you work with one channel only. Bitmaps have accessor methods (GetPixel and such) with huge computational overhead, working with arrays is by orders of magnitude faster (I know from personal experience), the only issue is that you can't display them as they are (you would have to convert the array back into image, which is fairly simple). But since you seem to want to do some sort of analysis on the data, I think array would be much more suitable for your needs.
I can post code samples detailing conversion from bitmap (either WPF or WinForms) to array an back if you want.
But remember, that 32bit .NET application can use approximately 1.2-1.4 gigabytes of memory - you have to fit in this space or you start getting OutOfMemory exceptions.
I eventually decided that the best course of action was to only work with the tiles, and then have an array that holds the actual information about each tile that I need. Given the number of tiles, it was the only sensible thing I could do.
Like CommanderZ said. Its Windows PRESENTATION Foundation, not Windows Image-manipulation Foundation.
You should try to either find some kind of image-manipulation library, but looking at size of your image, then doing everything yourself might be only way.
Especialy, you probably wont be able to work with bitmap as a whole, so you are going to work with tiles. Then it becomes problematic if you need to work with neighboring pixels. But I guess you should look into this yourself.

Categories

Resources