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.


    Converting images to webp or jpeg2000 in Pythonista

    Pythonista
    5
    27
    7137
    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.
    • Niklas
      Niklas last edited by

      Hi!

      Is it possible to convert images from png or jpg format to webp or jpeg2000 in Pythonista? I have Googled and tested different ways but canโ€™t get it to work. Anyone else here who has managed to do it?

      Best regards, Niklas

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

        https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save

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

          Thank you, I will try to make that work! ๐Ÿ™‚

          Best regards, Niklas

          mikael 2 Replies Last reply Reply Quote 0
          • mikael
            mikael @Niklas last edited by mikael

            @Niklas, unfortunately it looks like the version of PIL included with Pythonista is too old to recognize .webp, and not compiled with j2k support.

            I tested with:

            import photos
            
            photo = photos.get_assets()[-1].get_image()
            
            photo.save('test.j2k')
            
            1 Reply Last reply Reply Quote 0
            • mikael
              mikael @Niklas last edited by

              @Niklas, iOS Safari supports webp since iOS 14, so conversion should be possible in a WebView via JavaScript. Relevant-looking js sample here.

              And Apple Shortcuts supports image conversion to JPEG2000, so you might be able to do everything there, or branch out to run just the conversion in Shortcuts.

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

                Thank you, @mikael, doing it in Shortcuts worked perfectly! ๐Ÿ™‚ Like you, I tested different ways of making it work in Pythonista, but gave up. If someone else needs it, the shortcuts is here:

                https://www.icloud.com/shortcuts/de01f3230990494b85129535fa855d5d

                You can pick images from Photos or Files and it converts them to jpeg2000. Then you can save them back to Photos or Files.

                Hopefully it will be possible to do this in Pythonista eventually. ๐Ÿ™‚

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

                  @Niklas I think that it could be possible that
                  In Pythonista

                  • you ask/get the image
                  • you save the file in Files (in an external folder)
                  • you start a shortcut which
                    In your shortcut
                  • you get the file from Files
                  • you convert to jpeg2000
                  • you save in Files
                  • you start Pythonista script
                    In Pythonista
                  • you get the converted file
                  • ...

                  ร‰dit: sorry, if it was what you want to say by "Hopefully it will be possible to do this in Pythonista eventually."

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

                    Thank you! Iโ€™m thinking of doing something like that, but more or less only do the .jp2 conversion in Shortcuts and everything else in Pythonista. ๐Ÿ™‚

                    What I meant by the sentence you quoted, is that I hope Pythonista will get built-in support for webp and jpeg2000 conversions in the future. Since that is what Google recommends if you want high website rankings in their search results, I think Pythonista would be a good place to have it on iPad.

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

                      I believe that CGCreateDestination supports writing to j2k.

                      https://stackoverflow.com/questions/19749482/how-do-i-convert-uiimage-to-j2k-jpeg2000-in-ios

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

                        I tried to read and follow what they did there, but it was above my knowledge level. Thanks anyway! ๐Ÿ™‚

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

                          A related question:

                          If I get a jp2 image from Shortcuts via the clipboard, can I save it to Files in Pythonista? When I try to do it with image.save(image-to-save) I get an OSError: encoder jpeg2k not available, which I can understand. I think there should be a way to disregard the file type and save it the way it came, without making any changes other than the file name.

                          Is this possible?

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

                            @Niklas why are you passing the image file as an image ? In shortcuts, you could save it in Files.

                            ร‰dit: what do you want to do with this image in Pythonista?

                            1 Reply Last reply Reply Quote 0
                            • mikael
                              mikael @Niklas last edited by

                              @Niklas, PIL images have the tobytes method that could possibly do the trick, but see the warning in doc.

                              Probably better to save in Files, as @cvp suggested, and just pass the path. Then you can handle it in Pythonista like any other binary file.

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

                                @cvp, my intention was to do as much as possible in Pythonista, since I find Shortcuts so slow. Your question got me to think and I went with your suggestion instead. ๐Ÿ™‚ Also, I already had a shortcut that did most of what I wanted.

                                @mikael, thanks for suggesting tobytes. I will try to keep that in mind for another time. ๐Ÿ™‚

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

                                  @Niklas I've tried during some hours to convert @JonB 's idea into Pythonista, but without any success. Sorry

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

                                    @cvp, want to share the code for some joint debugging?

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

                                      @mikael I think it is far from my skills

                                      '''
                                      https://stackoverflow.com/questions/19749482/how-do-i-convert-uiimage-to-j2k-jpeg2000-in-ios
                                      
                                      #import <ImageIO/ImageIO.h> // or @import ImageIO if modules enabled
                                      #import <MobileCoreServices/MobileCoreServices.h>
                                      
                                      // ...    
                                      
                                      // quality is 0-1 (0 = smallest file size, 1 = lossless quality)
                                      + (NSData*) convertToJPEG2000:(UIImage*)image withQuality:(float)quality
                                      {
                                          NSMutableData* d = [NSMutableData data];
                                          CGImageDestinationRef destinationRef = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)d, kUTTypeJPEG2000, 1, NULL);
                                          CGImageDestinationSetProperties(destinationRef, NULL);
                                          CGImageDestinationAddImage(destinationRef, image.CGImage, (__bridge CFDictionaryRef)@{ (NSString*)kCGImageDestinationLossyCompressionQuality: @(quality) });
                                      
                                          if (!CGImageDestinationFinalize(destinationRef))
                                          {
                                              d = nil;
                                          }
                                          CFRelease(destinationRef);
                                      
                                          return d;
                                      }
                                      '''
                                      from   objc_util import *
                                      import time
                                      import ui
                                      
                                      d = NSMutableData
                                      
                                      CGImageDestinationCreateWithData = c.CGImageDestinationCreateWithData
                                      CGImageDestinationCreateWithData.restype = c_void_p
                                      CGImageDestinationCreateWithData.argtypes = [c_void_p, c_void_p, c_void_p, c_void_p]
                                      
                                      kUTTypeJPEG2000 = 'public.jpeg-2000'	# UTI for a Jpeg2000
                                      
                                      imagedest = CGImageDestinationCreateWithData(d, kUTTypeJPEG2000, 1, None)
                                      
                                      CGImageDestinationSetProperties = c.CGImageDestinationSetProperties
                                      CGImageDestinationSetProperties.restype = None
                                      CGImageDestinationSetProperties.argtypes = [c_void_p, c_void_p]
                                      CGImageDestinationSetProperties(d, None)
                                      
                                      img = ui.Image.named('test:Peppers').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL).objc_instance
                                      
                                      CGImageDestinationAddImage = c.CGImageDestinationAddImage
                                      CGImageDestinationAddImage.restype = None
                                      CGImageDestinationAddImage.argtypes = [c_void_p, c_void_p, c_void_p]
                                      CGImageDestinationAddImage(d, img, None)# {ns('kCGImageDestinationLossyCompressionQuality'):1})
                                      time.sleep(3)
                                      
                                      CFRelease = c.CFRelease
                                      CFRelease.restype = None
                                      CFRelease.argtypes = [c_void_p]
                                      CFRelease(d)
                                      
                                      mikael 1 Reply Last reply Reply Quote 0
                                      • mikael
                                        mikael @cvp last edited by

                                        @cvp, yeah, it looked more challenging than usual. Would it matter if you objc_util.load_framework('ImageIO') or not?

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

                                          @mikael sincerely, I don't know, I have stopped to spend time with this test.

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

                                            You were really close! CGDestnationXXX() takes imagedest as first param. ine of the signatures was wrong (needed a size_t), and the kUTType ought to be an nsstring.

                                            This seems to work!
                                            (edit: refactored into a convienent function)
                                            (edit again, fixed a typo, added quality)

                                            '''
                                            https://stackoverflow.com/questions/19749482/how-do-i-convert-uiimage-to-j2k-jpeg2000-in-ios
                                            
                                            #import <ImageIO/ImageIO.h> // or @import ImageIO if modules enabled
                                            #import <MobileCoreServices/MobileCoreServices.h>
                                            
                                            // ...    
                                            
                                            // quality is 0-1 (0 = smallest file size, 1 = lossless quality)
                                            + (NSData*) convertToJPEG2000:(UIImage*)image withQuality:(float)quality
                                            {
                                                NSMutableData* d = [NSMutableData data];
                                                CGImageDestinationRef destinationRef = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)d, kUTTypeJPEG2000, 1, NULL);
                                                CGImageDestinationSetProperties(destinationRef, NULL);
                                                CGImageDestinationAddImage(destinationRef, image.CGImage, (__bridge CFDictionaryRef)@{ (NSString*)kCGImageDestinationLossyCompressionQuality: @(quality) });
                                            
                                                if (!CGImageDestinationFinalize(destinationRef))
                                                {
                                                    d = nil;
                                                }
                                                CFRelease(destinationRef);
                                            
                                                return d;
                                            }
                                            '''
                                            from   objc_util import *
                                            import ctypes
                                            import time
                                            import ui
                                            load_framework('ImageIO')
                                            
                                            CGImageDestinationCreateWithData = c.CGImageDestinationCreateWithData
                                            CGImageDestinationCreateWithData.restype = c_void_p
                                            CGImageDestinationCreateWithData.argtypes = [c_void_p, c_void_p, ctypes.c_size_t, c_void_p]
                                            
                                            CGImageDestinationSetProperties = c.CGImageDestinationSetProperties
                                            CGImageDestinationSetProperties.restype = None
                                            CGImageDestinationSetProperties.argtypes = [c_void_p, c_void_p]
                                            
                                            CGImageDestinationAddImage = c.CGImageDestinationAddImage
                                            CGImageDestinationAddImage.restype = None
                                            CGImageDestinationAddImage.argtypes = [c_void_p, c_void_p, c_void_p]
                                            
                                            CGImageDestinationFinalize=c.CGImageDestinationFinalize
                                            CGImageDestinationFinalize.restype=ctypes.c_int
                                            CGImageDestinationFinalize.argtypes=[c_void_p]
                                            
                                            CFRelease = c.CFRelease
                                            CFRelease.restype = None
                                            CFRelease.argtypes = [c_void_p]
                                            
                                            kUTTypeJPEG2000 =  c_void_p.in_dll(c,'kUTTypeJPEG2000')    # UTI for a Jpeg2000
                                            kCGImageDestinationLossyCompressionQuality=c_void_p.in_dll(c,'kCGImageDestinationLossyCompressionQuality')
                                            
                                            '''def convert_image_to_jpeg2000(uiimg, out_filename, quality=1):
                                            	uiimage=ui.Image
                                            	out_filename=str
                                            	quality: 0=smallest, 1=lossless'''
                                            def convert_image_to_jpeg2000(uiimg, out_filename, quality=1):
                                            	d = NSMutableData.new()
                                            	imagedest = CGImageDestinationCreateWithData(d, kUTTypeJPEG2000, 1, None)
                                            
                                            	CGImageDestinationSetProperties(imagedest, None)
                                            
                                            	#img = ui.Image.named('test:Peppers').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL).objc_instance
                                            
                                            	CGImageDestinationAddImage(imagedest, uiimg.objc_instance.CGImage(),ns({'kCGImageDestinationLossyCompressionQuality':quality}))
                                            
                                            	if not CGImageDestinationFinalize(imagedest):
                                            		raise Exception('Image Conversion Failed')
                                            	CFRelease(imagedest)
                                            
                                            	with open(out_filename,'wb') as f:
                                            		f.write(nsdata_to_bytes(d))
                                            
                                            if __name__=='__main__': 		
                                            	img=ui.Image.named('test:Lenna')
                                            	convert_image_to_jpeg2000(img, 'lenna.j2k',0)
                                            
                                            	import console
                                            	console.quicklook('lenna.j2k')
                                            	print('success!' )
                                            	
                                            
                                            cvp 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Powered by NodeBB Forums | Contributors