31 #include "../../include/effects/Mask.h" 36 Mask::Mask() : reader(NULL), replace_image(false), needs_refresh(true) {
38 init_effect_details();
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;
182 Json::CharReaderBuilder rbuilder;
183 Json::CharReader* reader(rbuilder.newCharReader());
186 bool success = reader->parse( value.c_str(),
187 value.c_str() + value.size(), &root, &errors );
192 throw InvalidJSON(
"JSON could not be parsed (or is invalid)");
199 catch (
const std::exception& e)
202 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
213 if (!root[
"replace_image"].isNull())
215 if (!root[
"brightness"].isNull())
217 if (!root[
"contrast"].isNull())
219 if (!root[
"reader"].isNull())
221 #pragma omp critical (open_mask_reader) 224 needs_refresh =
true;
226 if (!root[
"reader"][
"type"].isNull())
237 std::string type = root[
"reader"][
"type"].asString();
239 if (type ==
"FFmpegReader") {
242 reader =
new FFmpegReader(root[
"reader"][
"path"].asString());
245 #ifdef USE_IMAGEMAGICK 246 }
else if (type ==
"ImageReader") {
249 reader =
new ImageReader(root[
"reader"][
"path"].asString());
253 }
else if (type ==
"QtImageReader") {
256 reader =
new QtImageReader(root[
"reader"][
"path"].asString());
259 }
else if (type ==
"ChunkReader") {
262 reader =
new ChunkReader(root[
"reader"][
"path"].asString(), (
ChunkVersion) root[
"reader"][
"chunk_version"].asInt());
278 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
279 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
281 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
282 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
283 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
true, requested_frame);
295 root[
"reader"] =
add_property_json(
"Source", 0.0,
"reader", reader->
Json(), NULL, 0, 1,
false, requested_frame);
297 root[
"reader"] =
add_property_json(
"Source", 0.0,
"reader",
"{}", NULL, 0, 1,
false, requested_frame);
300 return root.toStyledString();
void SetJson(std::string value)
Load JSON string into this object.
This class reads a special chunk-formatted file, which can be easily shared in a distributed environm...
Json::Value JsonValue()
Generate Json::JsonValue for this object.
bool replace_image
Replace the frame image with a grayscale image representing the mask. Great for debugging a mask...
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...
float End()
Get end position (in seconds) of clip (trim end of video)
virtual void Close()=0
Close the reader (and any resources it was consuming)
This abstract class is the base class, used by all readers in libopenshot.
int Layer()
Get layer of clip on timeline (lower number is covered by higher numbers)
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.
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
This class uses the ImageMagick++ libraries, to open image files, and return openshot::Frame objects ...
This class uses the FFmpeg libraries, to open video files and audio files, and return openshot::Frame...
Keyframe contrast
Contrast keyframe to control the hardness of the wipe effect / mask.
std::string Id()
Get basic properties.
float Position()
Get position on timeline (in seconds)
bool has_single_image
Determines if this file only contains a single image.
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Json::Value add_property_choice_json(std::string name, int value, int selected_value)
Generate JSON choice for a property (dropdown properties)
ChunkVersion
This enumeration allows the user to choose which version of the chunk they would like (low...
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
Mask()
Blank constructor, useful when using Json to load the effect properties.
std::string class_name
The class name of the effect.
std::string name
The name of the effect.
std::string Json()
Get and Set JSON methods.
openshot::ReaderInfo info
Information about the current media file.
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.
virtual std::string Json()=0
Get and Set JSON methods.
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.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
Keyframe brightness
Brightness keyframe to control the wipe / mask effect. A constant value here will prevent animation...
bool has_video
Determines if this effect manipulates the image of a frame.
Exception for invalid JSON.
double GetValue(int64_t index) const
Get the value at a specific index.
int constrain(int color_value)
Constrain a color value from 0 to 255.
This class uses the Qt library, to open image files, and return openshot::Frame objects containing th...
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)
float Start()
Get start position (in seconds) of clip (trim start of video)
std::string PropertiesJSON(int64_t requested_frame)
virtual void Open()=0
Open the reader (and start consuming resources, such as images or video files)
EffectInfoStruct info
Information about the current effect.
virtual bool IsOpen()=0
Determine if reader is open or closed.