32 init_effect_details();
44 init_effect_details();
48void Sharpen::init_effect_details()
53 info.
description =
"Boost edge contrast to make video details look crisper.";
65 std::shared_ptr<QImage> mask_image, int64_t frame_number)
const
78 #pragma omp parallel for schedule(static)
80 const int idx =
i * 4;
98static void boxes_for_gauss(
double sigma,
int b[3])
101 double wi = std::sqrt((12.0 * sigma * sigma / n) + 1.0);
102 int wl = int(std::floor(wi));
105 double mi = (12.0 * sigma * sigma - n*wl*wl - 4.0*n*wl - 3.0*n)
107 int m = int(std::round(mi));
108 for (
int i = 0; i < n; ++i)
109 b[i] = i < m ? wl : wu;
113static void blur_axis(
const QImage& src, QImage& dst,
int r,
bool vertical)
121 int H = src.height();
122 int bpl = src.bytesPerLine();
123 const uchar* in = src.bits();
124 uchar* out = dst.bits();
125 int window = 2*r + 1;
128 #pragma omp parallel for
129 for (
int y = 0; y < H; ++y) {
130 const uchar* rowIn = in + y*bpl;
131 uchar* rowOut = out + y*bpl;
132 double sB = rowIn[0]*(r+1), sG = rowIn[1]*(r+1),
133 sR = rowIn[2]*(r+1), sA = rowIn[3]*(r+1);
134 for (
int x = 1; x <= r; ++x) {
135 const uchar* p = rowIn + std::min(x, W-1)*4;
136 sB += p[0]; sG += p[1]; sR += p[2]; sA += p[3];
138 for (
int x = 0; x < W; ++x) {
139 uchar* o = rowOut + x*4;
140 o[0] = uchar(sB / window + 0.5);
141 o[1] = uchar(sG / window + 0.5);
142 o[2] = uchar(sR / window + 0.5);
143 o[3] = uchar(sA / window + 0.5);
145 const uchar* addP = rowIn + std::min(x+r+1, W-1)*4;
146 const uchar* subP = rowIn + std::max(x-r, 0)*4;
147 sB += addP[0] - subP[0];
148 sG += addP[1] - subP[1];
149 sR += addP[2] - subP[2];
150 sA += addP[3] - subP[3];
155 #pragma omp parallel for
156 for (
int x = 0; x < W; ++x) {
157 double sB = 0, sG = 0, sR = 0, sA = 0;
158 const uchar* p0 = in + x*4;
159 sB = p0[0]*(r+1); sG = p0[1]*(r+1);
160 sR = p0[2]*(r+1); sA = p0[3]*(r+1);
161 for (
int y = 1; y <= r; ++y) {
162 const uchar* p = in + std::min(y, H-1)*bpl + x*4;
163 sB += p[0]; sG += p[1]; sR += p[2]; sA += p[3];
165 for (
int y = 0; y < H; ++y) {
166 uchar* o = out + y*bpl + x*4;
167 o[0] = uchar(sB / window + 0.5);
168 o[1] = uchar(sG / window + 0.5);
169 o[2] = uchar(sR / window + 0.5);
170 o[3] = uchar(sA / window + 0.5);
172 const uchar* addP = in + std::min(y+r+1, H-1)*bpl + x*4;
173 const uchar* subP = in + std::max(y-r, 0)*bpl + x*4;
174 sB += addP[0] - subP[0];
175 sG += addP[1] - subP[1];
176 sR += addP[2] - subP[2];
177 sA += addP[3] - subP[3];
184static void box_blur(
const QImage& src, QImage& dst,
double rf,
bool vertical)
186 int r0 = int(std::floor(rf));
190 blur_axis(src, dst, r0, vertical);
193 QImage a(src.size(), QImage::Format_ARGB32);
194 QImage b(src.size(), QImage::Format_ARGB32);
195 blur_axis(src, a, r0, vertical);
196 blur_axis(src, b, r1, vertical);
198 int pixels = src.width() * src.height();
199 const uchar* pa = a.bits();
200 const uchar* pb = b.bits();
201 uchar* pd = dst.bits();
202 #pragma omp parallel for
203 for (
int i = 0; i < pixels; ++i) {
204 for (
int c = 0; c < 4; ++c) {
205 pd[i*4+c] = uchar((1.0 - f) * pa[i*4+c]
214static void gauss_blur(
const QImage& src, QImage& dst,
double sigma)
217 boxes_for_gauss(sigma, b);
218 QImage t1(src.size(), QImage::Format_ARGB32);
219 QImage t2(src.size(), QImage::Format_ARGB32);
221 double r = 0.5 * (b[0] - 1);
222 box_blur(src , t1, r,
false);
223 box_blur(t1, t2, r,
true);
225 r = 0.5 * (b[1] - 1);
226 box_blur(t2, t1, r,
false);
227 box_blur(t1, t2, r,
true);
229 r = 0.5 * (b[2] - 1);
230 box_blur(t2, t1, r,
false);
231 box_blur(t1, dst, r,
true);
236 std::shared_ptr<Frame> frame, int64_t frame_number)
238 auto img = frame->GetImage();
239 if (!
img ||
img->isNull())
241 if (
img->format() != QImage::Format_ARGB32)
242 *
img =
img->convertToFormat(QImage::Format_ARGB32);
244 int W =
img->width();
245 int H =
img->height();
246 if (
W <= 0 ||
H <= 0)
255 double sigma = std::max(0.1,
rpx *
H / 720.0);
262 int bplS =
img->bytesPerLine();
268 #pragma omp parallel for reduction(max:maxDY)
269 for (
int y = 0; y <
H; ++y) {
272 for (
int x = 0; x <
W; ++x) {
276 double dY = std::abs(0.114*
dB + 0.587*
dG + 0.299*
dR);
285 #pragma omp parallel for
286 for (
int y = 0; y <
H; ++y) {
289 for (
int x = 0; x <
W; ++x) {
297 double dY = 0.114*
dB + 0.587*
dG + 0.299*
dR;
300 if (std::abs(
dY) <
thr)
304 auto halo = [](
double d) {
305 return (255.0 - std::abs(
d)) / 255.0;
316 const double wB = 0.114,
wG = 0.587,
wR = 0.299;
347 for (
int c = 0;
c < 3; ++
c)
354 for (
int c = 0;
c < 3; ++
c)
366 for (
int c = 0;
c < 3; ++
c) {
429 "Mode",
mode,
"int",
"",
nullptr, 0, 1,
false, t);
433 "Channel",
channel,
"int",
"",
nullptr, 0, 2,
false, t);
438 "Mask Mode",
mask_mode,
"int",
"",
nullptr, 0, 1,
false, t);
441 return root.toStyledString();
Header file for all Exception classes.
Header file for Sharpen effect class.
Json::Value add_property_choice_json(std::string name, int value, int selected_value) const
Generate JSON choice for a property (dropdown properties)
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.
bool mask_invert
Invert grayscale mask values before blending.
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
Json::Value BasePropertiesJSON(int64_t requested_frame) const
Generate JSON object of base properties (recommended to be used by all effects)
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
EffectInfoStruct info
Information about the current effect.
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.
int mode
Sharpening mode (0 = UnsharpMask, 1 = HighPassBlend)
std::string Json() const override
Get and Set JSON methods.
Keyframe radius
Radius of the blur used in sharpening (0 to 10 pixels for 1080p)
std::shared_ptr< Frame > GetFrame(std::shared_ptr< Frame > frame, int64_t frame_number) override
This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame...
Json::Value JsonValue() const override
Generate Json::Value for this object.
int mask_mode
Mask behavior mode for this effect.
Sharpen()
Default constructor.
void ApplyCustomMaskBlend(std::shared_ptr< QImage > original_image, std::shared_ptr< QImage > effected_image, std::shared_ptr< QImage > mask_image, int64_t frame_number) const override
Optional override for effects with custom mask implementation.
void SetJson(const std::string value) override
Load JSON string into this object.
int channel
Channel to apply sharpening to (0 = All, 1 = Luma, 2 = Chroma)
bool UseCustomMaskBlend(int64_t frame_number) const override
Optional override for effects that need custom mask behavior.
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Keyframe amount
Amount of sharpening to apply (0 to 2)
std::string PropertiesJSON(int64_t requested_frame) const override
Keyframe threshold
Threshold for applying sharpening (0 to 1)
This namespace is the default namespace for all code in the openshot library.
@ SHARPEN_MASK_LIMIT_TO_AREA
@ SHARPEN_MASK_VARY_STRENGTH
const Json::Value stringToJson(const std::string value)
bool has_video
Determines if this effect manipulates the image of a frame.
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.