[AG-TECH] shared image thingy

Dave Semeraro semeraro at ncsa.uiuc.edu
Fri Sep 26 11:34:55 CDT 2003


Hi guys,

I have written a python shared image viewer similar to Justin's. I have 
tested it under WindowsXP.
It seems to work. I have attached the first version of the python code, the 
.app file, and the mime
entry in my mailcap file below. Setup is similar to the other shared 
applictions. Have a test
drive and give me feedback... or not. I am working on the markup part of 
the tool.

This thing is very basic. There is no scrolling so if you load an image 
that is bigger than the
window you will only see part of it. I plan on fixing that. Quite frankly, 
I was thrilled to be able
to get this much working given my limited experience with python.

Have fun,
Dave

Dave Semeraro Ph.D.
Visualization and Virtual Environments Group
NCSA University of Illinois
605 E. Springfield Ave.
Champaign, IL 61820
Semeraro at ncsa.uiuc.edu
(217) 244-1852
-------------- next part --------------
"""
This is the Access Grid Enabled version of the Basic Image viewer. It does the same
thing as the Basic Image ( load an image into a window ) but will share the image over
the Access Grid. Again there is no way to pan or scroll the window. This is just an
attempt to get the BasicImage viewer to work over the AG. The scheme is that the script is executed 
and given an application URL... like this AGBasicImage appurl. There is no error handling in
this version.

Dave Semeraro
NCSA-UIUC
2003
"""

# generic and gui related imports
import os
import sys
from wxPython.wx import*
import base64
import cPickle
import string

# AG related imports
import logging
from AccessGrid.hosting.pyGlobus import Client
from AccessGrid import Events
from AccessGrid import EventClient


ID_OPEN = 101
ID_EXIT = 102

wildcard = "Gif Files (*.GIF)|*.gif|"\
		"JPEG Files (*.JPG)|*.jpg|"\
		"All Files (*.*)|*.*"

# this is an image holder object.. guess what it does. 
class ImageHolder:
	def __init__(self,image,name):
		self.imagename = name
		self.width = str(image.GetWidth())
		self.height = str(image.GetHeight())
		self.data = base64.encodestring(image.GetData())

# A helper class to hide all the AG ugly 
class AGSharedObject:
	def __init__(self,url):
		self.logname = "AGBasicImagelog"
		self.appUrl = None
		self.appName        = "Basic Image"
		self.appDescription = "Access Grid Shared Image"
		self.appMimetype    = "application/x-ag-basic-image"
		self.init_logging(self.logname)

		self.log.debug("AGSharedObject: initialize with url = %s ", url)
		self.appUrl = url
		self.log.debug("AGSharedObject: Getting application proxy")
		self.appProxy = Client.Handle(self.appUrl).GetProxy()
		self.log.debug("AGSharedObject: join application")
		(self.puid,self.prid) = self.appProxy.Join()
		self.log.debug("AGSharedObject: get data channel")
		(self.chanid,self.esl) = self.appProxy.GetDataChannel(self.prid)
		self.eventClient = EventClient.EventClient(self.prid,self.esl,self.chanid)
		self.eventClient.Start()
		self.eventClient.Send(Events.ConnectEvent(self.chanid,self.prid))
		self.log.debug("AGSharedObject: connected and event channel started")

	def init_logging(self,logname):
		logFormat = "%(name)-17s %(asctime)s %(levelname)-5s %(message)s"
		self.log = logging.getLogger(logname)
		self.log.setLevel(logging.DEBUG)
		self.log.addHandler(logging.StreamHandler())

	def GetData(self,dataname):
		self.log.debug("looking for data: %s", dataname)
		tim = self.appProxy.GetData(self.prid,dataname)
		if len(tim) > 0:
			return tim
		else:
			return None

	def PutData(self,dataname,data):
		self.log.debug("loading data named: %s into server",dataname)
		self.appProxy.SetData(self.prid,dataname,data)

	def RegisterEvent(self,eventname,callback):
		self.log.debug("Registering event %s :",eventname)
		self.eventClient.RegisterCallback(eventname,callback)

	def SendEvent(self,eventname,eventdata):
		self.eventClient.Send(Events.Event(eventname,self.chanid,(self.puid,eventdata)))

class ImageWindow(wxWindow):
	def __init__(self,parent,ID):
		wxWindow.__init__(self,parent,ID,style=wxNO_FULL_REPAINT_ON_RESIZE)
		self.imagefile = None
		self.image = None
		self.SetBackgroundColour("WHITE")
		self.InitBuffer()
		EVT_IDLE(self,self.OnIdle)
		EVT_SIZE(self,self.OnSize)
		EVT_PAINT(self,self.OnPaint)
		
	def InitBuffer(self):
		size = self.GetClientSize()
		if self.image == None:
			self.buffer = wxEmptyBitmap(size.width,size.height)
			dc = wxBufferedDC(None,self.buffer)
			dc.SetBackground(wxBrush(self.GetBackgroundColour()))
			dc.Clear()
		else:
			self.buffer = self.image.ConvertToBitmap()
			dc = wxBufferedDC(None,self.buffer)
			dc.SetBackground(wxBrush(self.GetBackgroundColour()))
		self.reInitBuffer = false

	def LoadImageFromFilename(self,imagefilename):
		self.imagefile = imagefilename
		self.image = wxImage(self.imagefile)
		self.reInitBuffer = true

	def LoadImage(self,animage):
		imgdat = base64.decodestring(animage.data)
		self.image = wxEmptyImage(string.atoi(animage.width),string.atoi(animage.height))
		self.image.SetData(imgdat)
		self.reInitBuffer = true

	def OnIdle(self,event):
		if self.reInitBuffer:
			self.InitBuffer()
			self.Refresh(FALSE)

	def OnSize(self,event):
		self.reInitBuffer = true

	def OnPaint(self,event):
		dc = wxBufferedPaintDC(self,self.buffer)
		
class ImageFrame(wxFrame):
	def __init__(self,parent,ID):
		wxFrame.__init__(self,parent,ID,"AGImage: no image loaded",size=(800,600),
						 style=wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
		menu = wxMenu()
		menu.Append(ID_OPEN,"&Open","Open an image file")
		menu.AppendSeparator()
		menu.Append(ID_EXIT,"&Exit","Terminate with extreme prejudice")
		menubar = wxMenuBar()
		menubar.Append(menu,"&File")
		self.SetMenuBar(menubar)

		EVT_MENU(self,ID_OPEN, self.On_Open)
		EVT_MENU(self,ID_EXIT, self.On_Exit)

		# start the ag stuff and see if there is an image already there
		self.imagedataname = "AGStoredimage"
		self.wind = ImageWindow(self,-1)
		self.AG = AGSharedObject(sys.argv[1])
		animage = self.AG.GetData(self.imagedataname)
		self.AG.RegisterEvent("NewImage",self.HandleNewImage)
		if animage == None:
			print "No image found in server"
		else:
			self.localimage = cPickle.loads(animage)
			self.SetTitle(self.localimage.imagename)
			self.wind.LoadImage(self.localimage)

	def On_Open(self,event):
		dlg = wxFileDialog(self,"Select An Image", os.getcwd(), "",wildcard,wxOPEN)
		if dlg.ShowModal() == wxID_OK:
			self.wind.LoadImageFromFilename(dlg.GetPath())
			self.SetTitle(dlg.GetPath())
			# push the data to the venue server
			# construct an object that contains the data, pickle it and shove it
			agimage = ImageHolder(self.wind.image,dlg.GetPath())
			self.AG.PutData(self.imagedataname,cPickle.dumps(agimage,0))
			# now fire the event that tells everyone else the image is changed
			self.AG.SendEvent("NewImage","spoot")

	def HandleNewImage(self,eventdata):
		# received notification that there is a new image on the server
		(senderId,data) = eventdata.data
		if senderId != self.AG.puid:
			animage = self.AG.GetData(self.imagedataname)
			self.localimage = cPickle.loads(animage)
			self.SetTitle(self.localimage.imagename)
			self.wind.LoadImage(self.localimage)

	def On_Exit(self,event):
		self.Close(true)

class MyApp(wxApp):
	def OnInit(self):
		self.imagedataname = "AGstoredimage"
		wxInitAllImageHandlers()
		frame = ImageFrame(None,-1)
		frame.Show(true)
		self.SetTopWindow(frame)
		return true

app = MyApp(0)
app.MainLoop()
-------------- next part --------------
[application]
name = Basic Image
description = This is the basic image application.
mimetype = application/x-ag-basic-image

-------------- next part --------------
application/x-ag-basic-image;"C:\DOCUME~1\ALLUSE~1\APPLIC~1\ACCESS~1\APPLIC~1\BasicImage\AGBasicImage.PY %s"; description=This is AGBasicImage; nametemplate=%s.agbasicimage


More information about the ag-tech mailing list