37 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) {
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();
51 void ColorShift::init_effect_details()
59 info.
description =
"Shift the colors of an image up, down, left, and right (with infinite wrapping).";
66 std::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();
Keyframe alpha_y
Shift the Alpha Y coordinates (up or down)
std::string Id() const
Get the Id of this clip object.
Keyframe red_x
Shift the Red X coordinates (left or right)
float Start() const
Get start position (in seconds) of clip (trim start of video)
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
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.
Keyframe blue_x
Shift the Blue X coordinates (left or right)
Keyframe green_y
Shift the Green Y coordinates (up or down)
Keyframe green_x
Shift the Green X coordinates (left or right)
std::string PropertiesJSON(int64_t requested_frame) const override
const Json::Value stringToJson(const std::string value)
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
Header file for Color Shift effect class.
bool has_audio
Determines if this effect manipulates the audio of a frame.
Header file for all Exception classes.
Keyframe alpha_x
Shift the Alpha X coordinates (left or right)
Keyframe red_y
Shift the Red Y coordinates (up or down)
Json::Value JsonValue() const override
Generate Json::Value for this object.
std::string class_name
The class name of the effect.
std::string name
The name of the effect.
float Duration() const
Get the length of this clip (in seconds)
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
This namespace is the default namespace for all code in the openshot library.
Json::Value JsonValue() const
Generate Json::Value for this object.
std::string description
The description of this effect and what it does.
bool has_video
Determines if this effect manipulates the image of a frame.
Exception for invalid JSON.
double GetValue(int64_t index) const
Get the value at a specific index.
std::string Json() const override
Generate JSON string of this object.
std::string parent_effect_id
Id of the parent effect (if there is one)
float Position() const
Get position on timeline (in seconds)
float End() const
Get end position (in seconds) of clip (trim end of video)
A Keyframe is a collection of Point instances, which is used to vary a number or property over time...
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.
int Layer() const
Get layer of clip on timeline (lower number is covered by higher numbers)
EffectInfoStruct info
Information about the current effect.
Keyframe blue_y
Shift the Blue Y coordinates (up or down)
ColorShift()
Blank constructor, useful when using Json to load the effect properties.