.hpiファイルの.jpg / .pngコンポーネントを抽出するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/228165

  •  03-07-2019
  •  | 
  •  

質問

昔の写真オブジェクトのディスクに出くわしましたが、残念なことに、会社(hemera)がそれをサポートしていないことがわかりました。これにより、.hpiファイルが山積みになりました。幸いなことに、この情報のjpgおよびpngコンポーネントの抽出について見つけましたファイル。

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

open(I, "$name") || die;
binmode(I);

昔の写真オブジェクトのディスクに出くわしましたが、残念なことに、会社(hemera)がそれをサポートしていないことがわかりました。これにより、.hpiファイルが山積みになりました。幸いなことに、この情報のjpgおよびpngコンポーネントの抽出について見つけましたファイル。

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

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

CDから取得した現在のテストファイルの16進ダンプは、次のように役立ちます。

<*> = <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進ダンプは、次のように役立ちます。

<*>
役に立ちましたか?

解決

正規表現が間違っているようです。それが私のために小さな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ファイルを提供します。

他のヒント

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__

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

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()

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

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

から入手できます。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top