Question

Je suis tombé par hasard sur mes disques d'objet photographique plutôt anciens, et j'ai malheureusement appris que la société (hemera) ne la supportait plus. cela m'a laissé avec toute une pile de fichiers .hpi. Heureusement, j'ai trouvé cette information sur l'extraction des composants jpg et png de le fichier.

Malheureusement, je n'ai pas réussi à le faire fonctionner. Quelqu'un peut-il comprendre ce qui ne va pas avec ce code? Je serais heureux avec une solution PHP ou Python si Perl n'est pas votre truc. :)

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

Je suis tombé par hasard sur mes disques d'objet photographique plutôt anciens, et j'ai malheureusement appris que la société (hemera) ne la supportait plus. cela m'a laissé avec toute une pile de fichiers .hpi. Heureusement, j'ai trouvé cette information sur l'extraction des composants jpg et png de le fichier.

Malheureusement, je n'ai pas réussi à le faire fonctionner. Quelqu'un peut-il comprendre ce qui ne va pas avec ce code? Je serais heureux avec une solution PHP ou Python si Perl n'est pas votre truc. :)

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

Le fichier hexadécimal du fichier de test que j'ai gravé sur un CD est ici, si cela peut aider:

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

Le fichier hexadécimal du fichier de test que j'ai gravé sur un CD est ici, si cela peut aider:

<*>
Était-ce utile?

La solution

Il semble que l'expression rationnelle soit fausse. C'est pourquoi j'ai écrit un petit programme en C pour le faire à ma place:

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

Cela fonctionne avec les paramètres de ligne de commande input.hpi output.jpg output.png. La gestion des erreurs n’est pas correcte à 100%, mais c’est suffisant pour toujours vous dire si quelque chose ne va pas et la plupart du temps ce qu’il est. Pour les fichiers volumineux, vous devrez agrandir MAX_SIZE.

Voici un script shell que vous pouvez appeler avec * .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

La commande composite facultative (fournie avec ImageMagick) créera une nouvelle image PNG avec le masque appliqué en tant que canal alpha. Notez que ce fichier sera environ 5 fois plus volumineux que les fichiers d'origine.

Notez que certains fichiers HPI sont fournis sans masque. Dans ce cas, mon programme fonctionnera toujours, mais donnera un fichier PNG vide.

Autres conseils

J'ai eu un problème similaire lors de l'extraction d'images d'un document MS Word. Voici le programme que j'ai écrit pour ça. Il extrait uniquement les fichiers PNG, cependant:

#!/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__

Ce n'est pas une solution à faire soi-même, mais cette application , qui est freeware pour usage personnel, indique qu'il peut convertir les fichiers hpi.

Pour ceux qui arrivent ici par Google, j'ai écrit un script Python qui résout ce problème uniquement pour les images 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()

Pour les fichiers .jpeg et .mov , il existe recoverjpeg , que j'ai testé sur linux (mais peut être compatible avec d'autres plates-formes).

Sur certains systèmes Debian, il est disponible via pour obtenir l’installation récupérée

.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top