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();
40 horizontal_radius(new_horizontal_radius), vertical_radius(new_vertical_radius),
41 sigma(new_sigma), iterations(new_iterations)
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);
127 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) red[i] = blur_red[i];
128 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) green[i] = blur_green[i];
129 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blue[i] = blur_blue[i];
130 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) alpha[i] = blur_alpha[i];
134 if (vertical_radius_value > 0.0) {
136 int *bxs = initBoxes(sigma_value, vertical_radius_value);
139 boxBlurT(red, blur_red, frame_image->width(), frame_image->height(), vertical_radius_value);
140 boxBlurT(green, blur_green, frame_image->width(), frame_image->height(), vertical_radius_value);
141 boxBlurT(blue, blur_blue, frame_image->width(), frame_image->height(), vertical_radius_value);
142 boxBlurT(alpha, blur_alpha, frame_image->width(), frame_image->height(), vertical_radius_value);
148 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) red[i] = blur_red[i];
149 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) green[i] = blur_green[i];
150 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blue[i] = blur_blue[i];
151 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) alpha[i] = blur_alpha[i];
156 for (
int pixel = 0, byte_index=0; pixel < frame_image->width() * frame_image->height(); pixel++, byte_index+=4)
159 unsigned char R = blur_red[pixel];
160 unsigned char G = blur_green[pixel];
161 unsigned char B = blur_blue[pixel];
162 unsigned char A = blur_alpha[pixel];
165 pixels[byte_index] = R;
166 pixels[byte_index + 1] = G;
167 pixels[byte_index + 2] = B;
168 pixels[byte_index + 3] = A;
186 int* Blur::initBoxes(
float sigma,
int n)
188 float wIdeal = sqrt((12.0 * sigma * sigma / n) + 1.0);
189 int wl = floor(wIdeal);
190 if (wl % 2 == 0) wl--;
193 float mIdeal = (12.0 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4.0 * wl - 4);
194 int m = round(mIdeal);
196 int *sizes =
new int[n]();
197 for (
int i = 0; i < n; i++) sizes[i] = i < m ? wl : wu;
202 void Blur::boxBlurH(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
203 float iarr = 1.0 / (r + r + 1);
204 for (
int i = 0; i < h; i++) {
205 int ti = i * w, li = ti, ri = ti + r;
206 int fv = scl[ti], lv = scl[ti + w - 1], val = (r + 1) * fv;
207 for (
int j = 0; j < r; j++) val += scl[ti + j];
208 for (
int j = 0; j <= r; j++) {
209 val += scl[ri++] - fv;
210 tcl[ti++] = round(val * iarr);
212 for (
int j = r + 1; j < w - r; j++) {
213 val += scl[ri++] - scl[li++];
214 tcl[ti++] = round(val * iarr);
216 for (
int j = w - r; j < w; j++) {
217 val += lv - scl[li++];
218 tcl[ti++] = round(val * iarr);
223 void Blur::boxBlurT(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
224 float iarr = 1.0 / (r + r + 1);
225 for (
int i = 0; i < w; i++) {
226 int ti = i, li = ti, ri = ti + r * w;
227 int fv = scl[ti], lv = scl[ti + w * (h - 1)], val = (r + 1) * fv;
228 for (
int j = 0; j < r; j++) val += scl[ti + j * w];
229 for (
int j = 0; j <= r; j++) {
231 tcl[ti] = round(val * iarr);
235 for (
int j = r + 1; j < h - r; j++) {
236 val += scl[ri] - scl[li];
237 tcl[ti] = round(val * iarr);
242 for (
int j = h - r; j < h; j++) {
244 tcl[ti] = round(val * iarr);
266 root[
"sigma"] = sigma.JsonValue();
279 bool success = reader.parse( value, root );
282 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
292 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
303 if (!root[
"horizontal_radius"].isNull())
305 if (!root[
"vertical_radius"].isNull())
307 if (!root[
"sigma"].isNull())
308 sigma.SetJsonValue(root[
"sigma"]);
309 if (!root[
"iterations"].isNull())
318 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
319 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
321 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
322 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
323 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
328 root[
"sigma"] =
add_property_json(
"Sigma", sigma.GetValue(requested_frame),
"float",
"", &
sigma, 0, 100,
false, requested_frame);
332 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.