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;
126 const float inv_w = 1.0f / window;
129 #pragma omp parallel for
130 for (
int y = 0; y < H; ++y) {
131 const uchar* rowIn = in + y*bpl;
132 uchar* rowOut = out + y*bpl;
133 int sB = rowIn[0]*(r+1), sG = rowIn[1]*(r+1), sR = rowIn[2]*(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];
138 for (
int x = 0; x < W; ++x) {
139 uchar* o = rowOut + x*4;
140 o[0] = uchar(sB * inv_w + 0.5f);
141 o[1] = uchar(sG * inv_w + 0.5f);
142 o[2] = uchar(sR * inv_w + 0.5f);
144 const uchar* addP = rowIn + std::min(x+r+1, W-1)*4;
145 const uchar* subP = rowIn + std::max(x-r, 0)*4;
146 sB += addP[0] - subP[0];
147 sG += addP[1] - subP[1];
148 sR += addP[2] - subP[2];
153 #pragma omp parallel for
154 for (
int x = 0; x < W; ++x) {
155 const uchar* p0 = in + x*4;
156 int sB = p0[0]*(r+1), sG = p0[1]*(r+1), sR = p0[2]*(r+1);
157 for (
int y = 1; y <= r; ++y) {
158 const uchar* p = in + std::min(y, H-1)*bpl + x*4;
159 sB += p[0]; sG += p[1]; sR += p[2];
161 for (
int y = 0; y < H; ++y) {
162 uchar* o = out + y*bpl + x*4;
163 o[0] = uchar(sB * inv_w + 0.5f);
164 o[1] = uchar(sG * inv_w + 0.5f);
165 o[2] = uchar(sR * inv_w + 0.5f);
167 const uchar* addP = in + std::min(y+r+1, H-1)*bpl + x*4;
168 const uchar* subP = in + std::max(y-r, 0)*bpl + x*4;
169 sB += addP[0] - subP[0];
170 sG += addP[1] - subP[1];
171 sR += addP[2] - subP[2];
178static void box_blur(
const QImage& src, QImage& dst,
double rf,
bool vertical)
180 int r0 = int(std::floor(rf));
184 blur_axis(src, dst, r0, vertical);
187 QImage a(src.size(), QImage::Format_ARGB32);
188 QImage b(src.size(), QImage::Format_ARGB32);
189 blur_axis(src, a, r0, vertical);
190 blur_axis(src, b, r1, vertical);
192 int pixels = src.width() * src.height();
193 const uchar* pa = a.bits();
194 const uchar* pb = b.bits();
195 uchar* pd = dst.bits();
196 const float ff = float(f);
197 const float ff1 = 1.0f - ff;
198 #pragma omp parallel for
199 for (
int i = 0; i < pixels; ++i) {
200 for (
int c = 0; c < 3; ++c) {
201 pd[i*4+c] = uchar(ff1 * pa[i*4+c] + ff * pb[i*4+c] + 0.5f);
208static void gauss_blur(
const QImage& src, QImage& dst,
double sigma)
211 boxes_for_gauss(sigma, b);
212 QImage t1(src.size(), QImage::Format_ARGB32);
213 QImage t2(src.size(), QImage::Format_ARGB32);
215 double r = 0.5 * (b[0] - 1);
216 box_blur(src , t1, r,
false);
217 box_blur(t1, t2, r,
true);
219 r = 0.5 * (b[1] - 1);
220 box_blur(t2, t1, r,
false);
221 box_blur(t1, t2, r,
true);
223 r = 0.5 * (b[2] - 1);
224 box_blur(t2, t1, r,
false);
225 box_blur(t1, dst, r,
true);
230 std::shared_ptr<Frame> frame, int64_t frame_number)
232 auto img = frame->GetImage();
233 if (!
img ||
img->isNull())
235 if (
img->format() != QImage::Format_ARGB32)
236 *
img =
img->convertToFormat(QImage::Format_ARGB32);
238 int W =
img->width();
239 int H =
img->height();
240 if (
W <= 0 ||
H <= 0)
248 if (
amt == 0.0 ||
rpx <= 0.0)
252 double sigma = std::max(0.1,
rpx *
H / 720.0);
259 int bplS =
img->bytesPerLine();
266 #pragma omp parallel for reduction(max:maxDY)
267 for (
int y = 0; y <
H; ++y) {
270 for (
int x = 0; x <
W; ++x) {
274 float dY = std::abs(0.114f*
dB + 0.587f*
dG + 0.299f*
dR);
284 #pragma omp parallel for
285 for (
int y = 0; y <
H; ++y) {
288 for (
int x = 0; x <
W; ++x) {
296 float dY = 0.114f*
dB + 0.587f*
dG + 0.299f*
dR;
299 if (std::abs(
dY) <
thr)
303 auto halo = [](
float d) {
304 return (255.0f - std::abs(
d)) * (1.0f / 255.0f);
311 const float wB = 0.114f,
wG = 0.587f,
wR = 0.299f;
341 for (
int c = 0;
c < 3; ++
c)
347 for (
int c = 0;
c < 3; ++
c)
359 for (
int c = 0;
c < 3; ++
c) {
422 "Mode",
mode,
"int",
"",
nullptr, 0, 1,
false, t);
426 "Channel",
channel,
"int",
"",
nullptr, 0, 2,
false, t);
431 "Mask Mode",
mask_mode,
"int",
"",
nullptr, 0, 1,
false, t);
434 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.