21     init_effect_details();
 
   28     init_effect_details();
 
   32 void Shift::init_effect_details()
 
   40     info.
description = 
"Shift the image up, down, left, and right (with infinite wrapping).";
 
   47 std::shared_ptr<openshot::Frame> 
Shift::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
 
   50     std::shared_ptr<QImage> frame_image = frame->GetImage();
 
   51     unsigned char *pixels = (
unsigned char *) frame_image->bits();
 
   54     double x_shift = 
x.
GetValue(frame_number);
 
   55     double x_shift_limit = fmod(fabs(x_shift), 1.0);
 
   56     double y_shift = 
y.
GetValue(frame_number);
 
   57     double y_shift_limit = fmod(fabs(y_shift), 1.0);
 
   60     unsigned char *temp_row = 
new unsigned char[frame_image->width() * 4]();
 
   64     for (
int row = 0; row < frame_image->height(); row++) {
 
   66         int starting_row_pixel = row * frame_image->width();
 
   67         memcpy(temp_row, &pixels[starting_row_pixel * 4], 
sizeof(
char) * frame_image->width() * 4);
 
   72             int relative_pixel_start = (int)round(frame_image->width() * x_shift_limit);
 
   73             memcpy(&pixels[(starting_row_pixel + relative_pixel_start) * 4], &temp_row[0], 
sizeof(
char) * (frame_image->width() - relative_pixel_start) * 4);
 
   76             memcpy(&pixels[starting_row_pixel * 4], &temp_row[(frame_image->width() - relative_pixel_start) * 4], 
sizeof(
char) * relative_pixel_start * 4);
 
   77         } 
else if (x_shift < 0.0) {
 
   79             int relative_pixel_start = (int)round(frame_image->width() * x_shift_limit);
 
   80             memcpy(&pixels[starting_row_pixel * 4], &temp_row[relative_pixel_start * 4], 
sizeof(
char) * (frame_image->width() - relative_pixel_start) * 4);
 
   83             memcpy(&pixels[(starting_row_pixel + (frame_image->width() - relative_pixel_start)) * 4], &temp_row[0], 
sizeof(
char) * relative_pixel_start * 4);
 
   88     unsigned char *temp_image = 
new unsigned char[frame_image->width() * frame_image->height() * 4]();
 
   89     memcpy(temp_image, pixels, 
sizeof(
char) * frame_image->width() * frame_image->height() * 4);
 
   95         int relative_pixel_start = frame_image->width() * (int)round(frame_image->height() * y_shift_limit);
 
   96         memcpy(&pixels[relative_pixel_start * 4], temp_image, 
sizeof(
char) * ((frame_image->width() * frame_image->height()) - relative_pixel_start) * 4);
 
   99         memcpy(pixels, &temp_image[((frame_image->width() * frame_image->height()) - relative_pixel_start) * 4], 
sizeof(
char) * relative_pixel_start * 4);
 
  101     } 
else if (y_shift < 0.0) {
 
  103         int relative_pixel_start = frame_image->width() * (int)round(frame_image->height() * y_shift_limit);
 
  104         memcpy(pixels, &temp_image[relative_pixel_start * 4], 
sizeof(
char) * ((frame_image->width() * frame_image->height()) - relative_pixel_start) * 4);
 
  107         memcpy(&pixels[((frame_image->width() * frame_image->height()) - relative_pixel_start) * 4], temp_image, 
sizeof(
char) * relative_pixel_start * 4);
 
  148     catch (
const std::exception& e)
 
  151         throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
 
  162     if (!root[
"x"].isNull())
 
  164     if (!root[
"y"].isNull())
 
  179     return root.toStyledString();