大多数现代CMOS相机都可以产生12bit的Bayered图像。 什么是最快方式将12位的图像数据转换为16位,这样可以进行处理?实际问题是用4个零填充每个12位数,可以假设小端,SSE2 / SSE3 / SS4也可以接受。
已添加代码:
int* imagePtr = (int*)Image.data;
fixed (float* imageData = img.Data)
{
float* imagePointer = imageData;
for (int t = 0; t < total; t++)
{
int i1 = *imagePtr;
imagePtr = (int*)((ushort*)imagePtr + 1);
int i2 = *imagePtr;
imagePtr = (int*)((ushort*)imagePtr + 2);
*imagePointer = (float)(((i1 << 4) & 0x00000FF0) | ((i1 >> 8) & 0x0000000F));
imagePointer++;
*imagePointer = (float)((i1 >> 12) & 0x00000FFF);
imagePointer++;
*imagePointer = (float)(((i2 >> 4) & 0x00000FF0) | ((i2 >> 12) & 0x0000000F));
imagePointer++;
*imagePointer = (float)((i2 >> 20) & 0x00000FFF);
imagePointer++;
}
}
答案 0 :(得分:2)
我无法保证最快,但这是一种使用SSE的方法。每次迭代完成8次12-16位转换,每步完成两次转换(大约)(即每次迭代需要多个步骤)。
这种方法横跨xmm寄存器中16位边界周围的12位整数。下面显示了这是如何完成的。
load
AAAB BBCC CDDD EEEF FFGG GHHH JJJK KKLL
^^^
>>2
00AA ABBB CCCD DDEE EFFF GGGH HHJJ JKKK
^^^ ^^^
>>2
0000 AAAB BBCC CDDD EEEF FFGG GHHH JJJK
^^^ ^^^
>>2
0000 00AA ABBB CCCD DDEE EFFF GGGH HHJJ
^^^ ^^^
>>2
0000 0000 AAAB BBCC CDDD EEEF FFGG GHHH
^^^
在每一步,我们都可以提取对齐的12位整数并将它们存储在xmm1寄存器中。最后,我们的xmm1将如下所示。问号表示我们不关心的值。
AAA? ?BBB CCC? ?DDD EEE? ?FFF GGG? ?HHH
将高对齐整数(A,C,E,G)提取到xmm2,然后在xmm2上执行4位右逻辑字移位。这会将高对齐整数转换为低对齐。将这些调整后的整数混合回xmm1。 xmm1的状态现在是:
?AAA ?BBB ?CCC ?DDD ?EEE ?FFF ?GGG ?HHH
最后,我们可以用每个单词的0FFFh屏蔽掉整数(即将?转换为0)。
0AAA 0BBB 0CCC 0DDD 0EEE 0FFF 0GGG 0HHH
现在xmm1包含八个连续转换的整数。
以下NASM程序演示了此算法。
global main
segment .data
sample dw 1234, 5678, 9ABCh, 1234, 5678, 9ABCh, 1234, 5678
low12 times 8 dw 0FFFh
segment .text
main:
movdqa xmm0, [sample]
pblendw xmm1, xmm0, 10000000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 01100000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00011000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00000110b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00000001b
pblendw xmm2, xmm1, 10101010b
psrlw xmm2, 4
pblendw xmm1, xmm2, 10101010b
pand xmm1, [low12] ; low12 could be stored in another xmm register
答案 1 :(得分:1)
我尝试围绕SSSE3指令构建解决方案PSHUFB
;
给定A = [a0,a1,a2,a3 ... a7],B = [b0,b1,b2,.. b7];
PSHUFB(A,B) = [a_b0, a_b1, a_b2, ... a_b7],
除了结果字节为零,如果bX的最高位为1。
因此,如果
A = [aa ab bb cc cd dd ee ef] == input vector
C=PSHUFB(A, [0 1 1 2 3 4 4 5]) = [aa ab ab bb cc cd cd dd]
C=PSRLW (C, [4 0 4 0]) = [0a aa ab bb 0c cc cd dd] // (>> 4)
C=PSLLW (C, 4) = [aa a0 bb b0 cc c0 dd d0] // << by immediate
完整的解决方案将读取3或6 mmx / xmm寄存器,每轮输出4/8 mmx / xmm寄存器。中间两个输出必须从两个输入块组合,需要一些额外的复制和寄存器组合。