I have a project that displays DPX files (an image file format common in digital film) in a PictureBox on a form. It works but takes several seconds to display a typical image that is 2048x 1556 pixels. Not so bad but .NET can display a similarly sized TIFF file in under a second.
My display routine is primitive it just reads each 32 bit word from the file, unpacks the three 10 bit RGB values to 8 bits and finally sets the pixel value in a bitmap with the unpacked 8bit RGB values and repeats for the 3 million plus pixels involved!
Doe anyone have any ideas how I might be able to approach the speed of .NET on a TIFF
Thanks in advance
Steve

Advice needed please - How to display an image from a file quickly?
DFlatGuy
AmitJoshi
Your direct access to the integers in the bitmap worked a treat.
Using setpixel took around 7 seconds to process the file.
Using EffectBuffer.Integers to allow direct access the bitmap brings the time down to about 0.9 secs - an improvement beyond my wildest dreams.
Thanks again
Steve
Misch
Firstly this is only of interest if you have lots of small bitmaps -- 85K is small. Secondly you would have to prevent fragmentation within your own array. So I don't see a big advantage, but I thow the idea out there anyway.
johnd2
When DisposeBitmap is called, both the handle and the Bitmap are disposed. That should free the block of memory used for pixels and make it eligible for garbage collection. However, if the block is larger than 85K (I think) it will go into the large object heap (LOH) and not the regular heap. In this heap, memory is not compacted, but even if not compacted, it is free, so eventually it should be reused. So it could be the GC is just not being agressive enough. Does it eventually stop getting larger Does GC.Collect make any difference, after DisposeBitmap
I don't think there is a bug in GCHandle.
The CLR profiler will show you exactly what is happening in both heaps.
PaulFnNY
Hi Staehff,
If you control the bitmap format, you can read in the bytes and push them into the effect buffer as pixels (4 bytes each). If you do not control the format or you wish to use the Bitmap loading methods, you have to accept that they will allocate memory, and you cannot access that memory as you can with a pinned array. The reason is, there is a conversion process during the loading of a from the disk (unless you control that). Even if you load the bitmap yourself, you need a binary stream, so unless you construct that binary stream to use the same pinned array as your effect buffer, it will also allocate memory.
In short it is possible but difficult without controlling the bitmap format entirely.
Regards,
Frank Hileman
www.vgdotnet.com
JDSS
Hi,
I got a similar problem: I have to show a sequence of bitmaps from the hard disk on the display for simulation purpose.
This job must be done in a minimum of time, because the main issue is the analysis of the shown content. So I found your thread..
My question is: how can I make my program using one and the same part of memory each time a new bitmap is loaded This is necessary due to avoiding out-of-memory exceptions and due to increasing speed. All the pictures have the same size and pixelformat.
So maybe you know a way to realize it using managed code (programming in C++/CLI ...but understanding C# too)
Thanks
Staehff
eric_delage
The problem is SetPixel. The stream may be a bottleneck after you fix the SetPixel problem. Here is a class for extremely fast bitmap processing, without using unsafe code -- actually it seems to be faster than unsafe.
We are using the 32bppPARGB format as this is the format ultimately used internally by GDI+. It is the fastest format. For each integer in the Integers array, the most significant byte is the alpha, followed by the red byte, then green, then blue. So to get the alpha: value >> 24. To get the red: (value >> 16) & 0xFF.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Runtime.InteropServices;
internal sealed class EffectBuffer
{
private uint[] ints;
private GCHandle handle;
private Bitmap bitmap;
public EffectBuffer(int bufferWidth, int bufferHeight)
{
AllocateBitmap(bufferWidth, bufferHeight);
}
public void AllocateBitmap(int width, int height)
{
if (Width == width && Height == height)
return;
DisposeBitmap();
if (width == 0 || height == 0)
return;
// 4 bytes per pixel, format: ARGB
ints = new uint[width * height];
// if not pinned the GC can move around the array
handle = GCHandle.Alloc(ints, GCHandleType.Pinned);
IntPtr pointer = Marshal.UnsafeAddrOfPinnedArrayElement(ints, 0);
bitmap = new Bitmap(width , height, width * 4, PixelFormat.Format32bppPArgb, pointer);
}
public void Dispose()
{
DisposeBitmap();
}
private void DisposeBitmap()
{
if (bitmap != null)
{
handle.Free();
bitmap.Dispose();
bitmap = null;
ints = null;
}
}
/// <summary>
/// A bitmap that can be rendered upon, or rendered to another graphics.
/// </summary>
public Bitmap Bitmap
{
get { return bitmap; }
}
/// <summary>Width of <see cref="Bitmap"/>.</summary>
public int Width
{
get { return bitmap == null 0 : bitmap.Width; }
}
/// <summary>Height of <see cref="Bitmap"/>.</summary>
public int Height
{
get { return bitmap == null 0 : bitmap.Height; }
}
/// <summary>
/// The integers that make up the pixels in <see cref="Bitmap"/>. The
/// pixels can be modified directly by modifying this array.
/// The pixels must contain premuliplied ARGB: R, G, and B
/// components cannot be larger than the A component.
/// </summary>
public uint[] Integers
{
get { return ints; }
}
}
jimmyglo
Thanks for the reply.
Here's the code snippet that gets and processes the data into a bitmap.
Bitmap preview = new Bitmap(xpixels, ypixels, PixelFormat.Format24bppRgb);
//get to the image data
r.BaseStream.Position = image_data_offset;
//main loop: for every pixel in file set the bitmap pixel
for (int y = 0; y < ypixels; y++)
{
for (int x = 0; x < xpixels; x++)
{
dpxpixel = r.ReadInt32();
//winpixelblue = (dpxpixel >> 4) & Rmask;
//winpixelgreen = (dpxpixel >> 14 ) &Rmask;
//winpixelred = (dpxpixel >> 24) & Rmask;
preview.SetPixel(x, y, Color.FromArgb((dpxpixel >> 24) &Rmask,
(dpxpixel >> 14) & Rmask, (dpxpixel >> 4) & Rmask));
}
}
//tidy up
r.Close();
//set the image property and return true;
this.mpreviewimage = (Image) preview;
return true;
Rmask is 0x000000ff to mask off the RGB values to 8 bit.
I have wondered about the bitmap constructor that takes a pointer but haven't had the courage to experiment yet. Another idea was to read everything in one hit and then work through it.
Any pointers (!) you can offer will be most welcome.
Cheers
Steve
delantian
In fact every time I create an EffectBuffer with a different size that amount of memory gets added to the memory usage. Looking at your code I can see that before a new size is allocated space the old one is released so am not really sure what is going on.
It may be that the Garbage collector will sort things out when it needs to but i've had the memory usage up to 200MB from a no image norm of 25MB.
Any ideas what might be happening
Cheers
Steve
bogomil
I've had another play around and the memory does not keep on growing it does get reclaimed - seems to be when a new effectbuffer is created - from time to time. Adding a GC.Collect gets it back straightaway. I guess it's something to do with the large object heap you mentioned.
I've downloaded CLR Profiler but am not sure it is compatible with the Beta 2 .Net I'm using.
Thanks for the help - I think I'm just going to move on and keep an eye out for memory usage issues but all seems to be OK.
Cheers
Steve