I am looking to take snapshots of a live DigiScan image.
However, I want to do so only when a complete (or nearly so) frame has been acquired!
Attaching an event handler to a live DigiScan image does not work, as the image 'changes' with each line acquired serially.
I am hoping to monitor just the last few pixels of the live image and only capture an image when those change. Is this possible?
Your suggestion is exactly what I did: Using the data_changed event as a trigger, and in the event handling method check the value of the last image pixel for if it has changed. (The initial value of the first pass is guaranteed to be zero. From then on, keep the value of a check.)
So, essentially you’ve answered your own question - what remains unclear?
You can check a single pixel using the GetPixel()
command, or the img[x,y]
notation.
Example
class CFrameCompleteListen
{
number lastPixelValue
number listenID
number frameCount, sx, sy
void OnDataChanged( object self, number flags, image img )
{
number value = img.GetPixel( sx-1,sy-1)
if ( value == lastPixelValue )
return
frameCount++
lastPixelValue = value
Result( "\n Image [" + img.GetLabel() + "] frame #"+ frameCount + " complete." )
if ( 3 <= frameCount )
{
ImageRemoveEventListener( img, listenID )
Result("\n Listening stopped." )
}
}
object Launch( object self, image img )
{
lastPixelValue = 0
frameCount = 0
sx = img.ImageGetDimensionSize(0)
sy = img.ImageGetDimensionSize(1)
listenID = ImageAddEventListener( img, self, "data_changed:OnDataChanged" )
Result("\n Listening started." )
return self
}
}
Alloc( CFrameCompleteListen ).Launch( GetFrontImage() )
This answer is merely to post the alternate strategy mentioned in the comments to the answer with the original example script. Please note that the following altered version DOES NOT WORK since the attempt to register an image change listener seems to fail (the listener object is immediately released).
class CFrameCompleteListen2
{
number lastPixelValue
number listenID
number frameCount
void OnDataChanged( object self, number flags, image img )
{
Result("\n Change event." )
number value = img.GetPixel( 0, 0 )
if ( value == lastPixelValue )
return
frameCount++
lastPixelValue = value
Result( "\n Image [" + img.GetLabel() + "] frame #"+ frameCount + " complete." )
if ( 3 <= frameCount )
{
ImageRemoveEventListener( img, listenID )
Result("\n Listening stopped." )
}
}
object Launch( object self, image img )
{
lastPixelValue = img.GetPixel( 0, 0 )
frameCount = 0
listenID = ImageAddEventListener( img, self, "data_changed:OnDataChanged" )
Result("\n Listening started." )
return self
}
~CFrameCompleteListen2( object self )
{
Result( "\n Listener released.\n" )
}
}
void main()
{
image targetImage := GetFrontImage()
number targetW = targetImage.ImageGetDimensionSize(0)
number targetH = targetImage.ImageGetDimensionSize(1)
image lastPixelImage := targetImage[targetH - 1, targetW - 1, targetH, targetW]
lastPixelImage.ShowImage()
object listener = Alloc( CFrameCompleteListen2 ).Launch( lastPixelImage )
}
main()
Edit: by BmyGuest (see comments):
The following script shows, that displaying a "sliced" memory creates a new image with a new reference:
ClearResults()
image newFull := RealImage("Full",4,100,100)
Result("\n Image label 'full':" + newFull.ImageGetLabel() + " | ID:" + newFull.ImageGetID())
newFull.ShowImage()
Result("\n Image label 'full':" + newFull.ImageGetLabel() + " | ID:" + newFull.ImageGetID())
image getFull := GetFrontImage()
Result("\n Image label 'full' (front):" + getFull.ImageGetLabel() + " | ID:" + getFull.ImageGetID())
image slice := newFull[0,0,2,2]
Result("\n Image label 'slice':" + slice.ImageGetLabel() + " | ID:" + newFull.ImageGetID())
slice.ShowImage()
Result("\n Image label 'slice':" + slice.ImageGetLabel() + " | ID:" + newFull.ImageGetID())
image getSlice := GetFrontImage()
Result("\n Image label 'slice' (front):" + getSlice.ImageGetLabel() + " | ID:" + getSlice.ImageGetID())
The output of that script is something like:
Consequently, the listener script above fails and unregisters the listener because the 'lastPixelImage' does not reference the shown 1-pixel image and hence goes out of scope immediately (removing the listener in the process). The script does work, if one grabs the displayed image after showing it and using that one as reference. Accordingly, the script would also work if the sliced image variable would be held in scope.