首先,如果这是重复,我道歉;但今天我的Google-fu似乎让我失望了。
我正在为Photoshop编写图像格式模块,这种格式的保存选项之一包括一个4位alpha通道。当然,我必须转换的数据是8位/ 1字节alpha - 所以我需要基本上采用alpha的每两个字节,并将其合并为一个。
我的尝试(下面),我相信还有很大的改进空间:
for(int x=0,w=0;x < alphaData.size();x+=2,w++)
{
short ashort=(alphaData[x] << 8)+alphaData[x+1];
alphaFinal[w]=(unsigned char)ashort;
}
alphaData和alphaFinal分别是包含8位alpha数据和4位alpha数据的向量。我意识到将两个字节减少到一个值,必然会导致“分辨率”的丢失,但我不禁想到有更好的方法可以做到这一点。
有关额外信息,这里是反向循环(将4位alpha从格式转换为8位for Photoshop)
alphaData与上面的目的相同,imgData是一个保存原始图像数据的无符号字符向量。 (在该格式的特定变体中,在图像的实际rgb数据之后添加了alpha数据)
for(int b=alphaOffset,x2=0;b < (alphaOffset+dataLength); b++,x2+=2)
{
unsigned char lo = (imgData[b] & 15);
unsigned char hi = ((imgData[b] >> 4) & 15);
alphaData[x2]=lo*17;
alphaData[x2+1]=hi*17;
}
答案 0 :(得分:1)
你确定它是
alphaData[x2]=lo*17;
alphaData[x2+1]=hi*17;
而不是
alphaData[x2]=lo*16;
alphaData[x2+1]=hi*16;
在任何情况下,要生成与您发布的解码功能一起使用的值,您只需要反转操作。因此,乘以17将除以17,并且移位和掩码将重新排序为:
for(int x=0,w=0;x < alphaData.size();x+=2,w++)
{
unsigned char alpha1 = alphaData[x] / 17;
unsigned char alpha2 = alphaData[x+1] / 17;
Assert(alpha1 < 16 && alpha2 < 16);
alphaFinal[w]=(alpha2 << 4) | alpha1;
}
答案 1 :(得分:0)
short ashort=(alphaData[x] << 8)+alphaData[x+1];
alphaFinal[w]=(unsigned char)ashort;
你实际上在alphaFinal中丢失了alphaData [x]。您将alphaData [x]向左移8位,然后分配8个低位。
你的for循环也是不安全的,如果由于某种原因alphaData.size()是奇数,你将超出范围。
答案 2 :(得分:0)
output = (input >> 4); /* truncate four bits */
如果你不熟悉二进制移位,请使用这个随机的8位数字:
10110110
>> 1
= 01011011
>> 1
= 00101101
>> 1
= 00010110
>> 1
= 00001011
所以,
10110110
>> 4
= 00001011
反转,左移......
input = (output << 4); /* expand four bits */
,使用与之前相同的随机8位数的结果,
00001011
>> 4
= 10110000
显然,正如您所指出的,丢失了4位精度。但是你会惊讶地发现它在完全合成的作品中几乎没有注意到。
答案 3 :(得分:0)
此代码
for(int x=0,w=0;x < alphaData.size();x+=2,w++)
{
short ashort=(alphaData[x] << 8)+alphaData[x+1];
alphaFinal[w]=(unsigned char)ashort;
}
坏了。给定
#include <iostream>
using std::cout;
using std::endl;
typedef unsigned char uchar;
int main() {
uchar x0 = 1; // for alphaData[x]
uchar x1 = 2; // for alphaData[x+1]
short ashort = (x0 << 8) + x1; // The value 0x0102
uchar afinal = (uchar)ashort; // truncates to 0x02.
cout << std::hex
<< "x0 = 0x" << x0 << " << 8 = 0x" << (x0 << 8) << endl
<< "x1 = 0x" << x1 << endl
<< "ashort = 0x" << ashort << endl
<< "afinal = 0x" << (unsigned int)afinal << endl
;
}
如果您说您的源流包含存储在8位存储值中的4位对序列,您需要将其重新存储为单个8位值,那么您需要的是:
for(int x=0,w=0;x < alphaData.size();x+=2,w++)
{
unsigned char aleft = alphaData[x] & 0x0f; // 4 bits.
unsigned char aright = alphaData[x + 1] & 0x0f; // 4 bits.
alphaFinal[w] = (aleft << 4) | (aright);
}
“&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; 4&gt;相当于”* 16“,因为”&gt;&gt;&gt; 4“相当于”/ 16“。