如何将一个16位无符号整数转换为较大的8位无符号整数?

4

我有一个函数需要返回一个16位无符号整数向量,但是对于另一个我也调用这个函数的函数,我需要以8位无符号整数向量格式输出。例如,如果我开始是这样的:

std::vector<uint16_t> myVec(640*480);

我该如何将它转换成以下格式:
std::vector<uint8_t> myVec2(640*480*4);

更新(更多信息): 我正在使用libfreenect及其getDepth()方法。我已经修改了它以输出一个16位无符号整数向量,以便我可以检索深度数据(以毫米为单位)。然而,我也想显示深度数据。我正在使用来自freenect安装的一些示例代码c ++,它使用glut并需要一个8位无符号整数向量来显示深度,但是,我需要16位来检索以毫米为单位的深度并将其记录到文本文件中。因此,我希望在glut的绘制函数中以16位无符号整数向量的形式检索数据,然后进行转换,以便我可以使用已经编写好的glut函数显示它。


需要更多信息。8位值如何与16位值相关联? - Galik
如果不复制数据(即您想重新分配所有权并重新解释底层缓冲区的类型),这将非常困难,因为std::vector没有公开任何外部覆盖其内部缓冲区指针的方法。 - Dai
你想做的事情比仅仅将16位数字转换为8位数字更加复杂,请查看我的答案获取更多信息。 - RyanP
那么您的两个向量中都有相同数量的值对吗?如何将16位的单个值转换为8位?它们需要以某种方式进行缩放吗?最大的 16 位值是否需要映射到最大的 8 位值(例如)? - Galik
这真的很困惑。 - Lightness Races in Orbit
显示剩余2条评论
3个回答

3
我该如何将它转换为以下格式: std::vector myVec2; 使得myVec2.size()是myVec.size()的两倍?
myVec2.reserve(myVec.size() * 2);
for (auto it = begin(myVec); it!=end(myVec); ++it)
{
    uint8_t val = static_cast<uint8_t>(*it); // isolate the low 8 bits
    myVec2.push_back(val);
    val = static_cast<uint8_t>((*it) >> 8); // isolate the upper 8 bits
    myVec2.push_back(val);
}

或者你可以改变push_back()的顺序,如果需要确定哪个字节先出现(上半部分还是下半部分)。


3
根据您的更新,假设8位无符号整数将显示为灰度图像,您需要类似于亮度转移函数的内容。基本上,您的输出函数正在寻找将数据映射到0-255值,但您不一定希望它们直接对应于毫米。如果您的所有数据都来自0-3mm呢?那么您的图像看起来几乎是黑色的。如果它全部是300-400mm呢?那么它将完全变成白色,因为它被剪切为255。
一个简单的方法是找到最小和最大值,然后执行以下操作:
double scale = 255.0 / (double)(maxVal - minVal);
for( int i = 0; i < std::min(myVec.size(), myVec2.size()); ++i )
{
    myVec2.at(i) = (unsigned int)((double)(myVec.at(i)-minVal) * scale);
}

根据数据的分布情况,您可能需要做一些更复杂的操作以充分利用动态范围。
编辑:这假设您的glut函数正在创建图像,如果它将8位值用作图形的输入,则可以忽略。
编辑2:在您的其他更新后进行更新。如果您想填充一个640x480x4向量,显然您正在处理图像。您需要执行我上面概述的操作,但还需要考虑红色、绿色、蓝色和Alpha等四个维度。Alpha通道始终需要为255(这控制其透明度,您不希望它是透明的),至于另外3个通道...如果您将所有3个通道(通道指红、绿和蓝)设置为相同的值,则它看起来会呈现灰度。例如,如果我的数据范围为0-25毫米,对于值为10毫米的像素,我将设置数据为255/(25-0)* 10 = 102,因此像素将是(102,102,102,255)。
编辑3:添加关于亮度传输函数的维基百科链接 - https://en.wikipedia.org/wiki/Color_mapping

-1

直接的方法:

std::vector<std::uint8_t> myVec2(myVec.size() * 2);
std::memcpy(myVec2.data(), myVec.data(), myVec.size());

或使用标准库

std::copy( begin(myVec), end(myVec), begin(myVec2));

1
这个结果会受到机器的字节序影响吗? - triple_r
@triple_r 是的,如果在具有相同字节序的计算机上撤消操作,那么就不会有问题。但目前尚不清楚操作者打算如何解释这些数据。 - RyanP
@triple_r 如果按照RyanP所说的,它并没有被明确定义,那么这样做是可以的。我认为std::copy不应该有这个问题。 - edmz
是的,你说得对。我只是好奇memcpy会发生什么。 - triple_r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接