Re: Bitmap <-> ArrayList of points
- From: Tamas Demjen <tdemjen@xxxxxxxxx>
- Date: Wed, 02 Aug 2006 11:50:49 -0700
Iwanow wrote:
Thank you for that hint. Up to now, I've been using... ArrayLists to
store my data.
ArrayList stores System::Object^ managed handles. If you add an integer value to an ArrayList, it wraps that value into a managed object. This is called boxing. The C++/CLI compiler automatically generates code that wraps your integer value into a garbage collected object. In the old MC++, you had to explicitly __box() them. Either way, this is a major performance penalty, and a waste of memory too. That's why I suggested using array<unsigned char>, or even List<unsigned char> (if you're programming in .NET 2.0). List has an overhead to array, but if used correctly, it's almost negligible. It's like the difference between char* and std::string.
I use Bitmap objects as sources of original images, and a destinations
after processing. I usually access them through either:
- bmp->GetPixel(x, y).GetBrightnes() or
- bmp->SetBixel(x, y, Color)
Both functions are called within 'for' loops mentioned in my first
post. Will they work faster with cli::array?
I'm pretty sure that grabbing a pointer to the raw image data would be many times faster than GetPixel. I don't know how GetPixel works, but it must do at least a multiplication and an addition (usually TopLeftPtr + x - y * BytesPerLine, assuming the image is upside down). This is many times slower than incrementing a pointer.
Even if you use array<unsigned char>, using the array syntax happens to be much slower for me than interior_ptr<unsigned char>. What I do is the following:
array<unsigned char> buffer = gcnew array<unsigned char>(width * height);
interior_ptr<unsigned short> ptr = &buffer[0];
while(/*...*/)
{
*ptr++ = /*...*/;
}
This trick alone made my code about twice as fast than using array syntax, like buffer[offset++].
I'm not familiar with the Bitmap class, but I know it has a way to lock its pixels and get a byte pointer to its raw underlying data. Here's an example:
http://vbforums.com/showthread.php?t=260903
I think the C# byte* is the same as the C++/CLI interior_ptr<unsigned char>.
I recommend that you research Bitmap::LockBits and BitmapData a bit:
http://msdn2.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx
Note that if you do this, you must deal with the following:
- windows bitmaps are upside down
- the raw data depends on the bits per pixel value. There are 1, 4, 8, 16, 24, 32-bit images. You must decode the color data from the raw bits on your own (which is very easy with 8 and 24-bit images, a bit tricky with 16-bit images, but I refuse to work directly with 16-bit bitmap)
- each line begins on a DWORD boundary, so usually there are some padding bytes after the last pixel in each line. Here's how to calculate the number of bytes per line:
BytesPerLine = (Width * BitsPerPixel + 31) / 32 * 4 * Height;
Since images are upside down, the last line is in fact the first, and instead of incrementing the line pointer by BytesPerLine, you have to decrement it.
Note that I have very little .NET experience compared to unmanaged code. 99.99% of my code is native C++. You should really do your own benchmarking with your own algorithm, but you should get much better result with Bitmap::LockBits than with GetPixel.
Tom
.
- References:
- Bitmap <-> ArrayList of points
- From: Iwanow
- Re: Bitmap <-> ArrayList of points
- From: Tamas Demjen
- Re: Bitmap <-> ArrayList of points
- From: Iwanow
- Bitmap <-> ArrayList of points
- Prev by Date: Re: Any CreateProcess API alternative?
- Next by Date: XmlWriterSettings settings = gcnew XmlWriterSettings(); - No copy constructor?
- Previous by thread: Re: Bitmap <-> ArrayList of points
- Next by thread: Portable C++
- Index(es):
Relevant Pages
|