Skip to content

Implement Windows Beauty

On Windows, the Facebetter SDK is accessed through its C++ interface. This guide follows the C++ Desktop Demo as a reference for the complete integration flow.

Include Headers

cpp
#include <facebetter/beauty_effect_engine.h>
#include <facebetter/beauty_params.h>
#include <facebetter/image_frame.h>
#include <facebetter/type_defines.h>

using namespace facebetter;
using namespace facebetter::beauty_params;

Integration Overview

Configure logging → Create engine → Enable beauty types → Set params → Process frames → Render result

1. Configure Logging (optional)

Call this before creating the engine so that initialization log messages are captured.

cpp
LogConfig log_cfg;
log_cfg.console_enabled = true;   // print to console
log_cfg.file_enabled    = false;  // no log file
log_cfg.level           = LogLevel::Info;
BeautyEffectEngine::SetLogConfig(log_cfg);

Log levels (ascending): Trace / Debug / Info / Warn / Error / Critical.


2. Create the Engine

cpp
EngineConfig eng_cfg;
eng_cfg.app_id        = "your_app_id";
eng_cfg.app_key       = "your_app_key";
eng_cfg.resource_path = "resource/resource.fbd";  // relative or absolute path
eng_cfg.external_context = false;                 // SDK manages its own OpenGL context

std::shared_ptr<BeautyEffectEngine> engine = BeautyEffectEngine::Create(eng_cfg);
if (!engine) {
    // Check app_id / app_key / resource_path
    return -1;
}

resource_path must point to the resource.fbd file shipped with the SDK, which contains AI models and filter assets.


3. Enable Beauty Types

All beauty types are disabled by default and must be explicitly enabled:

cpp
engine->SetBeautyTypeEnabled(BeautyType::Basic,   true);  // skin beauty
engine->SetBeautyTypeEnabled(BeautyType::Reshape, true);  // face reshaping
engine->SetBeautyTypeEnabled(BeautyType::Makeup,  true);  // makeup
engine->SetBeautyTypeEnabled(BeautyType::Sticker, true);  // stickers

4. Set Beauty Parameters

All parameter values are in the range [0.0, 1.0]. A value of 0 disables the effect.

Basic Beauty

cpp
engine->SetBeautyParam(Basic::Smoothing,  0.5f); // smoothing
engine->SetBeautyParam(Basic::Whitening,  0.3f); // whitening
engine->SetBeautyParam(Basic::Rosiness,   0.2f); // rosy tone
engine->SetBeautyParam(Basic::Sharpening, 0.4f); // sharpening

Skin-Only Beauty

Use SetSkinOnlyBeauty to set whether beauty effects are applied only to skin regions. When enabled, beauty effects (smoothing, whitening, etc.) will only be applied to detected skin areas, leaving non-skin areas unchanged.

cpp
// Enable skin-only beauty
engine->SetSkinOnlyBeauty(true);

// Disable skin-only beauty (apply to entire image)
engine->SetSkinOnlyBeauty(false);

TIP

After enabling skin-only beauty, even with high beauty parameter values, non-skin areas (such as background, clothing, etc.) will not be affected.

Face Reshape

cpp
engine->SetBeautyParam(Reshape::FaceThin,    0.4f); // face slimming
engine->SetBeautyParam(Reshape::FaceVShape,  0.3f); // V-face
engine->SetBeautyParam(Reshape::FaceNarrow,  0.2f); // narrow face
engine->SetBeautyParam(Reshape::FaceShort,   0.2f); // short face
engine->SetBeautyParam(Reshape::Cheekbone,   0.3f); // cheekbone slimming
engine->SetBeautyParam(Reshape::Jawbone,     0.2f); // jaw slimming
engine->SetBeautyParam(Reshape::Chin,        0.2f); // chin slimming
engine->SetBeautyParam(Reshape::NoseSlim,    0.3f); // nose bridge slimming
engine->SetBeautyParam(Reshape::EyeSize,     0.4f); // eye enlarging
engine->SetBeautyParam(Reshape::EyeDistance, 0.1f); // eye distance

Makeup

cpp
engine->SetBeautyParam(Makeup::Lipstick, 0.6f); // lipstick
engine->SetBeautyParam(Makeup::Blush,    0.4f); // blush

Stickers

Pass a sticker ID string to activate; pass an empty string to disable. Built-in sticker IDs are bundled in resource.fbd:

cpp
engine->SetSticker("rabbit");  // enable the "rabbit" sticker
engine->SetSticker("");        // disable sticker

Filters (LUT)

cpp
engine->SetFilter("chuxin");       // apply filter
engine->SetFilterIntensity(0.8f);  // filter intensity
engine->SetFilter("");             // disable filter

5. Process Frames

Typical per-frame processing:

cpp
// Create an input frame from in-memory RGBA data (video stream)
auto input_frame = ImageFrame::CreateWithRGBA(
    rgba_data, width, height, stride);

// Set frame type: Video (live stream) or Image (single photo)
input_frame->type = FrameType::Video;

// Process
auto output_frame = engine->ProcessImage(input_frame);

if (output_frame && output_frame->Data()) {
    int w            = output_frame->Width();
    int h            = output_frame->Height();
    const uint8_t* p = output_frame->Data(); // RGBA, same format as input
}

Load from file (single-image mode):

cpp
auto input_frame  = ImageFrame::CreateWithFile("input.jpg");
input_frame->type = FrameType::Image;
auto output_frame = engine->ProcessImage(input_frame);

Convert output format if needed:

cpp
auto bgra_frame = output_frame->Convert(Format::BGRA);
auto i420_frame = output_frame->Convert(Format::I420);

6. OpenGL Integration (render preview)

Upload the processed RGBA data to an OpenGL texture:

cpp
// Create texture (once)
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Upload per frame
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
             output_frame->Width(), output_frame->Height(),
             0, GL_RGBA, GL_UNSIGNED_BYTE, output_frame->Data());

// Render with ImGui or a custom quad
ImGui::Image(
    static_cast<ImTextureID>(static_cast<intptr_t>(tex)),
    ImVec2(img_w, img_h));

7. Full Example (real-time processing loop)

The snippet below is drawn directly from the demo and shows the complete processing loop with frame-rate limiting:

cpp
#include <facebetter/beauty_effect_engine.h>
#include <facebetter/beauty_params.h>
#include <facebetter/image_frame.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>

using namespace facebetter;
using namespace facebetter::beauty_params;

// --- Initialization ---
LogConfig log_cfg;
log_cfg.console_enabled = true;
log_cfg.level = LogLevel::Info;
BeautyEffectEngine::SetLogConfig(log_cfg);

EngineConfig eng_cfg;
eng_cfg.app_id           = "your_app_id";
eng_cfg.app_key          = "your_app_key";
eng_cfg.resource_path    = "resource/resource.fbd";
eng_cfg.external_context = false;

auto engine = BeautyEffectEngine::Create(eng_cfg);
engine->SetBeautyTypeEnabled(BeautyType::Basic,   true);
engine->SetBeautyTypeEnabled(BeautyType::Reshape, true);
engine->SetBeautyTypeEnabled(BeautyType::Makeup,  true);
engine->SetBeautyTypeEnabled(BeautyType::Sticker, true);

engine->SetBeautyParam(Basic::Smoothing,  0.5f);
engine->SetBeautyParam(Reshape::FaceThin, 0.4f);
engine->SetBeautyParam(Makeup::Lipstick,  0.6f);

// --- Processing loop (~30 fps) ---
double last_time = 0.0;
const double kInterval = 1.0 / 30.0;
GLuint preview_tex = 0;

while (!glfwWindowShouldClose(window)) {
    glfwPollEvents();
    double now = glfwGetTime();
    if (now - last_time >= kInterval) {
        auto input = ImageFrame::CreateWithRGBA(
            rgba_buffer, width, height, stride);
        input->type = FrameType::Video;

        auto output = engine->ProcessImage(input);
        if (output && output->Data()) {
            if (preview_tex == 0) {
                glGenTextures(1, &preview_tex);
                glBindTexture(GL_TEXTURE_2D, preview_tex);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            }
            glBindTexture(GL_TEXTURE_2D, preview_tex);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                         output->Width(), output->Height(),
                         0, GL_RGBA, GL_UNSIGNED_BYTE, output->Data());
        }
        last_time = now;
    }
    // ... ImGui render ...
}

// --- Cleanup ---
if (preview_tex) glDeleteTextures(1, &preview_tex);
engine.reset();

Quick Reference

BeautyType

ValueDescription
BeautyType::BasicSkin beauty
BeautyType::ReshapeFace reshaping
BeautyType::MakeupMakeup
BeautyType::StickerStickers

Basic Parameters

ParameterDescription
Basic::SmoothingSkin smoothing
Basic::WhiteningSkin whitening
Basic::RosinessRosy tone
Basic::SharpeningSharpening

Skin-Only Beauty

MethodDescription
SetSkinOnlyBeauty(true)Enable skin-only beauty
SetSkinOnlyBeauty(false)Disable skin-only beauty

Reshape Parameters

ParameterDescription
Reshape::FaceThinFace slimming
Reshape::FaceVShapeV-face
Reshape::FaceNarrowNarrow face
Reshape::FaceShortShort face
Reshape::CheekboneCheekbone slimming
Reshape::JawboneJaw slimming
Reshape::ChinChin slimming
Reshape::NoseSlimNose bridge slimming
Reshape::EyeSizeEye enlarging
Reshape::EyeDistanceEye distance

Makeup Parameters

ParameterDescription
Makeup::LipstickLipstick
Makeup::BlushBlush

ImageFrame Factory Methods

MethodDescription
ImageFrame::CreateWithFile(path)Load from file (JPEG/PNG/BMP)
ImageFrame::CreateWithRGBA(data, w, h, stride)Create from in-memory RGBA data
ImageFrame::CreateWithBGRA(data, w, h, stride)Create from in-memory BGRA data
ImageFrame::CreateWithRGB(data, w, h, stride)Create from in-memory RGB data
ImageFrame::CreateWithI420(w, h, y, sy, u, su, v, sv)Create from I420 YUV data
ImageFrame::CreateWithNV12(w, h, y, sy, uv, suv)Create from NV12 data
frame->Convert(Format::RGBA)Convert to another format (returns new frame)