MotionImage

From XPUB & Lens-Based wiki

Based on code of MotionBox, now we use images captured by Motion, plus the "movement rectangle" data to dynamically display the image data in PyGame.

Media:Motionimage.zip

rm *.jpg
motion -c motionimage.conf | python -u motionimage.py
#!/usr/bin/python

import sys
import pygame
from pygame.locals import *
from pygame.time import Clock
from time import sleep
import thread

def scaleToFitBox(size, box):
	"""
	size should be a tuple (pair) of form (w, h)
	box is also a tuple (bw, bh)
	returns a new tuple of a size,
	preserving the ratio of size, but fitting in the box
	(scaling up or down as needed)
	"""
	(sw, sh) = size
	(bw, bh) = box
	# nw, nh represent the "new" width and height to return
	# 1. try fitting box width
	nw = bw
	# nh can be calculated based on the aspect ratio of the sourcea
	nh = int((float(sh)/sw)*nw)
	# fit the box?
	if (nh <= bh):
		# if so, return it
		return (nw, nh)
	else:	
		# two big? then fit the height
		nh = bh
		# nw can be calculated based on the aspect ratio of the sourcea
		nw = int((float(sw)/sh)*nh)
		return (nw, nh)


def main():
	mfullimage = None
	mimage = None
	(mx, my, mw, mh) = (10, 10, 50, 50)
	pygame.init()
	# screen = pygame.display.set_mode((640, 480), FULLSCREEN, 32)
	screen = pygame.display.set_mode((640, 480), 0, 32)
	pygame.display.set_caption("motionbox")
	clock = Clock()
	while True:
		# TIMING
		clock.tick(30)
		
		# PROCESS EVENTS
		for event in pygame.event.get():
			if event.type==QUIT or \
			(event.type == KEYDOWN and event.key == K_ESCAPE):
				sys.exit()
			elif event.type == KEYDOWN and event.key == K_f:
				# http://www.pygame.org/docs/ref/display.html#pygame.display.toggle_fullscreen
				pygame.display.toggle_fullscreen()
			elif event.type == USEREVENT:
				mx = event.x
				my = event.y
				mw = event.w
				mh = event.h
				mx -= mw/2
				my -= mh/2
				mfilename = event.filename
				mfullimage = pygame.image.load(mfilename).convert()
				# "crop" the full image by creating a new surface of the right size
				# and using the blit command to copy the interesting rect to it
				subimage = pygame.Surface((mw, mh), 0, mfullimage)
				subimage.blit(mfullimage, (0, 0), (mx, my, mw, mh))
				# mimage = mfullimage.subsurface((mx, my, mw, mh))
				(nw, nh) = scaleToFitBox((mw, mh), (640, 480))
				subimage = pygame.transform.scale(subimage, (nw, nh))
				# figure out new position to draw the scaled up image
				# (simply center the image based on it's new size)
				mx = (640 - nw) / 2
				my = (480 - nh) / 2
		#mx += 1
		#if (mx > 500): mx = 0
		screen.fill((0, 0, 0))
		# draw rectangle using current position & size
		if mfullimage:
			#screen.blit(mfullimage, (0,0))
			# screen.blit(mfullimage, (mx, my), (mx, my, mw, mh))
			screen.blit(subimage, (mx, my))
			# draw test rect
			#pygame.draw.rect(screen, (255, 0, 0), (mx, my, mw, mh), 1)
		
		pygame.display.update()
		# sleep(0.01)

# start pygame in a separate thread
# starting a thread is like running a program with & on the shell
thread.start_new_thread(main, ())


# READ INFO FROM STDIN
while 1:
	line = sys.stdin.readline()
	if (not line): break
	line = line.strip()
	try:
		if line.startswith("image"):
			# print "read image data:", line
			(x, y, w, h, numpixels, filename) = line.split()[1:]
			x = int(x)
			y = int(y)
			w = int(w)
			h = int(h)
			# create a custom "event" and send it (post it) to the pygame loop
			evt = pygame.event.Event(USEREVENT, {"x" : x, "y": y, "w":w, "h":h, "filename": filename})
			pygame.event.post(evt)
	except ValueError:
		print "bad image line", line