读取二进制16位流文件并写入16位PGM(C++)

Read binary 16bit streamfile and write to 16bit PGM (C++)

本文关键字:16位 PGM C++ 二进制 文件 读取      更新时间:2023-10-16

这是我迄今为止使用搜索功能的第一篇文章。但现在我在以下问题上浪费了一整天的时间:

我录制了一个12位(写为16位)的灰度视频,并将其直接写入二进制流文件(没有标题或类似内容)。

现在的任务是读取文件并将每一帧输出为16位pgm。

下面的剪辑说明了我的尝试。输出是一个有效的pgm,但带有"白噪声"。

    ...
    imageBufferShort = new short[imageWidth*imageHeight* sizeof(short)];
    ...
    streamFileHandle.read(reinterpret_cast<char*>(imageBufferShort),2*imageWidth*imageHeight); //double amount because 8bit chars!
    // As .read only takes chars, I thought, that I just read the double amount of char-bytes and when it is interpreted as short (=16bit) everything is ok?!?
    ...now the pgm output:
    std::ofstream f_hnd(fileName,std::ios_base::out |std::ios_base::binary |std::ios_base::trunc);
    // write simple header
    f_hnd.write("P5n",3);
    f_hnd << imageWidth << " " << imageHeight << "n4095n";  //4095 should tell the pgm to use 2 bytes for each pixel
    f_hnd.write(reinterpret_cast<char*>(imageBufferShort),2*imageWidth*imageHeight);
    f_hnd.close();

同样,该文件是生成的和可查看的,但包含垃圾。最初的猜测可以吗?读取2个"字符"并将其作为一个"短"字符处理?我还在每一行后面都尝试了一个空格,但这没有任何变化,所以我决定发布这个更短的代码。

谢谢你的帮助!

正如@Domi和@JoeZ所指出的:您的endianness可能被搞砸了。意思是,你的字节顺序是错误的。

为了解决这个问题,您必须对每个像素进行迭代,并在将其写回文件之前交换其字节数。

问题已解决。非常感谢大家。无尽确实是问题所在。解决方案如下:

    f_hnd << "P5" << " " << imDimensions.GetWidth() << " " << imDimensions.GetHeight() << " " << "4095n";
    // convert imageBufferShort to Big-Endian format
    unsigned short imageBufferShortBigEndian[imDimensions.GetWidth()*imDimensions.GetHeight()];
    for (int k=0 ; k<imDimensions.GetWidth()*imDimensions.GetHeight() ; k++)
    {
        imageBufferShortBigEndian[k] = ( (imageBufferShort[k] << 8) | (imageBufferShort[k] >> 8) );
    }
    f_hnd.write(reinterpret_cast<char*>(imageBufferShortBigEndian),2*imDimensions.GetWidth()*imDimensions.GetHeight());
    f_hnd.close();

imageBufferShort还具有一个无符号短数组。如果使用带符号的类型,则位移转换会稍微困难一些。

再次感谢!