Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chromakey fix for pre-multiplied Alpha #643

Merged
merged 2 commits into from
Mar 12, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 19 additions & 13 deletions src/effects/ChromaKey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,24 @@ std::shared_ptr<openshot::Frame> ChromaKey::GetFrame(std::shared_ptr<openshot::F
for (int pixel = 0, byte_index=0; pixel < image->width() * image->height(); pixel++, byte_index+=4)
{
// Get the RGB values from the pixel
unsigned char R = pixels[byte_index];
unsigned char G = pixels[byte_index + 1];
unsigned char B = pixels[byte_index + 2];
unsigned char A = pixels[byte_index + 3];

// Get distance between mask color and pixel color
long distance = Color::GetDistance((long)R, (long)G, (long)B, mask_R, mask_G, mask_B);

// Alpha out the pixel (if color similar)
if (distance <= threshold)
// MATCHED - Make pixel transparent
pixels[byte_index + 3] = 0;
// Remove the premultiplied alpha values from R,G,B
float A = float(pixels[byte_index + 3]);
unsigned char R = (pixels[byte_index] / A) * 255.0;
unsigned char G = (pixels[byte_index + 1] / A) * 255.0;
unsigned char B = (pixels[byte_index + 2] / A) * 255.0;

// Get distance between mask color and pixel color
long distance = Color::GetDistance((long)R, (long)G, (long)B, mask_R, mask_G, mask_B);

if (distance <= threshold) {
// MATCHED - Make pixel transparent
// Due to premultiplied alpha, we must also zero out
// the individual color channels (or else artifacts are left behind)
pixels[byte_index] = 0;
pixels[byte_index + 1] = 0;
pixels[byte_index + 2] = 0;
pixels[byte_index + 3] = 0;
}
}

// return the modified frame
Expand Down Expand Up @@ -168,7 +174,7 @@ std::string ChromaKey::PropertiesJSON(int64_t requested_frame) const {
root["color"]["red"] = add_property_json("Red", color.red.GetValue(requested_frame), "float", "", &color.red, 0, 255, false, requested_frame);
root["color"]["blue"] = add_property_json("Blue", color.blue.GetValue(requested_frame), "float", "", &color.blue, 0, 255, false, requested_frame);
root["color"]["green"] = add_property_json("Green", color.green.GetValue(requested_frame), "float", "", &color.green, 0, 255, false, requested_frame);
root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 25, false, requested_frame);
root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 125, false, requested_frame);

// Return formatted string
return root.toStyledString();
Expand Down