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

Method GetFrame

src/effects/Saturation.cpp:110–232  ·  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

108// This method is required for all derived classes of EffectBase, and returns a
109// modified openshot::Frame object
110std::shared_ptr<openshot::Frame> Saturation::GetFrame(std::shared_ptr<openshot::Frame> frame, int64_t frame_number)
111{
112 // Get the frame's image
113 std::shared_ptr<QImage> frame_image = frame->GetImage();
114
115 if (!frame_image)
116 return frame;
117
118 const int pixel_count = frame_image->width() * frame_image->height();
119
120 // Get keyframe values for this frame
121 const float saturation_value = saturation.GetValue(frame_number);
122 const float saturation_value_R = saturation_R.GetValue(frame_number);
123 const float saturation_value_G = saturation_G.GetValue(frame_number);
124 const float saturation_value_B = saturation_B.GetValue(frame_number);
125
126 // Constants used for color saturation formula
127 const float pR = 0.299f;
128 const float pG = 0.587f;
129 const float pB = 0.114f;
130 const float sqrt_pR = std::sqrt(pR);
131 const float sqrt_pG = std::sqrt(pG);
132 const float sqrt_pB = std::sqrt(pB);
133 // Rec.601 fixed-point luma weights used in many image/video pipelines.
134 // This avoids per-pixel sqrt() while keeping output stable.
135 static const std::array<float, 65026> sqrt_lut = [] {
136 std::array<float, 65026> lut{};
137 for (int i = 0; i <= 65025; ++i)
138 lut[i] = std::sqrt(static_cast<float>(i));
139 return lut;
140 }();
141
142 // Loop through pixels
143 unsigned char *pixels = reinterpret_cast<unsigned char *>(frame_image->bits());
144 // LUT for undoing premultiplication without a per-pixel divide.
145 static const std::array<float, 256> inv_alpha = [] {
146 std::array<float, 256> lut{};
147 lut[0] = 0.0f;
148 for (int i = 1; i < 256; ++i)
149 lut[i] = 255.0f / static_cast<float>(i);
150 return lut;
151 }();
152 const auto clamp_i = [](int value) -> int {
153 if (value < 0) return 0;
154 if (value > 255) return 255;
155 return value;
156 };
157
158 const auto apply_saturation = [&](int &R, int &G, int &B) {
159 // Approximate sqrt(R^2*pR + G^2*pG + B^2*pB) with fixed-point weighted
160 // intensity and lookup table. 77/150/29 ~= 0.299/0.587/0.114.
161 const int weighted_sq = (77 * R * R + 150 * G * G + 29 * B * B + 128) >> 8;
162 const float p = sqrt_lut[weighted_sq];
163
164 // Adjust common saturation
165 R = clamp_i(static_cast<int>(p + (R - p) * saturation_value));
166 G = clamp_i(static_cast<int>(p + (G - p) * saturation_value));
167 B = clamp_i(static_cast<int>(p + (B - p) * saturation_value));

Callers

nothing calls this directly

Calls 2

GetImageMethod · 0.80
GetValueMethod · 0.80

Tested by

no test coverage detected