31 #include "../../include/effects/Mask.h"
36 Mask::Mask() : reader(NULL), replace_image(false), needs_refresh(true) {
38 init_effect_details();
43 reader(mask_reader), brightness(mask_brightness), contrast(mask_contrast), replace_image(false), needs_refresh(true)
46 init_effect_details();
50 void Mask::init_effect_details()
57 info.
name =
"Alpha Mask / Wipe Transition";
58 info.
description =
"Uses a grayscale mask image to gradually wipe / transition between 2 images.";
65 std::shared_ptr<Frame>
Mask::GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number) {
67 std::shared_ptr<QImage> frame_image = frame->GetImage();
70 #pragma omp critical (open_mask_reader)
72 if (reader && !reader->
IsOpen())
81 #pragma omp critical (open_mask_reader)
84 (original_mask && original_mask->size() != frame_image->size())) {
87 std::shared_ptr<QImage> mask_without_sizing = std::shared_ptr<QImage>(
88 new QImage(*reader->
GetFrame(frame_number)->GetImage()));
91 original_mask = std::shared_ptr<QImage>(
new QImage(
92 mask_without_sizing->scaled(frame_image->width(), frame_image->height(), Qt::IgnoreAspectRatio,
93 Qt::SmoothTransformation)));
98 needs_refresh =
false;
101 unsigned char *pixels = (
unsigned char *) frame_image->bits();
102 unsigned char *mask_pixels = (
unsigned char *) original_mask->bits();
114 for (
int pixel = 0, byte_index=0; pixel < original_mask->width() * original_mask->height(); pixel++, byte_index+=4)
117 R = mask_pixels[byte_index];
118 G = mask_pixels[byte_index + 1];
119 B = mask_pixels[byte_index + 2];
122 gray_value = qGray(R, G, B);
125 factor = (259 * (contrast_value + 255)) / (255 * (259 - contrast_value));
126 gray_value =
constrain((factor * (gray_value - 128)) + 128);
129 gray_value += (255 * brightness_value);
137 pixels[byte_index + 0] = gray_value;
138 pixels[byte_index + 1] = gray_value;
139 pixels[byte_index + 2] = gray_value;
142 A = pixels[byte_index + 3];
143 pixels[byte_index + 3] =
constrain(A - gray_value);
170 root[
"reader"] = Json::objectValue;
187 catch (
const std::exception& e)
190 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
201 if (!root[
"replace_image"].isNull())
203 if (!root[
"brightness"].isNull())
205 if (!root[
"contrast"].isNull())
207 if (!root[
"reader"].isNull())
209 #pragma omp critical (open_mask_reader)
212 needs_refresh =
true;
214 if (!root[
"reader"][
"type"].isNull())
225 std::string type = root[
"reader"][
"type"].asString();
227 if (type ==
"FFmpegReader") {
230 reader =
new FFmpegReader(root[
"reader"][
"path"].asString());
233 #ifdef USE_IMAGEMAGICK
234 }
else if (type ==
"ImageReader") {
237 reader =
new ImageReader(root[
"reader"][
"path"].asString());
241 }
else if (type ==
"QtImageReader") {
244 reader =
new QtImageReader(root[
"reader"][
"path"].asString());
247 }
else if (type ==
"ChunkReader") {
250 reader =
new ChunkReader(root[
"reader"][
"path"].asString(), (
ChunkVersion) root[
"reader"][
"chunk_version"].asInt());
266 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
267 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
269 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
270 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
271 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
true, requested_frame);
283 root[
"reader"] =
add_property_json(
"Source", 0.0,
"reader", reader->
Json(), NULL, 0, 1,
false, requested_frame);
285 root[
"reader"] =
add_property_json(
"Source", 0.0,
"reader",
"{}", NULL, 0, 1,
false, requested_frame);
288 return root.toStyledString();
This class reads a special chunk-formatted file, which can be easily shared in a distributed environm...
float End() const
Get end position (in seconds) of clip (trim end of video)
float Start() const
Get start position (in seconds) of clip (trim start of video)
float Duration() const
Get the length of this clip (in seconds)
std::string Id() const
Get basic properties.
Json::Value add_property_choice_json(std::string name, int value, int selected_value) const
Generate JSON choice for a property (dropdown properties)
int Layer() const
Get layer of clip on timeline (lower number is covered by higher numbers)
float Position() const
Get position on timeline (in seconds)
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.
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
int constrain(int color_value)
Constrain a color value from 0 to 255.
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
EffectInfoStruct info
Information about the current effect.
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
This class uses the ImageMagick++ libraries, to open image files, and return openshot::Frame objects ...
Exception for invalid JSON.
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.
Mask()
Blank constructor, useful when using Json to load the effect properties.
bool replace_image
Replace the frame image with a grayscale image representing the mask. Great for debugging a mask.
Keyframe brightness
Brightness keyframe to control the wipe / mask effect. A constant value here will prevent animation.
std::string PropertiesJSON(int64_t requested_frame) const override
Json::Value JsonValue() const override
Generate Json::Value for this object.
std::string Json() const override
Get and Set JSON methods.
void SetJson(const std::string value)
Load JSON string into this object.
Keyframe contrast
Contrast keyframe to control the hardness of the wipe effect / mask.
void SetJsonValue(const Json::Value root)
Load Json::Value 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...
This class uses the Qt library, to open image files, and return openshot::Frame objects containing th...
This abstract class is the base class, used by all readers in libopenshot.
virtual bool IsOpen()=0
Determine if reader is open or closed.
openshot::ReaderInfo info
Information about the current media file.
virtual std::string Json() const =0
Get and Set JSON methods.
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
virtual Json::Value JsonValue() const =0
Generate Json::Value for this object.
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
virtual void Close()=0
Close the reader (and any resources it was consuming)
This namespace is the default namespace for all code in the openshot library.
ChunkVersion
This enumeration allows the user to choose which version of the chunk they would like (low,...
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.
bool has_single_image
Determines if this file only contains a single image.