Blitting

  • Thread starter Thread starter Jon Slaughter
  • Start date Start date
J

Jon Slaughter

Is it faster to modify array of ints as 32-bit pixel data and then somehow
turn that into a bitmap or use lockbits? I'm having a little performance
issues with lock bits unfortunately. I figure that I shouldn't have any
issues writing to an array and then maybe there is a faster way to convert
that into a bitmap than using lockbits?


Thanks,
Jon
 
Hi John,
What performance issues are you having with LockBits? If you're programming
C# then you should surely be using unsafe code and not the Marshal class for
access.

--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
Bob Powell said:
Hi John,
What performance issues are you having with LockBits? If you're
programming C# then you should surely be using unsafe code and not the
Marshal class for access.


Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the code I
pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that said to
use this method.

When I run this under VS I get about 1fps. When I run it outside of VS I get
about 10-20fps or so. (it might actually be fast but its slightly jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);
 
Jon Slaughter said:
Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the code I
pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that said to
use this method.

When I run this under VS I get about 1fps. When I run it outside of VS I
get about 10-20fps or so. (it might actually be fast but its slightly
jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

ReadOnly doesn't look right for this.
unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);

Which part is the slowdown (use Diagnostics.Stopwatch)? The LockBits,
filling in the array, UnlockBits, or DrawImage?

I doubt the computations are the bottleneck, but you can surely remove some
redundant code there, use repeated addition to find row instead of
multiplying by y, precompute x*PixelSize, and (c / 255). Also multiplying
will be much faster than Math.Pow for the integral cases.

If I'm right and the for loops are fast enough, then you can surely get a
very good frame rate (i.e. hit monitor's refresh rate with plenty of cycles
to spare) using OpenGL with glDrawPixels. A little more work for you, but
you'll get direct transfers to video memory and thence to the screen. If
you move up to a texture with glTexImage2D, a lot of effects become
essentially free at that point as well (transparency for watermarking or
fading in and out, rotation, stretching, etc).
 
Jon Slaughter said:
bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

ReadOnly works for you here? I've always gotten "attempt to write to
protected memory" exceptions whenever I tried to write to memory I've
obtained via a readonly lockbits <g>

What is the original bitmap's depth/pixel format? If I rember correctly, i
have had performance problems in the past with LockBits when using palette
(8bpp grayscale) bitmaps created from jpegs.

--
Doug Semler, MCPD
a.a. #705, BAAWA. EAC Guardian of the Horn of the IPU (pbuhh).
The answer is 42; DNRC o-
Gur Hfrarg unf orpbzr fb shyy bs penc gurfr qnlf, abbar rira
erpbtavmrf fvzcyr guvatf yvxr ebg13 nalzber. Fnq, vfa'g vg?
 
Doug Semler said:
ReadOnly works for you here? I've always gotten "attempt to write to
protected memory" exceptions whenever I tried to write to memory I've
obtained via a readonly lockbits <g>

I write ReadWrite and others and all the same result. The page I got this
code from had ReadOnly so I kepted it. Since I don't really know what it
does I kepted it like that. (even though one would expect that it would
prevent writing to the bits).
What is the original bitmap's depth/pixel format? If I rember correctly,
i have had performance problems in the past with LockBits when using
palette (8bpp grayscale) bitmaps created from jpegs.

32bit. ARGB. I guess atleast. I'm just creating a standard bitmap which I
suppose uses the display device parameters. Didn't really bother with
checking since I figure if it was something strange then it wouldn't look
right. (if it was 16 bits then and I treated it was 32bit then I wouldn't
get the correct picture).
 
Ben Voigt said:
Jon Slaughter said:
Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the code I
pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that said
to use this method.

When I run this under VS I get about 1fps. When I run it outside of VS I
get about 10-20fps or so. (it might actually be fast but its slightly
jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

ReadOnly doesn't look right for this.
unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);

Which part is the slowdown (use Diagnostics.Stopwatch)? The LockBits,
filling in the array, UnlockBits, or DrawImage?

I doubt the computations are the bottleneck, but you can surely remove
some redundant code there, use repeated addition to find row instead of
multiplying by y, precompute x*PixelSize, and (c / 255). Also multiplying
will be much faster than Math.Pow for the integral cases.

If I'm right and the for loops are fast enough, then you can surely get a
very good frame rate (i.e. hit monitor's refresh rate with plenty of
cycles to spare) using OpenGL with glDrawPixels. A little more work for
you, but you'll get direct transfers to video memory and thence to the
screen. If you move up to a texture with glTexImage2D, a lot of effects
become essentially free at that point as well (transparency for
watermarking or fading in and out, rotation, stretching, etc).
Yes, I should be able to get it a good frame rate. I just need to work at
the pixel level because I am trying to do a physics simulation. The display
is only to display the result of the simulation periodically. I have some
other simulations that I've done but I didn't use lock bits and they seem
pretty fast. This is first time I'm using lock bits but potentially code is
slow when I'm actually doing the simulation(but shouldn't be that slow).

What I did notice is that when I run it under VS its about 20 times slower
even if in active mode. So the debugger is making it very slow and I
probably got confused when I was running it and with the simulation.

Essentially I'm calculating two gaussians and maybe the math library is
pretty slow. I guess I'll need to precalculate the guassians and see how
that works. I'll try to profile it sometime but distracted writing a vector
library ATM.

Thanks,
Jon
 
Jon Slaughter said:
Ben Voigt said:
Jon Slaughter said:
Hi John,
What performance issues are you having with LockBits? If you're
programming C# then you should surely be using unsafe code and not the
Marshal class for access.



Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the code
I pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that said
to use this method.

When I run this under VS I get about 1fps. When I run it outside of VS I
get about 10-20fps or so. (it might actually be fast but its slightly
jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

ReadOnly doesn't look right for this.
unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);

Which part is the slowdown (use Diagnostics.Stopwatch)? The LockBits,
filling in the array, UnlockBits, or DrawImage?

I doubt the computations are the bottleneck, but you can surely remove
some redundant code there, use repeated addition to find row instead of
multiplying by y, precompute x*PixelSize, and (c / 255). Also
multiplying will be much faster than Math.Pow for the integral cases.

If I'm right and the for loops are fast enough, then you can surely get a
very good frame rate (i.e. hit monitor's refresh rate with plenty of
cycles to spare) using OpenGL with glDrawPixels. A little more work for
you, but you'll get direct transfers to video memory and thence to the
screen. If you move up to a texture with glTexImage2D, a lot of effects
become essentially free at that point as well (transparency for
watermarking or fading in and out, rotation, stretching, etc).
Yes, I should be able to get it a good frame rate. I just need to work at
the pixel level because I am trying to do a physics simulation. The
display is only to display the result of the simulation periodically. I
have some other simulations that I've done but I didn't use lock bits and
they seem pretty fast. This is first time I'm using lock bits but
potentially code is slow when I'm actually doing the simulation(but
shouldn't be that slow).

What I did notice is that when I run it under VS its about 20 times slower
even if in active mode. So the debugger is making it very slow and I
probably got confused when I was running it and with the simulation.

Essentially I'm calculating two gaussians and maybe the math library is
pretty slow. I guess I'll need to precalculate the guassians and see how
that works. I'll try to profile it sometime but distracted writing a
vector library ATM.

Ah, yes, with only 256 values a lookup table will be several orders of
magnitude faster than calling Pow inside the loop. I hadn't even considered
that. I really meant for you to first measure timing and find out which
part was the bottleneck.
 
Ben Voigt said:
Jon Slaughter said:
Ben Voigt said:
Hi John,
What performance issues are you having with LockBits? If you're
programming C# then you should surely be using unsafe code and not the
Marshal class for access.



Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the code
I pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that said
to use this method.

When I run this under VS I get about 1fps. When I run it outside of VS
I get about 10-20fps or so. (it might actually be fast but its slightly
jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R, System.Drawing.Imaging.ImageLockMode.ReadOnly,
bitmap.PixelFormat);

ReadOnly doesn't look right for this.


unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);



Which part is the slowdown (use Diagnostics.Stopwatch)? The LockBits,
filling in the array, UnlockBits, or DrawImage?

I doubt the computations are the bottleneck, but you can surely remove
some redundant code there, use repeated addition to find row instead of
multiplying by y, precompute x*PixelSize, and (c / 255). Also
multiplying will be much faster than Math.Pow for the integral cases.

If I'm right and the for loops are fast enough, then you can surely get
a very good frame rate (i.e. hit monitor's refresh rate with plenty of
cycles to spare) using OpenGL with glDrawPixels. A little more work for
you, but you'll get direct transfers to video memory and thence to the
screen. If you move up to a texture with glTexImage2D, a lot of effects
become essentially free at that point as well (transparency for
watermarking or fading in and out, rotation, stretching, etc).
Yes, I should be able to get it a good frame rate. I just need to work at
the pixel level because I am trying to do a physics simulation. The
display is only to display the result of the simulation periodically. I
have some other simulations that I've done but I didn't use lock bits and
they seem pretty fast. This is first time I'm using lock bits but
potentially code is slow when I'm actually doing the simulation(but
shouldn't be that slow).

What I did notice is that when I run it under VS its about 20 times
slower even if in active mode. So the debugger is making it very slow and
I probably got confused when I was running it and with the simulation.

Essentially I'm calculating two gaussians and maybe the math library is
pretty slow. I guess I'll need to precalculate the guassians and see how
that works. I'll try to profile it sometime but distracted writing a
vector library ATM.

Ah, yes, with only 256 values a lookup table will be several orders of
magnitude faster than calling Pow inside the loop. I hadn't even
considered that. I really meant for you to first measure timing and find
out which part was the bottleneck.

But I commented out the calculation and it was just as slow. I think it has
to do when in debugging mode. Anyways, I started a new projected and used
lock bits and its much faster... I guess I can get around 40 frames per
second when just changing the colors in a simple way.

Strangely though I rewrote Exp to use lookups and its no faster than
Math.Exp... so I gotta see what I can do about that ;/

Thanks,
Jon
 
Jon Slaughter said:
Ben Voigt said:
Jon Slaughter said:
Hi John,
What performance issues are you having with LockBits? If you're
programming C# then you should surely be using unsafe code and not
the Marshal class for access.



Did you look at my code? I'm not sure what you mean by unsafe and
marshaling? I used unsafe to access the lockbits... its all in the
code I pasted...

crap... lol, I guess I didn't paste any code ;/

Ok, here it is... Its kinda messy but shows what I'm doing when using
lockbits(I pretty much copied and pasted from some other site that
said to use this method.

When I run this under VS I get about 1fps. When I run it outside of VS
I get about 10-20fps or so. (it might actually be fast but its
slightly jerky)


Thanks,
Jon

bmd = bitmap.LockBits(R,
System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

ReadOnly doesn't look right for this.


unsafe

{

for (int y = 0; y < bmd.Height; y++)

{

byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

for (int x = 0; x < bmd.Width; x++)

{

c = (int)(t) % 255;



row[x * PixelSize + 2] = (byte)(255*(Math.Pow((c/255F),0.8)));

row[x * PixelSize + 1] = (byte)(255*(Math.Pow((c/255F),2)));

row[x * PixelSize + 0] = (byte)(255*(Math.Pow((c/255F),3)));

}

}

} // unsafe

bitmap.UnlockBits(bmd);



BitmapGraphics2.DrawImage(bitmap, 0, 0);



Which part is the slowdown (use Diagnostics.Stopwatch)? The LockBits,
filling in the array, UnlockBits, or DrawImage?

I doubt the computations are the bottleneck, but you can surely remove
some redundant code there, use repeated addition to find row instead of
multiplying by y, precompute x*PixelSize, and (c / 255). Also
multiplying will be much faster than Math.Pow for the integral cases.

If I'm right and the for loops are fast enough, then you can surely get
a very good frame rate (i.e. hit monitor's refresh rate with plenty of
cycles to spare) using OpenGL with glDrawPixels. A little more work
for you, but you'll get direct transfers to video memory and thence to
the screen. If you move up to a texture with glTexImage2D, a lot of
effects become essentially free at that point as well (transparency for
watermarking or fading in and out, rotation, stretching, etc).
Yes, I should be able to get it a good frame rate. I just need to work
at the pixel level because I am trying to do a physics simulation. The
display is only to display the result of the simulation periodically. I
have some other simulations that I've done but I didn't use lock bits
and they seem pretty fast. This is first time I'm using lock bits but
potentially code is slow when I'm actually doing the simulation(but
shouldn't be that slow).

What I did notice is that when I run it under VS its about 20 times
slower even if in active mode. So the debugger is making it very slow
and I probably got confused when I was running it and with the
simulation.

Essentially I'm calculating two gaussians and maybe the math library is
pretty slow. I guess I'll need to precalculate the guassians and see how
that works. I'll try to profile it sometime but distracted writing a
vector library ATM.

Ah, yes, with only 256 values a lookup table will be several orders of
magnitude faster than calling Pow inside the loop. I hadn't even
considered that. I really meant for you to first measure timing and find
out which part was the bottleneck.

But I commented out the calculation and it was just as slow. I think it
has to do when in debugging mode. Anyways, I started a new projected and
used lock bits and its much faster... I guess I can get around 40 frames
per second when just changing the colors in a simple way.

Strangely though I rewrote Exp to use lookups and its no faster than
Math.Exp... so I gotta see what I can do about that ;/

You built a lookup array for c => (byte)(255*(Math.Pow((c/255F),0.8))),
right?

That will be much faster than a Dictionary<float, float> for Math.Pow
itself. Also, the overhead of lazy initialization is going to be
considerable, just precompute the whole table.

Actually, you can use an int* instead of byte* in your unsafe loop, and
return the whole R-G-B composite from the lookup table.
 
Back
Top