diff options
author | Jack Ha <jackha@gmail.com> | 2018-02-05 16:36:42 +0300 |
---|---|---|
committer | Jack Ha <jackha@gmail.com> | 2018-02-05 16:36:42 +0300 |
commit | 0e7edc3eaf5ccf52f21c2ea0229b529f8ed344e5 (patch) | |
tree | d5a77100f37346cb87dce169ea14a52ba1996015 /cura/Snapshot.py | |
parent | a3ed385259c03f1a950c85cd5f9f8e6e72fae27f (diff) |
CURA-4425 the thumbnail now crops correctly
Diffstat (limited to 'cura/Snapshot.py')
-rw-r--r-- | cura/Snapshot.py | 74 |
1 files changed, 23 insertions, 51 deletions
diff --git a/cura/Snapshot.py b/cura/Snapshot.py index f12ff3e0e1..ff915eeaeb 100644 --- a/cura/Snapshot.py +++ b/cura/Snapshot.py @@ -17,11 +17,16 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator class Snapshot: + ## Return a QImage of the scene + # Uses PreviewPass that leaves out some elements + # Aspect ratio assumes a square @staticmethod def snapshot(width = 300, height = 300): scene = Application.getInstance().getController().getScene() active_camera = scene.getActiveCamera() render_width, render_height = active_camera.getWindowSize() + render_width = int(render_width) + render_height = int(render_height) preview_pass = PreviewPass(render_width, render_height) root = scene.getRoot() @@ -29,7 +34,6 @@ class Snapshot: # determine zoom and look at bbox = None - hulls = None for node in DepthFirstIterator(root): if type(node) == ConvexHullNode: print(node) @@ -38,16 +42,12 @@ class Snapshot: bbox = node.getBoundingBox() else: bbox = bbox + node.getBoundingBox() - convex_hull = node.getMeshData().getConvexHullTransformedVertices(node.getWorldTransformation()) - if hulls is None: - hulls = convex_hull - else: - hulls = numpy.concatenate((hulls, convex_hull), axis = 0) if bbox is None: bbox = AxisAlignedBox() look_at = bbox.center + # guessed size so the objects are hopefully big size = max(bbox.width, bbox.height, bbox.depth * 0.5) # Somehow the aspect ratio is also influenced in reverse by the screen width/height @@ -56,56 +56,27 @@ class Snapshot: projection_matrix.setPerspective(30, render_width / render_height, 1, 500) camera.setProjectionMatrix(projection_matrix) + # Looking from this direction (x, y, z) in OGL coordinates looking_from_offset = Vector(1, 1, 2) if size > 0: # determine the watch distance depending on the size looking_from_offset = looking_from_offset * size * 1.3 - camera.setViewportSize(render_width, render_height) - camera.setWindowSize(render_width, render_height) camera.setPosition(look_at + looking_from_offset) camera.lookAt(look_at) - # we need this for the projection calculation - hulls4 = numpy.ones((hulls.shape[0], 4)) - hulls4[:, :-1] = hulls - #position = Vector(10, 10, 10) - # projected_position = camera.project(position) - preview_pass.setCamera(camera) - preview_pass.setSize(render_width, render_height) # texture size preview_pass.render() pixel_output = preview_pass.getOutput() - print("Calculating image coordinates...") - view = camera.getWorldTransformation().getInverse() - min_x, max_x, min_y, max_y = render_width, 0, render_height, 0 - for hull_coords in hulls4: - projected_position = view.getData().dot(hull_coords) - projected_position2 = projection_matrix.getData().dot(projected_position) - #xx, yy = camera.project(Vector(data = hull_coords)) - # xx, yy range from -1 to 1 - xx = projected_position2[0] / projected_position2[2] / 2.0 - yy = projected_position2[1] / projected_position2[2] / 2.0 - # x, y 0..render_width/height - x = int(render_width / 2 + xx * render_width / 2) - y = int(render_height / 2 + yy * render_height / 2) - min_x = min(x, min_x) - max_x = max(x, max_x) - min_y = min(y, min_y) - max_y = max(y, max_y) - print(min_x, max_x, min_y, max_y) - - # print("looping all pixels in python...") - # min_x_, max_x_, min_y_, max_y_ = render_width, 0, render_height, 0 - # for y in range(int(render_height)): - # for x in range(int(render_width)): - # color = pixel_output.pixelColor(x, y) - # if color.alpha() > 0: - # min_x_ = min(x, min_x_) - # max_x_ = max(x, max_x_) - # min_y_ = min(y, min_y_) - # max_y_ = max(y, max_y_) - # print(min_x_, max_x_, min_y_, max_y_) + # Look at the resulting image to get a good crop. + # Get the pixels as byte array + pixel_array = pixel_output.bits().asarray(pixel_output.byteCount()) + # Convert to numpy array, assume it's 32 bit (it should always be) + pixels = numpy.frombuffer(pixel_array, dtype=numpy.uint8).reshape([render_height, render_width, 4]) + # Find indices of non zero pixels + nonzero_pixels = numpy.nonzero(pixels) + min_y, min_x, min_a_ = numpy.amin(nonzero_pixels, axis=1) + max_y, max_x, max_a_ = numpy.amax(nonzero_pixels, axis=1) # make it a square if max_x - min_x >= max_y - min_y: @@ -114,11 +85,12 @@ class Snapshot: else: # make x bigger min_x, max_x = int((max_x + min_x) / 2 - (max_y - min_y) / 2), int((max_x + min_x) / 2 + (max_y - min_y) / 2) - copy_pixel_output = pixel_output.copy(min_x, min_y, max_x - min_x, max_y - min_y) + cropped_image = pixel_output.copy(min_x, min_y, max_x - min_x, max_y - min_y) - # Scale it to the correct height - image = copy_pixel_output.scaledToHeight(height, QtCore.Qt.SmoothTransformation) - # Then chop of the width - cropped_image = image.copy(image.width() // 2 - width // 2, 0, width, height) + # Scale it to the correct size + scaled_image = cropped_image.scaled( + width, height, + aspectRatioMode = QtCore.Qt.IgnoreAspectRatio, + transformMode = QtCore.Qt.SmoothTransformation) - return cropped_image + return scaled_image |