Как я могу извлечь .jpg / .png компоненты файла .hpi? - PullRequest
3 голосов
/ 23 октября 2008

Я наткнулся на свои довольно древние диски с фотообъектами, и, к сожалению, обнаружил, что компания (Хемера) больше не оказывает ей поддержку. это оставило мне целую кучу файлов .hpi. К счастью, я нашел эту информацию при извлечении компонентов jpg и png из файла.

К сожалению, я не смог заставить его работать. Может кто-нибудь выяснить, что не так с этим кодом? Я был бы счастлив с PHP или Python решением, если Perl не ваша вещь. :)

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; };

hexdump текущего тестового файла, который я вырвал с CD, здесь, если это вообще поможет:

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

Ответы [ 5 ]

5 голосов
/ 23 октября 2008

У меня была похожая проблема при извлечении изображений из документа 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__
4 голосов
/ 23 октября 2008

Кажется, регулярное выражение неверно. Вот почему я написал небольшую программу на 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.

2 голосов
/ 23 января 2011

Для тех, кто прибывает сюда через Google, я написал скрипт на Python, который решает эту проблему только для изображений PNG:

#!/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()
2 голосов
/ 23 октября 2008

Не решение для вашей собственной программы, но это приложение, бесплатное для личного использования, заявляет, что оно может конвертировать файлы hpi.

0 голосов
/ 27 апреля 2012

Для файлов .jpeg и .mov существует recoverjpeg , который я тестировал на linux (но может быть совместим с другими платформами).

В некоторых системах Debian это доступно через apt get install recoverjpeg

...