ロゴ メインコンテンツへ
RSSフィード
「開発記録」に関連する記事一覧

オリジナル映像編集ソフト開発記録 - レイヤーモード機能 -

2013/02/03
(この記事の文字数: 194)

オリジナル映像編集ソフトにレイヤーモードを切り替えられる機能をつけました。

下記の15種類のレイヤーモードをとりあえず実装しました。

説明とか何も入ってないですが、どなたかのお役に立つかもしれないので、レイヤーモードごとの画像ブレンドをする関数のC++ソースコードを載せておきます。

ただし、Photoshopなどのレイヤーモードと比べると結果が異なる可能性は十分にありますのでご注意ください。



typedef float BlendCalcType;

inline BlendCalcType BlendValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return blend_value;
}

inline BlendCalcType DarkenValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return base_value < blend_value? base_value : blend_value;
}

inline BlendCalcType MultiplyValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value = blend_value/255.0f;
    if( tmp_value > 1.0f)
    {
        tmp_value = 1.0f;
    }
    return base_value * tmp_value;
}

inline BlendCalcType BurnValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value;
    if (blend_value == 0) tmp_value = 0;
    else tmp_value = 255 - ((255 - base_value) * 255 / blend_value);

    return (tmp_value < 0)? 0 : tmp_value;
}

inline BlendCalcType LightenValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return base_value > blend_value? base_value : blend_value;
}

inline BlendCalcType AddValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value = base_value + blend_value;
    if( tmp_value > 255.0 )
    {
        tmp_value = 255.0;
    }
    return tmp_value;
}

inline BlendCalcType ScreenValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return 255 - ((255 - base_value) * (255 - blend_value)) / 255;
}

inline BlendCalcType DodgeValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value;
    if (blend_value == 255){ tmp_value = 255; }
    else{ tmp_value = base_value * 255 / (255 - blend_value); }

    return (tmp_value > 255)? 255 : tmp_value;
}

inline BlendCalcType OverlayValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value;
    if (base_value < 128){ tmp_value = base_value * blend_value * 2 / 255; }
    else{ tmp_value = 2 * (base_value + blend_value - base_value * blend_value / 255) - 255; }

    return (tmp_value > 255)? 255 : tmp_value;
}

inline BlendCalcType SoftLightValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return blend_value < 128?
        (pow((base_value / 255), ((255 - blend_value)) / 128)) * 255
        : pow((base_value / 255), (128 / blend_value)) * 255;
}

inline BlendCalcType HardLightValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value;
    if (blend_value < 128){ tmp_value = base_value * blend_value * 2 / 255; }
    else{ tmp_value = 2 * (base_value + blend_value - base_value * blend_value / 255) - 255; }

    return (tmp_value > 255)? 255: tmp_value;
}

inline BlendCalcType SubtractValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    BlendCalcType tmp_value = base_value - blend_value;
    return tmp_value < 0? 0 : tmp_value;
}

inline BlendCalcType DifferenceValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return fabs(base_value - blend_value);
}

inline BlendCalcType DivideValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    if( blend_value==0 ){ return 255; }
    BlendCalcType tmp_value = base_value * 255 / blend_value;
    return tmp_value>255? 255: tmp_value;
}

inline BlendCalcType ExclusionValue(
    BlendCalcType base_value, BlendCalcType blend_value
)
{
    return base_value + blend_value - 2 * base_value * blend_value / 255;
}

template<typename _Type>
void BlendMain(
    _Type       *io_base_img, 
    const _Type *in_overlay_img,
    const u8    *in_alpha_data, 
    u32 width_step, u32 height, u32 num_channels, 
    BlendCalcType (*BlendFunc) ( BlendCalcType, BlendCalcType )
)
{
    float transmittance;
    const _Type *blend_ptr = in_overlay_img;
    const u8 *alpha_ptr  = in_alpha_data;
    _Type *dst_ptr     = io_base_img;
    _Type *dst_end_ptr = dst_ptr + width_step * height;
    _Type *c_ep;
    double tmp_value;
    for( ; dst_ptr!=dst_end_ptr; ++alpha_ptr ) 
    {
        transmittance = (*alpha_ptr)/255.0f;
        for( c_ep = dst_ptr + num_channels; dst_ptr!=c_ep; ++dst_ptr, ++blend_ptr) 
        {
            *dst_ptr = *dst_ptr * (1.0f-transmittance) +
                (_Type)BlendFunc( (BlendCalcType)*dst_ptr, (BlendCalcType)*blend_ptr ) * transmittance;
        }
    }
}

  このエントリーをはてなブックマークに追加  

<<「開発記録」の記事一覧に戻る

コメント(0 件)



コンテンツロード: 0.0082 sec
Copyright(C)2006-2024 puarts All Rights Reserved