19 ColorShift::ColorShift() : red_x(0.0), red_y(0.0), green_x(0.0), green_y(0.0), blue_x(0.0), blue_y(0.0), alpha_x(0.0), alpha_y(0.0) {
21 init_effect_details();
26 red_x(red_x), red_y(red_y), green_x(green_x), green_y(green_y), blue_x(blue_x), blue_y(blue_y), alpha_x(alpha_x), alpha_y(alpha_y)
29 init_effect_details();
33 void ColorShift::init_effect_details()
41 info.
description =
"Shift the colors of an image up, down, left, and right (with infinite wrapping).";
48 std::shared_ptr<openshot::Frame>
ColorShift::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
51 std::shared_ptr<QImage> frame_image = frame->GetImage();
52 unsigned char *pixels = (
unsigned char *) frame_image->bits();
55 int frame_image_width = frame_image->width();
56 int frame_image_height = frame_image->height();
61 int red_x_shift_limit = round(frame_image_width * fmod(fabs(red_x_shift), 1.0));
63 int red_y_shift_limit = round(frame_image_height * fmod(fabs(red_y_shift), 1.0));
66 int green_x_shift_limit = round(frame_image_width * fmod(fabs(green_x_shift), 1.0));
68 int green_y_shift_limit = round(frame_image_height * fmod(fabs(green_y_shift), 1.0));
71 int blue_x_shift_limit = round(frame_image_width * fmod(fabs(blue_x_shift), 1.0));
73 int blue_y_shift_limit = round(frame_image_height * fmod(fabs(blue_y_shift), 1.0));
76 int alpha_x_shift_limit = round(frame_image_width * fmod(fabs(alpha_x_shift), 1.0));
78 int alpha_y_shift_limit = round(frame_image_height * fmod(fabs(alpha_y_shift), 1.0));
81 unsigned char *temp_image =
new unsigned char[frame_image_width * frame_image_height * 4]();
82 memcpy(temp_image, pixels,
sizeof(
char) * frame_image_width * frame_image_height * 4);
85 int starting_row_index = 0;
94 int red_starting_row_index = 0;
95 int green_starting_row_index = 0;
96 int blue_starting_row_index = 0;
97 int alpha_starting_row_index = 0;
99 int red_pixel_offset = 0;
100 int green_pixel_offset = 0;
101 int blue_pixel_offset = 0;
102 int alpha_pixel_offset = 0;
105 for (
int row = 0; row < frame_image_height; row++) {
106 for (
int col = 0; col < frame_image_width; col++) {
108 starting_row_index = row * frame_image_width * 4;
109 byte_index = starting_row_index + (col * 4);
110 red_starting_row_index = starting_row_index;
111 green_starting_row_index = starting_row_index;
112 blue_starting_row_index = starting_row_index;
113 alpha_starting_row_index = starting_row_index;
115 red_pixel_offset = col;
116 green_pixel_offset = col;
117 blue_pixel_offset = col;
118 alpha_pixel_offset = col;
121 R = temp_image[byte_index];
122 G = temp_image[byte_index + 1];
123 B = temp_image[byte_index + 2];
124 A = temp_image[byte_index + 3];
127 if (red_x_shift > 0.0)
128 red_pixel_offset = (col + red_x_shift_limit) % frame_image_width;
129 if (red_x_shift < 0.0)
130 red_pixel_offset = (frame_image_width + col - red_x_shift_limit) % frame_image_width;
131 if (green_x_shift > 0.0)
132 green_pixel_offset = (col + green_x_shift_limit) % frame_image_width;
133 if (green_x_shift < 0.0)
134 green_pixel_offset = (frame_image_width + col - green_x_shift_limit) % frame_image_width;
135 if (blue_x_shift > 0.0)
136 blue_pixel_offset = (col + blue_x_shift_limit) % frame_image_width;
137 if (blue_x_shift < 0.0)
138 blue_pixel_offset = (frame_image_width + col - blue_x_shift_limit) % frame_image_width;
139 if (alpha_x_shift > 0.0)
140 alpha_pixel_offset = (col + alpha_x_shift_limit) % frame_image_width;
141 if (alpha_x_shift < 0.0)
142 alpha_pixel_offset = (frame_image_width + col - alpha_x_shift_limit) % frame_image_width;
145 if (red_y_shift > 0.0)
146 red_starting_row_index = ((row + red_y_shift_limit) % frame_image_height) * frame_image_width * 4;
147 if (red_y_shift < 0.0)
148 red_starting_row_index = ((frame_image_height + row - red_y_shift_limit) % frame_image_height) * frame_image_width * 4;
149 if (green_y_shift > 0.0)
150 green_starting_row_index = ((row + green_y_shift_limit) % frame_image_height) * frame_image_width * 4;
151 if (green_y_shift < 0.0)
152 green_starting_row_index = ((frame_image_height + row - green_y_shift_limit) % frame_image_height) * frame_image_width * 4;
153 if (blue_y_shift > 0.0)
154 blue_starting_row_index = ((row + blue_y_shift_limit) % frame_image_height) * frame_image_width * 4;
155 if (blue_y_shift < 0.0)
156 blue_starting_row_index = ((frame_image_height + row - blue_y_shift_limit) % frame_image_height) * frame_image_width * 4;
157 if (alpha_y_shift > 0.0)
158 alpha_starting_row_index = ((row + alpha_y_shift_limit) % frame_image_height) * frame_image_width * 4;
159 if (alpha_y_shift < 0.0)
160 alpha_starting_row_index = ((frame_image_height + row - alpha_y_shift_limit) % frame_image_height) * frame_image_width * 4;
163 pixels[red_starting_row_index + 0 + (red_pixel_offset * 4)] = R;
164 pixels[green_starting_row_index + 1 + (green_pixel_offset * 4)] = G;
165 pixels[blue_starting_row_index + 2 + (blue_pixel_offset * 4)] = B;
166 pixels[alpha_starting_row_index + 3 + (alpha_pixel_offset * 4)] = A;
213 catch (
const std::exception& e)
216 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
227 if (!root[
"red_x"].isNull())
229 if (!root[
"red_y"].isNull())
231 if (!root[
"green_x"].isNull())
233 if (!root[
"green_y"].isNull())
235 if (!root[
"blue_x"].isNull())
237 if (!root[
"blue_y"].isNull())
239 if (!root[
"alpha_x"].isNull())
241 if (!root[
"alpha_y"].isNull())
262 return root.toStyledString();