Results 1 to 22 of 22

Thread: [RESOLVED] Getting Average RGB Color Value of Entire Screen

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jun 2008
    Posts
    90

    Resolved [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Hi all

    Does anyone know if there is a way of getting the average RGB colour value of the entire screen? I'm toying with the idea of writing some software that will emulate (very loosely) an 'ambilight' type TV for use while gaming.

    The idea is, average the RGB colour value of the screen (the total value or at least a definable section of it) while gaming and output that RGB value via DMX protocol (standard protocol used to control lights via lighting consoles and software in clubs / at gigs / on TV etc) to a set of DMX enabled LED lights sat behind the monitor. Whatever method is used would need to be efficient so that it could react to screen changes in real time.

    I've got all the required hardware and can code the DMX protocol no problems, I'm just missing the colour detection portion!

    Any help would be great

  2. #2
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: Getting Average RGB Color Value of Entire Screen

    A very slow method would be to take a screen shot of the screen, loop through each pixel, get the value of that pixel using Bitmap.GetPixel, convert the color to it's RGB equivalent, store that RGB value into a collection, then get the average of that collection most likely using LINQ.

    Edit:

    Here is a function that returns a bitmap of the entire screen:
    Code:
    Private Function Screenshot() As Bitmap
    	Dim b As Bitmap = New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    	
    	Using g As Graphics = Graphics.FromImage(b)
    		g.CopyFromScreen(0, 0, 0, 0, b.Size, CopyPixelOperation.SourceCopy)
    		g.save
    	End Using
    	
    	Return b
    End Function
    Here is a function that returns all RGB values in the bitmap:
    Code:
    Private Structure RGB
    	Public Property R As Integer
    	Public Property G As Integer
    	Public Property B As Integer
    End Structure
    
    Private Function GetAllRGB(ByVal img As Bitmap) As RGB()
    	Dim rgbCollection As List(Of RGB) = New List(Of RGB)
    	
    	For x As Integer = 0 To img.Width
    		For y As Integer = 0 To img.Height
    			Dim pixelColor As Color = img.GetPixel(x, y)
    			Dim pixelRGB As RGB = New RGB With {.R = pixelColor.R, .G = pixelColor.G, .B = pixelColor.B}
    			
    			rgbCollection.Add(pixelRGB)
    		Next
    	Next
    	
    	Return rgbCollection.ToArray()
    End Function
    Getting the average is your job, I'm not at a computer with VS installed and I don't trust my LINQ skills enough to freehand the code like I did for the others.
    Last edited by dday9; Sep 11th, 2014 at 11:22 AM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Jun 2008
    Posts
    90

    Re: Getting Average RGB Color Value of Entire Screen

    Cheers for the pointer. That works fine, if a little slow (about 0.5 second delay), but it does do exactly what I want!

    I'll work on it. I can certainly speed it up by just sampling every 10th pixel for example (on both axis, this cuts calculations down from averaging over a million pixels to ~10,000), and I'm damn sure there are other ways I can speed it up.

    Cheers, you're a star

  4. #4
    Fanatic Member
    Join Date
    Aug 2004
    Location
    Essex, UK
    Posts
    750

    Re: Getting Average RGB Color Value of Entire Screen

    You might want to consider converting the RGB values to luminance, which will give you the overall "brightness" of the image. Luminance = R * 0.3 + G * 0.59 + B * 0.11.

    Also check out fastpix from boops boops. It really speeds up reading and writing bitmap RGB values:

    http://www.vbforums.com/showthread.p...hlight=fastpix
    Last edited by paulg4ije; Sep 11th, 2014 at 02:59 PM.

  5. #5
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by Duckfather View Post
    Cheers for the pointer. That works fine, if a little slow (about 0.5 second delay), but it does do exactly what I want!

    I'll work on it. I can certainly speed it up by just sampling every 10th pixel for example (on both axis, this cuts calculations down from averaging over a million pixels to ~10,000), and I'm damn sure there are other ways I can speed it up.

    Cheers, you're a star
    Ok ... if you want to do this quickly you could:

    Create a new bitmap that is smaller (1x1) ... turn InterpolationMode to high and draw the large screen shot on the smaller bitmap using drawImage and specifying the small 1x1 area then do your check on the one pixel... InterpolationMode means the downsized pixels when drawing a smaller image get averaged to the pixels they are fitting into.

    Or ... use LockBits as this is much faster than getpixel...

    I prefer the 2nd method ... but the top suggestion would probably be easier for a n00b, and prob just as fast.

    Kris

  6. #6
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: Getting Average RGB Color Value of Entire Screen

    id suggest lockbits and calculating the sum of R/G/B while iterating over the pixels then divide each by the number of pixels.
    this should be the fastest way.

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Jun 2008
    Posts
    90

    Resolved Re: Getting Average RGB Color Value of Entire Screen

    Guys, I just wrote a quick mockup of the interpolation idea and that works great for my purposes. The response shows no physically observable delay. I have to put in a routine to very quickly fade the colours in / out anyway (from previous experience writing code for DMX controlled lights, just snapping to the new colour can be very jarring), so this will now be the limiting factor in the responsiveness of the code, not the speed of the calculation.

    Great advice guys, you've just helped me take my gaming immersion to the next level, hehehe, cheers
    Last edited by Duckfather; Sep 12th, 2014 at 05:57 AM. Reason: Typos

  8. #8
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    I'm interested in seeing you implement this, is there anyway you could post a video or even a few screenshots of it in action?
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  9. #9
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by digitalShaman View Post
    id suggest lockbits and calculating the sum of R/G/B while iterating over the pixels then divide each by the number of pixels.
    this should be the fastest way.
    As I stated ...

    Also for everyone's info I wrote this quick comparison:

    vb Code:
    1. Using b As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    2.             Using g = Graphics.FromImage(b)
    3.                 g.CopyFromScreen(0, 0, 0, 0, b.Size)
    4.             End Using
    5.  
    6.             Dim OutColor As Color
    7.             Dim st As Date
    8.             Dim TotalTime As Double
    9.  
    10.  
    11.  
    12.  
    13.             'Interpolation Method
    14.             Using bOut As New Bitmap(1, 1) '<<< - i keep the bout object outside of the loop ... because if you want speed you would not re-create the bitmap object all the time
    15.                 Using g = Graphics.FromImage(bOut) '<<< - same with this ""
    16.                     st = Now
    17.                     For i = 1 To 100
    18.                         g.InterpolationMode = Drawing2D.InterpolationMode.High
    19.                         g.DrawImage(b, New Rectangle(0, 0, 1, 1))
    20.                         OutColor = b.GetPixel(0, 0)
    21.                     Next
    22.                     TotalTime = Now.Subtract(st).TotalMilliseconds
    23.                     Debug.Print("Interpolation Method: " & OutColor.ToString & " " & TotalTime & "ms")
    24.                 End Using
    25.             End Using
    26.  
    27.  
    28.  
    29.  
    30.             'LockBits Method
    31.             st = Now
    32.             For i = 1 To 100
    33.                 Dim bmpData As System.Drawing.Imaging.BitmapData = b.LockBits(New Rectangle(0, 0, b.Width, b.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
    34.                 Dim bitmapAddress As IntPtr = bmpData.Scan0
    35.  
    36.                 Dim iCount As Integer
    37.                 Dim Max = (b.Width * b.Height * 4) - 4 '<<< - Edit as faster than: CInt(bmpData.Stride * bmpData.Height) - 4
    38.                 Dim TotalR = 0&
    39.                 Dim TotalG = 0&
    40.                 Dim TotalB = 0&
    41.  
    42.                 For iPixel = 0 To Max Step 4
    43.                     iCount += 1
    44.                     TotalR += System.Runtime.InteropServices.Marshal.ReadByte(bitmapAddress, iPixel + 2)
    45.                     TotalG += System.Runtime.InteropServices.Marshal.ReadByte(bitmapAddress, iPixel + 1)
    46.                     TotalB += System.Runtime.InteropServices.Marshal.ReadByte(bitmapAddress, iPixel)
    47.                 Next
    48.  
    49.                 Dim TotalPixels = (Max / 4) + 1
    50.                 OutColor = Color.FromArgb(TotalR \ TotalPixels, TotalG \ TotalPixels, TotalB \ TotalPixels)
    51.                 b.UnlockBits(bmpData)
    52.             Next
    53.  
    54.             TotalTime = Now.Subtract(st).TotalMilliseconds
    55.             Debug.Print("LockBits Method: " & OutColor.ToString & " " & TotalTime & "ms")
    56.  
    57.  
    58.  
    59.  
    60.         End Using

    The colour variations differ slightly (as I 1/2 expected, the "LockBits Method" will of course be more accurate)... but also the "Interpolation Method" that I suggested was actually consistently faster... but only by a little...

    I have changed the color of the word Color below so you can see the different results between the two methods.

    EDIT: Added results for several of my machines...

    Lenovo IdeaCenter Horizon 27 (GeForce GT620M/Intel HD Graphics 4000 / i7-3537U @ 1920x1080)
    Code:
    Interpolation Method: Color [A=255, R=214, G=219, B=233] 4234.5934ms
    LockBits Method: Color [A=255, R=221, G=223, B=225] 4593.9872ms
    Alienware X51 (GeForce GTX 650 Ti / i7-4770 @ 1920x1080)
    Code:
    Interpolation Method: Color [A=255, R=46, G=46, B=46] 8980.0117ms
    LockBits Method: Color [A=255, R=79, G=79, B=79] 9205.0151ms
    Custom Build (AMD Radeon R9200 / i7-4770 @ 1920x1080)
    Code:
    Interpolation Method: Color [A=255, R=1, G=61, B=111] 3165.1913ms
    LockBits Method: Color [A=255, R=52, G=136, B=189] 3413.2514ms
    Apple Retina Laptop (Original model) (GT650M / i7-3720QM @ 2880x1800)
    Code:
    Interpolation Method: Color [A=255, R=48, G=48, B=49] 9906.0174ms
    LockBits Method: Color [A=255, R=48, G=48, B=49] 11091.6195ms
    EDIT:

    Times will be a little out as I modified the code as this seems a little faster:
    Dim Max = (b.Width * b.Height * 4) - 4 '<<< - Edit as faster than: CInt(bmpData.Stride * bmpData.Height) - 4

    ... I should probably also state that the processing is done 100x per method, so times are for performing 100 of the operations.

    Kris

  10. #10
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by i00 View Post
    The colour variations differ slightly (as I 1/2 expected, the "LockBits Method" will of course be more accurate)... but also the "Interpolation Method" that I suggested was actually consistently faster... but only by a little...
    Kris,

    No offense intended, but that is a very inefficient LockBits implementation using three interop calls to get a color value. At least read a single integer and feed it into a Color structure. Or better yet read multiple values at a time. I prefer to read a one row at a time (others the whole thing) into an array and process that.

    Code:
    ' default new BitMap is 32 bit/pixel
    Using bm As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
       Using g As Graphics = Graphics.FromImage(bm)
          g.CopyFromScreen(Point.Empty, Point.Empty, bm.Size)
       End Using
    
       Dim sw As New Stopwatch
       sw.Start()
       Dim srcData As System.Drawing.Imaging.BitmapData
       Dim tmpColor As Color
       Dim Colors(0 To bm.Width - 1) As Int32
       Dim sumR, sumG, sumB As Int64
       Dim totalPixels As Int64 = bm.Width * bm.Height
       For y As Int32 = 0 To bm.Height - 1
          srcData = bm.LockBits(New Rectangle(0, y, bm.Width, 1), _
                                Drawing.Imaging.ImageLockMode.ReadWrite, _
                                bm.PixelFormat)
    
          System.Runtime.InteropServices.Marshal.Copy(srcData.Scan0, Colors, 0, bm.Width)
    
          For x As Int32 = 0 To bm.Width - 1
             tmpColor = Color.FromArgb(Colors(x))
             sumR += tmpColor.R
             sumG += tmpColor.G
             sumB += tmpColor.B
          Next x
          System.Runtime.InteropServices.Marshal.Copy(Colors, 0, srcData.Scan0, srcData.Width)
          bm.UnlockBits(srcData)
          srcData = Nothing
       Next y
       Dim avgColor As Color = Color.FromArgb(255, CType(sumR \ totalPixels, Int32), CType(sumG \ totalPixels, Int32), CType(sumB \ totalPixels, Int32))
       sw.Stop()
       Debug.WriteLine(sw.ElapsedMilliseconds)
    End Using ' bm

  11. #11
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by TnTinMN View Post
    Kris,

    No offense intended, but that is a very inefficient LockBits implementation using three interop calls to get a color value. At least read a single integer and feed it into a Color structure. Or better yet read multiple values at a time. I prefer to read a one row at a time (others the whole thing) into an array and process that.

    Code...
    Well your method crashed for me...

    Name:  Crash.jpg
Views: 3114
Size:  18.4 KB

    EDIT: This thing can't seem to attach images correctly without making them look like c*** ... anyway error is:

    Code:
    An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
    
    Additional information: Value of '437' is not valid for 'red'. 'red' should be greater than or equal to 0 and less than or equal to 255.
    ... but I did test this before with my LockBits loop set as this:

    vb Code:
    1. Dim bmpData As System.Drawing.Imaging.BitmapData = b.LockBits(New Rectangle(0, 0, b.Width, b.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
    2.  
    3.                 Dim TotalR = 0&
    4.                 Dim TotalG = 0&
    5.                 Dim TotalB = 0&
    6.                 Dim TotalPixels = b.Height * b.Width
    7.                 Dim Colors(0 To TotalPixels) As Integer
    8.  
    9.                 System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, Colors, 0, TotalPixels)
    10.                 For Each item In Colors
    11.                     Dim TheColor = Color.FromArgb(item)
    12.                     TotalR += TheColor.R
    13.                     TotalG += TheColor.G
    14.                     TotalB += TheColor.B
    15.                 Next
    16.  
    17.                 OutColor = Color.FromArgb(TotalR \ TotalPixels, TotalG \ TotalPixels, TotalB \ TotalPixels)
    18.                 b.UnlockBits(bmpData)

    ... any problems with that?? ... because it seems to be about 2x as slow ??? .. I thought it would have been faster too!

    EDIT 2:

    Times are:

    Code:
    Interpolation Method: Color [A=255, R=214, G=219, B=233] 4866.2455ms
    LockBits Multiple Interop Method: Color [A=255, R=218, G=220, B=224] 5074.3848ms
    LockBits Single Interop Method: Color [A=255, R=218, G=220, B=224] 8212.4781ms
    EDIT 3:

    OK ... the reason that the method suggested by TnTinMN is really slow is because it creates a color object for each pixel ... which is EXTREMELY slow ... (tmpColor = Color.FromArgb(Colors(x))) ...

    If you have any suggestions on how to better it or my method let me know. ...

    Kris

  12. #12
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Based on that blurry image you have shown, it looks like you pasted my code inside a loop. The the summation variables will need to be set to initialize to zero on each iteration.

  13. #13
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by TnTinMN View Post
    Based on that blurry image you have shown, it looks like you pasted my code inside a loop. The the summation variables will need to be set to initialize to zero on each iteration.
    Did you read the whole post with the edits? ... all but the last would have been there judging by the time of your post.
    I Modified my answer and my method is still faster as creating a color object for each pixel appears to be much slower....

    ... and yes the error message was a c&p of your code (which I stated: "Well your method crashed for me") ... I didn't look into the error at all to be honest tho as I already did this before as stated above ... just slightly differently ... I went to my shadowcopy backup and posted my original in the post also ...

    But, as stated before, all of that would have been in there already when you looked @ it judging by the time on your reply.

    EDIT: Also the image was not blury ... vbforums seems to poorly resize all images > 600px wide to be 600px wide

    Kris

  14. #14
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Looking for an efficient method? Scale the screen grab down to 1*1 pixel bitmap and get the colour of the pixel with Bitmap.GetPixel. There's no point in using LockBits for a small image because it has quite an overhead. BB

  15. #15
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    iOO ,

    You are correct that using the color structure is slow and I got lazy in using that versus just typing out the bit shift/mask operations. A much faster result can be obtained by swapping out that code with this. It takes about half the time as using the structure.

    Code:
    For x As Int32 = 0 To bm.Width - 1
       sumR += (Colors(x) >> 16) And &HFF
       sumG += (Colors(x) >> 8) And &HFF
       sumB += Colors(x) And &HFF
    Next x
    One issue that I have noticed with the color array method is that there appears to be a point where processing smaller parts of the image is faster than locking the whole image and getting all the values in an array at once. That is the reason I set my code up to process a single row at a time. This just may be a memory available issue though.

  16. #16
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by boops boops View Post
    Looking for an efficient method? Scale the screen grab down to 1*1 pixel bitmap and get the colour of the pixel with Bitmap.GetPixel. There's no point in using LockBits for a small image because it has quite an overhead. BB
    Well it's still ALOT faster than your method ... as I discussed, and like I said when I originally posted, LockBits would be my preferred method, but the other way may be easier for n00bs.

    Kris

  17. #17
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by TnTinMN View Post
    iOO ,

    You are correct that using the color structure is slow and I got lazy in using that versus just typing out the bit shift/mask operations. A much faster result can be obtained by swapping out that code with this. It takes about half the time as using the structure.

    Code:
    For x As Int32 = 0 To bm.Width - 1
       sumR += (Colors(x) >> 16) And &HFF
       sumG += (Colors(x) >> 8) And &HFF
       sumB += Colors(x) And &HFF
    Next x
    One issue that I have noticed with the color array method is that there appears to be a point where processing smaller parts of the image is faster than locking the whole image and getting all the values in an array at once. That is the reason I set my code up to process a single row at a time. This just may be a memory available issue though.
    Will check it in a few hours ... on the road atm

    ... hrm ... faster processing for smaller parts ... I would have thought that processing the whole thing would be faster if you have the memory to handle it ... which shouldn't be that demanding ....

    Kris

  18. #18
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by TnTinMN View Post
    A much faster result can be obtained by swapping out that code with this. It takes about half the time as using the structure.
    Ya wow, went from around 45ms to 5ms on my PC.

    Code:
    Compiled x64, FW 4.0, Win7-64, 1920x1080, i7-3770.
    
        i00: Color [A=255, R=156, G=149, B=173] 16.4221ms
        i00: Color [A=255, R=156, G=149, B=173] 16.4107ms
        i00: Color [A=255, R=156, G=149, B=173] 16.3723ms
        i00: Color [A=255, R=156, G=149, B=173] 17.5805ms
        i00: Color [A=255, R=156, G=149, B=173] 16.9348ms
    TnTinMN: Color [A=255, R=156, G=149, B=173] 5.2121ms
    TnTinMN: Color [A=255, R=156, G=149, B=173] 5.1542ms
    TnTinMN: Color [A=255, R=156, G=149, B=173] 5.1653ms
    TnTinMN: Color [A=255, R=156, G=149, B=173] 5.1776ms
    TnTinMN: Color [A=255, R=156, G=149, B=173] 5.1758ms
    Cool code guys!

  19. #19
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Quote Originally Posted by TnTinMN View Post
    iOO ,

    You are correct that using the color structure is slow and I got lazy in using that versus just typing out the bit shift/mask operations. A much faster result can be obtained by swapping out that code with this. It takes about half the time as using the structure.

    Code:
    For x As Int32 = 0 To bm.Width - 1
       sumR += (Colors(x) >> 16) And &HFF
       sumG += (Colors(x) >> 8) And &HFF
       sumB += Colors(x) And &HFF
    Next x
    One issue that I have noticed with the color array method is that there appears to be a point where processing smaller parts of the image is faster than locking the whole image and getting all the values in an array at once. That is the reason I set my code up to process a single row at a time. This just may be a memory available issue though.
    Just stoped and hooked into home ... you are correct ...

    Interpolation Method: Color [A=255, R=214, G=219, B=233] 4467.9798ms
    LockBits Multiple Interop Method: Color [A=255, R=218, G=221, B=224] 4722.1495ms
    LockBits Single Interop Method: Color [A=255, R=218, G=221, B=224] 4274.852ms

  20. #20
    PowerPoster i00's Avatar
    Join Date
    Mar 2002
    Location
    1/2 way accross the galaxy.. and then some
    Posts
    2,388

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    Sweet ... cutting it into chunks is faster! ...

    Interpolation Method: Color [A=255, R=214, G=219, B=233] 4453.9713ms
    LockBits Multiple Interop Method: Color [A=255, R=217, G=220, B=223] 4690.1284ms
    LockBits Single Interop Method: Color [A=255, R=217, G=220, B=223] 4272.8512ms
    LockBits Single Interop TnTinMN Method: Color [A=255, R=217, G=220, B=223] 2477.652ms

    Kris

  21. #21
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    what is the quickest code now? i have not seen any suggestion that is just using a 24bpp byte array or maybe i have not looked closely enough. when using a byte array there is no need for shifting around aso, just a for i to step 3 loop and adding array(x), array(x+1) and array(x+2) to the three different channels inside the loop. and it is what is inside the loop that matters (ok, if the source image is not 24bpp then it needs to be converterd upfront or the loop needs to do a step 4 in case of 32bpp)
    Last edited by digitalShaman; Sep 14th, 2014 at 04:00 AM.

  22. #22
    Frenzied Member
    Join Date
    May 2014
    Location
    Central Europe
    Posts
    1,372

    Re: [RESOLVED] Getting Average RGB Color Value of Entire Screen

    this is what i meant:
    Code:
        Private Sub AvgColors(ByVal InBitmap As Bitmap)
            Dim btPixels(InBitmap.Height * InBitmap.Width * 3 - 1) As Byte
            Dim hPixels As GCHandle = GCHandle.Alloc(btPixels, GCHandleType.Pinned)
            Dim bmp24Bpp As New Bitmap(InBitmap.Width, InBitmap.Height, InBitmap.Width * 3, _
              Imaging.PixelFormat.Format24bppRgb, hPixels.AddrOfPinnedObject)
    
            Using gr As Graphics = Graphics.FromImage(bmp24Bpp)
                gr.DrawImageUnscaledAndClipped(InBitmap, New Rectangle(0, 0, _
                  bmp24Bpp.Width, bmp24Bpp.Height))
            End Using
    
            Dim sumRed As Int32
            Dim sumGreen As Int32
            Dim sumBlue As Int32
    
            For i = 0 To btPixels.Length - 1 Step 3
                sumRed += btPixels(i)
                sumGreen += btPixels(i + 1)
                sumBlue += btPixels(i + 2)
            Next
            hPixels.Free()
            Dim avgRed As Byte = CByte(sumRed / (btPixels.Length / 3))
            Dim avgGreen As Byte = CByte(sumGreen / (btPixels.Length / 3))
            Dim avgBlue As Byte = CByte(sumBlue / (btPixels.Length / 3))
        End Sub
    it does also include the conversion to 24bpp which needs to be considered for fair speed comparisons and i have not verified the correct output (red and blue most likely switched).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width