You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VirtualDub插件开发:YUV图像色相调整不影响亮度的实现问询

调整YUV空间UV分量色相的实现方案

嘿,这个需求我太熟悉了!你要在不影响亮度的前提下调整色相,刚好可以直接在YUV空间对UV分量做旋转变换——完全碰不到Y分量,完美契合你的要求。

核心原理

YUV色彩空间里,U和V分量构成了一个二维平面:每个(UV)点的角度对应色相,距离原点的距离对应饱和度。调整色相本质上就是把这个平面上的所有点旋转指定角度,完全不会改变Y(亮度)值。

你的UV取值范围是-0.5到+0.5,我们只需要基于这个范围做旋转计算即可,步骤如下:

具体实现步骤

  1. 把UV从字节值转成归一化范围:
    你当前的U/V是0-255的字节值,先转成-0.5到+0.5的归一化值:

    float U_norm = (U / 255.0f) - 0.5f;
    float V_norm = (V / 255.0f) - 0.5f;
    
  2. 应用旋转矩阵计算调整后的UV:
    色相调整-45度,对应弧度是-π/4。旋转矩阵的公式是:

    U' = U_norm * cosθ - V_norm * sinθ
    V' = U_norm * sinθ + V_norm * cosθ

    因为cos(-45°)=sin(45°)=√2/2≈0.7071,sin(-45°)=-√2/2≈-0.7071,代入后可以简化为:

    const float sqrt2_over_2 = 0.70710678118f; // 预计算√2/2,提升性能
    float U_rotated = U_norm * sqrt2_over_2 + V_norm * sqrt2_over_2;
    float V_rotated = -U_norm * sqrt2_over_2 + V_norm * sqrt2_over_2;
    
  3. 把归一化值转回字节范围并 clamp:
    旋转后的UV可能超出-0.5到+0.5的范围,转成0-255字节值时需要限制范围,避免颜色异常:

    int U_new = static_cast<int>( (U_rotated + 0.5f) * 255.0f );
    int V_new = static_cast<int>( (V_rotated + 0.5f) * 255.0f );
    // 确保值在0-255之间,需要包含<algorithm>头文件
    U_new = std::clamp(U_new, 0, 255);
    V_new = std::clamp(V_new, 0, 255);
    

完整代码整合

结合你现有的代码,完整实现如下:

#include <algorithm> // 用于std::clamp

// ... 你的现有代码 ...
Pixel32 *dst= fa->dst.data;
int U= (*dst>>16) & 0xff;
int Y= (*dst>> 8) & 0xff;
int V= (*dst ) & 0xff;

// 色相调整-45度的核心逻辑
float U_norm = (U / 255.0f) - 0.5f;
float V_norm = (V / 255.0f) - 0.5f;

const float sqrt2_over_2 = 0.70710678118f;
float U_rotated = U_norm * sqrt2_over_2 + V_norm * sqrt2_over_2;
float V_rotated = -U_norm * sqrt2_over_2 + V_norm * sqrt2_over_2;

int U_new = static_cast<int>( (U_rotated + 0.5f) * 255.0f );
int V_new = static_cast<int>( (V_rotated + 0.5f) * 255.0f );
U_new = std::clamp(U_new, 0, 255);
V_new = std::clamp(V_new, 0, 255);

// 写回调整后的像素值
*dst = (U_new << 16) | (Y << 8) | V_new;

额外注意事项

  • 性能优化:如果是固定调整-45度,直接用预计算的sqrt2_over_2比调用cos()/sin()函数快很多,适合插件这种对性能敏感的场景。
  • 数据类型:一定要用浮点类型做中间计算,避免整数除法导致精度丢失。
  • 范围限制:std::clamp是C++17及以后的函数,如果你的编译器版本较低,可以手动实现范围限制:U_new = std::max(0, std::min(U_new, 255));

内容的提问来源于stack exchange,提问作者Captain Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:01:55