| 
									
										
										
										
											2000-09-22 12:46:19 +00:00
										 |  |  | '''
 | 
					
						
							|  |  |  | ImageMac.py by Trocca Riccardo (rtrocca@libero.it) | 
					
						
							|  |  |  | This module provides functions to display images and Numeric arrays | 
					
						
							|  |  |  | It provides two classes ImageMacWin e NumericMacWin and two simple methods showImage and | 
					
						
							|  |  |  | showNumeric. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | They work like this: | 
					
						
							|  |  |  | showImage(Image,"optional window title",zoomFactor) | 
					
						
							|  |  |  | the same for showNumeric | 
					
						
							|  |  |  | zoomfactor (defaults to 1) allows to zoom in the image by a factor of 1x 2x 3x and so on | 
					
						
							|  |  |  | I did't try with a 0.5x or similar. | 
					
						
							|  |  |  | The windows don't provide a scrollbar or a resize box. | 
					
						
							|  |  |  | Probably a better solution (and more similar to the original implementation in PIL and NumPy) | 
					
						
							|  |  |  | would be to save a temp file is some suitable format and then make an application (through appleevents) to open it. | 
					
						
							|  |  |  | Good guesses should be GraphicConverter or PictureViewer. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | However the classes ImageMacWin e NumericMacWin use an extended version of PixMapWrapper in order to  | 
					
						
							|  |  |  | provide an image buffer and then blit it in the window. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Being one of my first experiences with Python I didn't use Exceptions to signal error conditions, sorry. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | import W | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | from Carbon import Qd | 
					
						
							| 
									
										
										
										
											2000-09-22 12:46:19 +00:00
										 |  |  | from ExtPixMapWrapper import * | 
					
						
							|  |  |  | from Numeric import * | 
					
						
							|  |  |  | import Image | 
					
						
							|  |  |  | import macfs | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ImageMacWin(W.Window): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self,size=(300,300),title="ImageMacWin"): | 
					
						
							|  |  |  | 		self.pm=ExtPixMapWrapper() | 
					
						
							|  |  |  | 		self.empty=1 | 
					
						
							|  |  |  | 		self.size=size | 
					
						
							|  |  |  | 		W.Window.__init__(self,size,title) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def Show(self,image,resize=0): | 
					
						
							|  |  |  | 		#print "format: ", image.format," size: ",image.size," mode: ",image.mode | 
					
						
							|  |  |  | 		#print "string len :",len(image.tostring()) | 
					
						
							|  |  |  | 		self.pm.fromImage(image) | 
					
						
							|  |  |  | 		self.empty=0 | 
					
						
							|  |  |  | 		if resize: | 
					
						
							|  |  |  | 			self.size=(image.size[0]*resize,image.size[1]*resize) | 
					
						
							|  |  |  | 			W.Window.do_resize(self,self.size[0],self.size[1],self.wid) | 
					
						
							|  |  |  | 		self.do_drawing() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_drawing(self): | 
					
						
							|  |  |  | 		#print "do_drawing" | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		Qd.RGBForeColor( (0,0,0) ) | 
					
						
							|  |  |  | 		Qd.RGBBackColor((65535, 65535, 65535)) | 
					
						
							|  |  |  | 		Qd.EraseRect((0,0,self.size[0],self.size[1])) | 
					
						
							|  |  |  | 		if not self.empty: | 
					
						
							|  |  |  | 			#print "should blit" | 
					
						
							|  |  |  | 			self.pm.blit(0,0,self.size[0],self.size[1]) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	def do_update(self,macoswindowid,event): | 
					
						
							|  |  |  | 		#print "update" | 
					
						
							|  |  |  | 		self.do_drawing() | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | class NumericMacWin(W.Window): | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def __init__(self,size=(300,300),title="ImageMacWin"): | 
					
						
							|  |  |  | 		self.pm=ExtPixMapWrapper() | 
					
						
							|  |  |  | 		self.empty=1 | 
					
						
							|  |  |  | 		self.size=size | 
					
						
							|  |  |  | 		W.Window.__init__(self,size,title) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def Show(self,num,resize=0): | 
					
						
							|  |  |  | 		#print "shape: ", num.shape | 
					
						
							|  |  |  | 		#print "string len :",len(num.tostring()) | 
					
						
							|  |  |  | 		self.pm.fromNumeric(num) | 
					
						
							|  |  |  | 		self.empty=0 | 
					
						
							|  |  |  | 		if resize: | 
					
						
							|  |  |  | 			self.size=(num.shape[1]*resize,num.shape[0]*resize) | 
					
						
							|  |  |  | 			W.Window.do_resize(self,self.size[0],self.size[1],self.wid) | 
					
						
							|  |  |  | 		self.do_drawing() | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	def do_drawing(self): | 
					
						
							|  |  |  | 		#print "do_drawing" | 
					
						
							|  |  |  | 		self.SetPort() | 
					
						
							|  |  |  | 		Qd.RGBForeColor( (0,0,0) ) | 
					
						
							|  |  |  | 		Qd.RGBBackColor((65535, 65535, 65535)) | 
					
						
							|  |  |  | 		Qd.EraseRect((0,0,self.size[0],self.size[1])) | 
					
						
							|  |  |  | 		if not self.empty: | 
					
						
							|  |  |  | 			#print "should blit" | 
					
						
							|  |  |  | 			self.pm.blit(0,0,self.size[0],self.size[1]) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	def do_update(self,macoswindowid,event): | 
					
						
							|  |  |  | 		#print "update" | 
					
						
							|  |  |  | 		self.do_drawing() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | Some utilities: convert an Image to a NumPy array and viceversa. | 
					
						
							|  |  |  | The Image2Numeric function doesn't make any color space conversion. | 
					
						
							|  |  |  | The Numeric2Image function returns an L or RGB or RGBA images depending on the shape of | 
					
						
							|  |  |  | the array: | 
					
						
							|  |  |  | 	(x,y)	-> 	'L' | 
					
						
							|  |  |  | 	(x,y,1)	-> 	'L' | 
					
						
							|  |  |  | 	(x,y,3)	->	'RGB' | 
					
						
							|  |  |  | 	(x,y,4)	->	'RGBA' | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | def Image2Numeric(im): | 
					
						
							|  |  |  | 	tmp=fromstring(im.tostring(),UnsignedInt8) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (im.mode=='RGB')|(im.mode=='YCbCr'): | 
					
						
							|  |  |  | 		bands=3 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (im.mode=='RGBA')|(im.mode=='CMYK'): | 
					
						
							|  |  |  | 		bands=4 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (im.mode=='L'): | 
					
						
							|  |  |  | 		bands=1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp.shape=(im.size[0],im.size[1],bands) | 
					
						
							|  |  |  | 	return transpose(tmp,(1,0,2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def Numeric2Image(num): | 
					
						
							|  |  |  | 	#sometimes a monoband image's shape can be (x,y,1), other times just (x,y). Here w deal with both | 
					
						
							|  |  |  | 	if len(num.shape)==3:  | 
					
						
							|  |  |  | 		bands=num.shape[2] | 
					
						
							|  |  |  | 		if bands==1: | 
					
						
							|  |  |  | 			mode='L' | 
					
						
							|  |  |  | 		elif bands==3: | 
					
						
							|  |  |  | 			mode='RGB' | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			mode='RGBA' | 
					
						
							|  |  |  | 		return Image.fromstring(mode,(num.shape[1],num.shape[0]),transpose(num,(1,0,2)).astype(UnsignedInt8).tostring()) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		return Image.fromstring('L',(num.shape[1],num.shape[0]),transpose(num).astype(UnsignedInt8).tostring())	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def showImage(im,title="ImageWin",zoomFactor=1): | 
					
						
							|  |  |  | 	imw=ImageMacWin((300,200),title) | 
					
						
							|  |  |  | 	imw.open() | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		imw.Show(im,zoomFactor ) | 
					
						
							|  |  |  | 	except MemoryError,e: | 
					
						
							|  |  |  | 		imw.close() | 
					
						
							|  |  |  | 		print "ImageMac.showImage: Insufficient Memory" | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def showNumeric(num,title="NumericWin",zoomFactor=1): | 
					
						
							|  |  |  | 	#im=Numeric2Image(num) | 
					
						
							|  |  |  | 	numw=NumericMacWin((300,200),title) | 
					
						
							|  |  |  | 	numw.open() | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		numw.Show(num,zoomFactor ) | 
					
						
							|  |  |  | 	except MemoryError: | 
					
						
							|  |  |  | 		numw.close() | 
					
						
							|  |  |  | 		print "ImageMac.showNumeric Insufficient Memory" | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | GimmeImage pops up a file dialog and asks for an image file. | 
					
						
							|  |  |  | it returns a PIL image. | 
					
						
							|  |  |  | Optional argument: a string to be displayed by the dialog.  | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | def GimmeImage(prompt="Image File:"): | 
					
						
							|  |  |  | 	import macfs | 
					
						
							|  |  |  | 	fsspec, ok = macfs.PromptGetFile(prompt) | 
					
						
							|  |  |  | 	if ok: | 
					
						
							|  |  |  | 		path = fsspec.as_pathname() | 
					
						
							|  |  |  | 		return Image.open(path) | 
					
						
							|  |  |  | 	return None | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | This is just some experimental stuff: | 
					
						
							|  |  |  | 	Filter3x3 a convolution filter (too slow use signal tools instead) | 
					
						
							|  |  |  | 	diffBWImage subtracts 2 images contained in NumPy arrays | 
					
						
							|  |  |  | 	averageN it computes the average of a list incrementally | 
					
						
							|  |  |  | 	BWImage converts an RGB or RGBA image (in a NumPy array) to BW | 
					
						
							|  |  |  | 	SplitBands splits the bands of an Image (inside a NumPy) | 
					
						
							|  |  |  | 	NumHisto and PlotHisto are some experiments to plot an intesity histogram | 
					
						
							|  |  |  | '''
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def Filter3x3(mul,fi,num): | 
					
						
							|  |  |  | 	(a,b,c,d,e,f,g,h,i)=fi | 
					
						
							|  |  |  | 	print fi | 
					
						
							|  |  |  | 	num.shape=(num.shape[0],num.shape[1]) | 
					
						
							|  |  |  | 	res=zeros(num.shape) | 
					
						
							|  |  |  | 	for x in range(1,num.shape[0]-1): | 
					
						
							|  |  |  | 		for y in range(1,num.shape[1]-1): | 
					
						
							|  |  |  | 			xb=x-1 | 
					
						
							|  |  |  | 			xa=x+1 | 
					
						
							|  |  |  | 			yb=y-1 | 
					
						
							|  |  |  | 			ya=y+1 | 
					
						
							|  |  |  | 			res[x,y]=int((a*num[xb,yb]+b*num[x,yb]+c*num[xa,yb]+d*num[xb,y]+e*num[x,y]+f*num[xa,y]+g*num[xb,ya]+h*num[x,ya]+i*num[xa,ya])/mul) | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | def diffBWImage(num1,num2): | 
					
						
							|  |  |  | 	return 127+(num1-num2)/2 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def averageN(N,avrg,new): | 
					
						
							|  |  |  | 	return ((N-1)*avrg+new)/N | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | def BWImage(num): | 
					
						
							|  |  |  | 	if num.shape[2]==3: | 
					
						
							|  |  |  | 		bw=array(((0.3086,0.6094,0.0820))) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		bw=array(((0.3086,0.6094,0.0820,0))) | 
					
						
							|  |  |  | 	res=innerproduct(num,bw) | 
					
						
							|  |  |  | 	res.shape=(res.shape[0],res.shape[1]) | 
					
						
							|  |  |  | 	return res | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def SplitBands(num): | 
					
						
							|  |  |  | 	x=num.shape[0] | 
					
						
							|  |  |  | 	y=num.shape[1] | 
					
						
							|  |  |  | 	if num.shape[2]==3: | 
					
						
							|  |  |  | 		return (reshape(num[:,:,0],(x,y)),reshape(num[:,:,1],(x,y)),reshape(num[:,:,2],(x,y))) | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		return (reshape(num[:,:,0],(x,y)),reshape(num[:,:,1],(x,y)),reshape(num[:,:,2],(x,y)),reshape(num[:,:,3],(x,y))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def NumHisto(datas): | 
					
						
							|  |  |  | 	#print "type(datas) ",type(datas) | 
					
						
							|  |  |  | 	a=ravel(datas) | 
					
						
							|  |  |  | 	n=searchsorted(sort(a),arange(0,256)) | 
					
						
							|  |  |  | 	n=concatenate([n,[len(a)]]) | 
					
						
							|  |  |  | 	return n[1:]-n[:-1] | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | def PlotHisto(datas,ratio=1): | 
					
						
							|  |  |  | 	from graphite import * | 
					
						
							|  |  |  | 	from MLab import max | 
					
						
							|  |  |  | 	h=NumHisto(datas) | 
					
						
							|  |  |  | 	#print "histo: ",h | 
					
						
							|  |  |  | 	#print "histo.shape: ",h.shape | 
					
						
							|  |  |  | 	maxval=max(h) | 
					
						
							|  |  |  | 	#print "maxval ",maxval | 
					
						
							|  |  |  | 	h.shape=(256,1) | 
					
						
							|  |  |  | 	x=arange(0,256) | 
					
						
							|  |  |  | 	x.shape=(256,1) | 
					
						
							|  |  |  | 	datah=concatenate([x,h],1) | 
					
						
							|  |  |  | 	print "data: " | 
					
						
							|  |  |  | 	print datah | 
					
						
							|  |  |  | 	g=Graph() | 
					
						
							|  |  |  | 	g.datasets.append(Dataset(datah)) | 
					
						
							|  |  |  | 	f0=PointPlot() | 
					
						
							|  |  |  | 	f0.lineStyle = LineStyle(width=2, color=red, kind=SOLID) | 
					
						
							|  |  |  | 	g.formats = [f0] | 
					
						
							|  |  |  | 	g.axes[X].range = [0,255] | 
					
						
							|  |  |  | 	g.axes[X].tickMarks[0].spacing = 10 | 
					
						
							|  |  |  | 	#g.axes[X].tickMarks[0].labels = "%d" | 
					
						
							|  |  |  | 	g.axes[Y].range = [0,maxval/ratio] | 
					
						
							|  |  |  | 	g.bottom = 370 | 
					
						
							|  |  |  | 	g.top =10 | 
					
						
							|  |  |  | 	g.left=10 | 
					
						
							|  |  |  | 	g.right=590 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	genOutput(g,'QD',size=(600,400)) | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | def test(): | 
					
						
							|  |  |  | 	import MacOS | 
					
						
							|  |  |  | 	import Image | 
					
						
							|  |  |  | 	import ImageFilter | 
					
						
							|  |  |  | 	import Numeric | 
					
						
							|  |  |  | 	fsspec, ok = macfs.PromptGetFile("Image File:") | 
					
						
							|  |  |  | 	if ok:  | 
					
						
							|  |  |  | 		path = fsspec.as_pathname() | 
					
						
							|  |  |  | 		im=Image.open(path) | 
					
						
							|  |  |  | 		#im2=im.filter(ImageFilter.SMOOTH) | 
					
						
							|  |  |  | 		showImage(im,"normal") | 
					
						
							|  |  |  | 		num=Image2Numeric(im) | 
					
						
							|  |  |  | 		#num=Numeric.transpose(num,(1,0,2)) | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		showNumeric(num,"Numeric") | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		print "num.shape ",num.shape | 
					
						
							|  |  |  | 		showImage(Numeric2Image(num),"difficile") | 
					
						
							|  |  |  | 		#showImage(im.filter(ImageFilter.SMOOTH),"smooth") | 
					
						
							|  |  |  | 		#showImage(im.filter(ImageFilter.FIND_EDGES).filter(ImageFilter.SHARPEN),"detail") | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 		print "here" | 
					
						
							|  |  |  | 	else: | 
					
						
							|  |  |  | 		print "did not open file" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  | 	test() |