31 #include "../../include/effects/Blur.h" 36 Blur::Blur() : horizontal_radius(6.0), vertical_radius(6.0), sigma(3.0), iterations(3.0) {
38 init_effect_details();
47 init_effect_details();
51 void Blur::init_effect_details()
66 std::shared_ptr<Frame>
Blur::GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number)
69 std::shared_ptr<QImage> frame_image = frame->GetImage();
79 unsigned char *red =
new unsigned char[frame_image->width() * frame_image->height()]();
80 unsigned char *green =
new unsigned char[frame_image->width() * frame_image->height()]();
81 unsigned char *blue =
new unsigned char[frame_image->width() * frame_image->height()]();
82 unsigned char *alpha =
new unsigned char[frame_image->width() * frame_image->height()]();
84 unsigned char *blur_red =
new unsigned char[frame_image->width() * frame_image->height()]();
85 unsigned char *blur_green =
new unsigned char[frame_image->width() * frame_image->height()]();
86 unsigned char *blur_blue =
new unsigned char[frame_image->width() * frame_image->height()]();
87 unsigned char *blur_alpha =
new unsigned char[frame_image->width() * frame_image->height()]();
90 unsigned char *pixels = (
unsigned char *) frame_image->bits();
91 for (
int pixel = 0, byte_index=0; pixel < frame_image->width() * frame_image->height(); pixel++, byte_index+=4)
94 unsigned char R = pixels[byte_index];
95 unsigned char G = pixels[byte_index + 1];
96 unsigned char B = pixels[byte_index + 2];
97 unsigned char A = pixels[byte_index + 3];
107 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_red[i] = red[i];
108 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_green[i] = green[i];
109 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_blue[i] = blue[i];
110 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blur_alpha[i] = alpha[i];
113 for (
int iteration = 0; iteration < iteration_value; iteration++)
116 if (horizontal_radius_value > 0.0) {
118 int *bxs = initBoxes(sigma_value, horizontal_radius_value);
121 boxBlurH(red, blur_red, frame_image->width(), frame_image->height(), horizontal_radius_value);
122 boxBlurH(green, blur_green, frame_image->width(), frame_image->height(), horizontal_radius_value);
123 boxBlurH(blue, blur_blue, frame_image->width(), frame_image->height(), horizontal_radius_value);
124 boxBlurH(alpha, blur_alpha, frame_image->width(), frame_image->height(), horizontal_radius_value);
130 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) red[i] = blur_red[i];
131 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) green[i] = blur_green[i];
132 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blue[i] = blur_blue[i];
133 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) alpha[i] = blur_alpha[i];
137 if (vertical_radius_value > 0.0) {
139 int *bxs = initBoxes(sigma_value, vertical_radius_value);
142 boxBlurT(red, blur_red, frame_image->width(), frame_image->height(), vertical_radius_value);
143 boxBlurT(green, blur_green, frame_image->width(), frame_image->height(), vertical_radius_value);
144 boxBlurT(blue, blur_blue, frame_image->width(), frame_image->height(), vertical_radius_value);
145 boxBlurT(alpha, blur_alpha, frame_image->width(), frame_image->height(), vertical_radius_value);
151 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) red[i] = blur_red[i];
152 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) green[i] = blur_green[i];
153 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) blue[i] = blur_blue[i];
154 for (
int i = 0; i < (frame_image->width() * frame_image->height()); i++) alpha[i] = blur_alpha[i];
159 for (
int pixel = 0, byte_index=0; pixel < frame_image->width() * frame_image->height(); pixel++, byte_index+=4)
162 unsigned char R = blur_red[pixel];
163 unsigned char G = blur_green[pixel];
164 unsigned char B = blur_blue[pixel];
165 unsigned char A = blur_alpha[pixel];
168 pixels[byte_index] = R;
169 pixels[byte_index + 1] = G;
170 pixels[byte_index + 2] = B;
171 pixels[byte_index + 3] = A;
189 int* Blur::initBoxes(
float sigma,
int n)
191 float wIdeal = sqrt((12.0 *
sigma *
sigma / n) + 1.0);
192 int wl = floor(wIdeal);
193 if (wl % 2 == 0) wl--;
196 float mIdeal = (12.0 *
sigma *
sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4.0 * wl - 4);
197 int m = round(mIdeal);
199 int *sizes =
new int[n]();
200 for (
int i = 0; i < n; i++) sizes[i] = i < m ? wl : wu;
205 void Blur::boxBlurH(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
206 float iarr = 1.0 / (r + r + 1);
207 for (
int i = 0; i < h; i++) {
208 int ti = i * w, li = ti, ri = ti + r;
209 int fv = scl[ti], lv = scl[ti + w - 1], val = (r + 1) * fv;
210 for (
int j = 0; j < r; j++) val += scl[ti + j];
211 for (
int j = 0; j <= r; j++) {
212 val += scl[ri++] - fv;
213 tcl[ti++] = round(val * iarr);
215 for (
int j = r + 1; j < w - r; j++) {
216 val += scl[ri++] - scl[li++];
217 tcl[ti++] = round(val * iarr);
219 for (
int j = w - r; j < w; j++) {
220 val += lv - scl[li++];
221 tcl[ti++] = round(val * iarr);
226 void Blur::boxBlurT(
unsigned char *scl,
unsigned char *tcl,
int w,
int h,
int r) {
227 float iarr = 1.0 / (r + r + 1);
228 for (
int i = 0; i < w; i++) {
229 int ti = i, li = ti, ri = ti + r * w;
230 int fv = scl[ti], lv = scl[ti + w * (h - 1)], val = (r + 1) * fv;
231 for (
int j = 0; j < r; j++) val += scl[ti + j * w];
232 for (
int j = 0; j <= r; j++) {
234 tcl[ti] = round(val * iarr);
238 for (
int j = r + 1; j < h - r; j++) {
239 val += scl[ri] - scl[li];
240 tcl[ti] = round(val * iarr);
245 for (
int j = h - r; j < h; j++) {
247 tcl[ti] = round(val * iarr);
281 Json::CharReaderBuilder rbuilder;
282 Json::CharReader* reader(rbuilder.newCharReader());
285 bool success = reader->parse( value.c_str(),
286 value.c_str() + value.size(), &root, &errors );
291 throw InvalidJSON(
"JSON could not be parsed (or is invalid)");
298 catch (
const std::exception& e)
301 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
312 if (!root[
"horizontal_radius"].isNull())
314 if (!root[
"vertical_radius"].isNull())
316 if (!root[
"sigma"].isNull())
318 if (!root[
"iterations"].isNull())
327 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
328 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
330 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
331 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
332 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
341 return root.toStyledString();
std::string PropertiesJSON(int64_t requested_frame)
Json::Value JsonValue()
Generate Json::JsonValue for this object.
float End()
Get end position (in seconds) of clip (trim end of video)
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. ...
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
int GetInt(int64_t index) const
Get the rounded INT value at a specific index.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
bool has_audio
Determines if this effect manipulates the audio of a frame.
std::string Id()
Get basic properties.
float Position()
Get position on timeline (in seconds)
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.
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
std::string class_name
The class name of the effect.
Blur()
Blank constructor, useful when using Json to load the effect properties.
std::string name
The name of the effect.
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...
Json::Value add_property_json(std::string name, float value, std::string type, std::string memo, Keyframe *keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame)
Generate JSON for a property.
This namespace is the default namespace for all code in the openshot library.
Json::Value JsonValue() const
Generate Json::JsonValue 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.
std::string Json()
Get and Set JSON methods.
void SetJson(std::string value)
Load JSON string into this object.
Exception for invalid JSON.
double GetValue(int64_t index) const
Get the value at a specific index.
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.