# VBForums CodeBank > CodeBank - Visual Basic .NET >  FastPix: Rapid Pixel Processing for Dummies and Dudes

## boops boops

EDIT October 2013: FastPix code modified to handle the Byte Array correctly. See post #38 below.

People are forever complaining about the slowness of *GetPixel* and *SetPixel*. They probably weren't designed for processing whole images (or if they were, they were designed very badly). DotNet has an answer to that, but it's not an easy one to get your head around: the Bitmap class methods LockBits and UnlockBits.

The main idea of *FastPix* is to provide a substitute for GetPixel and SetPixel which seem to work about 10 to 15 times as fast as the original ones. But it has more to offer.

There are plenty of examples on the web of classes that encapsulate LockBits/UnlockBits. The ones I have seen are often hampered because they try to deal with different bitmap formats. But as far as I can see nearly all the bitmaps we deal with are either 24 bits (digital photos, some drawing programs) or 32 bits (drawing programs with transparency). GDI+ converts 24 bit images internally to 32 bits anyway, so I have designed FastPix to work with 32 bits only. It makes the code simpler and opens up the possibility of processing bitmaps as Integer arrays, which are blindingly fast. FastPix includes a *ConvertFormat* method for converting bitmap pixel formats or you can use:

vb.net Code:
Dim img = Image.FromFile(filename)Dim bmp As New Bitmap(img)
The bitmap New sub converts a loaded image (but not an image file) to 32 bits.

*To start using Fastpix*, download the attached zip file and unzip it to a convenient folder. In Visual Studio, select Project/Add Existing Item... and import the unzipped .vb file into your project.

Here is an example of how you use the *FastPix GetPixel and SetPixel substitutes*. Their format is the same as the ones in the Bitmap class:

vb.net Code:
Using fp as New FastPix(myBitmap)       Dim myColor As Color =  fp.GetPixel(x, y)       fp.SetPixel(x, y, Color.Orange)    End Using
*Always declare a FastPix object with a Using loop, or otherwise Dispose it as soon as you have finished with it. The UnLockBits is in the Dispose method, so you will not be able to see your resulting bitmap until Dispose has been called either implicitly (with End Using) or directly.*

FastPix also offers you the bitmap in the form of an *Integer Array* and its performance leaves even the Fastpix GetPixel/SetPixel in the dust. Here's an example of how you use it:

vb.net Code:
Using fp as New FastPix(myBitmap)           'Make a local reference to the array; it is roughly 4x as fast as direct references to fp.PixelArray:           Dim pixels as Integer() = fp.PixelArray               For i as integer = 0 to pixels.Length - 1                    'example: substitute a color                   if pixels(i) = Color.Red.ToArgb then pixels(i) = Color.Blue.ToArgb                    'example: invert the color                   pixels(i) = pixels(i) XOR $HFFFFFF                Next            End Using
Note how the inversion is done using only a logical instruction and a bit mask. If you can restrict yourself to techniques like that and to integer arithmetic, and avoid all references to objects outside the Class, you can get fantastic performance. For example, inverting the colors of a 10 MP digital photo can be done over *100x* as fast as with old-fashioned GetPixel and SetPixel (150x if you don't count the LockBits/UnlockBits overhead). 

Of course, many kinds of pixel processing require you to get at the *A, R, G and B bytes* of the pixel. You can extract those from an integer using the BitConverter.GetBytes method, but that would slow things down terribly. Instead, it is possible to extract the bytes with *masks* and *logic/shift operations* only. They are probably just as fast as integer arithmetic. Here is an example which fades a bitmap by leveling all the Alpha byte values to a maximum level:

vb.net Code:
Dim _alpha As Byte 'Level Alpha down to this value Using fp as New FastPix(myBitmap)   Dim pixels as Integer() = fp.PixelArray   Dim px As Integer = pixels(j)   Dim pxAlpha As Integer = (px >> 24) And &HFF 'shift alpha byte to bottom end, clear rest   If pxAlpha > _alpha Then       pxAlpha = CInt(_alpha) << 24      pixels(j) = (px And &HFFFFFF) Or pxAlpha 'replace original alpha value   End If End Using

If you don't like the look of that, FastPix also provides a *Byte array* to make byte operations a bit less intimidating. Possibly it's not as fast as the integer array version. The bytes are in the order B, G, R, A for each pixel. Here's another example of fading a bitmap. Note the *extra parameter* in the FastPix declaration:

vb.net Code:
Using fp As New FastPix(myBitmap, True)   Dim bytes As byte() = fp.ColorByteArray   'Modify the Alpha bytes to make the bitmap 50% transparent:    For i As Integer = 3 to bytes.Length - 1 Step 4           bytes(i) = 127    NextEnd Using

I hope you find it useful. Comments and criticism welcome. BB

----------


## tan2010

Wow, your code looks very lean and effective. How do i apply it to my project so that it can help me sharpen the image using track bar.
Please show me some coding!

----------


## boops boops

Thanks for the compliment. I may be able to help you improve the performance, but I won't have time today. I'll look at it in the weekend. BB

----------


## formlesstree4

This is a great entry into the codebank boops, well done!

----------


## Schravendeel

Wow. Cant believe that this has so few replies. This is just pure epicness! As you said, the slowness of GetPixel and SetPixel has always annoyed me, this finally fixes this issue. Yay!  :wave: 

Many  for you sir!  :Smilie:

----------


## moti barski

```
Using fp as New FastPix(myBitmap)
```

myBitmap = bitmap variable ?

----------


## boops boops

@Schravendeel. Thanks for your compliments!
@Moti. Yes, it just stand for the name of your own bitmap. Sorry it wasn't clear.
@Everyone. New version coming soon!

BB

----------


## moti barski

testing report :
form controls :
picturebox : with image in it, streched
button
textbox

code used with fast pix class :


```
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim bm As Bitmap
        bm = PictureBox1.Image
        Using fp As New FastPix(bm)
            Dim myColor As Color = fp.GetPixel(20, 20)
            fp.SetPixel(20, 20, Color.Orange)
            TextBox1.Text = myColor.ToString
        End Using
    End Sub
End Class
```

a glitch fired up :

A first chance exception of type 'System.FormatException' occurred in pixelTest1.exe

in the class line (after the if line):

If pFSize <> 32 OrElse bmp.PixelFormat = PixelFormat.Indexed Then
            Throw New FormatException _
                ("FastPix is designed to deal only with 32-bit pixel non-indexed formats. Your bitmap has " _
                & pFSize & "-bit pixels. You can convert it using FastPix.ConvertFormat.")
        Else

----------


## formlesstree4

Moti, it specifically tells you how to deal with the problem right in the error message.

----------


## moti barski

only .bmp ?

----------


## formlesstree4

The program tells you the exact call to use in order to (hopefully) remove the error.

----------


## moti barski

please stop the guessing game

this also glitches:


```
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim bm As Bitmap
        bm = PictureBox1.Image
        Using fp As New FastPix(bm)
            FastPix.ConvertFormat(bm, Imaging.PixelFormat.Alpha)
            Dim myColor As Color = fp.GetPixel(20, 20)
            fp.SetPixel(20, 20, Color.Orange)
            TextBox1.Text = myColor.ToString
        End Using

    End Sub
End Class
```

----------


## formlesstree4

You don't seem to get it. I'm not guessing; I'm telling you exactly what you need to hear. You need to convert it before you actually use the image otherwise you'll throw the exception. You know the method to use to perform the conversion, just change where it's being called. It's not that hard.

----------


## moti barski

this ? FastPix.ConvertFormat(bm, Imaging.PixelFormat.Alpha)
where should it go ?

----------


## formlesstree4

Before the Using statement...

----------


## moti barski

> Before the Using statement...


A first chance exception of type 'System.ArgumentException' occurred in System.Drawing.dll

 :Mad:  :Mad:  :Mad:  :Mad:  :Mad:  :Mad:  :Mad:  :Mad:  at the situation

----------


## formlesstree4

How is that my problem? That's an exception in System.Drawing.dll, not FastPixel. Try wrapping Try-Catch statements around it and see what you get. Don't get mad at the person that's hand-feeding you help and try using some common logic to fix a problem.

----------


## moti barski

I am not mad at you you're cool the glitches are what got to me
I"ll just hope senior boobs hook me up with a walkthrough

----------


## Nightwalker83

> I am not mad at you you're cool the glitches are what got to me
> I"ll just hope senior boobs hook me up with a walkthrough


Download the attachment in the first post. The author "boops boops" included a couple of examples in the downloadable file that have be commented out.

----------


## boops boops

See post #1 in this thread:


> nearly all the bitmaps we deal with are either 24 bits (digital photos, some drawing programs) or 32 bits (drawing programs with transparency). GDI+ converts 24 bit images internally to 32 bits anyway, so I have designed FastPix to work with 32 bits only. It makes the code simpler and opens up the possibility of processing bitmaps as Integer arrays, which are blindingly fast. FastPix includes a *ConvertFormat* method for converting bitmap pixel formats.


 BB

----------


## moti barski

senior convertFormat glitched, before that there was another glitch and
walkthrough pliz

----------


## Milk

Moti, I propose that you are the glitch.

Imaging.PixelFormat.Alpha is not a pixel format it is a flag, there is not such thing as a bitmap with a format of Alpha. 

The ConvertFormat() format parameter is optional you do not need to pass it, if you do pass it use one of the formats that start with Format32bpp.

You must convert the Bitmap before you pass it to the FastPix constructor not after.

PictureBox1.Image must contain a valid GDI Bitmap.

----------


## moti barski

so, it is a fluke if a bitmap work with the class, thanks milk now I get it

----------


## boops boops

Edit: follow Milk's advice. The next version of FastPix will make it a bit easier to avoid that mistake. BB

----------


## formlesstree4

> so, it is a fluke if a bitmap work with the class, thanks milk now I get it


No fluke; it's pretty much spelled out how to make it work.

----------


## moti barski

and if I had wheels I'd be a wagon

----------


## formlesstree4

> and if I had wheels I'd be a wagon


How does that even relate to this situation? You're merely making an analogy that has no reference to the subject at hand. I'm sorry but it wouldn't take very long to work with the code and produce the desired effect you want.

----------


## sacramento

Hi:

I had download your code but VB don't recognize fastpix...

*Type 'Fastpix' is not defined*

Any suggestion?

Thanks

----------


## boops boops

1. download the zip file
2. unzip it to obtain FastPix.vb
3. save the file wherever you like to keep your downloaded code.
4. in Visual Studio, right-click on your project name
5. select Add Existing Item
6. browse to find the FastPix.vb file and select it
7. now you can use Faspix in the project.

BB

----------


## sacramento

Hi:

Thanks for your answear...
I have one doubt her.e..your code could adapt to rotate images or graphics?

----------


## boops boops

> Hi:
> 
> Thanks for your answear...
> I have one doubt her.e..your code could adapt to rotate images or graphics?


It could be used for that in theory, but I doubt if it would be worth the effort. The GDI+ plus methods for rotation (Bitmap.RotateFlip, Graphics.RotateTransform etc.) seem pretty efficient to me. I suppose they use the same Math methods as you would use yourself on an array of pixels.

BB

----------


## sacramento

Hi:

Ok...thanks

----------


## SaxxonPike

I've been using a different method for about a year without fail. It doesn't involve marshalling anything.

I write this from memory, please excuse me if it is incorrect..

vb.net Code:
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
 Public Class DirectBitmap
    
    Private Handle as GCHandle
    Public Readonly Pixels() as Int32
    Public Readonly Bitmap as Bitmap
    Public Readonly Width as Integer
    Public Readonly Height as Integer
    
    Public Sub New(NewWidth as Integer, NewHeight as Integer)
        Dim Area as Integer
        Width = NewWidth
        Height = NewHeight
        Area = Width * Height
        Redim Pixels(Area - 1)
        Handle = GCHandle.Alloc(Pixels, GCHandleType.Pinned)
        Bitmap = New Bitmap(Width, Height, 4 * Width, PixelFormat.Format32bppPArgb, Handle.AddrOfPinnedObject)
    End Sub
    
    Protected Overrides Sub Finalize()
        Bitmap = Nothing
        Handle.Free()
        Handle = Nothing
        Pixels = Nothing
        MyBase.Finalize()
    End Sub
End Class

----------


## boops boops

Hi SaxxonPike,

I compared the "pinned array" method with "lockbits" when I was developing FastPix. It appeared that the pixel processing speed was more or less identical for the two methods, but the instantiation time for the pinned array was much longer, regardless of the bitmap size. I was also uncertain whether the pinned array code might yield problems further down the line (compared to the well-tried lockbits) so I decided to leave it on the shelf. 

It's easy to make mistakes when comparing performance, so now (with more experience) I should take a new look at it. Maybe I could try the code you have posted instead of my own version, which was based on a CodeProject example. So thanks for posting it.

Besides, the pinned array approach has significant advantages when you need to process the same bitmap over and over again. Unlike lockbits, you don't have to unlock the bitmap to get at the results so you only have to create the array once. There may also be some advantage to processing the pinned array in an Unsafe block in Csharp, but from what I have read I wouldn't expect it to make a spectacular difference.

BB

----------


## SaxxonPike

> Hi SaxxonPike,
> 
> I compared the "pinned array" method with "lockbits" when I was developing FastPix. It appeared that the pixel processing speed was more or less identical for the two methods, but the instantiation time for the pinned array was much longer, regardless of the bitmap size. I was also uncertain whether the pinned array code might yield problems further down the line (compared to the well-tried lockbits) so I decided to leave it on the shelf.


My guess would be that the garbage collector has to make special provisions as it cannot do anything with a pinned object. It's really useful if it's something like a screen buffer that won't change for the duration of execution. I am currently using it for a game project and notice no significant slowdowns as a result of creating and disposing bitmaps created in this manner, but I haven't done performance testing extensively as you have.

Doesn't seem like I'm able to edit the code, after throwing it into VB I realized that "Bitmap" was a class name being used as a variable. Whoops  :Smilie:  The code should work otherwise (if you originally try it, all pixels will have value 0- completely transparent).




> There may also be some advantage to processing the pinned array in an Unsafe block in Csharp, but from what I have read I wouldn't expect it to make a spectacular difference.


I thought about using the Unsafe block as I also work with C#; however, that might require special permissions for the end-user and a special configuration for the program. I'm not a big fan of this myself  :Smilie:

----------


## boops boops

> Doesn't seem like I'm able to edit the code, after throwing it into VB I realized that "Bitmap" was a class name being used as a variable. Whoops  The code should work otherwise (if you originally try it, all pixels will have value 0- completely transparent).


Try putting square brackets round the identifier [Bitmap]. BB

----------


## supray

HI

How I can display the modified image ( should be shown as 50% transparent, while the pciture in PictureBox2 appear as same as  source..i,e PictureBox1)
Should I need to convert the colorbyte array to bmp..or something like that..?

vb.net Code:
PictureBox1.Image = New Bitmap("8.jpg") ' source image
         Dim b = New Bitmap("8.jpg")
        FastPix.ConvertFormat(b, Imaging.PixelFormat.Format32bppArgb)
         Using fp As New FastPix(b, True)
            Dim bytes As Byte() = fp.ColorByteArray
            'Modify the Alpha bytes to make the bitmap 50% transparent:
            For i As Integer = 0 To bytes.Length - 1 Step 4
                bytes(i) = 127
            Next
        End Using
         PictureBox2.Image = b ' altered image
[/QUOTE]

----------


## boops boops

Hi supray,

You have discovered an error in FastPix. It seems I never tested the Byte array (ColorByteArray) properly. Thanks for that, and my apologies. 

Fortunately it wasn't hard to fix. What I had to do was  to declare _UseByteArray at class level, and then test it in the Dispose sub so as to write the correct data to the bitmap.



```
'added at Class level
Private _UseByteArray As Boolean

'added in the New sub
_UseByteArray = UseByteArray

'changed in the Dispose sub, instead of only writing _PixelData back to the bitmap:
If _UseByteArray Then
	If _ByteData IsNot Nothing Then Marshal.Copy(_ByteData, 0, _bmpData.Scan0, _ByteData.Length)
Else
	If _PixelData IsNot Nothing Then Marshal.Copy(_PixelData, 0, _bmpData.Scan0, _PixelData.Length)
End If
```

There's no need to make these changes yourself. I've posted the corrected FastPix Class as a new attachment to Post #1, because it's easier for people to find there. 

There is something else. The bytes in the Btye array are not stored in ARGB order but the reverse BGRA. You have to realize this if you are using the Byte array. Fortunately, the the only change needed in the code is to correct the byte array example in the FastPix comments, as well line 9 of own your code. All that's needed is to change 0 to 3: 


```
For i As Integer = 3 To bytes.Length -1 Step 4
```

That will make sure only the A bytes are changed. Make this change, and use the new version of FastPix from post #1, and your code should work ok.

BB

----------


## supray

Thank you so much. Indeed its now working great !!!
Great job !!!

----------


## supray

Hi 

Something I dont understand well...its my inablity. I was trying to use its different feature. 
I wanted to change the pixel color at (x,y) in steps so that it will appear as a uniforn grid (x, y dotted mesh grid line drawn on image..).

The following code does not work (gives error : out of bound of the array). Am I missing something ?

vb.net Code:
PictureBox1.Image = New Bitmap("8.jpg")
         Dim b = New Bitmap("8.jpg")
        FastPix.ConvertFormat(b, Imaging.PixelFormat.Format32bppArgb)
         Using fp As New FastPix(b)
             Dim pixels As Integer() = fp.PixelArray
             For x As Integer = 0 To pixels.Length - 1 Step 200
                For y As Integer = 0 To pixels.Length - 1 Step 200
                     Dim myColor As Color = fp.GetPixel(x, y)
                    fp.SetPixel(x, y, Color.Orange)
                    
                Next
            Next
        End Using
 PictureBox2.Image = b

while the following code works but the dot in each row shifted so that it seems the lines are drawn diagonally and ofcourse only set of parallel line (diagonally)


vb.net Code:
PictureBox1.Image = New Bitmap("8.jpg")
         Dim b = New Bitmap("8.jpg")
        FastPix.ConvertFormat(b, Imaging.PixelFormat.Format32bppArgb)
         Using fp As New FastPix(b)
             Dim pixels As Integer() = fp.PixelArray
             For x As Integer = 0 To pixels.Length - 1 Step 200
                 pixels(x) = Color.Blue.ToArgb()
                    
            Next
        End Using
 PictureBox2.Image = b

does PixelArray retrun a array for each horizontal row of the image ?

----------


## boops boops

> Hi 
> does PixelArray retrun a array for each horizontal row of the image ?


No, it just returns a single array for the whole image. This is for reasons of efficiency: one dimensional arrays are quite a bit faster to index than two dimensional arrays. In your code, you are mixing up the two approaches. If you are using PixelArray you would normally calculate the index as y * bitmap.Width + x. But FastPix.GetPixel and SetPixel do that calculation for you. So you could change your loop to this:


```
Using fp As New FastPix(b)       
     For x As Integer = 0 To b.Width - 1 Step 20
           For y As Integer = 0 To b.Height - 1 Step 20
              fp.SetPixel(x, y, Color.Orange)          
           Next
     Next
End Using
PictureBox2.Image = b
```

The Step value above gives the pixel spacing of the grid lines, so I guess you want something less than 200 pixels!

By the way, Graphics commands like DrawLine and DrawImage don't have the efficiency drawbacks of Bitmap.SetPixel and Bitmap.GetPixel. So you might consider drawing your grid in the Paint sub of the PictureBox, instead of using FastPix. It wouldn't surprise me if it was even more efficient. For example:


```
Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
     Using pn As New Pen(Brushes.Orange)
	pn.DashStyle = Drawing2D.DashStyle.Dot
	For x As Integer = 0 To PictureBox1.Width Step 20
		e.Graphics.DrawLine(pn, x, 0, x, PictureBox1.Height)
	Next
	For y As Integer = 0 To PictureBox1.Height Step 20
		e.Graphics.DrawLine(pn, 0, y, PictureBox1.Width, y)			
        Next
     End Using
End Sub
```

If you want a different dot spacing, you could set the pen's DashStyle to Custom instead of to Dot as above:


```
pn.DashStyle = Drawing2D.DashStyle.Custom
pn.DashPattern = {1, 3}
```

That would give a 1 pixel dash (a dot) with 3 pixels of space.

BB

----------


## Stealthrt

Hey all i am trying to get my images to look nice and smooth (antialiasing) from using a mask in order to make the round image as you see below:


The original image looks like this:


The mask for the image above looks like this (the red being the mask color to take out):


It works but it gives me those not-so-nice jagged edges around it. The mask is an .png and also the image itself is a .png.

The code i use to make the mask is this:


```
    picNextTopic1.Image = Image.FromStream(wc.OpenRead(anAPI.wallOrgPostImage(keying).Replace("{width}", "50").Replace("{height}", "50"))) 'Download the image from the website.                  
    picNextTopic1.Image = ApplyMask(New Bitmap(picNextTopic1.Image), New Bitmap(My.Resources.mask), Color.Red) 'Apply mask to the downloaded image above.
```

The ApplyMask function is this:


```
    Public Function ApplyMask(ByVal bImg As Bitmap, ByVal bMask As Bitmap, ByVal maskColor As Color) As Image
        Dim wImg As Integer = bImg.Width
        Dim hImg As Integer = bImg.Height
        Dim wMask As Integer = bMask.Width
        Dim hMask As Integer = bMask.Height
        Dim intMask As Integer = maskColor.ToArgb
        Dim intTransparent As Integer = Color.Transparent.ToArgb

        Using fpImg As New FastPix(bImg)
            Using fpMask As New FastPix(bMask)
                Dim pixelsImg = fpImg.PixelArray
                Dim pixelsMask = fpMask.PixelArray

                For y As Integer = 0 To Math.Min(hImg, hMask) - 1
                    For x As Integer = 0 To Math.Min(wImg, wMask) - 1
                        Dim iImg As Integer = (y * wImg) + x
                        Dim iMask As Integer = (y * wMask) + x

                        If pixelsMask(iMask) = intMask Then
                            pixelsImg(iImg) = intTransparent
                        End If
                    Next
                Next
            End Using
        End Using

        Return bImg
    End Function
```

Any help to smooth this out would be great! Thanks!

----------


## boops boops

Hi Stealthrt,

If your mask is always defined geometrically, like your circular mask in the example, it shouldn't be too difficult. In that case, you can draw the shape on the red background with Graphics.SmoothingMode=Antialias and then Graphics.FillElllipse, and GDI+ will give the shape an anti-aliased edge. Then you can copy the red component of the mask pixels to the transparency of the image pixels much as you are doing at present. This should work too for more complex shapes such as rounded rectangles and text, in fact anything you can define as a GraphicsPath.

Otherwise -- as far as I know -- things are likely to be rather more difficult, although there are various possibilities. If the mask image consists of a "blob" of unknown shape, it's possible to analyse the edge as a polygon using the Marching Squares Algorithm. I've been thinking of posting an example of that algorithm in VB.Net to this code bank, but it will have to wait. For a good explanation, see this link. 

An alternative is to "feather" the edges of the image. That means nibbling away the edge pixels of the masked image with decreasing transparency: Paint.Net and many other drawing programs have tools for doing that. It should also be possible to do it in VB.Net, although it may not be quick. Another possibility would be to apply a blur (box blur for simplicity, Gaussian blur for better results) to the borders of the image against a transparent background; that would be more like true anti-aliasing.

It's an interesting problem which I would like to tackle but I won't have time until the New Year.

BB

----------


## KM94

Hi!

What if I wanted to do this with a window handle using hDC/hWnd? Must I take screenshots of the application and then compare them or is there a way to replace the bitmap with a window handle?

Thanks.  :Smilie:

----------


## boops boops

Hi KM,

The FastPix class works only with 32-bit bitmaps. If you want to get a snapshot of your own form, complete with controls, you could consider using the form's DrawToBitmap method; it has a few limitations but it's simple to code. If it's another application, then I guess there isn't much alternative to getting a screenshot.

BB

----------


## Shaggy Hiker

I don't know if this will be seen, but I was wondering whether the timing was done with Integer Overflow Checks on or off? This code seems like it would really benefit from having them off, which should be safe to do. That might get you a couple more x in speed (to explain that odd statement, I'm making a reference to the fact that you already have 100x, so this might add a few more x).

----------


## boops boops

> I don't know if this will be seen, but I was wondering whether the timing was done with Integer Overflow Checks on or off? This code seems like it would really benefit from having them off, which should be safe to do. That might get you a couple more x in speed (to explain that odd statement, I'm making a reference to the fact that you already have 100x, so this might add a few more x).


In the conditions under which I originally tested it (WinXP sp3, VB2008 express/.Net 3.5) it didn't make any apparent difference. As is often the case, a different OS/Framework version could have a significant effect. Incidentally, measuring only the pixel processing and not the time to instantiate/dispose the Fastpix object gave a speed gain of around 250x compared to GetPixel/SetPixel for image colour inversion; that might be relevant when successive operations have to be done on the same bitmap.

In case you are interested, the VB2008 test rig I used for checking these assertions is attached. It's a bit ramshackle but I hope it will be self-explanatory. I had a default test image in the Resources folder but the forum wouldn't let me include it in the zip file. I've attached it separately in case it's needed, but you can load your own images. Comments and criticisms of the actual testing assumptions are of course welcome.

BB

----------


## Stealthrt

> Hi Stealthrt,
> 
> If your mask is always defined geometrically, like your circular mask in the example, it shouldn't be too difficult. In that case, you can draw the shape on the red background with Graphics.SmoothingMode=Antialias and then Graphics.FillElllipse, and GDI+ will give the shape an anti-aliased edge. Then you can copy the red component of the mask pixels to the transparency of the image pixels much as you are doing at present. This should work too for more complex shapes such as rounded rectangles and text, in fact anything you can define as a GraphicsPath.
> 
> Otherwise -- as far as I know -- things are likely to be rather more difficult, although there are various possibilities. If the mask image consists of a "blob" of unknown shape, it's possible to analyse the edge as a polygon using the Marching Squares Algorithm. I've been thinking of posting an example of that algorithm in VB.Net to this code bank, but it will have to wait. For a good explanation, see this link. 
> 
> An alternative is to "feather" the edges of the image. That means nibbling away the edge pixels of the masked image with decreasing transparency: Paint.Net and many other drawing programs have tools for doing that. It should also be possible to do it in VB.Net, although it may not be quick. Another possibility would be to apply a blur (box blur for simplicity, Gaussian blur for better results) to the borders of the image against a transparent background; that would be more like true anti-aliasing.
> 
> It's an interesting problem which I would like to tackle but I won't have time until the New Year.
> ...


Were you able to check on this, boops boops?  :Smilie:

----------


## kebo

BB,
This is good stuff. Thanks for putting it out there. 

I am curious about how this compares to drawing using DirectX. I have a charting class that I use DX with so I can show dozens of charts each with 1,000+ points simultaneously with a 1 second refresh. When I first built the class, it absolutely choked using GDI. DirectX was the only way I could draw what I needed fast enough.

As I  I understand it, FastPix essentially lock the image in memory and allows you to manipulate the raw data rather than having to go through the framework methods. With DX, you essentially create an array of vectors and present them. Beyond that I have no clue how DX works, but I am curious if you have done any, or have an idea of how FastPix would compare against DX. I realize that DX is used more as a 3D model environment, but it can also be use very effectively in 2D space as well.

I'd love to hear your thoughts. 
kevin

----------


## boops boops

I sometimes wonder why GetPixel and SetPixel weren't made more efficient in the first place. It's as though LockBits was added on to System.Drawing as an afterthought, as a slightly hacky extension for geeks only. LockBits and hence also FastPix utilize methods of the System.Drawing.Bitmap, so they are firmly rooted in GDI+. That's why they are closely associated with Windows.Forms, and seem relatively at home with VB.Net. But pixel-based processing with GDI+ relies on the CPU. Once you have decided what you want to paint, it doesn't paint pixels onto the screen any faster than GDI+ can achieve. 

I don't have much experience with DirectX (or related packages such as XNA) but it's clearly capable of slapping pixels onto the screen much faster than GDI+ can. DirectX is also particularly good for things like animation, 3D drawings, transparency (and hence anti-aliasing) and colour gradients, because it can take full advantage of modern graphics hardware (GPU). It doesn't work well with individual pixels but I should think you could do highly efficient image processing in terms of triangle meshes and textures.

Interestingly, the .Net framework has a nicely packaged version of DirectX (in particular, the subset known as Direct3D) built into it. It doesn't involve downloading and installing special DLLs and it's accessible in Visual Studio just by selecting a suitable project template. It adapts to different graphics hardware capabilities and it has sound memory management. All its classes and interfaces are exhaustively documented in msdn complete with coding examples in Csharp and usually in VB.Net too. It's called WPF. 

BB

----------


## Peter Porter

Boops, have you ever thought about using GPU CUDA's to speed up FastPix?

I'm sure people would pay for that version!  :Smilie:

----------


## Peter Porter

Boops, have you ever thought about using GPU CUDA's to speed up FastPix?

I'm sure people would pay for that version!  :Smilie:

----------


## boops boops

Hi Peter,
sorry I didn't answer earlier, it seems like the forum has unsubscribed me from everything so I don't get notified. As to your question,


> have you ever thought about using GPU CUDA's to speed up FastPix?


The answer is No.

Wikipedia explains that CUDA is a technology for use with suitably enabled NVIDIA GPU hardware, which is designed for programming in languages such as C++. Its main purpose is to provide efficient high-resolution 3D graphics. That's a long way from simple 2D image processing in VB.Net which could be the business of LockBits or FastPix. Maybe there are applications that benefit from combining them, but I suspect it would be bit like trying to pair an alloy bicycle wheel (FastPix) with a formula 1 engine (CUDA etc.); you'd have to think carefully about the drive train :Big Grin: !

If I felt a need to combine pixel based image processing with fast 3D rendering, I would consider using a WriteableBitmap in WPF with its rendering based on Direct3D. And I expect there are other, better ways of exploiting GPU hardware.

BB

----------


## ste_wilko

Hi boops, sorry to resurrect such an old post but I am after a little help. I'm trying to use fastpix to make an "on the fly" green screen application, wherein the user selects a background from a selection of predefined images; then they take a photo that shows them on their chosen background in real time (like a photo booth) I did download Peter's project and saw that it worked flawlessly, but I didn't really understand the code to translate it into what I'm trying to achieve. Any help would be greatly appreciated

----------

