Compare pixel range on screen to a saved image
Scenario: We stream the BBC news channel through a laptop hooked to a PC in reception for our clients. Annoyingly the stream is interrupted randomly (the line isn't dropping, it's the BBC's problem). Therefore when it's interrupted we get an error screen appearing which we have to go and manually refresh to get the stream back playing.
My intentions are to build an app which will be run alongside (silently) the stream monitoring intermittently a range of pixels. If the range matches the error screen that I mentioned previously then I'd call "Esc" to exit the full screen and then "F5" to refresh the browser and finally a double click on a specified coordinate to bring it back to full screen.
Problem: I've been doing some googling and so far have only seen related posts where the comparison is between two saved images. Due to this I expect the answer to be "Take a screenshot every now and then, compare, return result".
Is there a way to accomplish this without taking screen shots?
Re: Compare pixel range on screen to a saved image
There is no easy way that I know of. What I would do is Use the graphics.copyfromscreen and save it to a bitmap. I Use lockbits to get an array of Integers or bytes and compare it with the image that I already have of the error screen. This whole operation shouldn't take very long so it should be ideal.
Re: Compare pixel range on screen to a saved image
I did a small experiment on my computer to test how long it would take for what I said. My code grab's a screenshot the size of my screen and gets a byte array of the pixels, It then compares the array with another array of the same size and sets a boolean variable if the pixels don't match. All this under 50 Milliseconds.
Re: Compare pixel range on screen to a saved image
Wow, I'm quite surprised by that sort of speed.
Any chance you could post your code for me to refer to? I'm thinking this would (as expected) be the easiest option.
I'm actually noticing I'm going to have to compare the screenshot to several images (apparently the "error messages" appear to be inconsistent), at the speed you're suggesting this would make no noticeable difference though.
Re: Compare pixel range on screen to a saved image
I created a Blank Project for this.
You need a reference to System.Drawing And System.Windows.Forms
vb.net Code:
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Diagnostics
Module Monitor
Private [Exit] As Boolean
WithEvents Tmr As Timers.Timer
Sub Main()
Tmr = New Timers.Timer(1000)
Tmr.Start()
While Not [Exit]
Threading.Thread.Sleep(100)
End While
End Sub
Dim Reference(2983341) As Byte ' should be populated with the error image data.
Private Sub Tmr_Elapsed(sender As Object, e As Timers.ElapsedEventArgs) Handles Tmr.Elapsed
Dim st As Stopwatch = Stopwatch.StartNew
Dim ScreenCap As New Bitmap(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height, Imaging.PixelFormat.Format24bppRgb)
Using g As Graphics = Graphics.FromImage(ScreenCap)
g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.WorkingArea.Size)
End Using
Dim BMD As Imaging.BitmapData = ScreenCap.LockBits(New Rectangle(0, 0, ScreenCap.Width, ScreenCap.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format24bppRgb)
Dim Buffer((ScreenCap.Width * ScreenCap.Height - 1) * 3) As Byte
Marshal.Copy(BMD.Scan0, Buffer, 0, Buffer.Length)
ScreenCap.UnlockBits(BMD)
Dim IsCorrect As Boolean
For i = 0 To Buffer.Length - 1 Step 3
If Buffer(i) <> Reference(i) Then
IsCorrect = False
Exit For
End If
Next
'Test IsCorrect here and act on it.
st.Stop()
MsgBox(st.ElapsedMilliseconds.ToString)
End Sub
End Module
Re: Compare pixel range on screen to a saved image
I am trying to do something very similar but I need to do a screenshot every second and compare it with the last screenshot taken and see if they match.... any code ideas how I would do this?