MCPcopy Create free account
hub / github.com/OpenShot/libopenshot / GetFrame

Method GetFrame

src/effects/Mask.cpp:57–165  ·  view source on GitHub ↗

This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame object

Source from the content-addressed store, hash-verified

55// This method is required for all derived classes of EffectBase, and returns a
56// modified openshot::Frame object
57std::shared_ptr<openshot::Frame> Mask::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number) {
58 // Get frame image first
59 std::shared_ptr<QImage> frame_image = frame->GetImage();
60 if (!frame_image || frame_image->isNull())
61 return frame;
62
63 // No reader (bail on applying the mask)
64 auto original_mask = ResolveMaskImage(frame_image, frame_number);
65 if (!original_mask || original_mask->isNull())
66 return frame;
67
68 // Grab raw pointers and dimensions one time
69 unsigned char* pixels = reinterpret_cast<unsigned char*>(frame_image->bits());
70 unsigned char* mask_pixels = reinterpret_cast<unsigned char*>(original_mask->bits());
71 const int num_pixels = original_mask->width() * original_mask->height();
72
73 // Evaluate brightness and contrast keyframes just once
74 double contrast_value = contrast.GetValue(frame_number);
75 double brightness_value = brightness.GetValue(frame_number);
76
77 int brightness_adj = static_cast<int>(255 * brightness_value);
78 float contrast_factor = 20.0f / std::max(0.00001f, 20.0f - static_cast<float>(contrast_value));
79 const bool output_mask = replace_image;
80 const auto clamp_u8 = [](int value) -> unsigned char {
81 if (value < 0) return 0;
82 if (value > 255) return 255;
83 return static_cast<unsigned char>(value);
84 };
85 // Precompute gray->adjusted-gray mapping for this frame's brightness/contrast.
86 std::array<unsigned char, 256> adjusted_gray{};
87 for (int gray = 0; gray < 256; ++gray) {
88 const int adjusted = static_cast<int>(contrast_factor * ((gray + brightness_adj) - 128) + 128);
89 adjusted_gray[gray] = clamp_u8(adjusted);
90 }
91 // 8-bit multiply lookup for premultiplied alpha channel scaling.
92 static const std::array<std::array<unsigned char, 256>, 256> mul_lut = [] {
93 std::array<std::array<unsigned char, 256>, 256> lut{};
94 for (int alpha = 0; alpha < 256; ++alpha) {
95 for (int value = 0; value < 256; ++value) {
96 lut[alpha][value] = static_cast<unsigned char>((value * alpha) / 255);
97 }
98 }
99 return lut;
100 }();
101
102 // Separate loops keep the hot path branch-free per pixel.
103 if (output_mask) {
104 #pragma omp parallel for if(num_pixels >= 16384) schedule(static)
105 for (int i = 0; i < num_pixels; ++i) {
106 const int idx = i * 4;
107 const int R = mask_pixels[idx + 0];
108 const int G = mask_pixels[idx + 1];
109 const int B = mask_pixels[idx + 2];
110 const int A = mask_pixels[idx + 3];
111
112 const int gray = ((R * 11) + (G * 16) + (B * 5)) >> 5;
113 const int diff = A - adjusted_gray[gray];
114 const unsigned char new_val = clamp_u8(diff);

Callers

nothing calls this directly

Calls 2

GetImageMethod · 0.80
GetValueMethod · 0.80

Tested by

no test coverage detected