下面是C语言软件实现的alpha混合,功能与使用完全一致
//RGB888 转 RGB565
#ifndef RGB565
#define RGB565(color) ((((color) >> 19) & 0x1f) << 11) \
|((((color) >> 10) & 0x3f) << 5) \
|(((color) >> 3) & 0x1f)
#endif //RGB565
//RGB565转RGB888
#ifndef RGB888
#define RGB888(color) ((((color) >> 8) & 0xF8) << 16) \
|((((color) >> 3) & 0xFC) << 8) \
|(((color) << 3) & 0xFC)
#endif //RGB888
//RGB888转ARGB8888
#ifndef RGB888toARGB
#define RGB888toARGB(color) (color|0xFF000000)
#endif //RGB888toARGB
//ARGB 格式数据定义
typedef struct
{
u8 mB;
u8 mG;
u8 mR;
u8 mA;
}ARGB_DATA_TYPE;
//获取一个像素的数据长度
static u8 DMA2D_GetPidexByteSize(DMA2D_COLOR_MODE ColorMode)
{
switch (ColorMode)
{
case DMA2D_COLOR_ARGB8888: return 4;
case DMA2D_COLOR_RGB888: return 3;
default: return 2;
}
}
//转换一个像素为ARGB格式
static u32 __inline DMA2D_ConvPidexToARGB(u32 Color, DMA2D_COLOR_MODE ColorMode)
{
switch (ColorMode)
{
case DMA2D_COLOR_ARGB8888: //输入像素为ARGB8888,不用转换
{
return Color;
}
case DMA2D_COLOR_RGB888: //输入像素为RGB888,加上alpha通道数据
{
return RGB888toARGB(Color);
}
default: //输入像素为RGB565
{
return RGB888toARGB(RGB888(Color));
}
}
}
//处理一个像素的Alpha设置
static void __inline DMA2D_PidexAlphaModeHandle(u32 *pColor, u8 Alpha, DMA2D_ALPHA_MODE AlphaMode)
{
u16 temp;
ARGB_DATA_TYPE* pPidex = (ARGB_DATA_TYPE*)pColor;
switch (AlphaMode)
{
case DMA2D_ALPHA_REPLACE ://原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0]
{
pPidex->mA = Alpha;
}break;
case DMA2D_ALPHA_PRODUCT ://原始前景层图像的 alpha 通道值替换为 ALPHA[7: 0] 与原始 alpha 通道值的乘积
{
temp = Alpha;
temp *= pPidex->mA;
pPidex->mA = temp / 255;
}break;
default: break;//不修改前景层图像的 alpha 通道值
}
}
//进行2个像素混合,必须是ARGB888格式
static void __inline DMA2D_PixelMixing(ARGB_DATA_TYPE* pInBackPidex, ARGB_DATA_TYPE* pInForePidex, ARGB_DATA_TYPE* pOutPidex)
{
ARGB_DATA_TYPE tempARGB;
//先计算底层(背景默认为黑色)-底层有个黑色幕布,如果背景层的Alpha不是255,会先进行计算
if (pInBackPidex->mA < 255)
{
tempARGB.mR = ((u32)(pInBackPidex->mA) * pInBackPidex->mR) / 255;
tempARGB.mG = ((u32)(pInBackPidex->mA) * pInBackPidex->mG) / 255;
tempARGB.mB = ((u32)(pInBackPidex->mA) * pInBackPidex->mB) / 255;
}
else
{
memcpy(&tempARGB, pInBackPidex, 4); //不用计算混合,直接使用背景层
}
//背景层与前景层混合
pOutPidex->mR = (((u32)(pInForePidex->mA) * pInForePidex->mR) + (u32)(255 - pInForePidex->mA) * tempARGB.mR) / 255;
pOutPidex->mG = (((u32)(pInForePidex->mA) * pInForePidex->mG) + (u32)(255 - pInForePidex->mA) * tempARGB.mG) / 255;
pOutPidex->mB = (((u32)(pInForePidex->mA) * pInForePidex->mB) + (u32)(255 - pInForePidex->mA) * tempARGB.mB) / 255;
pOutPidex->mA = 0xFF; //混合后的最终图像不需要Alpha了,因为屏幕显示只需要RGB即可
}
//将ARGB8888数据格式转换为输出所需格式
static u32 __inline DMA2D_ARGBtOConvPidex(u32 Color, DMA2D_COLOR_MODE ColorMode)
{
switch (ColorMode)
{
case DMA2D_COLOR_ARGB8888: //输出像素为ARGB8888,不用转换
{
return Color;
}
case DMA2D_COLOR_RGB888: //输出像素为RGB888,去掉alpha通道数据
{
return Color & 0x00FFFFFF;
}
default: //输出像素为RGB565
{
return RGB565(Color);
}
}
}
/*************************************************************************************************************************
* 函数 : void DMA2D_FillImage_PixelMixing(DMA2D_PixelMixing_Parm *pParm)
* 功能 : DMA2D进行矩形图形填充(会执行像素格式转换与Alpha混合)
* 参数 : pParm:所需的参数,见DMA2D_PixelMixing_Parm
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2020-03-14
* 最后修改时间 : 2020-03-14
* 说明 : 用于填充图形,实现STM32F7的 DMA2D像素混合功能
*************************************************************************************************************************/
void DMA2D_FillImage_PixelMixing(DMA2D_PixelMixing_Parm* pParm)
{
u32 x, y;
//像素点缓冲区
u32 InBackPidex; //输入的背景像素
u32 InForePidex; //输入的前景像素
u32 OutPidex; //输出的像素
//像素点指针-用于alpha混合
ARGB_DATA_TYPE* pInBackPidex; //输入的背景像素ARGB格式指针
ARGB_DATA_TYPE* pInForePidex; //输入的前景像素ARGB格式指针
ARGB_DATA_TYPE* pOutPidex; //输出的像素ARGB格式指针
//像素大小-单位字节
u8 InBackPidexSize; //输入的背景像素
u8 InForePidexSize; //输入的前景像素
u8 OutPidexSize; //输出的像素
//当前处理的像素位置指针-字节指针
u8* pInBackPidexBytePoint; //输入的背景像素处理位置指针
u8* pInForePidexBytePoint; //输入的前景像素处理位置指针
u8* pOutPidexBytePoint; //输出的像素字节指针
//像素指针初始化
pInBackPidex = (ARGB_DATA_TYPE*)&InBackPidex; //输入的背景像素
pInForePidex = (ARGB_DATA_TYPE*)&InForePidex; //输入的前景像素
pOutPidex = (ARGB_DATA_TYPE*)&OutPidex; //输出的像素
//像素大小初始化
InBackPidexSize = DMA2D_GetPidexByteSize(pParm->InBackColorMode); //输入的背景像素
InForePidexSize = DMA2D_GetPidexByteSize(pParm->InForeColorMode); //输入的前景像素
OutPidexSize = DMA2D_GetPidexByteSize(pParm->OutColorMode); //输出的像素
//像素处理位置指针初始化
pInBackPidexBytePoint = (u8*)pParm->InBackImageAddr; //输入的背景像素处理位置指针
pInForePidexBytePoint = (u8*)pParm->InForeImageAddr; //输入的前景像素处理位置指针
pOutPidexBytePoint = (u8*)pParm->OutImageAddr; //输出的像素字节指针
for (y = 0; y < pParm->ImageHeight; y++)
{
for (x = 0; x < pParm->ImageWidth; x++)
{
//像素数据初始化为0
InBackPidex = 0; InForePidex = 0; OutPidex = 0;
//读取一个背景像素,转换为ARGB格式
memcpy(&InBackPidex, pInBackPidexBytePoint, InBackPidexSize); //读取一个输入的背景像素
InBackPidex = DMA2D_ConvPidexToARGB(InBackPidex, pParm->InBackColorMode); //转换为ARGB
DMA2D_PidexAlphaModeHandle(&InBackPidex, pParm->InBackAlpha, pParm->InBackAlphaMode); //处理一个像素的Alpha设置
pInBackPidexBytePoint += InBackPidexSize; //指针跳到下一个像素
//读取一个前景像素,转换为ARGB格式
memcpy(&InForePidex, pInForePidexBytePoint, InForePidexSize); //读取一个输入的前景像素
InForePidex = DMA2D_ConvPidexToARGB(InForePidex, pParm->InForeColorMode); //转换为ARGB
DMA2D_PidexAlphaModeHandle(&InForePidex, pParm->InForeAlpha, pParm->InForeAlphaMode); //处理一个像素的Alpha设置
pInForePidexBytePoint += InForePidexSize; //指针跳到下一个像素
//Alpha混合
DMA2D_PixelMixing(pInBackPidex, pInForePidex, pOutPidex); //进行2个像素混合,必须是ARGB888格式
//输出像素转换
OutPidex = DMA2D_ARGBtOConvPidex(OutPidex, pParm->OutColorMode); //将ARGB8888数据格式转换为输出所需格式
//拷贝最终数据到输出缓冲区中
memcpy(pOutPidexBytePoint, &OutPidex, OutPidexSize);
pOutPidexBytePoint += OutPidexSize; //指针跳到下一个像素
}
//一行处理完了,需要跳过一些X值
pInBackPidexBytePoint += pParm->InBackImageOffsetX * InBackPidexSize;
pInForePidexBytePoint += pParm->InForeImageOffsetX * InForePidexSize;
pOutPidexBytePoint += pParm->OutImageOffsetX * OutPidexSize;
}
}
|