Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Nov 29th, 2011  |  syntax: Python  |  size: 8.02 KB  |  views: 31  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. import wx
  2. import wx.glcanvas
  3. import numpy
  4.  
  5. def makeWindow():
  6.     global window
  7.     window = ViewerWindow(None, tileShape = (3, 3), tileSize = 512)
  8.    
  9.     # Generate a test image to display -- a sequence of squares.
  10.     width = 2056
  11.     height = 2548
  12.     data = numpy.zeros((width, height), dtype = numpy.uint16)
  13.     base = 0
  14.     for i in xrange(0, width, 512):
  15.         for j in xrange(0, height, 512):
  16.             data[i:i+512, j:j+512] = base
  17.             base += 50
  18.     # Downsample to make the image reasonably displayable on a normal monitor.
  19.     window.viewer.setImage(data[::2, ::2])
  20.  
  21. class App(wx.App):
  22.     def OnInit(self):
  23.         makeWindow()
  24.         return True
  25.  
  26. from OpenGL.GL import *
  27.  
  28. ## Simple window that contains a GLViewer instance.
  29. class ViewerWindow(wx.Frame):
  30.     def __init__(self, parent, tileShape, tileSize, *args, **kwargs):
  31.         wx.Frame.__init__(self, parent, *args, **kwargs)
  32.  
  33.         self.viewer = GLViewer(self, tileShape, tileSize, **kwargs)
  34.         self.Show()
  35.         self.Bind(wx.EVT_SIZE, self.onSize)
  36.  
  37.     def onSize(self, event):
  38.         self.viewer.setSize(list(self.GetSize()))
  39.         event.Skip()
  40.  
  41.  
  42. class GLViewer(wx.glcanvas.GLCanvas):
  43.     ## Instantiate.
  44.     def __init__(self, parent, tileShape, tileSize, *args, **kwargs):
  45.         wx.glcanvas.GLCanvas.__init__(self, parent, *args, **kwargs)
  46.  
  47.         ## Edge length of one tile.
  48.         self.tileSize = tileSize
  49.  
  50.         ## Shape of our tile grid.
  51.         self.tileShape = tileShape
  52.  
  53.         ## 2D array of Image instances. We'll create these when we get
  54.         # some image data to work with.
  55.         self.tiles = []
  56.  
  57.         ## Whether or not we've done some one-time initialization work.
  58.         self.haveInitedGL = False
  59.  
  60.         self.scaleX = self.scaleY = 1.0
  61.  
  62.         wx.EVT_PAINT(self, self.OnPaint)
  63.    
  64.        
  65.     def InitGL(self):
  66.         self.w, self.h = self.GetClientSizeTuple()
  67.         self.SetCurrent()
  68.         glClearColor(0.3, 0.3, 0.3, 0.0)   ## background color
  69.  
  70.         self.haveInitedGL = True
  71.  
  72.  
  73.     ## Receive a new image and parcel it up into our smaller Image instances.
  74.     # Create those instances at this time if we don't have them already.
  75.     def setImage(self, newImage):
  76.         self.SetCurrent()
  77.  
  78.         print "Updating new image to one of shape",newImage.shape
  79.  
  80.         # Ensure that we have the right amount of data to put into our
  81.         # Images, by filling in any missing data with zeros. There's an
  82.         # implicit assumption here that newImage is smaller than or
  83.         # equal in size to our tiles' total combined area.
  84.         width = self.tileShape[0] * self.tileSize
  85.         height = self.tileShape[1] * self.tileSize
  86.         paddedImage = numpy.zeros((width, height), dtype = newImage.dtype)
  87.         paddedImage[:newImage.shape[0], :newImage.shape[1]] = newImage
  88.  
  89.         print "Made padded image of shape",paddedImage.shape
  90.  
  91.         for i in xrange(self.tileShape[0]):
  92.             self.tiles.append([])
  93.             for j in xrange(self.tileShape[1]):
  94.                 subData = paddedImage[
  95.                         i * self.tileSize : (i + 1) * self.tileSize,
  96.                         j * self.tileSize : (j + 1) * self.tileSize]
  97.                 self.tiles[i].append(Image(subData))
  98.  
  99.         wx.CallAfter(self.changeHistScale, newImage.min(), newImage.max())
  100.  
  101.         self.Refresh()
  102.  
  103.  
  104.     ## Rescale our images so smin displays as black and smax as white.
  105.     def changeHistScale(self, smin ,smax):
  106.         for i in xrange(self.tileShape[0]):
  107.             for j in xrange(self.tileShape[1]):
  108.                 self.tiles[i][j].refresh(smin, smax)
  109.         self.Refresh(False)
  110.  
  111.  
  112.     def setSize(self, size):
  113.         xSize = float(self.tileShape[0] * self.tileSize)
  114.         ySize = float(self.tileShape[1] * self.tileSize)
  115.         self.scaleX = size[0] / xSize
  116.         self.scaleY = size[1] / ySize
  117.         self.w, self.h = size
  118.         self.Refresh(0)
  119.  
  120.        
  121.     def OnPaint(self, event):
  122.         try:
  123.             dc = wx.PaintDC(self)
  124.         except:
  125.             return
  126.  
  127.         if not self.haveInitedGL:
  128.             self.InitGL()
  129.  
  130.         self.SetCurrent()
  131.  
  132.         glViewport(0, 0, self.w, self.h)
  133.         glMatrixMode (GL_PROJECTION)
  134.         glLoadIdentity ()
  135.         glOrtho (0, self.w, 0, self.h, 1., -1.)
  136.         glMatrixMode (GL_MODELVIEW)
  137.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
  138.  
  139.         glPushMatrix()
  140.         glLoadIdentity()
  141.  
  142.         glScalef(self.scaleX, self.scaleY, 1)
  143.  
  144.         glEnable(GL_TEXTURE_2D)
  145.  
  146.         for i in xrange(self.tileShape[0]):
  147.             for j in xrange(self.tileShape[1]):
  148.                 glPushMatrix()
  149.                 glTranslatef(i * self.tileSize, j * self.tileSize, 0)
  150.                 self.tiles[i][j].render()
  151.                 glPopMatrix()
  152.  
  153.         glDisable(GL_TEXTURE_2D)
  154.         glPopMatrix()
  155.  
  156.         glFlush()
  157.         self.SwapBuffers()
  158.  
  159.  
  160. import OpenGL.GL as GL    
  161.  
  162. ## This class handles display of a single 2D array of pixel data.
  163. class Image:
  164.     def __init__(self, imageData):
  165.         self.imageData = imageData
  166.         self.bindTexture()
  167.  
  168.  
  169.     def bindTexture(self):
  170.         pic_ny, pic_nx = self.imageData.shape
  171.  
  172.         # Generate texture sizes that are powers of 2
  173.         tex_nx = 2
  174.         while tex_nx < pic_nx:
  175.             tex_nx *= 2
  176.         tex_ny = 2
  177.         while tex_ny < pic_ny:
  178.             tex_ny *= 2
  179.  
  180.         self.picTexRatio_x = float(pic_nx) / tex_nx
  181.         self.picTexRatio_y = float(pic_ny) / tex_ny
  182.  
  183.         self.textureID = GL.glGenTextures(1)
  184.         GL.glBindTexture(GL.GL_TEXTURE_2D, self.textureID)
  185.  
  186.         # Define this new texture object based on self.imageData's geometry
  187.         GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
  188.                 GL.GL_NEAREST)
  189.         GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
  190.                 GL.GL_NEAREST)
  191.  
  192.         imgType = self.imageData.dtype.type
  193.         GL.glTexImage2D(GL.GL_TEXTURE_2D,0,  GL.GL_RGB, tex_nx,tex_ny, 0,
  194.                      GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT, None)
  195.  
  196.  
  197.     # Re-load our image data onto the card, e.g. because our blackpoint and
  198.     # whitepoint have changed.
  199.     def refresh(self, imageMin, imageMax):
  200.         minMaxRange = float(imageMax - imageMin)
  201.         if abs(imageMax - imageMin) < 1:
  202.             minMaxRange = 1
  203.        
  204.         imgType = self.imageData.dtype.type
  205.         fBias = -imageMin / minMaxRange
  206.         f = ((1 << 16) - 1) / minMaxRange
  207.  
  208.         GL.glBindTexture(GL.GL_TEXTURE_2D, self.textureID)
  209.  
  210.         GL.glPixelTransferf(GL.GL_RED_SCALE,   f)
  211.         GL.glPixelTransferf(GL.GL_GREEN_SCALE, f)
  212.         GL.glPixelTransferf(GL.GL_BLUE_SCALE,  f)
  213.  
  214.         GL.glPixelTransferf(GL.GL_RED_BIAS,   fBias)
  215.         GL.glPixelTransferf(GL.GL_GREEN_BIAS, fBias)
  216.         GL.glPixelTransferf(GL.GL_BLUE_BIAS,  fBias)
  217.  
  218.         GL.glPixelTransferf(GL.GL_MAP_COLOR, False)
  219.  
  220.         GL.glPixelStorei(GL.GL_UNPACK_SWAP_BYTES,
  221.                 not self.imageData.dtype.isnative)
  222.         GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, self.imageData.itemsize)
  223.        
  224.         imgString = self.imageData.tostring()
  225.  
  226.         pic_ny, pic_nx = self.imageData.shape
  227.  
  228.         GL.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, pic_nx, pic_ny,
  229.                 GL.GL_LUMINANCE, GL.GL_UNSIGNED_SHORT, imgString)
  230.  
  231.  
  232.     def render(self):
  233.         cx,cy = self.imageData.shape[-1]/2., self.imageData.shape[-2]/2.
  234.         GL.glBindTexture(GL.GL_TEXTURE_2D, self.textureID)
  235.  
  236.         GL.glBegin(GL.GL_QUADS)
  237.        
  238.         pic_ny, pic_nx = self.imageData.shape
  239.  
  240.         ###//(0,0) at left bottom
  241.         GL.glTexCoord2f(0, 0)
  242.         GL.glVertex2i(0, 0)
  243.            
  244.         GL.glTexCoord2f(self.picTexRatio_x, 0)
  245.         GL.glVertex2i(pic_nx, 0)
  246.            
  247.         GL.glTexCoord2f(self.picTexRatio_x, self.picTexRatio_y)
  248.         GL.glVertex2i(pic_nx, pic_ny)
  249.            
  250.         GL.glTexCoord2f(0, self.picTexRatio_y)
  251.         GL.glVertex2i(0, pic_ny)
  252.  
  253.         GL.glEnd()
  254.  
  255.  
  256. app = App(redirect = False)
  257. app.MainLoop()
  258.  
  259.