omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    array display
    3
    11
    7152
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Brando
      Brando last edited by

      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.

      1 Reply Last reply Reply Quote 0
      • JonB
        JonB last edited by

        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.

        1 Reply Last reply Reply Quote 0
        • enceladus
          enceladus last edited by

          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')
          
          1 Reply Last reply Reply Quote 0
          • Brando
            Brando last edited by

            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.

            1 Reply Last reply Reply Quote 0
            • enceladus
              enceladus last edited by

              Can you post your code?It may help us to locate the problem.

              1 Reply Last reply Reply Quote 0
              • Brando
                Brando last edited by

                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()
                
                1 Reply Last reply Reply Quote 0
                • enceladus
                  enceladus last edited by enceladus

                  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()
                  
                  
                  
                  1 Reply Last reply Reply Quote 0
                  • Brando
                    Brando last edited by

                    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.

                    1 Reply Last reply Reply Quote 0
                    • enceladus
                      enceladus last edited by

                      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()
                      
                      
                      1 Reply Last reply Reply Quote 0
                      • JonB
                        JonB last edited by

                        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.

                        1 Reply Last reply Reply Quote 0
                        • enceladus
                          enceladus last edited by

                          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')
                          
                          
                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post
                          Powered by NodeBB Forums | Contributors