Forum Archive

PKCanvasView

cvp

Quick and dirty, as usual, but to be tried anyway

from objc_util import *
import ui

import console
import ui
from objc_util import *
import os

@on_main_thread
def main():
    global canvasView
    v = ui.View()
    w,h = ui.get_screen_size()
    #v.frame = (0,0,w,h)
    v.frame = (0,0,400,600)

    b_clear = ui.ButtonItem()
    b_clear.title = 'clear'
    def b_clear_action(sender):
        global canvasView
        canvasView.drawing = ObjCClass('PKDrawing').alloc().init()
    b_clear.action = b_clear_action 
    b_save = ui.ButtonItem()
    b_save.title = 'save'
    def b_save_action(sender):
        global canvasView
        img = canvasView.drawing().imageFromRect_scale_(canvasView.frame(),1.0)
        iv = ui.ImageView()
        w,h = 80,120
        iv.frame = (10,10,w,h)
        iv.border_width = 1
        v.add_subview(iv)       
        with ui.ImageContext(w,h) as ctx:
            img.drawInRect_(CGRect(CGPoint(0, 0), CGSize(w,h)))
            iv.image = ctx.get_image()              
    b_save.action = b_save_action       
    v.right_button_items = (b_clear, b_save)

    v.present('sheet')
    view = ObjCInstance(v)
    canvasView = ObjCClass('PKCanvasView').alloc().initWithFrame_(view.frame())
    view.addSubview_(canvasView)
    window = view.window()
    toolPicker = ObjCClass('PKToolPicker').alloc().init()
    toolPicker.setVisible_forFirstResponder_(True, canvasView)
    toolPicker.addObserver_(canvasView)
    canvasView.becomeFirstResponder()

main()

ChelsWin

Thanks for posting this. It is really helpful.
Would it be possible to save the drawing to camera roll?

cvp

@ChelsWin here-after, 3 methods:
1. In Pythonista, using depreciated method
2. In ObjectiveC, without passing via a temporary file
3. In Pythonista, using Photos module, passing via a temporary file because create_image_asset needs a file as parameter

        with ui.ImageContext(w,h) as ctx:
            img.drawInRect_(CGRect(CGPoint(0, 0), CGSize(w,h)))
            iv.image = ctx.get_image()  

        # save ui.Image using depreciated method
        import photos
        photos.save_image(iv.image)

        # save ui.Image in camera roll without passing via a file
        import threading            
        NSBundle.bundleWithPath_('/System/Library/Frameworks/Photos.framework').load()
        PHPhotoLibrary = ObjCClass('PHPhotoLibrary')
        PHAssetChangeRequest = ObjCClass('PHAssetChangeRequest')

        lib = PHPhotoLibrary.sharedPhotoLibrary()
        def change_block():
            req = PHAssetChangeRequest.creationRequestForAssetFromImage_(img)
        def perform_changes():
            lib.performChangesAndWait_error_(change_block, None)
        t = threading.Thread(target=perform_changes)
        t.start()
        t.join()

        # save ui.Image in camera roll, passing via a file
        import photos
        # Save as temporary JPEG file
        path = 'temp.jpg'
        with open(path, 'wb') as f:
            quality = 0.9 # From 0.0 (more compression) to 1.0 (better quality)
            f.write(iv.image.to_jpeg(quality))
        # Save file in camera roll
        photos.create_image_asset(path)
        # Remove temporary file
        os.remove(path)
ChelsWin

Awesome. Thanks for the help