3

私はかなり古い写真オブジェクト ディスクを偶然見つけましたが、悲しいことに会社 (hemera) がそれをサポートしていないことがわかりました。これにより、大量の .hpi ファイルが残されました。幸いなことに、ファイルの jpg および png コンポーネントの抽出に関するこの情報を見つけました。

残念ながら、私はそれを機能させることができませんでした。このコードの何が問題なのか、誰でも理解できますか? Perl が苦手な場合は、PHP または Python のソリューションがあれば幸いです。:)

open(I, "$name") || die;
binmode(I);
$_ = <I>;
close(I);

my ($j, $p) = m|^.{32}(.*)(\211PNG.*)$|s;
open(J, ">$name.jpg") &&
    do { binmode(J); print J $j; close J; };
open(P, ">$name.png") &&
    do { binmode(P); print P $p; close P; };

CD から入手した現在のテスト ファイルの 16 進ダンプは次のとおりです。

0000000 89 48 50 49 0d 0a 1a 0a 64 00 00 00 20 00 00 00
0000010 45 89 00 00 65 89 00 00 0a 21 00 00 00 d0 d0 00
4

5 に答える 5

5

MS Word 文書から画像を抽出する際にも同様の問題がありました。そのために書いたプログラムがこちら。ただし、PNG のみを抽出します。

#!/usr/bin/perl
use strict;

my $HEADER = "\211PNG";
my $FOOTER = "IEND\xAEB`\x82";

foreach my $file ( @ARGV )
     {
     print "Extracting $file\n";
     (my $image_base = $file) =~ s/(.*)\..*/$1/;

     my $data = do { local $/; open my( $fh ), $file; <$fh> };

     my $count = 0;

     while( $data =~ m/($HEADER.*?$FOOTER)/sg )
        {
        my $image      = $1;
        $count++;
        my $image_name = "$image_base.$count.png";
        open my $fh, "> $image_name" or warn "$image_name: $!", next;
        print "Writing $image_name: ", length($image), " bytes\n";
        print $fh $image;
        close $fh;
        }

    }


__END__
于 2008-10-23T01:54:56.590 に答える
4

正規表現が間違っているようです。そのため、私はそれを行うために小さな C プログラムを作成しました。

#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 1048576

char stuff[MAX_SIZE];

int main (int argc, char **argv)
{
    unsigned int j_off, j_len, p_off, p_len;
    FILE *fp, *jp, *pp;
    fp = fopen (argv[1], "r");
    if (!fp)    goto error;
    if (fseek (fp, 12, SEEK_SET))   goto error;
    if (!fread (&j_off, 4, 1, fp))  goto error;
    if (!fread (&j_len, 4, 1, fp))  goto error;
    if (!fread (&p_off, 4, 1, fp))  goto error;
    if (!fread (&p_len, 4, 1, fp))  goto error;
    fprintf (stderr, "INFO %s \t%d %d %d %d\n",
        argv[1], j_off, j_len, p_off, p_len);
    if (j_len > MAX_SIZE || p_len > MAX_SIZE) {
        fprintf (stderr, "%s: Chunk size too big!\n", argv[1]);
        return EXIT_FAILURE;
    }

    jp = fopen (argv[2], "w");
    if (!jp)    goto error;
    if (fseek (fp, j_off, SEEK_SET))    goto error;
    if (!fread (stuff, j_len, 1, fp))   goto error;
    if (!fwrite (stuff, j_len, 1, jp))  goto error;
    fclose (jp);

    pp = fopen (argv[3], "w");
    if (!pp)    goto error;
    if (fseek (fp, p_off, SEEK_SET))    goto error;
    if (!fread (stuff, p_len, 1, fp))   goto error;
    if (!fwrite (stuff, p_len, 1, pp))  goto error;
    fclose (pp);
    fclose (fp);
    return EXIT_SUCCESS;

error:
    perror (argv[1]);
    return EXIT_FAILURE;
}

これは、コマンド ライン パラメーター input.hpi output.jpg output.png で動作します。エラー処理は 100% 正しいわけではありませんが、何かが間違っているかどうか、そしてほとんどの場合、それが何であるかを常に教えてくれるだけで十分です。大きなファイルの場合、MAX_SIZE を拡大する必要があります。

以下は、*.hpi で呼び出すことができるシェル スクリプトです。

#!/bin/bash

dest=<destination-folder>

for arg in "$@"
do
  base=`echo $arg | cut -d'.' -f1`
  <executable> $arg $dest/original/$base.jpg $dest/mask/$base.png 2>>$dest/log
  #composite -compose CopyOpacity $dest/mask/$base.png $dest/original/$base.jpg $dest/rgba/$base.png
done

オプションの合成コマンド (ImageMagick に付属) は、アルファ チャネルとして適用されたマスクを持つ新しい PNG 画像を作成します。このファイルは、元のファイルの約 5 倍の大きさになることに注意してください。

一部の HPI ファイルはマスクなしで提供されることに注意してください。この場合、私のプログラムは引き続き動作しますが、空の PNG ファイルが生成されます。

于 2008-10-23T01:28:24.103 に答える
2

独自のプログラムではありませんが、個人使用のフリーウェアであるこのアプリケーションは、hpiファイルを変換できると述べています。

于 2008-10-23T02:08:01.573 に答える
2

Google からここに到着した人のために、PNG 画像のみでこの問題を解決する Python スクリプトを作成しました。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import re, sys

def main():
  if len(sys.argv) < 2:
    print """Usage:
  {0} BINARY_FILE PNG_PATH_TEMPLATE
Example:
  {0} bin/program 'imgs/image.{{0:03d}}.png'""".format(__file__)
    return
  binfile, pngpath_tpl = sys.argv[1:3]

  rx = re.compile("\x89PNG.+?IEND\xAEB`\x82", re.S)
  bintext = open(binfile, "rb").read()
  PNGs = rx.findall(bintext)

  for i, PNG in enumerate(PNGs):
    f = open(pngpath_tpl.format(i), "wb") # Simple string format.
    f.write(PNG)
    f.close()

if __name__ == "__main__":
  main()
于 2011-01-23T12:36:24.950 に答える
0

.jpegおよび.movファイルには、 Linuxでテストしたrecoverjpegがあります(ただし、他のプラットフォームと互換性がある場合があります)。

一部の debian システムでは、apt get install recoverjpeg

于 2012-04-27T17:25:25.857 に答える