OSB中的alpha模式
2025-04-24
4
0
alphpa模式有三种:
enum gs_image_alpha_mode {
GS_IMAGE_ALPHA_STRAIGHT,
GS_IMAGE_ALPHA_PREMULTIPLY_SRGB,
GS_IMAGE_ALPHA_PREMULTIPLY,
};
模式选择:
context->linear_alpha = obs_data_get_bool(settings, "linear_alpha");
context->linear_alpha ? GS_IMAGE_ALPHA_PREMULTIPLY_SRGB: GS_IMAGE_ALPHA_PREMULTIPLY
static void ffmpeg_source_defaults(obs_data_t *settings)
{
obs_data_set_default_bool(settings, "is_local_file", true);
obs_data_set_default_bool(settings, "looping", false);
obs_data_set_default_bool(settings, "clear_on_media_end", true);
obs_data_set_default_bool(settings, "restart_on_activate", true);
obs_data_set_default_bool(settings, "linear_alpha", false);
obs_data_set_default_int(settings, "reconnect_delay_sec", 10);
obs_data_set_default_int(settings, "buffering_mb", 2);
obs_data_set_default_int(settings, "speed_percent", 100);
}
GS_IMAGE_ALPHA_STRAIGHT
- 如果与目标大小相同,则整体复制
如果与目标行大小不同,则只取左侧
static void *ffmpeg_image_copy_data_straight(struct ffmpeg_image *info, AVFrame *frame) { const size_t linesize = (size_t)info->cx * 4; const size_t totalsize = info->cy * linesize; void *data = bmalloc(totalsize); const size_t src_linesize = frame->linesize[0]; if (linesize != src_linesize) { const size_t min_line = linesize < src_linesize ? linesize src_linesize; uint8_t *dst = data; const uint8_t *src = frame->data[0]; for (int y = 0; y < info->cy; y++) { memcpy(dst, src, min_line); dst += linesize; src += src_linesize; } } else { memcpy(data, frame->data[0], totalsize); } return data; }
GS_IMAGE_ALPHA_PREMULTIPLY_SRGB
const size_t linesize = (size_t)info->cx * 4;
const size_t totalsize = info->cy * linesize;
data = bmalloc(totalsize);
const size_t src_linesize = frame->linesize[0];
const size_t min_line = linesize < src_linesize ? linesize: src_linesize;
uint8_t *dst = data;
const uint8_t *src = frame->data[0];
const size_t row_elements = min_line >> 2;//width
if (alpha_mode == GS_IMAGE_ALPHA_PREMULTIPLY_SRGB)
{
for (int y = 0; y < info->cy; y++)
{
gs_premultiply_xyza_srgb_loop_restrict(dst, src, row_elements);
dst += linesize;
src += src_linesize;
}
}
static inline void
gs_premultiply_xyza_srgb_loop_restrict(uint8_t *__restrict dst,
const uint8_t *__restrict src,
size_t texel_count)
{
for (size_t i = 0; i < texel_count; ++i) {
gs_premultiply_xyza_srgb_restrict(dst, src);
dst += 4;
src += 4;
}
}
static inline void
gs_premultiply_xyza_srgb_restrict(uint8_t *__restrict dst,
const uint8_t *__restrict src)
{
uint8_t u[4];
float f[4];
memcpy(&u, src, sizeof(u));
//f = 1/255.0;
gs_u8x4_to_float4(f, u);
//调整数据
gs_float3_srgb_nonlinear_to_linear(f);
//rgb = rgb * a;
gs_premultiply_float4(f);
//调整数据
gs_float3_srgb_linear_to_nonlinear(f);
//rgb = f * 255.0f + 0.5f
gs_float3_to_u8x3(u, f);
memcpy(dst, &u, sizeof(u));
}
GS_IMAGE_ALPHA_PREMULTIPLY:
if (alpha_mode == GS_IMAGE_ALPHA_PREMULTIPLY)
{
for (int y = 0; y < info->cy; y++)
{
gs_premultiply_xyza_loop_restrict(dst, src, row_elements);
dst += linesize;
src += src_linesize;
}
}
static inline void
gs_premultiply_xyza_loop_restrict(uint8_t *__restrict dst,
const uint8_t *__restrict src,
size_t texel_count)
{
for (size_t i = 0; i < texel_count; ++i)
{
gs_premultiply_xyza_restrict(dst, src);
dst += 4;
src += 4;
}
}
static inline void gs_premultiply_xyza_restrict(uint8_t *__restrict dst,
const uint8_t *__restrict src)
{
uint8_t u[4];
float f[4];
memcpy(&u, src, sizeof(u));
//f = 1/255.0;
gs_u8x4_to_float4(f, u);
//rgb = rgb * a;
gs_premultiply_float4(f);
//rgb = f * 255.0f + 0.5f
gs_float3_to_u8x3(u, f);
memcpy(dst, &u, sizeof(u));
}
公共代码
static inline float gs_u8_to_float(uint8_t u)
{
return (float)u / 255.0f;
}
static inline void gs_u8x4_to_float4(float *f, const uint8_t *u)
{
f[0] = gs_u8_to_float(u[0]);
f[1] = gs_u8_to_float(u[1]);
f[2] = gs_u8_to_float(u[2]);
f[3] = gs_u8_to_float(u[3]);
}
static inline void gs_premultiply_float4(float *f)
{
f[0] *= f[3];
f[1] *= f[3];
f[2] *= f[3];
}
static inline void gs_float3_to_u8x3(uint8_t *u, const float *f)
{
u[0] = gs_float_to_u8(f[0]);
u[1] = gs_float_to_u8(f[1]);
u[2] = gs_float_to_u8(f[2]);
}
static inline uint8_t gs_float_to_u8(float f)
{
return (uint8_t)(f * 255.0f + 0.5f);
}