要处理8位像素,要做伽马校正而不丢失信息,我们通常会对值进行上采样,以16位或其他方式工作,然后将它们下采样到8位。
现在,这对我来说是一个新的领域,所以请原谅不正确的术语等。
根据我的需要,我选择使用“非标准”Q15,其中我只使用范围的上半部分(0.0-1.0),而0x8000代表1.0而不是-1.0。这使得在C中计算事物变得更加容易。
但我遇到了SSSE3的问题。它有PMULHRSW指令乘以Q15数字,但它使用Q15的“标准”范围是[-1,1-2 - 19],所以乘以(我的)0x8000(1.0)乘以0x4000(0.5)给出0xC000( - 0.5),因为它认为0x8000是-1。这很烦人。
我做错了什么?我应该将像素值保持在0000-7FFF范围内吗?难道这种失败的目的是它是一种定点格式吗?有没有解决的办法?也许有些技巧?
Q15上是否有某种明确的论文讨论了所有这些?
答案 0 :(得分:3)
就个人而言,我会选择将最大值限制为0x7FFF(~0.99something)的解决方案。
-1.0
到+1.0-one lsb
。算术运算效果不好,因为1 lsb的值在0的每一侧都不同!除非你能想象自己成功地向一组议论性代码审查人员争论说,额外的一点对于算法的运行至关重要,而不仅仅是“最后0.01%的性能”,坚持每个人都能理解的代码,并映射到您可用的硬件。
或者,重新安排您之前的操作,以便所有像素都与您最初的像素相反。或者采取以下操作来消除您之前发送的内容。然后使用Q15格式的-1.0
到0.0
的值。
答案 1 :(得分:2)
如果您确定不会使用任何“大于”$8000
的数字,唯一的问题是当至少有一个乘数为$8000
时(-1,尽管您希望它是1)。
在这种情况下,解决方案相当简单:
pmulhrsw xmm0, xmm1
psignw xmm0, xmm0
或者,在我们的案例中完全相同(谢谢,Peter Cordes!):
pmulhrsw xmm0, xmm1
pabsw xmm0, xmm0
这会将负值从–1
乘以其正值。