37ColorShift::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) {
39 init_effect_details();
44 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)
47 init_effect_details();
51void ColorShift::init_effect_details()
59 info.
description =
"Shift the colors of an image up, down, left, and right (with infinite wrapping).";
66std::shared_ptr<openshot::Frame>
ColorShift::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
69 std::shared_ptr<QImage> frame_image = frame->GetImage();
70 unsigned char *pixels = (
unsigned char *) frame_image->bits();
73 int frame_image_width = frame_image->width();
74 int frame_image_height = frame_image->height();
79 int red_x_shift_limit = round(frame_image_width * fmod(fabs(red_x_shift), 1.0));
81 int red_y_shift_limit = round(frame_image_height * fmod(fabs(red_y_shift), 1.0));
84 int green_x_shift_limit = round(frame_image_width * fmod(fabs(green_x_shift), 1.0));
86 int green_y_shift_limit = round(frame_image_height * fmod(fabs(green_y_shift), 1.0));
89 int blue_x_shift_limit = round(frame_image_width * fmod(fabs(blue_x_shift), 1.0));
91 int blue_y_shift_limit = round(frame_image_height * fmod(fabs(blue_y_shift), 1.0));
94 int alpha_x_shift_limit = round(frame_image_width * fmod(fabs(alpha_x_shift), 1.0));
96 int alpha_y_shift_limit = round(frame_image_height * fmod(fabs(alpha_y_shift), 1.0));
99 unsigned char *temp_image =
new unsigned char[frame_image_width * frame_image_height * 4]();
100 memcpy(temp_image, pixels,
sizeof(
char) * frame_image_width * frame_image_height * 4);
103 int starting_row_index = 0;
112 int red_starting_row_index = 0;
113 int green_starting_row_index = 0;
114 int blue_starting_row_index = 0;
115 int alpha_starting_row_index = 0;
117 int red_pixel_offset = 0;
118 int green_pixel_offset = 0;
119 int blue_pixel_offset = 0;
120 int alpha_pixel_offset = 0;
123 for (
int row = 0; row < frame_image_height; row++) {
124 for (
int col = 0; col < frame_image_width; col++) {
126 starting_row_index = row * frame_image_width * 4;
127 byte_index = starting_row_index + (col * 4);
128 red_starting_row_index = starting_row_index;
129 green_starting_row_index = starting_row_index;
130 blue_starting_row_index = starting_row_index;
131 alpha_starting_row_index = starting_row_index;
133 red_pixel_offset = 0;
134 green_pixel_offset = 0;
135 blue_pixel_offset = 0;
136 alpha_pixel_offset = 0;
139 R = temp_image[byte_index];
140 G = temp_image[byte_index + 1];
141 B = temp_image[byte_index + 2];
142 A = temp_image[byte_index + 3];
145 if (red_x_shift > 0.0)
146 red_pixel_offset = (col + red_x_shift_limit) % frame_image_width;
147 if (red_x_shift < 0.0)
148 red_pixel_offset = (frame_image_width + col - red_x_shift_limit) % frame_image_width;
149 if (green_x_shift > 0.0)
150 green_pixel_offset = (col + green_x_shift_limit) % frame_image_width;
151 if (green_x_shift < 0.0)
152 green_pixel_offset = (frame_image_width + col - green_x_shift_limit) % frame_image_width;
153 if (blue_x_shift > 0.0)
154 blue_pixel_offset = (col + blue_x_shift_limit) % frame_image_width;
155 if (blue_x_shift < 0.0)
156 blue_pixel_offset = (frame_image_width + col - blue_x_shift_limit) % frame_image_width;
157 if (alpha_x_shift > 0.0)
158 alpha_pixel_offset = (col + alpha_x_shift_limit) % frame_image_width;
159 if (alpha_x_shift < 0.0)
160 alpha_pixel_offset = (frame_image_width + col - alpha_x_shift_limit) % frame_image_width;
163 if (red_y_shift > 0.0)
164 red_starting_row_index = ((row + red_y_shift_limit) % frame_image_height) * frame_image_width * 4;
165 if (red_y_shift < 0.0)
166 red_starting_row_index = ((frame_image_height + row - red_y_shift_limit) % frame_image_height) * frame_image_width * 4;
167 if (green_y_shift > 0.0)
168 green_starting_row_index = ((row + green_y_shift_limit) % frame_image_height) * frame_image_width * 4;
169 if (green_y_shift < 0.0)
170 green_starting_row_index = ((frame_image_height + row - green_y_shift_limit) % frame_image_height) * frame_image_width * 4;
171 if (blue_y_shift > 0.0)
172 blue_starting_row_index = ((row + blue_y_shift_limit) % frame_image_height) * frame_image_width * 4;
173 if (blue_y_shift < 0.0)
174 blue_starting_row_index = ((frame_image_height + row - blue_y_shift_limit) % frame_image_height) * frame_image_width * 4;
175 if (alpha_y_shift > 0.0)
176 alpha_starting_row_index = ((row + alpha_y_shift_limit) % frame_image_height) * frame_image_width * 4;
177 if (alpha_y_shift < 0.0)
178 alpha_starting_row_index = ((frame_image_height + row - alpha_y_shift_limit) % frame_image_height) * frame_image_width * 4;
181 pixels[red_starting_row_index + 0 + (red_pixel_offset * 4)] = R;
182 pixels[green_starting_row_index + 1 + (green_pixel_offset * 4)] = G;
183 pixels[blue_starting_row_index + 2 + (blue_pixel_offset * 4)] = B;
184 pixels[alpha_starting_row_index + 3 + (alpha_pixel_offset * 4)] = A;
231 catch (
const std::exception& e)
234 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
245 if (!root[
"red_x"].isNull())
247 if (!root[
"red_y"].isNull())
249 if (!root[
"green_x"].isNull())
251 if (!root[
"green_y"].isNull())
253 if (!root[
"blue_x"].isNull())
255 if (!root[
"blue_y"].isNull())
257 if (!root[
"alpha_x"].isNull())
259 if (!root[
"alpha_y"].isNull())
268 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
269 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
271 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
272 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
273 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
289 return root.toStyledString();
Header file for Color Shift effect class.
Header file for all Exception classes.
float End() const
Get end position (in seconds) of clip (trim end of video)
float Start() const
Get start position (in seconds) of clip (trim start of video)
float Duration() const
Get the length of this clip (in seconds)
std::string Id() const
Get the Id of this clip object.
int Layer() const
Get layer of clip on timeline (lower number is covered by higher numbers)
float Position() const
Get position on timeline (in seconds)
Json::Value add_property_json(std::string name, float value, std::string type, std::string memo, const Keyframe *keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame) const
Generate JSON for a property.
Keyframe blue_x
Shift the Blue X coordinates (left or right)
std::string Json() const override
Generate JSON string of this object.
Keyframe red_y
Shift the Red Y coordinates (up or down)
Keyframe alpha_y
Shift the Alpha Y coordinates (up or down)
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number) override
This method is required for all derived classes of ClipBase, and returns a new openshot::Frame object...
void SetJson(const std::string value) override
Load JSON string into this object.
std::string PropertiesJSON(int64_t requested_frame) const override
Keyframe green_y
Shift the Green Y coordinates (up or down)
Keyframe alpha_x
Shift the Alpha X coordinates (left or right)
Json::Value JsonValue() const override
Generate Json::Value for this object.
Keyframe red_x
Shift the Red X coordinates (left or right)
Keyframe green_x
Shift the Green X coordinates (left or right)
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Keyframe blue_y
Shift the Blue Y coordinates (up or down)
ColorShift()
Blank constructor, useful when using Json to load the effect properties.
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
EffectInfoStruct info
Information about the current effect.
Exception for invalid JSON.
A Keyframe is a collection of Point instances, which is used to vary a number or property over time.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
double GetValue(int64_t index) const
Get the value at a specific index.
Json::Value JsonValue() const
Generate Json::Value for this object.
This namespace is the default namespace for all code in the openshot library.
const Json::Value stringToJson(const std::string value)
bool has_video
Determines if this effect manipulates the image of a frame.
std::string parent_effect_id
Id of the parent effect (if there is one)
bool has_audio
Determines if this effect manipulates the audio of a frame.
std::string class_name
The class name of the effect.
std::string name
The name of the effect.
std::string description
The description of this effect and what it does.