mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			277 lines
		
	
	
		
			No EOL
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			No EOL
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| '''
 | |
| 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
 | |
| from Carbon import Qd
 | |
| 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() | 
