Skip to content

Instantly share code, notes, and snippets.

@jin1016
Created April 6, 2014 04:26
Show Gist options
  • Save jin1016/10001549 to your computer and use it in GitHub Desktop.
Save jin1016/10001549 to your computer and use it in GitHub Desktop.
#ifndef __BLEND_VARIATION_H__
#define __BLEND_VARIATION_H__
/**
* アルファの扱い方によって発生するバリエーションを作りやすくするためのファンクタ
* blend_func は、
* tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s, tjs_uint32 a )
* を持つファンクタ
*/
//--------------------------------------------------------------------------------------------------------
// アルファの扱い
//--------------------------------------------------------------------------------------------------------
// srcのアルファを使用するバージョン
template<class blend_func>
struct normal_op {
blend_func func_;
inline normal_op() {}
inline normal_op(tjs_uint32 opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
tjs_uint32 a = (s>>24);
return func_(d,s,a);
}
};
//--------------------------------------------------------------------------------------------------------
// 透明度を指定するバージョン
template<class blend_func>
struct translucent_op {
const tjs_int opa_;
blend_func func_;
inline translucent_op() : opa_(255) {}
inline translucent_op(tjs_uint32 opa) : opa_(opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
tjs_uint32 a = ((s>>24)*opa_)>>8;
return func_(d,s,a);
}
};
//--------------------------------------------------------------------------------------------------------
// destアルファを保護するバージョン
template<class blend_func>
struct hda_op {
blend_func func_;
inline hda_op(){}
inline hda_op(tjs_uint32 opa){}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
tjs_uint32 a = (s>>24)
return (func_(d,s,a)&0x00ffffff) | (d&0xff000000);
}
};
//--------------------------------------------------------------------------------------------------------
// destアルファを保護し、透明度を指定するバージョン
template<class blend_func>
struct hda_translucent_op {
const tjs_uint32 opa_;
blend_func func_;
inline hda_translucent_op() : opa_(255) {}
inline hda_translucent_op(tjs_uint32 opa) : opa_(opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
tjs_uint32 a = ((s>>24)*opa_)>>8;
return (func_(d,s,a)&0x00ffffff) | (d&0xff000000);
}
};
//--------------------------------------------------------------------------------------------------------
// destのアルファを使用するバージョン
template<class blend_func>
struct dest_alpha_op {
blend_func func_;
inline normal_op() {}
inline normal_op(tjs_uint32 opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
#ifdef NOT_USE_TABLE
tjs_uint32 sa = s >> 24;
tjs_uint32 da = d >> 24;
tjs_uint32 sopa;
if( da ) {
float at = (float)(da/255.0);
float bt = (float)(sa/255.0);
float c = bt / at;
c /= (float)( (1.0 - bt + c) );
tjs_uint32 sopa = (tjs_uint32)(c*255);
} else {
sopa = 255;
}
tjs_uint32 destalpha = (unsigned char)( 255 - (255-da)*(255-sa)/ 255 );
#else
tjs_uint32 addr = ((s >> 16) & 0xff00) + (d>>24);
tjs_uint32 destalpha = TVPNegativeMulTable[addr]<<24;
tjs_uint32 sopa = TVPOpacityOnOpacityTable[addr];
#endif
return func_(d,s,sopa) + destalpha;
}
// (sa/da) / ( 1 - sa + (sa/da) )
// 1 / (sa+da)
// 1 - (1-da)*(1-sa)
// 1 - sa - da + da*sa
// ca = a + ba
// ca = a + ba;
// ca = a + ba;
// ca = a + (((255-a)*da)/255
};
//--------------------------------------------------------------------------------------------------------
// destのアルファを使用する、透明度を指定するバージョン
template<class blend_func>
struct dest_alpha_translucent_op {
const tjs_int opa_;
blend_func func_;
inline translucent_op() : opa_(255) {}
inline translucent_op(tjs_uint32 opa) : opa_(opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
#ifdef NOT_USE_TABLE
tjs_uint32 sa = ((s>>24)*opa_)>>8;
tjs_uint32 da = d >> 24;
tjs_uint32 sopa;
if( da ) {
float at = (float)(da/255.0);
float bt = (float)(sa/255.0);
float c = bt / at;
c /= (float)( (1.0 - bt + c) );
tjs_uint32 sopa = (tjs_uint32)(c*255);
} else {
sopa = 255;
}
tjs_uint32 destalpha = (unsigned char)( 255 - (255-da)*(255-sa)/ 255 );
#else
tjs_uint32 addr = (( (s>>24)*opa_) & 0xff00) + (d>>24);
tjs_uint32 destalpha = TVPNegativeMulTable[addr]<<24;
tjs_uint32 sopa = TVPOpacityOnOpacityTable[addr];
#endif
return func_(d,s,sopa) + destalpha;
}
};
//--------------------------------------------------------------------------------------------------------
#if 0
// 不透明バージョン 特殊版を作った方が高速
template<class blend_func>
struct opacity_op {
blend_func func_;
inline opacity_op(){}
inline opacity_op(tjs_uint32 opa){}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
return func_(d,s,255);
}
};
//--------------------------------------------------------------------------------------------------------
// 不透明バージョン 透明度を指定する
template<class blend_func>
struct opacity_translucent_op {
const tjs_uint32 opa_;
blend_func func_;
inline opacity_translucent_op() : opa_(255) {}
inline opacity_translucent_op(tjs_uint32 opa) : opa_(opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
return func_(d,s,opa_);
}
};
//--------------------------------------------------------------------------------------------------------
#endif
#endif // __BLEND_VARIATION_H__
#ifndef __ALPHA_BLEND_C_H__
#define __ALPHA_BLEND_C_H__
#include "blend_util_func.h"
#include "blend_variation.h"
//------------------------------------------------------------------------------
/**
* alpha_blend_functor; // dstアルファ無視
* alpha_blend_HDA_functor; // dstアルファ無視, dst アルファ保護
* alpha_blend_o_functor; // dstアルファ無視, opacity 指定
* alpha_blend_HDA_o_functor; // dstアルファ無視, dst アルファ保護, opacity 指定
*
* alpha_blend_d_functor; // dstアルファ有効
* alpha_blend_do_functor; // dstアルファ有効, opacity 指定
*
* alpha_blend_a_functor; // dstアルファ有効, addalpha(pre-multiplied alpha)
* alpha_blend_ao_functor; // dstアルファ有効, opacity 指定, addalpha(pre-multiplied alpha)
*/
//------------------------------------------------------------------------------
struct alpha_blend_func {
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s, tjs_uint32 a ) const {
tjs_uint32 d1 = d & 0xff00ff;
d1 = (d1 + (((s & 0xff00ff) - d1) * a >> 8)) & 0xff00ff;
d &= 0xff00;
s &= 0xff00;
return d1 + ((d + ((s - d) * a >> 8)) & 0xff00);
}
};
typedef normal_op<alpha_blend_func> alpha_blend_functor;
typedef translucent_op<alpha_blend_func> alpha_blend_o_functor;
typedef hda_op<alpha_blend_func> alpha_blend_HDA_functor;
typedef hda_translucent_op<alpha_blend_func> alpha_blend_HDA_o_functor;
typedef dest_alpha_op<alpha_blend_func> alpha_blend_d_functor;
typedef dest_alpha_translucent_op<alpha_blend_func> alpha_blend_do_functor;
//------------------------------------------------------------------------------
struct alpha_blend_a_functor {
premulalpha_blend_func blend_;
alpha_to_additive_alpha_func topremulalpha_;
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
return blend_( dest, topremulalpha_(s) );
}
};
//------------------------------------------------------------------------------
struct alpha_blend_ao_functor {
tjs_int opa_;
alpha_blend_a_functor blend_;
inline alpha_blend_ao_functor( tjs_int opa ) : opa_(opa) {}
inline tjs_uint32 operator()( tjs_uint32 d, tjs_uint32 s ) const {
s = (s & 0xffffff) + ((((s >> 24) * opa_) >> 8) << 24);
return blend_(d,s);
}
};
//------------------------------------------------------------------------------
#endif // __ALPHA_BLEND_C_H__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment