views:

615

answers:

1

Here is a problem. I want to visualize a specific vector field as a bitmap. It's ok with the representation itself, so I allready have some matrix of RGB lists like [255,255,115], but I have no good idea of how to draw it on screen. So far I make thousands of colored 1px rectangles, but this works too slow. I'm sure there is a better way to draw a bitmap.

+4  A: 

ATTEMPT 3 - I swear last one...

I believe this is the fastest pure TK way to do this. Generates 10,000 RGB values in a list of lists, creates a Tkinter.PhotoImage and then puts the pixel values into it.

import Tkinter, random
class App:
    def __init__(self, t):
        self.i = Tkinter.PhotoImage(width=100,height=100)
        colors = [[random.randint(0,255) for i in range(0,3)] for j in range(0,10000)]
        row = 0; col = 0
        for color in colors:
   self.i.put('#%02x%02x%02x' % tuple(color),(row,col))
   col += 1
   if col == 100:
    row +=1; col = 0        
        c = Tkinter.Canvas(t, width=100, height=100); c.pack()
        c.create_image(0, 0, image = self.i, anchor=Tkinter.NW)

t = Tkinter.Tk()
a = App(t)    
t.mainloop()

ATTEMPT 1 - using the create_rectangle method

I wrote this as a test. On my Intel Core 2 duo at 2.67 Ghz, it'll draw about 5000 pixels in 0.6 seconds including the time to generate my random RGB values:

from Tkinter import *
import random

def RGBs(num):
 # random list of list RGBs
 return [[random.randint(0,255) for i in range(0,3)] for j in range(0,num)]

def rgb2Hex(rgb_tuple):
    return '#%02x%02x%02x' % tuple(rgb_tuple)

def drawGrid(w,colors):
 col = 0; row = 0
 colors = [rgb2Hex(color) for color in colors]
 for color in colors:
  w.create_rectangle(col, row, col+1, row+1, fill=color, outline=color)
  col+=1
  if col == 100:
   row += 1; col = 0

root = Tk()
w = Canvas(root)
w.grid()
colors = RGBs(5000)
drawGrid(w,colors)
root.mainloop()

ATTEMPT 2 - Using PIL

I know you said TK only but PIL makes this really easy and fast.

def rgb2Hex(rgb_tuple):
    return '#%02x%02x%02x' % tuple(rgb_tuple)

num = 10000 #10,000 pixels in 100,100 image
colors = [[random.randint(0,255) for i in range(0,3)] for j in range(0,num)]
colors = [rgb2Hex(color) for color in colors]
im = Image.fromstring('RGB',(100,100),"".join(colors))
tkpi = ImageTk.PhotoImage(im)
## add to a label or whatever...
label_image = Tkinter.Label(root, image=tkpi)
Mark
attempt 3 can probably be sped up dramatically. It is generally much quicker to build up an array of pixels and do a single "put" rather than do a "put" for every single pixel.
Bryan Oakley