使用SSE2优化RGB565到RGB888的转换
Optimizing RGB565 to RGB888 conversions with SSE2
我正在尝试使用SSE2优化从565到888的像素深度转换,其基本公式为:
col8 = col5 << 3 | col5 >> 2
col8 = col6 << 2 | col6 >> 4
我取两个2x565 128位矢量,输出3x888 128位矢量。
经过一些掩蔽、移位和"或"运算,我得出了这样一个点,即在16位字中存储了两个具有((蓝色<<8)|红色)*8位颜色的矢量和一个具有零绿色值的类似矢量。现在我需要将它们组合成888输出。
BR: BR7-BR6-...-BR1-BR0
0G: 0G7-0G7-...-0G1-0G0
|
v
OUT1: R5-BGR4-...-BGR1-BGR0
在SSSE3中有一个_mm_shuffle_epi8(),它解决了我的需求,但由于我需要支持的硬件范围,我想将自己限制在SSE2。
- 它是小endian
你可以参考谷歌的libyuv项目,它有SSE2转换:
https://chromium.googlesource.com/libyuv/libyuv/+/master/source/row_win.cc
// pmul method to replicate bits.
// Math to replicate bits:
// (v << 8) | (v << 3)
// v * 256 + v * 8
// v * (256 + 8)
// G shift of 5 is incorporated, so shift is 5 + 8 and 5 + 3
// 20 instructions.
__declspec(naked)
void RGB565ToARGBRow_SSE2(const uint8* src_rgb565, uint8* dst_argb,
int width) {
__asm {
mov eax, 0x01080108 // generate multiplier to repeat 5 bits
movd xmm5, eax
pshufd xmm5, xmm5, 0
mov eax, 0x20802080 // multiplier shift by 5 and then repeat 6 bits
movd xmm6, eax
pshufd xmm6, xmm6, 0
pcmpeqb xmm3, xmm3 // generate mask 0xf800f800 for Red
psllw xmm3, 11
pcmpeqb xmm4, xmm4 // generate mask 0x07e007e0 for Green
psllw xmm4, 10
psrlw xmm4, 5
pcmpeqb xmm7, xmm7 // generate mask 0xff00ff00 for Alpha
psllw xmm7, 8
mov eax, [esp + 4] // src_rgb565
mov edx, [esp + 8] // dst_argb
mov ecx, [esp + 12] // width
sub edx, eax
sub edx, eax
convertloop:
movdqu xmm0, [eax] // fetch 8 pixels of bgr565
movdqa xmm1, xmm0
movdqa xmm2, xmm0
pand xmm1, xmm3 // R in upper 5 bits
psllw xmm2, 11 // B in upper 5 bits
pmulhuw xmm1, xmm5 // * (256 + 8)
pmulhuw xmm2, xmm5 // * (256 + 8)
psllw xmm1, 8
por xmm1, xmm2 // RB
pand xmm0, xmm4 // G in middle 6 bits
pmulhuw xmm0, xmm6 // << 5 * (256 + 4)
por xmm0, xmm7 // AG
movdqa xmm2, xmm1
punpcklbw xmm1, xmm0
punpckhbw xmm2, xmm0
movdqu [eax * 2 + edx], xmm1 // store 4 pixels of ARGB
movdqu [eax * 2 + edx + 16], xmm2 // store next 4 pixels of ARGB
lea eax, [eax + 16]
sub ecx, 8
jg convertloop
ret
}
}
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- SSE2优化用于从RGB565转换为RGB888(无alpha通道)
- 使用SSE2优化RGB565到RGB888的转换
- 为什么多次将RGB888转换为RGB565会导致颜色损失
- 如何将RGB888转换为拜耳GB/BG/GR格式
- 如何在C++中将16位十六进制颜色转换为RGB888值