Could use help with image resize glitch
I would appreciate some help. I have a modified pythonista example. It is a sketch view. I have added the ability to insert a picture and then sketch on top of it.
The issue is after I sketch on top of a picture, the image resizes and become distorted. The script sketches fine if no picture is inserted though so the inserted picture is screwing things up. If you run the code below you will see.
I have narrowed down the issue to the function
path_action()but cannot succeed in fixing it.
# coding: utf-8 # Sketch # A very simple drawing 'app' that demonstrates # custom views and saving images to the camera roll. import ui import photos import console # The PathView class is responsible for tracking # touches and drawing the current stroke. # It is used by SketchView. class PathView (ui.View): def __init__(self, frame): self.frame = frame self.flex = 'WH' self.path = None self.action = None def touch_began(self, touch): x, y = touch.location self.path = ui.Path() self.path.line_width = 3 self.path.line_join_style = ui.LINE_JOIN_ROUND self.path.line_cap_style = ui.LINE_CAP_ROUND self.path.move_to(x, y) def touch_moved(self, touch): x, y = touch.location self.path.line_to(x, y) self.set_needs_display() def touch_ended(self, touch): # Send the current path to the SketchView: if callable(self.action): self.action(self) # Clear the view (the path has now been rendered # into the SketchView's image view): self.path = None self.set_needs_display() def draw(self): if self.path: self.path.stroke() # The main SketchView contains a PathView for the current # line and an ImageView for rendering completed strokes. # It also manages the 'Clear' and 'Save' ButtonItems that # are shown in the title bar. class SketchView (ui.View): def __init__(self, width=1024, height=1024): self.bg_color = 'white' iv = ui.ImageView(frame=(0, 0, width, height)) pv = PathView(frame=self.bounds) pv.action = self.path_action self.add_subview(iv) self.add_subview(pv) save_button = ui.ButtonItem() save_button.title = 'Save' save_button.action = self.save_action clear_button = ui.ButtonItem() clear_button.title = 'New ' clear_button.tint_color = 'red' clear_button.action = self.clear_action view_button = ui.ButtonItem() view_button.title = ' Files' view_button.action = self.view_action self.right_button_items = [save_button, clear_button] self.left_button_items = [view_button] self.image_view = iv def path_action(self, sender): path = sender.path old_img = self.image_view.image width, height = self.image_view.width, self.image_view.height #width, height = ui.get_screen_size() with ui.ImageContext(width, height) as ctx: if old_img: old_img.draw() path.stroke() self.image_view.image = ctx.get_image() def clear_action(self, sender): self.image_view.image = None @ui.in_background def view_action(self, sender): self.image_view.image = ui.Image.from_data(photos.pick_image(raw_data=True)) def save_action(self, sender): if self.image_view.image: # We draw a new image here, so that it has the current # orientation (the canvas is quadratic). with ui.ImageContext(self.width, self.height) as ctx: self.image_view.image.draw() img = ctx.get_image() photos.save_image(img) console.hud_alert('Saved to Photos') else: console.hud_alert('No Image to Save', 'error') def load(self): # We use a quadratic canvas, so that the same image # can be used in portrait and landscape orientation. w, h = ui.get_screen_size() canvas_size = max(w, h) sv = SketchView(canvas_size, canvas_size) sv.name = 'Sketch Pad' sv.present('fullscreen') load(None)
image_view has a default content mode which is scaling the image as displayed, but not actually scaling the underlying image. set iv.content_mode=ui.CONTENT_TOP_LEFT to prevent that.
You maybe ought to scale the image in view_action before you set the imageview. Though doing so causes you to lose resolution.
Or better yet, keep the full rez image, but set
this requires you to set the width,height=old_img.size, but then also requires you to scale the path, or scale your touches perhaps.
Another problem: pathview defaults to flex=WH. Thus when presenting fullscreen, you no longer end up with a square canvas. Also, you might consider using canvas_size=min(w,h) so the entire canvas fits on screen.
finally...it seems somewhat inefficient to convert the path to an image every time. Perhaps it would be better to do that only once,when saving, instead storing a list of Paths.
Thank you @JonB . I appreciate your explanation. I have not fully succeeded in getting it to work as expected but hope to get your suggestions working soon.