#coding: utf-8
import ui
import photos
#### PointView: the little handlers on the corners of the crop area
class PointView(ui.View):
def __init__(self):
self.bounds = (0,0,44,44)
self.hidden = True
self.touch_enabled = False
self.flex = 'TBLR'
def draw(self):
contour = ui.Path.oval(14,14,16,16)
ui.set_color('#FF7349')
contour.fill()
oval = ui.Path.oval(18,18,8,8)
ui.set_color('#FF8B3F')
oval.fill()
#### CropArea: the almighty area that defines where you'll crop the image
class CropArea(ui.View):
def __init__(self):
self.hidden = True
self.touch_enabled = False
self.background_color = (1,0.54,0.24,0.3)
self.bounds = (0,0,2,2)
self.flex = 'WHTBLR'
##### DragView: the slutty view that lets you drag your finger all over it. CakeView?
class DragView (ui.View):
def __init__(self):
self.background_color = (1,1,1,0)
self.content_mode = ui.CONTENT_SCALE_ASPECT_FIT
self.crop_area = CropArea()
self.indicator_start = PointView()
self.indicator_end = PointView()
self.crop_pixels = ui.Label(number_of_lines=1, background_color=(1,0.54,0.24,1.0))
self.crop_pixels.flex = 'TBLR'
self.crop_pixels.hidden = True
self.crop_pixels.text_color = '#383838'
self.crop_pixels.height = 20
self.crop_pixels.alignment = ui.ALIGN_CENTER
self.add_subview(self.crop_pixels)
self.add_subview(self.crop_area)
self.add_subview(self.indicator_start)
def draw(self):
self.crop_button = ui.ButtonItem(title='Crop', enabled=False, action=self.crop_action, tint_color=(1,0.54,0.24,1.0))
self.superview.right_button_items = [self.crop_button]
self.clear_button = ui.ButtonItem(title='Clear', enabled=False, action=self.clear_action, tint_color=(1,0.54,0.24,1.0))
self.superview.left_button_items = [self.clear_button]
self.spinner = ui.ActivityIndicator()
self.spinner.style = ui.ACTIVITY_INDICATOR_STYLE_WHITE_LARGE
self.spinner.center = self.center
self.superview.add_subview(self.spinner)
def touch_began(self, touch):
self.crop_button.enabled = False
self.clear_button.enabled = False
if not self.indicator_end in self.subviews:
self.crop_area.bounds = (0,0,2,2)
self.indicator_start.center = touch.location
self.indicator_start.hidden = False
self.crop_area.x = touch.location[0]
self.crop_area.y = touch.location[1]
self.crop_area.hidden = False
self.crop_pixels.hidden = True
else:
tx, ty = touch.location
ax, ay, aw, ah = self.crop_area.frame
axx, ayy = ax + aw, ay + ah
sx, sy, sw, sh = self.indicator_start.frame
sxx, syy = sx + sw, sy + sh
ex, ey, ew, eh = self.indicator_end.frame
exx, eyy = ex + ew, ey + eh
if ax < tx < axx and ay < ty < ayy:
cx, cy = self.crop_area.center
self.drag_object = 0
self.objx, self.objy = cx - tx, cy - ty
elif sx < tx < sxx and sy < ty < syy:
cx, cy = self.indicator_start.center
self.drag_object = 1
self.objx, self.objy = tx - cx, ty - cy
elif ex < tx < exx and ey < ty < eyy:
cx, cy = self.indicator_end.center
self.drag_object = 2
self.objx, self.objy = tx - cx, ty - cy
else:
self.drag_object = None
self.remove_subview(self.indicator_end)
self.touch_began(touch)
def touch_moved(self, touch):
tx,ty = touch.location
if not self.indicator_end in self.subviews:
if tx < self.indicator_start.center[0]:
self.crop_area.x = tx
if ty < self.indicator_start.center[1]:
self.crop_area.y = ty
self.crop_area.width = abs(tx - self.indicator_start.center[0])
self.crop_area.height = abs(ty - self.indicator_start.center[1])
self.crop_pixels.hidden = False
self.crop_pixels.text = '%i x %i' % self.current_crop_size()
else:
if self.drag_object == 0:
self.crop_area.center = self.objx + tx, self.objy + ty
self.indicator_start.center = self.crop_area.x, self.crop_area.y
self.indicator_end.center = self.crop_area.x + self.crop_area.width, self.crop_area.y + self.crop_area.height
elif self.drag_object == 1:
self.indicator_start.center = self.objx + tx, self.objy + ty
self.crop_area.width = abs(self.indicator_end.center[0] - self.indicator_start.center[0])
self.crop_area.height = abs(self.indicator_end.center[1] - self.indicator_start.center[1])
self.crop_area.x, self.crop_area.y = self.indicator_start.center
self.crop_pixels.text = '%i x %i' % self.current_crop_size()
elif self.drag_object == 2:
self.indicator_end.center = self.objx + tx, self.objy + ty
self.crop_area.width = abs(self.indicator_end.center[0] - self.indicator_start.center[0])
self.crop_area.height = abs(self.indicator_end.center[1] - self.indicator_start.center[1])
self.crop_pixels.text = '%i x %i' % self.current_crop_size()
self.crop_pixels.x = self.crop_area.x
self.crop_pixels.y = self.crop_area.y + self.crop_area.height
def touch_ended(self, touch):
self.crop_button.enabled = True
self.clear_button.enabled = True
if not self.indicator_end in self.subviews:
self.add_subview(self.indicator_end)
self.indicator_end.center = touch.location
self.indicator_end.hidden = False
def clear_action(self, sender):
self.crop_button.enabled = False
self.indicator_end.hidden = True
self.remove_subview(self.indicator_end)
self.crop_area.hidden = True
self.indicator_start.hidden = True
self.crop_pixels.hidden = True
self.clear_button.enabled = False
def crop_action(self, sender):
self.spinner.start()
the_image = self.superview.image_view.image
iw, ih = the_image.size
fx, fy, fw, fh = self.crop_area.frame
scale = min(iw/self.width, ih/self.height)
dw, dh, dx, dy = fw * scale, fh * scale, fx * scale, fy * scale
with ui.ImageContext(dw,dh) as ctx:
with ui.ImageContext(iw,ih) as cropx:
the_image.clip_to_mask(dx,dy,dw,dh)
the_image.draw()
le_crop = cropx.get_image()
ui.concat_ctm(ui.Transform.translation(-dx, -dy))
le_crop.draw()
self.cropped_image = ctx.get_image()
self.show_crop = ui.ImageView()
self.show_crop.image = self.cropped_image
self.show_crop.content_mode = ui.CONTENT_SCALE_ASPECT_FIT
self.show_crop.flex = 'TBLR'
self.spinner.stop()
save_image = ui.ButtonItem(title='Save Image', action=self.save_to_camera_roll)
self.show_crop.right_button_items = [save_image]
self.show_crop.present('sheet')
def save_to_camera_roll(self, sender): ### Saves the cropped image to the Camera Roll
saved_photo = photos.save_image(self.cropped_image)
if saved_photo:
self.show_crop.close()
def current_crop_size(self): ## Calculates the real crop size to fill the label.
iw, ih = self.superview.image_view.image.size
fx, fy, fw, fh = self.crop_area.frame
scale = min(iw/self.width, ih/self.height)
dw, dh = fw * scale, fh * scale
return dw,dh
def layout(self): ## Fixes the position for the label that displays the actual pixels on device turn.
self.crop_pixels.x = self.crop_area.x
self.crop_pixels.y = self.crop_area.y + self.crop_area.height
###### DemoView: the patriarch of all views.
class DemoView (ui.View):
def __init__(self):
self.image_view = ui.ImageView(frame=self.bounds)
self.image_view.content_mode = ui.CONTENT_SCALE_ASPECT_FIT
self.image_view.flex = 'WH'
self.image_view.background_color = '#383838'
self.add_subview(self.image_view)
self.drag_view = DragView()
self.add_subview(self.drag_view)
def set_image(self, img):
self.image_view.image = img
self.layout()
def layout(self):
if self.image_view.image:
w, h = self.width, self.height
iw, ih = self.image_view.image.size
scale = min(w/iw, h/ih)
dw, dh = iw * scale, ih * scale
x, y = (w - dw) * 0.5, (h - dh) * 0.5
self.drag_view.frame = (x, y, dw, dh)
img = ui.Image.from_data(photos.pick_image(raw_data=True))
if img:
v = DemoView()
v.set_image(img)
v.present()
There are no comments yet.