You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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的映射逻辑。以下是修正后的实现:

关键步骤说明

  1. 正确读取float64数据:直接将二进制文件内容解析为double(C++中对应float64)数组,避免中间字节数组的精度损失。
  2. float64到int64的映射:根据图像的实际动态范围,将浮点数归一化后映射到int64的有效区间(如[0, INT64_MAX])。
  3. 色调映射与图像保存:将转换后的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 01:40:06