将浮点数的高度图数组导出为 16 位原始格式
Exporting heightmap array of floats to 16bit raw
我有一个 256x256 的 float
数组,代表高度图。
我想将其导出为每像素 16 位的 RAW 图像。将 float
转换为 uint16_t
的正确方法是什么? (我知道精度损失)
我用于测试的快速而肮脏的代码:
void ExportHeightmap(const Vector<float>& rHeights)
{
std::vector<uint16_t> output(256 * 256);
float min = std::numeric_limits<float>::max();
float max = std::numeric_limits<float>::min();
for (size_t i = 0; i < output.size(); ++i)
{
float f = rHeights[i];
if (min > f) min = f;
if (max < f) max = f;
output[i] = static_cast<uint16_t>(rHeights[i]);
}
std::cout << " Min: " << min << std::endl; // -49.77
std::cout << " Max: " << max << std::endl; // 357.84
std::fstream file("Heightmap.raw", std::ios::out | std::ios::binary);
file.write((char*)output.data(), output.size() * sizeof(uint16_t));
}
编辑:我的目标是将应用程序中制作的高度图导出到图像。
我假设,OP 想要使用 uint16_t
的整个范围,即 0 ... 65535。
在这种情况下,要将高度值移动并缩放到新范围,即缩放 (max - min) -> 65535,并平移 min -> 0。
这可能是这样的:
value - min
pixel = ----------- * 65535
max - min
在代码中:
#include <cstdint>
#include <iomanip>
#include <iostream>
std::uint16_t floatToUInt16(float value, float min, float max)
{
return (std::uint16_t)((value - min) / (max - min) * 65535.0f);
}
int main()
{
float min = -49.77f, max = 357.84f;
// some test values
float values[] = { 0.0f, min, max, min / 2, max / 2 };
// test conversion
for (float value : values) {
std::cout << std::fixed << std::setw(10) << value
<< " -> "
<< std::setw(5) << floatToUInt16(value, min, max)
<< '\n';
}
return 0;
}
输出:
0.000000 -> 8001
-49.770000 -> 0
357.839996 -> 65535
-24.885000 -> 4000
178.919998 -> 36768
如果这是在循环中完成的,我会稍微优化一下。
因此,66535.0f / (max - min)
是应用于所有高度值的固定因子。
所以,在进入循环之前计算这个因素是值得的。
我有一个 256x256 的 float
数组,代表高度图。
我想将其导出为每像素 16 位的 RAW 图像。将 float
转换为 uint16_t
的正确方法是什么? (我知道精度损失)
我用于测试的快速而肮脏的代码:
void ExportHeightmap(const Vector<float>& rHeights)
{
std::vector<uint16_t> output(256 * 256);
float min = std::numeric_limits<float>::max();
float max = std::numeric_limits<float>::min();
for (size_t i = 0; i < output.size(); ++i)
{
float f = rHeights[i];
if (min > f) min = f;
if (max < f) max = f;
output[i] = static_cast<uint16_t>(rHeights[i]);
}
std::cout << " Min: " << min << std::endl; // -49.77
std::cout << " Max: " << max << std::endl; // 357.84
std::fstream file("Heightmap.raw", std::ios::out | std::ios::binary);
file.write((char*)output.data(), output.size() * sizeof(uint16_t));
}
编辑:我的目标是将应用程序中制作的高度图导出到图像。
我假设,OP 想要使用 uint16_t
的整个范围,即 0 ... 65535。
在这种情况下,要将高度值移动并缩放到新范围,即缩放 (max - min) -> 65535,并平移 min -> 0。
这可能是这样的:
value - min
pixel = ----------- * 65535
max - min
在代码中:
#include <cstdint>
#include <iomanip>
#include <iostream>
std::uint16_t floatToUInt16(float value, float min, float max)
{
return (std::uint16_t)((value - min) / (max - min) * 65535.0f);
}
int main()
{
float min = -49.77f, max = 357.84f;
// some test values
float values[] = { 0.0f, min, max, min / 2, max / 2 };
// test conversion
for (float value : values) {
std::cout << std::fixed << std::setw(10) << value
<< " -> "
<< std::setw(5) << floatToUInt16(value, min, max)
<< '\n';
}
return 0;
}
输出:
0.000000 -> 8001
-49.770000 -> 0
357.839996 -> 65535
-24.885000 -> 4000
178.919998 -> 36768
如果这是在循环中完成的,我会稍微优化一下。
因此,66535.0f / (max - min)
是应用于所有高度值的固定因子。
所以,在进入循环之前计算这个因素是值得的。