Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Display data from an array
-
Hello, I'm relatively new to python and I'm trying to figure out how I make my array, full of 1's or 0's, display a black or white pixel graphically. I'm making a chip8 emulator and have searched the forums a little but it doesn't look like my question has come up.
-
I had this same problem when trying to port over an appleii simulator. So, I wrote a wrapper that lets you either pass in a whole array (numpy array) or blit a section (like for sprite based work), and display it as a ui.View
https://github.com/jsbain/applepy
See screen.py.depending on what you array looks like, a PIL Image might be a little faster. Also, format=jpg is somewhat faster too, though not pixel perfect.
The basic approach is to save an image to a bytesio, then turn into a ui.Image that can be displayed in a ImageView. the above code tries to make that process asynchronous. -
import numpy as np from PIL import Image import ui import io def ui2pil(ui_img): return Image.open(io.BytesIO(ui_img.to_png())) def pil2ui(pil_img): with io.BytesIO() as buffer: pil_img.save(buffer, format='PNG') return ui.Image.from_data(buffer.getvalue()) b = np.array(np.random.random((200,200))*2, dtype=np.uint8)*255 print(b) img = Image.fromarray(b, 'L') img.show() w,h = img.size v = ui.ImageView(frame=(0,0,w,h), image=pil2ui(img)) v.present('sheet')
-
Thank you both so much, I'm not really understanding fromarray(), does it only accept nested narray's and tuples? I keep getting a tuple index out of range.
-
Can you post your code?It may help us to locate the problem.
-
screen = np.array((0,0)*32*64)*2 b = np.array(screen, dtype=np.uint8)*255 print(b) img = Image.fromarray(b, 'L') img.show()
-
I am not sure what you are trying to do. May be look at the tutorials on numpy and pillow(PIL). Anyway here are some more examples
import numpy as np from PIL import Image screen = np.zeros((32,64)) b = np.array(screen, dtype=np.uint8)*255 print(b) img = Image.fromarray(b, 'L') img.show() from PIL import Image import numpy as np b = [0,255]*16 c = b*32 #print(c) d = np.array(c, dtype=np.uint8).reshape(32, 32) img = Image.fromarray(d, 'L') img.show()
-
Oops I forgot to explain. I want to have a 64 by 32 pixel image that can either be black or white that can be changed by editing the array's values.
-
Your can modify the second example to get the desired pattern. Here is another variation. It may be faster to manipulate the numpy arrays directly. Look at the numpy tutorials.
from PIL import Image import numpy as np b1 = [0,0,0,0,255,255,255,255]*4 b11 = b1*4 b2 = [255,255,255,255,0,0,0,0]*4 b22 = b2*4 c = (b11+b22)*8 #print(c) d = np.array(c, dtype=np.uint8).reshape(64, 32) print(d) img = Image.fromarray(d, 'L') img.show()
-
do take a look at the screen.py example, it should work for your needs.
@enceladus has a fine approach, but it will be impossibly slow if you are doing pixel by pixel writes in your simulation, as opposed to creating a full frame, and displaying complete frams at a time (the appleii simulation worked that way, since it was basically simulating down to the hardware level, and the old appleii didnt have like a separate video driver)
screen.py handles is by doing background conversions, and any calls to write data that happen too fast get grouped up and drawn at the next opportunity.
-
Here is a simple animation based on @JonB 's code. It uses latest update function (available in beta) instead of threads.
import ui import numpy as np import io from PIL import Image class Screen(ui.View): def __init__(self,w,h): self.width=w self.height=h self.S = np.zeros((w,h), dtype=np.uint8) self.offset = 0 self.S[self.offset:self.offset+20,:] = 255 img = Image.fromarray(self.S, 'L') self.B=io.BytesIO() img.save(self.B, format='PNG') self.update_interval = 1 def set_data(self): self.S[self.offset:(self.offset+20),:] = 0 self.offset = (self.offset+20)%self.width self.S[self.offset:self.offset+20,:] = 255 img = Image.fromarray(self.S, 'L') img.save(self.B, format='PNG') self.B.seek(0) def update(self): self.set_data() self.set_needs_display() def draw(self): ui.Image.from_data(self.B.getvalue()).draw() if __name__=='__main__': import time w=300 h=w s=Screen(w,h) s.present('sheet')