28 #include "../../include/effects/Mask.h" 33 Mask::Mask() : reader(NULL), replace_image(false), needs_refresh(true) {
35 init_effect_details();
43 init_effect_details();
47 void Mask::init_effect_details()
54 info.
name =
"Alpha Mask / Wipe Transition";
55 info.
description =
"Uses a grayscale mask image to gradually wipe / transition between 2 images.";
62 std::shared_ptr<Frame>
Mask::GetFrame(std::shared_ptr<Frame> frame, int64_t frame_number) {
64 std::shared_ptr<QImage> frame_image = frame->GetImage();
67 #pragma omp critical (open_mask_reader) 69 if (reader && !reader->
IsOpen())
78 #pragma omp critical (open_mask_reader) 81 (original_mask && original_mask->size() != frame_image->size())) {
84 std::shared_ptr<QImage> mask_without_sizing = std::shared_ptr<QImage>(
85 new QImage(*reader->
GetFrame(frame_number)->GetImage()));
88 original_mask = std::shared_ptr<QImage>(
new QImage(
89 mask_without_sizing->scaled(frame_image->width(), frame_image->height(), Qt::IgnoreAspectRatio,
90 Qt::SmoothTransformation)));
95 needs_refresh =
false;
98 unsigned char *pixels = (
unsigned char *) frame_image->bits();
99 unsigned char *mask_pixels = (
unsigned char *) original_mask->bits();
111 for (
int pixel = 0, byte_index=0; pixel < original_mask->width() * original_mask->height(); pixel++, byte_index+=4)
114 R = mask_pixels[byte_index];
115 G = mask_pixels[byte_index + 1];
116 B = mask_pixels[byte_index + 2];
119 gray_value = qGray(R, G, B);
122 factor = (259 * (contrast_value + 255)) / (255 * (259 - contrast_value));
123 gray_value =
constrain((factor * (gray_value - 128)) + 128);
126 gray_value += (255 * brightness_value);
134 pixels[byte_index + 0] = gray_value;
135 pixels[byte_index + 1] = gray_value;
136 pixels[byte_index + 2] = gray_value;
139 A = pixels[byte_index + 3];
140 pixels[byte_index + 3] =
constrain(A - gray_value);
167 root[
"reader"] = Json::objectValue;
180 bool success = reader.parse( value, root );
183 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
193 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
204 if (!root[
"replace_image"].isNull())
206 if (!root[
"brightness"].isNull())
208 if (!root[
"contrast"].isNull())
210 if (!root[
"reader"].isNull())
212 #pragma omp critical (open_mask_reader) 215 needs_refresh =
true;
217 if (!root[
"reader"][
"type"].isNull())
228 string type = root[
"reader"][
"type"].asString();
230 if (type ==
"FFmpegReader") {
233 reader =
new FFmpegReader(root[
"reader"][
"path"].asString());
236 #ifdef USE_IMAGEMAGICK 237 }
else if (type ==
"ImageReader") {
240 reader =
new ImageReader(root[
"reader"][
"path"].asString());
244 }
else if (type ==
"QtImageReader") {
247 reader =
new QtImageReader(root[
"reader"][
"path"].asString());
250 }
else if (type ==
"ChunkReader") {
253 reader =
new ChunkReader(root[
"reader"][
"path"].asString(), (
ChunkVersion) root[
"reader"][
"chunk_version"].asInt());
269 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
270 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
272 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
273 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
false, requested_frame);
274 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 30 * 60 * 60 * 48,
true, requested_frame);