📄 dxhelper.h
字号:
{
DWORD v = Sample;
DWORD r = (BYTE)(v >> 16);
DWORD g = (BYTE)(v >> 8);
DWORD b = (BYTE)(v);
DWORD sat = (r*306 + g*601 + b*117) / 1024;
v &= 0xFF000000;
v |= (sat << 16) | (sat << 8) | sat;
return v;
} /* DXConvertToGray */
//--- This returns into the destination the value of the source
// sample scaled by its own alpha (producing a premultiplied alpha sample)
//
inline DXPMSAMPLE DXPreMultSample(const DXSAMPLE & Src)
{
if(Src.Alpha == 255 )
{
return (DWORD)Src;
}
else if(Src.Alpha == 0 )
{
return 0;
}
else
{
unsigned t1, t2;
t1 = (Src & 0x00ff00ff) * Src.Alpha + 0x00800080;
t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
t2 = (((Src >> 8) & 0x000000ff) | 0x01000000) * Src.Alpha + 0x00800080;
t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
return (t1 | t2);
}
} /* DXPreMultSample */
inline DXPMSAMPLE * DXPreMultArray(DXSAMPLE *pBuffer, ULONG cSamples)
{
for (ULONG i = 0; i < cSamples; i++)
{
BYTE SrcAlpha = pBuffer[i].Alpha;
if (SrcAlpha != 0xFF)
{
if (SrcAlpha == 0)
{
pBuffer[i] = 0;
}
else
{
DWORD S = pBuffer[i];
DWORD t1 = (S & 0x00ff00ff) * SrcAlpha + 0x00800080;
t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
DWORD t2 = (((S >> 8) & 0x000000ff) | 0x01000000) * SrcAlpha + 0x00800080;
t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
pBuffer[i] = (t1 | t2);
}
}
}
return (DXPMSAMPLE *)pBuffer;
}
inline DXSAMPLE DXUnPreMultSample(const DXPMSAMPLE & Src)
{
if(Src.Alpha == 255 || Src.Alpha == 0)
{
return (DWORD)Src;
}
else
{
DXSAMPLE Dst;
Dst.Blue = (BYTE)((Src.Blue * 255) / Src.Alpha);
Dst.Green = (BYTE)((Src.Green * 255) / Src.Alpha);
Dst.Red = (BYTE)((Src.Red * 255) / Src.Alpha);
Dst.Alpha = Src.Alpha;
return Dst;
}
} /* DXUnPreMultSample */
inline DXSAMPLE * DXUnPreMultArray(DXPMSAMPLE *pBuffer, ULONG cSamples)
{
for (ULONG i = 0; i < cSamples; i++)
{
BYTE SrcAlpha = pBuffer[i].Alpha;
if (SrcAlpha != 0xFF && SrcAlpha != 0)
{
pBuffer[i].Blue = (BYTE)((pBuffer[i].Blue * 255) / SrcAlpha);
pBuffer[i].Green = (BYTE)((pBuffer[i].Green * 255) / SrcAlpha);
pBuffer[i].Red = (BYTE)((pBuffer[i].Red * 255) / SrcAlpha);
}
}
return (DXSAMPLE *)pBuffer;
}
//
// This returns the result of 255-Alpha which is computed by doing a NOT
//
inline BYTE DXInvertAlpha( BYTE Alpha ) { return (BYTE)~Alpha; }
inline DWORD DXScaleSample( DWORD Src, ULONG beta )
{
ULONG t1, t2;
t1 = (Src & 0x00ff00ff) * beta + 0x00800080;
t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
t2 = ((Src >> 8) & 0x00ff00ff) * beta + 0x00800080;
t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
return (DWORD)(t1 | t2);
}
inline DWORD DXScaleSamplePercent( DWORD Src, float Percent )
{
if (Percent > (254.0f / 255.0f)) {
return Src;
}
else
{
return DXScaleSample(Src, (BYTE)(Percent * 255));
}
}
inline void DXCompositeOver(DXPMSAMPLE & Dst, const DXPMSAMPLE & Src)
{
if (Src.Alpha)
{
ULONG Beta = DXInvertAlpha(Src.Alpha);
if (Beta)
{
Dst = Src + DXScaleSample(Dst, Beta);
}
else
{
Dst = Src;
}
}
}
inline DXPMSAMPLE DXCompositeUnder(DXPMSAMPLE Dst, DXPMSAMPLE Src )
{
return Dst + DXScaleSample(Src, DXInvertAlpha(Dst.Alpha));
}
inline DXBASESAMPLE DXApplyLookupTable(const DXBASESAMPLE Src, const BYTE * pTable)
{
DXBASESAMPLE Dest;
Dest.Blue = pTable[Src.Blue];
Dest.Green = pTable[Src.Green];
Dest.Red = pTable[Src.Red];
Dest.Alpha = pTable[Src.Alpha];
return Dest;
}
inline DXBASESAMPLE * DXApplyLookupTableArray(DXBASESAMPLE *pBuffer, ULONG cSamples, const BYTE * pTable)
{
for (ULONG i = 0; i < cSamples; i++)
{
DWORD v = pBuffer[i];
DWORD a = pTable[v >> 24];
DWORD r = pTable[(BYTE)(v >> 16)];
DWORD g = pTable[(BYTE)(v >> 8)];
DWORD b = pTable[(BYTE)v];
pBuffer[i] = (a << 24) | (r << 16) | (g << 8) | b;
}
return pBuffer;
}
inline DXBASESAMPLE * DXApplyColorChannelLookupArray(DXBASESAMPLE *pBuffer,
ULONG cSamples,
const BYTE * pAlphaTable,
const BYTE * pRedTable,
const BYTE * pGreenTable,
const BYTE * pBlueTable)
{
for (ULONG i = 0; i < cSamples; i++)
{
pBuffer[i].Blue = pBlueTable[pBuffer[i].Blue];
pBuffer[i].Green = pGreenTable[pBuffer[i].Green];
pBuffer[i].Red = pRedTable[pBuffer[i].Red];
pBuffer[i].Alpha = pAlphaTable[pBuffer[i].Alpha];
}
return pBuffer;
}
//
// CDXScale helper class
//
// This class uses a pre-computed lookup table to scale samples. For scaling large
// arrays of samples to a constant scale, this is much faster than using even MMX
// instructions. This class is usually declared as a member of another class and
// is most often used to apply a global opacity to a set of samples.
//
// When using this class, you must always check for the two special cases of clear
// and opaque before calling any of the scaling member functions. Do this by using
// the ScaleType() inline function. Your code should look somthing like this:
//
// if (ScaleType() == DXRUNTYPE_CLEAR)
// Do whatever you do for a 0 alpha set of samples -- usually just ignore them
// else if (ScaleType() == DXRUNTYPE_OPAQUE)
// Do whatever you would do for a non-scaled set of samples
// else
// Scale the samples by using ScaleSample or one of the ScaleArray members
//
// If you call any of the scaling members when the ScaleType() is either clear or
// opaque, you will GP fault becuase the lookup table will not be allocated.
//
// The scale can be set using either a floating point number between 0 and 1 using:
// CDXScale::SetScale / CDXScale::GetScale
// or you can use a byte integer value by using:
// CDXScale::SetScaleAlphaValue / CDXScale::GetScaleAlphaValue
//
class CDXScale
{
private:
float m_Scale;
BYTE m_AlphaScale;
BYTE *m_pTable;
HRESULT InternalSetScale(BYTE Scale)
{
if (m_AlphaScale == Scale) return S_OK;
if (Scale == 0 || Scale == 255)
{
delete m_pTable;
m_pTable = NULL;
}
else
{
if(!m_pTable)
{
m_pTable = new BYTE[256];
if(!m_pTable )
{
return E_OUTOFMEMORY;
}
}
for (int i = 0; i < 256; ++i )
{
m_pTable[i] = (BYTE)((i * Scale) / 255);
}
}
m_AlphaScale = Scale;
return S_OK;
}
public:
CDXScale() :
m_Scale(1.0f),
m_AlphaScale(0xFF),
m_pTable(NULL)
{}
~CDXScale()
{
delete m_pTable;
}
DXRUNTYPE ScaleType()
{
if (m_AlphaScale == 0) return DXRUNTYPE_CLEAR;
if (m_AlphaScale == 0xFF) return DXRUNTYPE_OPAQUE;
return DXRUNTYPE_TRANS;
}
HRESULT SetScaleAlphaValue(BYTE Alpha)
{
HRESULT hr = InternalSetScale(Alpha);
if (SUCCEEDED(hr))
{
m_Scale = ((float)Alpha) / 255.0f;
}
return hr;
}
BYTE GetScaleAlphaValue(void)
{
return m_AlphaScale;
}
HRESULT SetScale(float Scale)
{
HRESULT hr = S_OK;
if(( Scale < 0.0f ) || ( Scale > 1.0f ) )
{
hr = E_INVALIDARG;
}
else
{
ULONG IntScale = (ULONG)(Scale * 256.0f); // Round up alpha (.9999 = 255 = Solid)
if (IntScale > 255)
{
IntScale = 255;
}
hr = SetScaleAlphaValue((BYTE)IntScale);
if (SUCCEEDED(hr))
{
m_Scale = Scale;
}
}
return hr;
}
float GetScale() const
{
return m_Scale;
}
DXRUNTYPE ScaleType() const
{
return (m_pTable ? DXRUNTYPE_TRANS : (m_AlphaScale ? DXRUNTYPE_OPAQUE : DXRUNTYPE_CLEAR));
}
DWORD ScaleSample(const DWORD s) const
{
return DXApplyLookupTable((DXBASESAMPLE)s, m_pTable);
}
DXBASESAMPLE * ScaleBaseArray(DXBASESAMPLE * pBuffer, ULONG cSamples) const
{
return DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
}
DXPMSAMPLE * ScalePremultArray(DXPMSAMPLE * pBuffer, ULONG cSamples) const
{
return (DXPMSAMPLE *)DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
}
DXSAMPLE * ScaleArray(DXSAMPLE * pBuffer, ULONG cSamples) const
{
return (DXSAMPLE *)DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
}
DXSAMPLE * ScaleArrayAlphaOnly(DXSAMPLE *pBuffer, ULONG cSamples) const
{
const BYTE *pTable = m_pTable;
for (ULONG i = 0; i < cSamples; i++)
{
pBuffer[i].Alpha = pTable[pBuffer[i].Alpha];
}
return pBuffer;
}
};
inline DWORD DXWeightedAverage( DXBASESAMPLE S1, DXBASESAMPLE S2, ULONG Wgt )
{
_ASSERT( Wgt < 256 );
ULONG t1, t2;
ULONG InvWgt = Wgt ^ 0xFF;
t1 = (((S1 & 0x00ff00ff) * Wgt) + ((S2 & 0x00ff00ff) * InvWgt )) + 0x00800080;
t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -