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.


    How to load a custom scene Texture?

    Pythonista
    image texture scene
    3
    18
    6150
    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.
    • Moe
      Moe last edited by Moe

      Hi, I am trying to build a scene with custom textures, which I pre-process using PIL. From PIL I then convert them to ui.Image and then I want to load them as a Texture. Unfortunately, I cannot get them to load at all. Included is a minimum (non-) working example with a normal png in my project directory.

      import ui, scene
      
      image = ui.Image('sprite.png')
      image.show()	# this works
      texture = scene.Texture(image) # this fails
      '''
      Traceback (most recent call last):
        File "/private/var/mobile/Containers/Shared/AppGroup/73760516-2464-4322-8DCC-0525D46DFFC3/Pythonista3/Documents/smw/minimal_example.py", line 5, in <module>
          texture = scene.Texture(image)
      ValueError: Could not load image
      '''
      
      texture = scene.Texture('sprite.png') # this fails as well
      '''
      Traceback (most recent call last):
        File "/private/var/mobile/Containers/Shared/AppGroup/73760516-2464-4322-8DCC-0525D46DFFC3/Pythonista3/Documents/smw/minimal_example.py", line 6, in <module>
          texture = scene.Texture('sprite.png')
      ValueError: Image not found
      '''
      

      The sprite.png is a 32x32 PNG with a size of 981 bytes. I had no luck getting this to work with other images so far.
      Any help is appreciated.

      cvp stephen 2 Replies Last reply Reply Quote 0
      • cvp
        cvp @Moe last edited by cvp

        @Moe sure that sprite.png in the same folder as your script? For me, it is ok

        import ui, scene
        image = ui.Image('sprite.png')
        image.show()   												# this works
        texture = scene.Texture(image) 				# this works
        texture = scene.Texture('sprite.png') # this works
        
        stephen 1 Reply Last reply Reply Quote 0
        • Moe
          Moe last edited by

          Thanks for the suggestion, but the image is in the same directory. It is really odd that it does work for you, but not for me.

          I am on iOS 13.5 (17F75) with an iPad 7 and Pythonista 3.3 (330025)

          cvp 2 Replies Last reply Reply Quote 0
          • cvp
            cvp @Moe last edited by

            @Moe same iOS, Pythonista, iPad mini 4, but I did not test with a 32x32 png, I'll do it

            1 Reply Last reply Reply Quote 0
            • cvp
              cvp @Moe last edited by

              @Moe works with a 32x32

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

                Try to restart Pythonista

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

                  After testing with a bigger image (overworld_tileset.png, 565x564 px, 44kb) I got the same result.
                  Restarting Pythonista did not help, restarting the iPad did not help.

                  cvp 1 Reply Last reply Reply Quote 0
                  • cvp
                    cvp @Moe last edited by

                    @Moe sure you test with the little script, not with a bigger including the little

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

                      I now imported a photo I took with the iPad (JPG) via the little plus in the bottom left -> Import... -> Photo Library and it worked fine!

                      Maybe there is a problem using PNGs?

                      cvp 1 Reply Last reply Reply Quote 0
                      • cvp
                        cvp @Moe last edited by

                        @Moe I'had tried with a png. Could you rename your .jpg as .png and retry

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

                          I found the problem: The images I used For testing where saved in P / Indexed Color mode. This can be checked with PIL

                          from PIL import Image
                          
                          img = Image.open('sprite.png')
                          print(img.mode)
                          #> 'P'
                          

                          I converted them with img = img.convert('RGB') and saved them again. Now it works. It seems that the Texture class cannot handle files in mode P and does not fail gracefully. This is probably an oversight.
                          Thank you again @cvp for taking your time to help! Much appreciated.

                          cvp 1 Reply Last reply Reply Quote 0
                          • cvp
                            cvp @Moe last edited by cvp

                            @Moe Nice job! 🍾

                            My tested ping mode was RGBA

                            1 Reply Last reply Reply Quote 0
                            • stephen
                              stephen @Moe last edited by stephen

                              @Moe @cvp

                              You could use io. BytesIO in a Context manager soyou dont need to save and open the images. and when you use ui.Image.from_data(image_data[, scale]) and set scale to your IOS device pixel/point ratio. most comonly 2. (1:1, 2:1, 3:1 ...) this will scale your image properly to the screen. you can get this by calling scene.get_screen_scale()

                              heres an example:

                              import scene
                              import Image
                              import io
                              
                              cache = dict({
                                  "img1":"./image1.png",
                                  "img2":"./image2.png",
                              })
                              
                              for k,v in cache.items():
                                  with Image.open(v) as img:
                                      resized_img=img.resize(
                                          (int(img.size[0]/2), int(img.size[1]/2)), Image.ANTIALIAS)
                                          
                                      with io.BytesIO() as byteStream:
                                          resized_img.save(byteStream, "tiff")    
                                          ns.cache[k]=scene.Texture(ui.Image.from_data(byteStream.getvalue(), scene.get_screen_scale()))
                              
                              
                              1 Reply Last reply Reply Quote 0
                              • stephen
                                stephen @cvp last edited by ccc

                                @cvp said:

                                @Moe sure that sprite.png in the same folder as your script? For me, it is ok

                                import ui, scene
                                image = ui.Image('sprite.png')
                                image.show()   												# this works
                                texture = scene.Texture(image) 				# this works
                                texture = scene.Texture('sprite.png') # this works
                                

                                from my understanding shoudn't it be ui.Image.named('sprite.png')

                                cvp 1 Reply Last reply Reply Quote 0
                                • cvp
                                  cvp @stephen last edited by

                                  @stephen said:

                                  from my understanding shoudn't it be ui.Image.named('sprite.png')

                                  You're right but try it, it works also without .named

                                  stephen 1 Reply Last reply Reply Quote 1
                                  • stephen
                                    stephen @cvp last edited by

                                    @cvp

                                    well look at that... i think its all beena lie... lol jk but i do wonder what the method named might be doing that may be a benefit?

                                    cvp 1 Reply Last reply Reply Quote 0
                                    • cvp
                                      cvp @stephen last edited by

                                      @stephen said:

                                      what the method named might be doing that may be a benefit?

                                      No idea

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

                                        My current approach is to load the tileset.png which contains all the tiles. I then use Image.crop() for every tile I want to extract. I then upscale them using Image.resize() by some arbitrary factor, because if I would let the scene upscale the 8x8 textures to something like 64x64, the performance drops hard. Using BytesIO I convert them to ui.Image without saving them on disk and from there I can load them as a scene.Texture.

                                        But thank you for the hint that I can load the image and scale them in one operation!

                                        All I had to do to fix the original problem was converting the tileset.png to RGB mode.

                                        1 Reply Last reply Reply Quote 1
                                        • First post
                                          Last post
                                        Powered by NodeBB Forums | Contributors