如何在C++中将float64二进制图像转换为int64?
问题描述
我有一个以二进制格式存储的float64类型图像,希望读取文件内容并转换为int64格式以进行色调映射。求在C++中实现float图像到int64的转换方法,以下是我当前的文件读取代码:
#include <iostream> #include <stdlib.h> #include <fstream> #include <vector> #include "FreeImage.h" int main() { std::ifstream stream("c:/output/15_init_image.bin", std::ios::in | std::ios::binary); std::vector<uint8_t> contents((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); int width = 2048; // get the width of the image ; int height = 3096; // get the height of the image ; int bpp = 32; FreeImage_Initialise(); int pitch = 512; FIBITMAP* src = FreeImage_ConvertFromRawBitsEx(true, contents.data(), FIT_BITMAP, width, height, pitch, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, FALSE); FreeImage_Save(FIF_JPEG, src, "viewport.jpeg"); return 0; }
解决方案
当前代码的核心问题是将float64格式的二进制数据读取为uint8_t数组,丢失了原始浮点数的精度,且未处理float到int64的映射逻辑。以下是修正后的实现:
关键步骤说明
- 正确读取float64数据:直接将二进制文件内容解析为
double(C++中对应float64)数组,避免中间字节数组的精度损失。 - float64到int64的映射:根据图像的实际动态范围,将浮点数归一化后映射到int64的有效区间(如
[0, INT64_MAX])。 - 色调映射与图像保存:将转换后的int64数据映射回8位像素值,适配FreeImage的图像保存逻辑。
完整代码实现
#include <iostream> #include <fstream> #include <vector> #include <algorithm> #include <cstdint> #include <cmath> #include "FreeImage.h" int main() { const int width = 2048; const int height = 3096; const int channels = 3; // 根据实际图像通道数调整:1=灰度,3=RGB // 读取二进制float64文件 std::ifstream stream("c:/output/15_init_image.bin", std::ios::in | std::ios::binary); if (!stream.is_open()) { std::cerr << "文件打开失败!" << std::endl; return 1; } // 计算总像素元素数(每个通道对应一个float64值) const size_t total_elements = static_cast<size_t>(width) * height * channels; std::vector<double> float_data(total_elements); stream.read(reinterpret_cast<char*>(float_data.data()), total_elements * sizeof(double)); stream.close(); // 步骤1:float64转int64(基于图像全局动态范围映射) double min_val = *std::min_element(float_data.begin(), float_data.end()); double max_val = *std::max_element(float_data.begin(), float_data.end()); double range = max_val - min_val; if (range == 0.0) range = 1.0; // 防止除零错误 std::vector<int64_t> int64_data(total_elements); for (size_t i = 0; i < total_elements; ++i) { // 归一化到[0,1]后映射到int64全范围 double normalized = (float_data[i] - min_val) / range; int64_data[i] = static_cast<int64_t>(normalized * INT64_MAX); } // 步骤2:色调映射(示例:将int64值转换为8位像素用于JPEG保存) std::vector<uint8_t> image_data(total_elements); for (size_t i = 0; i < total_elements; ++i) { // 将int64范围缩放回0-255,确保数值在合法区间内 double normalized_int = static_cast<double>(int64_data[i]) / INT64_MAX; image_data[i] = static_cast<uint8_t>(std::clamp(normalized_int * 255.0, 0.0, 255.0)); } // 使用FreeImage保存为JPEG FreeImage_Initialise(); const int bpp = channels * 8; const int pitch = width * channels; // 每行像素的字节数 FIBITMAP* src = FreeImage_ConvertFromRawBitsEx( true, image_data.data(), FIT_BITMAP, width, height, pitch, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, FALSE ); if (src != nullptr) { FreeImage_Save(FIF_JPEG, src, "viewport.jpeg", JPEG_QUALITY_DEFAULT); FreeImage_Unload(src); } else { std::cerr << "创建FIBITMAP失败!" << std::endl; } FreeImage_DeInitialise(); return 0; }
注意事项
- 通道数调整:如果是单通道灰度图,将
channels设为1,同时修改bpp=8、pitch=width。 - 映射逻辑自定义:如果已知图像浮点数范围固定(如
[0,1]),可以直接省略极值计算,用int64_data[i] = static_cast<int64_t>(float_data[i] * INT64_MAX);完成转换。 - 色调映射扩展:实际应用中可在int64转换后加入自定义色调映射逻辑(如伽马校正、直方图均衡),再转换为8位像素值。
内容的提问来源于stack exchange,提问作者Andre Ahmed
相关产品推荐
相关产品推荐

