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 = 0;
116 green_pixel_offset = 0;
117 blue_pixel_offset = 0;
118 alpha_pixel_offset = 0;
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())
250 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
251 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
253 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
254 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
255 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
271 return root.toStyledString();
Header file for Color Shift effect class.
Header file for all Exception classes.
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)
virtual float End() const
Get end position (in seconds) of clip (trim end of video)
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)
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)
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 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.