28 #include "../../include/effects/Blur.h" 33 Blur::Blur() : horizontal_radius(6.0), vertical_radius(6.0), sigma(3.0), iterations(3.0) {
35 init_effect_details();
44 init_effect_details();
48 void Blur::init_effect_details()
63 std::shared_ptr<Frame>
Blur::GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number)
66 std::shared_ptr<QImage> frame_image = frame->GetImage();
76 unsigned char *red =
new unsigned char[frame_image->width() * frame_image->height()]();
77 unsigned char *green =
new unsigned char[frame_image->width() * frame_image->height()]();
78 unsigned char *blue =
new unsigned char[frame_image->width() * frame_image->height()]();
79 unsigned char *alpha =
new unsigned char[frame_image->width() * frame_image->height()]();
81 unsigned char *blur_red =
new unsigned char[frame_image->width() * frame_image->height()]();
82 unsigned char *blur_green =
new unsigned char[frame_image->width() * frame_image->height()]();
83 unsigned char *blur_blue =
new unsigned char[frame_image->width() * frame_image->height()]();
84 unsigned char *blur_alpha =
new unsigned char[frame_image->width() * frame_image->height()]();
87 unsigned char *pixels = (
unsigned char *) frame_image->bits();
88 for (
int pixel = 0, byte_index=0; pixel < frame_image->width() * frame_image->height(); pixel++, byte_index+=4)
91 unsigned char R = pixels[byte_index];
92 unsigned char G = pixels[byte_index + 1];
93 unsigned char B = pixels[byte_index + 2];
94 unsigned char A = pixels[byte_index + 3];
104 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_red[i] = red[i];
105 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_green[i] = green[i];
106 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_blue[i] = blue[i];
107 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_alpha[i] = alpha[i];
110 for (
int iteration = 0; iteration < iteration_value; iteration++)
113 if (horizontal_radius_value > 0.0) {
115 int *bxs = initBoxes(sigma_value, horizontal_radius_value);
118 boxBlurH(red, blur_red, frame_image->width(), frame_image->height(), horizontal_radius_value);
119 boxBlurH(green, blur_green, frame_image->width(), frame_image->height(), horizontal_radius_value);
120 boxBlurH(blue, blur_blue, frame_image->width(), frame_image->height(), horizontal_radius_value);
121 boxBlurH(alpha, blur_alpha, frame_image->width(), frame_image->height(), horizontal_radius_value);
128 if (vertical_radius_value > 0.0) {
130 int *bxs = initBoxes(sigma_value, vertical_radius_value);
133 boxBlurT(red, blur_red, frame_image->width(), frame_image->height(), vertical_radius_value);
134 boxBlurT(green, blur_green, frame_image->width(), frame_image->height(), vertical_radius_value);
135 boxBlurT(blue, blur_blue, frame_image->width(), frame_image->height(), vertical_radius_value);
136 boxBlurT(alpha, blur_alpha, frame_image->width(), frame_image->height(), vertical_radius_value);
144 for (
int pixel = 0, byte_index=0; pixel < frame_image->width() * frame_image->height(); pixel++, byte_index+=4)
147 unsigned char R = blur_red[pixel];
148 unsigned char G = blur_green[pixel];
149 unsigned char B = blur_blue[pixel];
150 unsigned char A = blur_alpha[pixel];
153 pixels[byte_index] = R;
154 pixels[byte_index + 1] = G;
155 pixels[byte_index + 2] = B;
156 pixels[byte_index + 3] = A;
174 int* Blur::initBoxes(
float sigma,
int n)
176 float wIdeal = sqrt((12.0 *
sigma *
sigma / n) + 1.0);
177 int wl = floor(wIdeal);
178 if (wl % 2 == 0) wl--;
181 float mIdeal = (12.0 *
sigma *
sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4.0 * wl - 4);
182 int m = round(mIdeal);
184 int *sizes =
new int[n]();
185 for (
int i = 0; i < n; i++) sizes[i] = i < m ? wl : wu;
190 void Blur::boxBlurH(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
191 float iarr = 1.0 / (r + r + 1);
192 for (
int i = 0; i < h; i++) {
193 int ti = i * w, li = ti, ri = ti + r;
194 int fv = scl[ti], lv = scl[ti + w - 1], val = (r + 1) * fv;
195 for (
int j = 0; j < r; j++) val += scl[ti + j];
196 for (
int j = 0; j <= r; j++) {
197 val += scl[ri++] - fv;
198 tcl[ti++] = round(val * iarr);
200 for (
int j = r + 1; j < w - r; j++) {
201 val += scl[ri++] - scl[li++];
202 tcl[ti++] = round(val * iarr);
204 for (
int j = w - r; j < w; j++) {
205 val += lv - scl[li++];
206 tcl[ti++] = round(val * iarr);
211 void Blur::boxBlurT(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
212 float iarr = 1.0 / (r + r + 1);
213 for (
int i = 0; i < w; i++) {
214 int ti = i, li = ti, ri = ti + r * w;
215 int fv = scl[ti], lv = scl[ti + w * (h - 1)], val = (r + 1) * fv;
216 for (
int j = 0; j < r; j++) val += scl[ti + j * w];
217 for (
int j = 0; j <= r; j++) {
219 tcl[ti] = round(val * iarr);
223 for (
int j = r + 1; j < h - r; j++) {
224 val += scl[ri] - scl[li];
225 tcl[ti] = round(val * iarr);
230 for (
int j = h - r; j < h; j++) {
232 tcl[ti] = round(val * iarr);
267 bool success = reader.parse( value, root );
270 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
280 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
291 if (!root[
"horizontal_radius"].isNull())
293 else if (!root[
"vertical_radius"].isNull())
295 else if (!root[
"sigma"].isNull())
297 else if (!root[
"iterations"].isNull())
306 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
307 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
309 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
310 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
311 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
320 return root.toStyledString();
string Json()
Get and Set JSON methods.
Json::Value JsonValue()
Generate Json::JsonValue for this object.
Json::Value JsonValue()
Generate Json::JsonValue for this object.
string PropertiesJSON(int64_t requested_frame)
float End()
Get end position (in seconds) of clip (trim end of video)
Json::Value add_property_json(string name, float value, string type, string memo, Keyframe *keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame)
Generate JSON for a property.
int Layer()
Get layer of clip on timeline (lower number is covered by higher numbers)
Keyframe iterations
Iterations keyframe. The # of blur iterations per pixel. 3 iterations = Gaussian. ...
string class_name
The class name of the effect.
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
bool has_audio
Determines if this effect manipulates the audio of a frame.
string Id()
Get basic properties.
float Position()
Get position on timeline (in seconds)
string name
The name of the effect.
Keyframe vertical_radius
Vertical blur radius keyframe. The size of the vertical blur operation in pixels. ...
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
string description
The description of this effect and what it does.
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
int GetInt(int64_t index)
Get the rounded INT value at a specific index.
Blur()
Blank constructor, useful when using Json to load the effect properties.
void SetJson(string value)
Load JSON string into this object.
std::shared_ptr< Frame > GetFrame(std::shared_ptr< Frame > frame, int64_t frame_number)
This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame...
double GetValue(int64_t index)
Get the value at a specific index.
This namespace is the default namespace for all code in the openshot library.
bool has_video
Determines if this effect manipulates the image of a frame.
Exception for invalid JSON.
A Keyframe is a collection of Point instances, which is used to vary a number or property over time...
float Duration()
Get the length of this clip (in seconds)
Keyframe sigma
Sigma keyframe. The amount of spread in the blur operation. Should be larger than radius...
float Start()
Get start position (in seconds) of clip (trim start of video)
Keyframe horizontal_radius
Horizontal blur radius keyframe. The size of the horizontal blur operation in pixels.
EffectInfoStruct info
Information about the current effect.