#!/usr/bin/env python

"""
a test of using numpy/PIL/wx for dispkyaing 64 bit greyscale images

requires a "hand.raw" data file for the image(s)

"""
import wx
import numpy as np

infilename = "hand.raw"

width = 470
height = 352
num_images = 96

image_array = np.fromfile(infilename, dtype=np.uint16).reshape((num_images, width, height))

def rbg_from_int16(arr):
    """
    converts a 2-d array of uint16 grayscale values to a 24 bit RGB array
    """
    max_value = np.iinfo(arr.dtype).max
    rgb = np.zeros((arr.shape)+(3,), dtype=np.uint8)
    ## note: you could probably use np.repeat() to do this a bit faster
    rgb[:,:,0] = arr * (255.0 / max_value)
    rgb[:,:,1] = rgb[:,:,0]
    rgb[:,:,2] = rgb[:,:,0]

    return rgb

class BitmapWindow(wx.Window):
    def __init__(self, parent, bytearray, *args, **kwargs):
        wx.Window.__init__(self, parent, *args, **kwargs)
        
        self.bytearray = bytearray
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        
    def OnPaint(self, evt):
        dc = wx.PaintDC(self)
        bmp = wx.BitmapFromBuffer(width, height, self.bytearray)
        dc.DrawBitmap(bmp, 0, 0 )

class DemoFrame(wx.Frame):
    def __init__(self, title = "Bitmap Demo"):
        wx.Frame.__init__(self, None , -1, title)

        # create the array and bitmap:
        self.image_array = image_array
        self.bytearray = np.zeros((width, height, 3), dtype=np.uint8)
        self.bytearray[:,:,:] = rbg_from_int16(self.image_array[20,:,:])
        self.image_count = 0
        
        self.BitmapWindow = BitmapWindow(self, self.bytearray, size=(width, height))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.BitmapWindow, 0, wx.ALL, 5)
        # set up the buttons
        ButtonSizer = self.SetUpTheButtons()
        sizer.Add(ButtonSizer, 0, wx.GROW)
        self.SetSizerAndFit(sizer)

        # now set up the timer:
        self.Timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer)

        self.Counter = 0

    def SetUpTheButtons(self):
        StartButton = wx.Button(self, wx.NewId(), "Start")
        StartButton.Bind(wx.EVT_BUTTON, self.OnStart)

        StopButton = wx.Button(self, wx.NewId(), "Stop")
        StopButton.Bind(wx.EVT_BUTTON, self.OnStop)

        QuitButton = wx.Button(self, wx.NewId(), "Quit")
        QuitButton.Bind(wx.EVT_BUTTON, self.OnQuit)

        self.Bind(wx.EVT_CLOSE, self.OnQuit)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add((1,1), 1)
        sizer.Add(StartButton, 0, wx.ALIGN_CENTER | wx.ALL, 4 )
        sizer.Add((1,1), 1)
        sizer.Add(StopButton, 0, wx.ALIGN_CENTER | wx.ALL, 4 )
        sizer.Add((1,1), 1)
        sizer.Add(QuitButton, 0, wx.ALIGN_CENTER | wx.ALL, 4 )
        sizer.Add((1,1), 1)
        return sizer

    def OnTimer(self,Event):
        print "The timer fired"
        self.image_count +=1
        if self.image_count == num_images:
            self.image_count = 0
        self.bytearray[:,:,:] = rbg_from_int16(self.image_array[self.image_count,:,:])
        self.Refresh()
        self.Update()

    def OnStart(self,Event):
        self.Timer.Start(500) # time between events (in milliseconds)

    def OnStop(self, Event=None):
        self.Timer.Stop()

    def OnQuit(self,Event):
        self.Destroy()

app = wx.PySimpleApp(0)
frame = DemoFrame()
frame.Show()
app.MainLoop()




