16位位图十六进制文件的文件格式是什么?

3

我是新手,如果我没有描述问题清楚,请原谅。

我有一个应该包含三个图像(宽度:640,高度:333)的十六进制文件。该十六进制文件大小为1.2MB。因此,如果我们进行一些计算,我们可以得出每个像素应该具有16位数据。

该文件的一些十六进制代码如下:

90 eb 6f 14 02 02 fd fd 4e 01 80 02 00 00 00 00
90 eb 6f 14 82 82 7d 7d 4e 01 80 02 03 00 00 00
90 eb 6f 14 c2 c2 3d 3d 4e 01 80 02 00 00 8e 08
a7 33 0f d4 00 01 00 01 00 01 43 01 f8 03 0e 17
00 01 00 00 00 00 02 00 00 00 00 00 00 00 01 00
00 04 00 00 01 01 00 00 00 00 00 00 00 00 00 00
00 00 01 01 00 00 00 00 00 01 00 00 00 00 00 00
00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00 00 00 00 00 00 00 01 00 00 00 00 00 00 01 01
00 00 00 00 01 00 00 00 00 00 00 00 00 00 01 01
00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00
00 01 00 00 08 01 00 00 00 00 00 00 00 00 00 00
00 01 00 00 00 00 00 01 00 00 00 00 00 0a 01 00
00 00 01 00 01 00 00 00 01 00 00 00 00 00 00 00
02 00 00 01 00 00 00 01 00 00 00 00 00 00 00 01

正如您所看到的,有一个包含4行内容的标题,其中3行相似。位图数据开始。重复行在文件中再次重复两次。因此,我假设每个3个图像的开头都有重复的结构。但是这些标题之间的数据为210 KB,这意味着每个像素8位。因此,我将每个8位读取为一个小整数,并将其设置为相应图像像素的rgb值。因此,我获得了3个灰度图像。文件中还有630 KB的未读数据。
这里是原始彩色图片的放大版本(原始版本的图片是彩色的),以及获得的图像。正如您所看到的,有一些像素(每个其他像素)与原始像素完全不同,但整个图像几乎正确。
因此,我的问题如下: 十六进制文件的真实结构是什么?我应该如何读取十六进制文件? 如何获得原始的彩色文件? 额外的630 KB数据是什么?错误的像素是什么?

这里还有原始图像(i.stack.imgur.com/NdBOa.png),灰度处理后的原始图像(i.stack.imgur.com/wDUPB.png)和处理后得到的图像(i.stack.imgur.com/lY3ib.png)。


1
你的原始文件是636x330而不是你所说的640x333 - 为什么?图片发生了什么使它变成这样 - 是哪个程序/工具造成的?工具的作者没有说明文件的工作原理吗?整个文件在哪里? - Mark Setchell
原始文件来自一款源代码不可用的软件。我认为它被裁剪成了636x330像素,但在二进制文件中,它有640x333字节的数据。该软件没有任何文档可供参考,我需要在C++代码中实现相同的功能。如果需要,我可以附上整个文件。 - l3enQ
以下是整个文件的内容:http://filebin.ca/2MAr1UtKowIR - l3enQ
1
如果你把整个文件都附上,我会玩弄它 - 呃,我的意思是“进行一些非常专业的取证分析”。 - Mark Setchell
我已经上传到filebin.ca/2MAr1UtKowIR。感谢你的努力。这个帖子的答案就像我所做的一样。http://stackoverflow.com/questions/11239203/with-c-and-qt-how-do-i-display-a-16-bit-raw-file-as-an-image - l3enQ
1个回答

2
没有什么确定的结论,但是这是我找到的东西...
如果你对文件进行十六进制转储并查看开头,你会发现90eb,如果你在整个文件中寻找它,你会得到以下结果:
xxd a.raw | egrep "90eb"

0000000: 90eb 6f14 0202 fdfd 4e01 8002 0000 0000  ..o.....N.......
0000010: 90eb 6f14 8282 7d7d 4e01 8002 0300 0000  ..o...}}N.......
0000020: 90eb 6f14 c2c2 3d3d 4e01 8002 0000 8e08  ..o...==N.......
0034340: e773 2bf4 90eb 6f14 c2c2 3d3d 4e01 8002  .s+...o...==N...
0068660: 0301 0100 ca03 0104 90eb 6f14 c2c2 3d3d  ..........o...==

数据似乎从每个90eb后开始的32字节。如果图像是640x333,则每个图像将有213,120个字节。因此,我们可以使用ImageMagick提取图像的基本平面/通道,如下所示:
dd if=a.raw bs=1 skip=64 count=213120 | convert -depth 8 -size 640x333 gray:- a.png

enter image description here

dd if=a.raw bs=1 skip=213860 count=213120 | convert -depth 8 -size 640x333 gray:- b.png

enter image description here

dd if=a.raw bs=1 skip=427656 count=213120 | convert -depth 8 -size 640x333 gray:- c.png

enter image description here

现在我们有一个问题 - 三张图片中的个别图像位置不同 - 如果我像这样将3帧动画在一起,您可以看到:
convert -delay 80 a.png b.png c.png -normalize  anim.gif

enter image description here

所以我有点迷失了——因为视角似乎在移动,那么是否存在多个相机呢?
我不知道——也许我的发现会启发其他人!让我们看看。
另一种方法可能是比较统计数据——如果你查看“原始”图像的统计数据,你会得到这些:
identify -verbose original.png | egrep "Red:|Green:|Blue:|mean:|deviation"
    Red:
      mean: 5.77718 (0.0226556)
      standard deviation: 17.0501 (0.066863)
    Green:
      mean: 13.7015 (0.0537312)
      standard deviation: 38.4053 (0.150609)
    Blue:
      mean: 10.2863 (0.0403386)
      standard deviation: 30.1792 (0.11835)

如果您现在查看上面提取的 a.pngb.pngc.png 的统计信息,您将得到以下结果:
identify -verbose a.png | egrep "Red:|Green:|Blue:|Gray:|mean:|deviation"
    Gray:
      mean: 2.48532 (0.00974635)
      standard deviation: 9.00678 (0.0353207)

identify -verbose b.png | egrep "Red:|Green:|Blue:|Gray:|mean:|deviation"
    Gray:
      mean: 10.1611 (0.0398473)
      standard deviation: 30.2288 (0.118544)


identify -verbose c.png | egrep "Red:|Green:|Blue:|Gray:|mean:|deviation"
    Gray:
      mean: 2.26135 (0.00886804)
      standard deviation: 7.43093 (0.0291409)

“原始”图像的统计数据与提取图像的假定“通道”之间似乎没有任何相关性……我认为这里发生的事情比我猜测的要多。”

谢谢你的努力,我用C++代码做了和你一样的事情。有3张照片是由同一台相机在3个时刻拍摄的。我通过C++代码获取了这三张图片;但问题是你可以看到每个像素中的噪声。所以我通过对邻近像素的值进行平均来消除噪声,并将其设置为有噪声的像素。所以我的问题是这些噪声是什么?或者每个像素都有16位数据,而每个其他像素都没有数据。 - l3enQ
2
或许这是 Bayer 矩阵,实际上有 4 个通道 - RGBR,就像数码相机一样,这可能解释了额外的数据... - Mark Setchell
也许是这种情况。原始彩色图像几乎是绿色和蓝色的。 那么如果是这种情况,我该如何在C++中读取它并将其分配给图片的像素? - l3enQ
2
这种方法被称为“去马赛克”,但我的想法只是一种直觉。https://en.wikipedia.org/wiki/Bayer_filter - Mark Setchell
谢谢你的好提示。看起来是正确的,所以我会尝试读取文件并进行去马赛克处理。我会告诉你我的进展情况。 - l3enQ
1
非常感谢。已经奏效。我用Matlab测试了一下。这是Matlab的代码:I = imread('mandi.tif'); J = demosaic(I,'bggr'); imshow(I); figure, imshow(J); - l3enQ

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