Bash 在二进制分隔符上拆分二进制文件?

Bash 在二进制分隔符上拆分二进制文件?,bash,unix,shell,binary,grep,Bash,Unix,Shell,Binary,Grep,我正在编写一个shell脚本,将MPO立体图3D图像转换为标准JPEG图像。MPO文件只是两个JPEG图像,连接在一起 因此,您可以通过查找第二个JPEG的幻数头(0xFFD8FFE1)的字节偏移量来拆分JPEG文件。我已经使用hextump/xxd、grep、head和tail手动完成了这项工作 这里的问题是grep:我可以使用什么来直接搜索二进制文件中的特定幻数,并返回字节偏移量?或者我根本不应该为此使用shell脚本?谢谢。我认为非常简单的自制方法将是您的最佳选择。根据二进制文件格式的所有

我正在编写一个shell脚本,将MPO立体图3D图像转换为标准JPEG图像。MPO文件只是两个JPEG图像,连接在一起

因此,您可以通过查找第二个JPEG的幻数头(0xFFD8FFE1)的字节偏移量来拆分JPEG文件。我已经使用hextump/xxd、grep、head和tail手动完成了这项工作


这里的问题是grep:我可以使用什么来直接搜索二进制文件中的特定幻数,并返回字节偏移量?或者我根本不应该为此使用shell脚本?谢谢。

我认为非常简单的自制方法将是您的最佳选择。根据二进制文件格式的所有特殊情况,执行此操作的代码将非常小

  • 使用
    mmap
    可以方便地查看内存中的文件
  • 开始扫描,并将字节偏移量保存在变量中,例如
    Start
  • 扫描,直到到达分隔符,保存结束偏移量,例如
    end
  • 创建一个新文件
  • 内存映射新文件
  • 将从
    start
    end
    的字节范围复制到新文件中
  • 关闭新文件并再次开始扫描
  • 您可以使用bbe()完成此操作,bbe()是一个用于二进制文件的类似sed的程序:

    要提取第一个JPEG,请使用:

    bbe -b '/\xFF\xD8\xFF\xE1/:' -e 'D 2' -o first_jpeg mpo_file
    
    对于第二个问题:

    bbe -b '/\xFF\xD8\xFF\xE1/:' -e 'D 1' -o second_jpeg mpo_file
    

    请注意,如果JPEG的幻数出现在MPO文件中的其他地方,则此操作将不起作用。

    我认为Bart已经解决了您最大的问题。。如果该二进制序列在该过程中重复,您将得到部分JPEG

    我做了一个快速测试,连接了一些JPEG,然后用awk提取它们(请注意,我文件中的幻数以0xE0结束,而不是0xE1结束):


    这对我来说似乎还可以,但上面提到的问题仍然没有得到处理,而且非常真实。

    FFE1不是某个jpeg“幻数”的一部分,它是APP1标记。而且不能保证它就在SOI标记FFD8之后。此外,您还应注意某些jpeg图像在EXIF块中嵌入缩略图jpeg。这很可能还包含一个APP1标记。

    我在下面找到了一个更好的MPO文件结构解释(以及如何正确处理它)

    编辑,2019年10月:

    由于博客条目现在是404s,下面是我基于它编写的脚本。我已经很多年没用了

    #!/usr/bin/env bash
    
    # Script to convert 3D MPO files, as used in the Fuji FinePix series of 3D cameras, into standard JPEG files.
    # Based on work by David Glover, posted at http://www.davidglover.org/2010/09/using-the-fuji-finepix-real-3d-w3-camera-on-a-mac-or-linuxunix.html
    # This script requires exiftool and ImageMagick.
    
    FULLNAME="$1"
    FILENAME="$(basename $FULLNAME)"
    DIRNAME="$(dirname $FULLNAME)"
    BASENAME="${FILENAME%.*}"
    
    # Create output directories
    mkdir -p "$DIRNAME"/stereoscopic-rl/
    mkdir -p "$DIRNAME"/stereoscopic-mpo/
    mkdir -p "$DIRNAME"/stereoscopic-anaglyph/
    mkdir -p "$DIRNAME"/monoscopic-l/
    mkdir -p "$DIRNAME"/monoscopic-r/
    
    # Create separate left and right images
    exiftool -trailer:all= "$FULLNAME" -o "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg
    exiftool "$FULLNAME" -mpimage2 -b > "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg
    
    # Move the MPO file to its new home
    mv "$FULLNAME" "$DIRNAME"/stereoscopic-mpo/
    
    # Determine parallax value and create cropped images for stereo generation
    # 36 is only appropriate for 4:3 or 3:2 images
    parallax=$(exiftool -b -Parallax "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg)
    parallax=$(echo "$parallax"*36+0.5 | bc | cut -d . -f 1)
    
    # The above pipeline can't deal with a parallax of zero
    # In theory, this fix doesn't cover values between zero and -1
    # TODO improve the calculation
    if [ ! $parallax ]; then
        parallax=0
    fi
    
    echo $parallax
    
    if [ $parallax -ge 0 ]; then
        convert "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg -crop +"$parallax"+0 "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
        convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg -crop -"$parallax"+0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    else
        convert "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg -crop -"$((-1*$parallax))"+0 "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
        convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg -crop +"$((-1*$parallax))"+0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    fi
    
    # Create stereoscopic images for cross-eye (right-left) and anaglyph (red-cyan) viewing
    convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg +append "$DIRNAME"/stereoscopic-rl/"$BASENAME"-stereoscopic-rl.jpg
    
    composite -stereo 0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg "$DIRNAME"/stereoscopic-anaglyph/"$BASENAME"-stereoscopic-anaglyph.jpg
    
    # Clean up separated parallax-corrected images
    rm "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
    rm "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    
    exit 0
    

    我猜幻数中的0xE1表示这是序列中的第二个图像,并且您从未拥有超过2个图像。根据需要进行调整。=)我不确定这一点,因为我在文件的开头也看到了0xE1。我给你答案检查,因为awk在每个Unix系统上都可用(它提醒我需要了解更多信息:)。我的shell脚本目前正在对image03.jpg或缺少image02.jpg进行一些基本检查并中止,这有助于处理幻数问题。我还可以检查EXIF头。不幸的是,尽管维基百科声称Digikam支持MPO,但我只知道有一个程序可以本机读取这些文件——Fujifilm Windows应用程序。必须查看他们的来源和我相机的文档。就目前而言,这很好。很高兴你能成功。。表示0xFF 0xD8是JPEG幻数的开始,因此很自然,它后面的内容取决于实现。感谢您让我注意到bbe!顺便说一下,您的Sourceforge链接已断开,bbe.sf.net是另一个项目。请注意,这些文件是由Fujifilm FinePix Real 3D W3相机生成的。此外,在MPO文件中,左镜头图像似乎位于第一位。抱歉。。。错误404我在答案中添加了我在2010年写的脚本;希望它能对你有所帮助。
    #!/usr/bin/env bash
    
    # Script to convert 3D MPO files, as used in the Fuji FinePix series of 3D cameras, into standard JPEG files.
    # Based on work by David Glover, posted at http://www.davidglover.org/2010/09/using-the-fuji-finepix-real-3d-w3-camera-on-a-mac-or-linuxunix.html
    # This script requires exiftool and ImageMagick.
    
    FULLNAME="$1"
    FILENAME="$(basename $FULLNAME)"
    DIRNAME="$(dirname $FULLNAME)"
    BASENAME="${FILENAME%.*}"
    
    # Create output directories
    mkdir -p "$DIRNAME"/stereoscopic-rl/
    mkdir -p "$DIRNAME"/stereoscopic-mpo/
    mkdir -p "$DIRNAME"/stereoscopic-anaglyph/
    mkdir -p "$DIRNAME"/monoscopic-l/
    mkdir -p "$DIRNAME"/monoscopic-r/
    
    # Create separate left and right images
    exiftool -trailer:all= "$FULLNAME" -o "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg
    exiftool "$FULLNAME" -mpimage2 -b > "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg
    
    # Move the MPO file to its new home
    mv "$FULLNAME" "$DIRNAME"/stereoscopic-mpo/
    
    # Determine parallax value and create cropped images for stereo generation
    # 36 is only appropriate for 4:3 or 3:2 images
    parallax=$(exiftool -b -Parallax "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg)
    parallax=$(echo "$parallax"*36+0.5 | bc | cut -d . -f 1)
    
    # The above pipeline can't deal with a parallax of zero
    # In theory, this fix doesn't cover values between zero and -1
    # TODO improve the calculation
    if [ ! $parallax ]; then
        parallax=0
    fi
    
    echo $parallax
    
    if [ $parallax -ge 0 ]; then
        convert "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg -crop +"$parallax"+0 "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
        convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg -crop -"$parallax"+0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    else
        convert "$DIRNAME"/monoscopic-l/"$BASENAME"-left.jpg -crop -"$((-1*$parallax))"+0 "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
        convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right.jpg -crop +"$((-1*$parallax))"+0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    fi
    
    # Create stereoscopic images for cross-eye (right-left) and anaglyph (red-cyan) viewing
    convert "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg +append "$DIRNAME"/stereoscopic-rl/"$BASENAME"-stereoscopic-rl.jpg
    
    composite -stereo 0 "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg "$DIRNAME"/stereoscopic-anaglyph/"$BASENAME"-stereoscopic-anaglyph.jpg
    
    # Clean up separated parallax-corrected images
    rm "$DIRNAME"/monoscopic-l/"$BASENAME"-left-cropped.jpg
    rm "$DIRNAME"/monoscopic-r/"$BASENAME"-right-cropped.jpg
    
    exit 0