Initial release
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,333 @@
|
||||
#ifndef __EXAMPLES_COMMON_COMMON_H__
|
||||
#define __EXAMPLES_COMMON_COMMON_H__
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "log.h"
|
||||
#include "resource_owners.hpp"
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
#define SAFE_STR(s) ((s) ? (s) : "")
|
||||
#define BOOL_STR(b) ((b) ? "true" : "false")
|
||||
|
||||
extern const char* const modes_str[];
|
||||
#define SD_ALL_MODES_STR "img_gen, adetailer, vid_gen, convert, upscale, metadata"
|
||||
|
||||
enum SDMode {
|
||||
IMG_GEN,
|
||||
ADETAILER,
|
||||
VID_GEN,
|
||||
CONVERT,
|
||||
UPSCALE,
|
||||
METADATA,
|
||||
MODE_COUNT
|
||||
};
|
||||
|
||||
struct StringOption {
|
||||
std::string short_name;
|
||||
std::string long_name;
|
||||
std::string desc;
|
||||
int concat;
|
||||
std::string* target;
|
||||
};
|
||||
|
||||
struct IntOption {
|
||||
std::string short_name;
|
||||
std::string long_name;
|
||||
std::string desc;
|
||||
int* target;
|
||||
};
|
||||
|
||||
struct FloatOption {
|
||||
std::string short_name;
|
||||
std::string long_name;
|
||||
std::string desc;
|
||||
float* target;
|
||||
};
|
||||
|
||||
struct BoolOption {
|
||||
std::string short_name;
|
||||
std::string long_name;
|
||||
std::string desc;
|
||||
bool keep_true;
|
||||
bool* target;
|
||||
};
|
||||
|
||||
struct ManualFunction {
|
||||
std::function<int(int, const char**, int, bool&)> _func;
|
||||
|
||||
ManualFunction() = default;
|
||||
|
||||
ManualFunction(std::function<int(int argc, const char** argv, int index, bool& valid)> func)
|
||||
: _func(std::move(func)) {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
ManualFunction(F func)
|
||||
: _func(make_function(func)) {
|
||||
}
|
||||
|
||||
int operator()(int argc, const char** argv, int index, bool& valid) const {
|
||||
return _func(argc, argv, index, valid);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F>
|
||||
static std::function<int(int, const char**, int, bool&)> make_function(F func) {
|
||||
if constexpr (std::is_invocable_v<F, int, const char**, int, bool&>) {
|
||||
return func;
|
||||
} else {
|
||||
return [func](int argc, const char** argv, int index, bool&) {
|
||||
return func(argc, argv, index);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ManualOption {
|
||||
std::string short_name;
|
||||
std::string long_name;
|
||||
std::string desc;
|
||||
ManualFunction cb;
|
||||
};
|
||||
|
||||
struct ArgOptions {
|
||||
std::vector<StringOption> string_options;
|
||||
std::vector<IntOption> int_options;
|
||||
std::vector<FloatOption> float_options;
|
||||
std::vector<BoolOption> bool_options;
|
||||
std::vector<ManualOption> manual_options;
|
||||
|
||||
static std::string wrap_text(const std::string& text, size_t width, size_t indent);
|
||||
void print() const;
|
||||
};
|
||||
|
||||
bool parse_options(int argc, const char** argv, const std::vector<ArgOptions>& options_list);
|
||||
bool decode_base64_image(const std::string& encoded_input,
|
||||
int target_channels,
|
||||
int expected_width,
|
||||
int expected_height,
|
||||
SDImageOwner& out_image);
|
||||
|
||||
struct SDContextParams {
|
||||
int n_threads = -1;
|
||||
std::string model_path;
|
||||
std::string clip_l_path;
|
||||
std::string clip_g_path;
|
||||
std::string clip_vision_path;
|
||||
std::string t5xxl_path;
|
||||
std::string llm_path;
|
||||
std::string llm_vision_path;
|
||||
std::string diffusion_model_path;
|
||||
std::string high_noise_diffusion_model_path;
|
||||
std::string uncond_diffusion_model_path;
|
||||
std::string embeddings_connectors_path;
|
||||
std::string vae_path;
|
||||
std::string vae_format = "auto";
|
||||
std::string audio_vae_path;
|
||||
std::string taesd_path;
|
||||
std::string esrgan_path;
|
||||
std::string control_net_path;
|
||||
std::string ip_adapter_path;
|
||||
std::string motion_module_path;
|
||||
std::string embedding_dir;
|
||||
std::string photo_maker_path;
|
||||
std::string pulid_weights_path;
|
||||
sd_type_t wtype = SD_TYPE_COUNT;
|
||||
std::string tensor_type_rules;
|
||||
std::string lora_model_dir = ".";
|
||||
std::string hires_upscalers_dir;
|
||||
|
||||
std::map<std::string, std::string> embedding_map;
|
||||
std::vector<sd_embedding_t> embedding_vec;
|
||||
|
||||
rng_type_t rng_type = CUDA_RNG;
|
||||
rng_type_t sampler_rng_type = RNG_TYPE_COUNT;
|
||||
bool offload_params_to_cpu = false;
|
||||
std::string max_vram = "0";
|
||||
bool stream_layers = false;
|
||||
bool eager_load = false;
|
||||
std::string backend;
|
||||
std::string params_backend;
|
||||
std::string split_mode;
|
||||
std::string model_args;
|
||||
bool auto_fit = false;
|
||||
std::string rpc_servers;
|
||||
std::string effective_backend;
|
||||
std::string effective_params_backend;
|
||||
bool enable_mmap = false;
|
||||
bool control_net_cpu = false;
|
||||
bool clip_on_cpu = false;
|
||||
bool vae_on_cpu = false;
|
||||
bool flash_attn = false;
|
||||
bool diffusion_flash_attn = false;
|
||||
bool diffusion_conv_direct = false;
|
||||
bool vae_conv_direct = false;
|
||||
|
||||
prediction_t prediction = PREDICTION_COUNT;
|
||||
lora_apply_mode_t lora_apply_mode = LORA_APPLY_AUTO;
|
||||
|
||||
bool force_sdxl_vae_conv_scale = false;
|
||||
|
||||
float flow_shift = INFINITY;
|
||||
ArgOptions get_options();
|
||||
void build_embedding_map();
|
||||
void prepare_backend_assignments();
|
||||
bool resolve(SDMode mode);
|
||||
bool validate(SDMode mode);
|
||||
bool resolve_and_validate(SDMode mode);
|
||||
std::string to_string() const;
|
||||
sd_ctx_params_t to_sd_ctx_params_t(bool taesd_preview);
|
||||
};
|
||||
|
||||
struct SDGenerationParams {
|
||||
// User-facing input fields.
|
||||
std::string prompt;
|
||||
std::string negative_prompt;
|
||||
std::string ad_model_path;
|
||||
std::string ad_prompt;
|
||||
std::string ad_negative_prompt;
|
||||
std::string extra_ad_args;
|
||||
int clip_skip = -1; // <= 0 represents unspecified
|
||||
int width = -1;
|
||||
int height = -1;
|
||||
int batch_count = 1;
|
||||
int qwen_image_layers = 3;
|
||||
int64_t seed = 42;
|
||||
float strength = 0.75f;
|
||||
float control_strength = 0.9f;
|
||||
float ip_adapter_strength = 1.0f;
|
||||
bool auto_resize_ref_image = true;
|
||||
bool increase_ref_index = false;
|
||||
bool embed_image_metadata = true;
|
||||
|
||||
std::string init_image_path;
|
||||
std::string end_image_path;
|
||||
std::string mask_image_path;
|
||||
std::string control_image_path;
|
||||
std::string ip_adapter_image_path;
|
||||
std::vector<std::string> ref_image_paths;
|
||||
std::vector<std::string> ref_video_paths;
|
||||
std::vector<std::string> ref_video_audio_paths;
|
||||
std::vector<std::string> ref_audio_paths;
|
||||
std::string control_video_path;
|
||||
|
||||
sd_sample_params_t sample_params;
|
||||
sd_sample_params_t high_noise_sample_params;
|
||||
std::string extra_sample_args;
|
||||
std::string high_noise_extra_sample_args;
|
||||
std::vector<int> skip_layers = {7, 8, 9};
|
||||
std::vector<int> high_noise_skip_layers = {7, 8, 9};
|
||||
|
||||
std::vector<float> custom_sigmas;
|
||||
|
||||
std::string cache_mode;
|
||||
std::string cache_option;
|
||||
std::string scm_mask;
|
||||
bool scm_policy_dynamic = true;
|
||||
sd_cache_params_t cache_params{};
|
||||
|
||||
float moe_boundary = 0.875f;
|
||||
int video_frames = 1;
|
||||
int fps = 16;
|
||||
float vace_strength = 1.f;
|
||||
sd_tiling_params_t vae_tiling_params = {false, false, 0, 0, 0.5f, 0.0f, 0.0f, nullptr};
|
||||
std::string extra_tiling_args;
|
||||
|
||||
std::string ref_image_args;
|
||||
|
||||
std::string pm_id_images_dir;
|
||||
std::string pm_id_embed_path;
|
||||
float pm_style_strength = 20.f;
|
||||
|
||||
std::string pulid_id_embedding_path;
|
||||
float pulid_id_weight = 1.0f;
|
||||
|
||||
int upscale_repeats = 1;
|
||||
int upscale_tile_size = 128;
|
||||
|
||||
bool circular = false;
|
||||
bool circular_x = false;
|
||||
bool circular_y = false;
|
||||
|
||||
bool hires_enabled = false;
|
||||
std::string hires_upscaler = "Latent";
|
||||
std::string hires_upscaler_model_path;
|
||||
float hires_scale = 2.f;
|
||||
int hires_width = 0;
|
||||
int hires_height = 0;
|
||||
int hires_steps = 0;
|
||||
float hires_denoising_strength = 0.7f;
|
||||
int hires_upscale_tile_size = 128;
|
||||
std::vector<float> hires_custom_sigmas;
|
||||
|
||||
std::map<std::string, float> lora_map;
|
||||
std::map<std::string, float> high_noise_lora_map;
|
||||
|
||||
// Derived and normalized fields.
|
||||
std::string prompt_with_lora; // for metadata record only
|
||||
std::vector<sd_lora_t> lora_vec;
|
||||
sd_hires_upscaler_t resolved_hires_upscaler;
|
||||
|
||||
// Owned execution payload.
|
||||
SDImageOwner init_image;
|
||||
SDImageOwner end_image;
|
||||
std::vector<SDImageOwner> ref_images;
|
||||
std::vector<std::vector<SDImageOwner>> ref_videos;
|
||||
std::vector<SDAudioOwner> ref_video_audios;
|
||||
std::vector<SDAudioOwner> ref_audios;
|
||||
SDImageOwner mask_image;
|
||||
SDImageOwner control_image;
|
||||
SDImageOwner ip_adapter_image;
|
||||
std::vector<SDImageOwner> pm_id_images;
|
||||
std::vector<SDImageOwner> control_frames;
|
||||
|
||||
// Backing storage for sd_img_gen_params_t view fields.
|
||||
std::vector<sd_image_t> ref_image_views;
|
||||
std::vector<std::vector<sd_image_t>> ref_video_frame_views;
|
||||
std::vector<sd_ref_video_t> ref_video_views;
|
||||
std::vector<sd_audio_t> ref_audio_views;
|
||||
std::vector<sd_image_t> pm_id_image_views;
|
||||
std::vector<sd_image_t> control_frame_views;
|
||||
|
||||
SDGenerationParams();
|
||||
SDGenerationParams(const SDGenerationParams& other) = default;
|
||||
SDGenerationParams& operator=(const SDGenerationParams& other) = default;
|
||||
SDGenerationParams(SDGenerationParams&& other) noexcept = default;
|
||||
SDGenerationParams& operator=(SDGenerationParams&& other) noexcept = default;
|
||||
ArgOptions get_options();
|
||||
bool from_json_str(const std::string& json_str,
|
||||
const std::function<std::string(const std::string&)>& lora_path_resolver = {});
|
||||
bool initialize_cache_params();
|
||||
void extract_and_remove_lora(const std::string& lora_model_dir);
|
||||
bool width_and_height_are_set() const;
|
||||
void set_width_and_height_if_unset(int w, int h);
|
||||
int get_resolved_width() const;
|
||||
int get_resolved_height() const;
|
||||
bool resolve(const std::string& lora_model_dir, const std::string& hires_upscalers_dir, bool strict = false);
|
||||
bool validate(SDMode mode);
|
||||
bool resolve_and_validate(SDMode mode,
|
||||
const std::string& lora_model_dir,
|
||||
const std::string& hires_upscalers_dir,
|
||||
bool strict = false);
|
||||
sd_img_gen_params_t to_sd_img_gen_params_t();
|
||||
sd_vid_gen_params_t to_sd_vid_gen_params_t();
|
||||
std::string to_string() const;
|
||||
};
|
||||
|
||||
std::string version_string();
|
||||
std::string build_sdcpp_image_metadata_json(const SDContextParams& ctx_params,
|
||||
const SDGenerationParams& gen_params,
|
||||
int64_t seed,
|
||||
SDMode mode = IMG_GEN);
|
||||
std::string get_image_params(const SDContextParams& ctx_params,
|
||||
const SDGenerationParams& gen_params,
|
||||
int64_t seed,
|
||||
SDMode mode = IMG_GEN);
|
||||
|
||||
#endif // __EXAMPLES_COMMON_COMMON_H__
|
||||
@@ -0,0 +1,115 @@
|
||||
#include "log.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
bool log_verbose = false;
|
||||
bool log_color = false;
|
||||
|
||||
std::string sd_basename(const std::string& path) {
|
||||
size_t pos = path.find_last_of('/');
|
||||
if (pos != std::string::npos) {
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
pos = path.find_last_of('\\');
|
||||
if (pos != std::string::npos) {
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
void print_utf8(FILE* stream, const char* utf8) {
|
||||
if (!utf8) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE h = (stream == stderr)
|
||||
? GetStdHandle(STD_ERROR_HANDLE)
|
||||
: GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
DWORD mode;
|
||||
BOOL is_console = GetConsoleMode(h, &mode);
|
||||
|
||||
if (is_console) {
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||
if (wlen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> wbuf(static_cast<size_t>(wlen));
|
||||
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wbuf.data(), wlen);
|
||||
|
||||
DWORD written;
|
||||
WriteConsoleW(h, wbuf.data(), wlen - 1, &written, NULL);
|
||||
} else {
|
||||
DWORD written;
|
||||
WriteFile(h, utf8, (DWORD)strlen(utf8), &written, NULL);
|
||||
}
|
||||
#else
|
||||
fputs(utf8, stream);
|
||||
#endif
|
||||
}
|
||||
|
||||
void log_print(enum sd_log_level_t level, const char* log, bool verbose, bool color) {
|
||||
int tag_color;
|
||||
const char* level_str;
|
||||
FILE* out_stream = (level == SD_LOG_ERROR) ? stderr : stdout;
|
||||
|
||||
if (!log || (!verbose && level <= SD_LOG_DEBUG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case SD_LOG_DEBUG:
|
||||
tag_color = 37;
|
||||
level_str = "DEBUG";
|
||||
break;
|
||||
case SD_LOG_INFO:
|
||||
tag_color = 34;
|
||||
level_str = "INFO";
|
||||
break;
|
||||
case SD_LOG_WARN:
|
||||
tag_color = 35;
|
||||
level_str = "WARN";
|
||||
break;
|
||||
case SD_LOG_ERROR:
|
||||
tag_color = 31;
|
||||
level_str = "ERROR";
|
||||
break;
|
||||
default:
|
||||
tag_color = 33;
|
||||
level_str = "?????";
|
||||
break;
|
||||
}
|
||||
|
||||
if (color) {
|
||||
fprintf(out_stream, "\033[%d;1m[%-5s]\033[0m ", tag_color, level_str);
|
||||
} else {
|
||||
fprintf(out_stream, "[%-5s] ", level_str);
|
||||
}
|
||||
print_utf8(out_stream, log);
|
||||
fflush(out_stream);
|
||||
}
|
||||
|
||||
void example_log_printf(sd_log_level_t level, const char* file, int line, const char* format, ...) {
|
||||
constexpr size_t LOG_BUFFER_SIZE = 4096;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
static char log_buffer[LOG_BUFFER_SIZE + 1];
|
||||
int written = snprintf(log_buffer, LOG_BUFFER_SIZE, "%s:%-4d - ", sd_basename(file).c_str(), line);
|
||||
|
||||
if (written >= 0 && written < static_cast<int>(LOG_BUFFER_SIZE)) {
|
||||
vsnprintf(log_buffer + written, LOG_BUFFER_SIZE - written, format, args);
|
||||
}
|
||||
size_t len = strlen(log_buffer);
|
||||
if (len == 0 || log_buffer[len - 1] != '\n') {
|
||||
strncat(log_buffer, "\n", LOG_BUFFER_SIZE - len);
|
||||
}
|
||||
|
||||
log_print(level, log_buffer, log_verbose, log_color);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef __EXAMPLE_LOG_H__
|
||||
#define __EXAMPLE_LOG_H__
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif // _WIN32
|
||||
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
extern bool log_verbose;
|
||||
extern bool log_color;
|
||||
|
||||
std::string sd_basename(const std::string& path);
|
||||
void print_utf8(FILE* stream, const char* utf8);
|
||||
void log_print(sd_log_level_t level, const char* log, bool verbose, bool color);
|
||||
void example_log_printf(sd_log_level_t level, const char* file, int line, const char* format, ...);
|
||||
|
||||
#define LOG_DEBUG(format, ...) example_log_printf(SD_LOG_DEBUG, __FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
#define LOG_INFO(format, ...) example_log_printf(SD_LOG_INFO, __FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
#define LOG_WARN(format, ...) example_log_printf(SD_LOG_WARN, __FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
#define LOG_ERROR(format, ...) example_log_printf(SD_LOG_ERROR, __FILE__, __LINE__, format, ##__VA_ARGS__)
|
||||
|
||||
#endif // __EXAMPLE_LOG_H__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
#ifndef __MEDIA_IO_H__
|
||||
#define __MEDIA_IO_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
enum class EncodedImageFormat {
|
||||
JPEG,
|
||||
PNG,
|
||||
WEBP,
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
EncodedImageFormat encoded_image_format_from_path(const std::string& path);
|
||||
|
||||
std::vector<uint8_t> encode_image_to_vector(EncodedImageFormat format,
|
||||
const uint8_t* image,
|
||||
int width,
|
||||
int height,
|
||||
int channels,
|
||||
const std::string& parameters = "",
|
||||
int quality = 90);
|
||||
|
||||
bool write_image_to_file(const std::string& path,
|
||||
const uint8_t* image,
|
||||
int width,
|
||||
int height,
|
||||
int channels,
|
||||
const std::string& parameters = "",
|
||||
int quality = 90);
|
||||
|
||||
uint8_t* load_image_from_file(const char* image_path,
|
||||
int& width,
|
||||
int& height,
|
||||
int expected_width = 0,
|
||||
int expected_height = 0,
|
||||
int expected_channel = 3);
|
||||
|
||||
bool load_sd_image_from_file(sd_image_t* image,
|
||||
const char* image_path,
|
||||
int expected_width = 0,
|
||||
int expected_height = 0,
|
||||
int expected_channel = 3);
|
||||
|
||||
uint8_t* load_image_from_memory(const char* image_bytes,
|
||||
int len,
|
||||
int& width,
|
||||
int& height,
|
||||
int expected_width = 0,
|
||||
int expected_height = 0,
|
||||
int expected_channel = 3);
|
||||
|
||||
int create_mjpg_avi_from_sd_images(const char* filename,
|
||||
sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
std::vector<uint8_t> create_mjpg_avi_from_sd_images_to_vector(sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
|
||||
#ifdef SD_USE_WEBP
|
||||
int create_animated_webp_from_sd_images(const char* filename,
|
||||
sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90);
|
||||
std::vector<uint8_t> create_animated_webp_from_sd_images_to_vector(sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90);
|
||||
#endif
|
||||
|
||||
#ifdef SD_USE_WEBM
|
||||
int create_webm_from_sd_images(const char* filename,
|
||||
sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
std::vector<uint8_t> create_webm_from_sd_images_to_vector(sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
#endif
|
||||
|
||||
int create_video_from_sd_images(const char* filename,
|
||||
sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
std::vector<uint8_t> create_video_from_sd_images_to_vector(const std::string& output_format,
|
||||
sd_image_t* images,
|
||||
int num_images,
|
||||
int fps,
|
||||
int quality = 90,
|
||||
const sd_audio_t* audio = nullptr);
|
||||
|
||||
bool write_wav_to_file(const std::string& path,
|
||||
const float* interleaved_samples,
|
||||
uint64_t sample_count,
|
||||
uint32_t channels,
|
||||
uint32_t sample_rate);
|
||||
|
||||
bool load_wav_from_file(const std::string& path,
|
||||
std::vector<float>& interleaved_samples,
|
||||
uint32_t& sample_rate,
|
||||
uint32_t& channels);
|
||||
|
||||
#endif // __MEDIA_IO_H__
|
||||
@@ -0,0 +1,276 @@
|
||||
#ifndef __EXAMPLE_RESOURCE_OWNERS_H__
|
||||
#define __EXAMPLE_RESOURCE_OWNERS_H__
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
struct FreeDeleter {
|
||||
void operator()(void* ptr) const {
|
||||
free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
struct FileCloser {
|
||||
void operator()(FILE* file) const {
|
||||
if (file != nullptr) {
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SDCtxDeleter {
|
||||
void operator()(sd_ctx_t* ctx) const {
|
||||
if (ctx != nullptr) {
|
||||
free_sd_ctx(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct UpscalerCtxDeleter {
|
||||
void operator()(upscaler_ctx_t* ctx) const {
|
||||
if (ctx != nullptr) {
|
||||
free_upscaler_ctx(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ADetailerCtxDeleter {
|
||||
void operator()(adetailer_ctx_t* ctx) const {
|
||||
if (ctx != nullptr) {
|
||||
free_adetailer_ctx(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using FreeUniquePtr = std::unique_ptr<T, FreeDeleter>;
|
||||
|
||||
using FilePtr = std::unique_ptr<FILE, FileCloser>;
|
||||
using SDCtxPtr = std::unique_ptr<sd_ctx_t, SDCtxDeleter>;
|
||||
using UpscalerCtxPtr = std::unique_ptr<upscaler_ctx_t, UpscalerCtxDeleter>;
|
||||
using ADetailerCtxPtr = std::unique_ptr<adetailer_ctx_t, ADetailerCtxDeleter>;
|
||||
|
||||
class SDImageOwner {
|
||||
private:
|
||||
static sd_image_t copy_image(const sd_image_t& image) {
|
||||
if (image.data == nullptr) {
|
||||
return {image.width, image.height, image.channel, nullptr};
|
||||
}
|
||||
|
||||
const size_t byte_count = static_cast<size_t>(image.width) * image.height * image.channel;
|
||||
uint8_t* raw_copy = static_cast<uint8_t*>(malloc(byte_count));
|
||||
if (raw_copy == nullptr) {
|
||||
return {0, 0, 0, nullptr};
|
||||
}
|
||||
|
||||
std::memcpy(raw_copy, image.data, byte_count);
|
||||
return {image.width, image.height, image.channel, raw_copy};
|
||||
}
|
||||
|
||||
sd_image_t image_ = {0, 0, 0, nullptr};
|
||||
|
||||
public:
|
||||
SDImageOwner() = default;
|
||||
explicit SDImageOwner(sd_image_t image)
|
||||
: image_(image) {
|
||||
}
|
||||
|
||||
SDImageOwner(const SDImageOwner& other)
|
||||
: image_(copy_image(other.image_)) {
|
||||
}
|
||||
|
||||
SDImageOwner& operator=(const SDImageOwner& other) {
|
||||
if (this != &other) {
|
||||
reset(copy_image(other.image_));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SDImageOwner(SDImageOwner&& other) noexcept
|
||||
: image_(other.release()) {
|
||||
}
|
||||
|
||||
SDImageOwner& operator=(SDImageOwner&& other) noexcept {
|
||||
if (this != &other) {
|
||||
reset();
|
||||
image_ = other.release();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SDImageOwner() {
|
||||
reset();
|
||||
}
|
||||
|
||||
sd_image_t* put() {
|
||||
if (image_.data != nullptr) {
|
||||
free(image_.data);
|
||||
image_.data = nullptr;
|
||||
}
|
||||
image_.width = 0;
|
||||
image_.height = 0;
|
||||
image_.channel = 0;
|
||||
return &image_;
|
||||
}
|
||||
|
||||
sd_image_t& get() {
|
||||
return image_;
|
||||
}
|
||||
|
||||
const sd_image_t& get() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
sd_image_t release() {
|
||||
sd_image_t image = image_;
|
||||
image_ = {0, 0, 0, nullptr};
|
||||
return image;
|
||||
}
|
||||
|
||||
void reset(sd_image_t image = {0, 0, 0, nullptr}) {
|
||||
if (image_.data != nullptr) {
|
||||
free(image_.data);
|
||||
}
|
||||
image_ = image;
|
||||
}
|
||||
};
|
||||
|
||||
class SDAudioOwner {
|
||||
private:
|
||||
uint32_t sample_rate_ = 0;
|
||||
uint32_t channels_ = 0;
|
||||
std::vector<float> samples_;
|
||||
|
||||
public:
|
||||
SDAudioOwner() = default;
|
||||
|
||||
void reset(std::vector<float> samples = {}, uint32_t sample_rate = 0, uint32_t channels = 0) {
|
||||
samples_ = std::move(samples);
|
||||
sample_rate_ = sample_rate;
|
||||
channels_ = channels;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return samples_.empty();
|
||||
}
|
||||
|
||||
sd_audio_t get() {
|
||||
return {sample_rate_,
|
||||
channels_,
|
||||
channels_ == 0 ? 0 : static_cast<uint64_t>(samples_.size() / channels_),
|
||||
samples_.empty() ? nullptr : samples_.data()};
|
||||
}
|
||||
|
||||
const std::vector<float>& samples() const {
|
||||
return samples_;
|
||||
}
|
||||
};
|
||||
|
||||
class SDImageVec {
|
||||
private:
|
||||
std::vector<sd_image_t> images_;
|
||||
|
||||
public:
|
||||
SDImageVec() = default;
|
||||
|
||||
SDImageVec(const SDImageVec&) = delete;
|
||||
SDImageVec& operator=(const SDImageVec&) = delete;
|
||||
|
||||
SDImageVec(SDImageVec&& other) noexcept
|
||||
: images_(std::move(other.images_)) {
|
||||
}
|
||||
|
||||
SDImageVec& operator=(SDImageVec&& other) noexcept {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
images_ = std::move(other.images_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~SDImageVec() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void push_back(sd_image_t image) {
|
||||
images_.push_back(image);
|
||||
}
|
||||
|
||||
void push_back(SDImageOwner&& image) {
|
||||
images_.push_back(image.release());
|
||||
}
|
||||
|
||||
void reserve(size_t count) {
|
||||
images_.reserve(count);
|
||||
}
|
||||
|
||||
void adopt(sd_image_t* images, int count) {
|
||||
clear();
|
||||
if (images == nullptr || count <= 0) {
|
||||
free(images);
|
||||
return;
|
||||
}
|
||||
|
||||
images_.reserve(static_cast<size_t>(count));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
images_.push_back(images[i]);
|
||||
}
|
||||
free(images);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return images_.size();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return images_.empty();
|
||||
}
|
||||
|
||||
int count() const {
|
||||
return static_cast<int>(images_.size());
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !images_.empty();
|
||||
}
|
||||
|
||||
sd_image_t* data() {
|
||||
return images_.data();
|
||||
}
|
||||
|
||||
const sd_image_t* data() const {
|
||||
return images_.data();
|
||||
}
|
||||
|
||||
sd_image_t& operator[](size_t index) {
|
||||
return images_[index];
|
||||
}
|
||||
|
||||
const sd_image_t& operator[](size_t index) const {
|
||||
return images_[index];
|
||||
}
|
||||
|
||||
std::vector<sd_image_t>& raw() {
|
||||
return images_;
|
||||
}
|
||||
|
||||
const std::vector<sd_image_t>& raw() const {
|
||||
return images_;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (sd_image_t& image : images_) {
|
||||
free(image.data);
|
||||
image.data = nullptr;
|
||||
}
|
||||
images_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __EXAMPLE_RESOURCE_OWNERS_H__
|
||||
Reference in New Issue
Block a user