Как я могу извлечь .jpg / .png компоненты файла .hpi?

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

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

<*> = <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, здесь, если это вообще поможет:

<*>
Это было полезно?

Решение

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top