> ## Documentation Index
> Fetch the complete documentation index at: https://docs.facebetter.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Implement Beauty

> Integrate the Facebetter SDK on Windows using the C++ interface

On Windows, the Facebetter SDK is accessed through its C++ interface. This guide follows the [C++ Desktop Demo](https://github.com/pixpark/facebetter-sdk) as a reference for the complete integration flow.

## Include Headers

```cpp theme={null}
#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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
// 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.
</Tip>

### Face Reshape

```cpp theme={null}
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 theme={null}
engine->SetBeautyParam(Makeup::Lipstick, 0.6f); // lipstick
engine->SetBeautyParam(Makeup::Blush,    0.4f); // blush
engine->SetLipstickStyle(LipstickStyle::Rouge); // lipstick style
engine->SetBlushStyle(BlushStyle::Classic);     // blush style
```

### Stickers

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

```cpp theme={null}
engine->SetSticker("rabbit");  // enable the "rabbit" sticker
engine->SetSticker("");        // disable sticker
```

### Filters (LUT)

```cpp theme={null}
engine->SetFilter("chuxin");       // apply filter
engine->SetFilterIntensity(0.8f);  // filter intensity
engine->SetFilter("");             // disable filter
```

***

## 5. Process Frames

Typical per-frame processing:

```cpp theme={null}
// 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 theme={null}
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 theme={null}
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 theme={null}
// 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 theme={null}
#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

| Value                 | Description    |
| --------------------- | -------------- |
| `BeautyType::Basic`   | Skin beauty    |
| `BeautyType::Reshape` | Face reshaping |
| `BeautyType::Makeup`  | Makeup         |
| `BeautyType::Sticker` | Stickers       |

### Basic Parameters

| Parameter           | Description    |
| ------------------- | -------------- |
| `Basic::Smoothing`  | Skin smoothing |
| `Basic::Whitening`  | Skin whitening |
| `Basic::Rosiness`   | Rosy tone      |
| `Basic::Sharpening` | Sharpening     |

### Skin-Only Beauty

| Method                     | Description              |
| -------------------------- | ------------------------ |
| `SetSkinOnlyBeauty(true)`  | Enable skin-only beauty  |
| `SetSkinOnlyBeauty(false)` | Disable skin-only beauty |

### Reshape Parameters

| Parameter              | Description          |
| ---------------------- | -------------------- |
| `Reshape::FaceThin`    | Face slimming        |
| `Reshape::FaceVShape`  | V-face               |
| `Reshape::FaceNarrow`  | Narrow face          |
| `Reshape::FaceShort`   | Short face           |
| `Reshape::Cheekbone`   | Cheekbone slimming   |
| `Reshape::Jawbone`     | Jaw slimming         |
| `Reshape::Chin`        | Chin slimming        |
| `Reshape::NoseSlim`    | Nose bridge slimming |
| `Reshape::EyeSize`     | Eye enlarging        |
| `Reshape::EyeDistance` | Eye distance         |

### Makeup Parameters

| Parameter          | Description |
| ------------------ | ----------- |
| `Makeup::Lipstick` | Lipstick    |
| `Makeup::Blush`    | Blush       |

### ImageFrame Factory Methods

| Method                                                  | Description                                   |
| ------------------------------------------------------- | --------------------------------------------- |
| `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) |
