This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame object
| 52 | // This method is required for all derived classes of EffectBase, and returns a |
| 53 | // modified openshot::Frame object |
| 54 | std::shared_ptr<openshot::Frame> Crop::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) |
| 55 | { |
| 56 | // Get the frame's image |
| 57 | std::shared_ptr<QImage> frame_image = frame->GetImage(); |
| 58 | |
| 59 | // Get current keyframe values |
| 60 | double left_value = left.GetValue(frame_number); |
| 61 | double top_value = top.GetValue(frame_number); |
| 62 | double right_value = right.GetValue(frame_number); |
| 63 | double bottom_value = bottom.GetValue(frame_number); |
| 64 | |
| 65 | // Get the current shift amount |
| 66 | double x_shift = x.GetValue(frame_number); |
| 67 | double y_shift = y.GetValue(frame_number); |
| 68 | |
| 69 | QSize sz = frame_image->size(); |
| 70 | |
| 71 | // Compute destination rectangle to paint into |
| 72 | QRectF paint_r( |
| 73 | left_value * sz.width(), top_value * sz.height(), |
| 74 | std::max(0.0, 1.0 - left_value - right_value) * sz.width(), |
| 75 | std::max(0.0, 1.0 - top_value - bottom_value) * sz.height()); |
| 76 | |
| 77 | // Copy rectangle is destination translated by offsets |
| 78 | QRectF copy_r = paint_r; |
| 79 | copy_r.translate(x_shift * sz.width(), y_shift * sz.height()); |
| 80 | |
| 81 | // Constrain offset copy rect to stay within image borders |
| 82 | if (copy_r.left() < 0) { |
| 83 | paint_r.setLeft(paint_r.left() - copy_r.left()); |
| 84 | copy_r.setLeft(0); |
| 85 | } |
| 86 | if (copy_r.right() > sz.width()) { |
| 87 | paint_r.setRight(paint_r.right() - (copy_r.right() - sz.width())); |
| 88 | copy_r.setRight(sz.width()); |
| 89 | } |
| 90 | if (copy_r.top() < 0) { |
| 91 | paint_r.setTop(paint_r.top() - copy_r.top()); |
| 92 | copy_r.setTop(0); |
| 93 | } |
| 94 | if (copy_r.bottom() > sz.height()) { |
| 95 | paint_r.setBottom(paint_r.bottom() - (copy_r.bottom() - sz.height())); |
| 96 | copy_r.setBottom(sz.height()); |
| 97 | } |
| 98 | |
| 99 | QImage cropped(sz, QImage::Format_RGBA8888_Premultiplied); |
| 100 | cropped.fill(Qt::transparent); |
| 101 | |
| 102 | QPainter p(&cropped); |
| 103 | p.drawImage(paint_r, *frame_image, copy_r); |
| 104 | p.end(); |
| 105 | |
| 106 | if (resize) { |
| 107 | // Resize image to match cropped QRect (reduce frame size) |
| 108 | frame->AddImage(std::make_shared<QImage>(cropped.copy(paint_r.toRect()))); |
| 109 | } else { |
| 110 | // Copy cropped image into transparent frame image (maintain frame size) |
| 111 | frame->AddImage(std::make_shared<QImage>(cropped.copy())); |