mirror of
https://github.com/python/cpython.git
synced 2025-08-02 16:13:13 +00:00
Contributed modules by Riccardo Trocca. Extended pixmap wrapper, NumPy visualiser and QuickTime to images.
This commit is contained in:
parent
fdd2269fcc
commit
d35509a82d
4 changed files with 614 additions and 0 deletions
277
Mac/Contrib/ImageHelpers/ImageMac.py
Normal file
277
Mac/Contrib/ImageHelpers/ImageMac.py
Normal file
|
@ -0,0 +1,277 @@
|
|||
'''
|
||||
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
|
||||
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()
|
Loading…
Add table
Add a link
Reference in a new issue