2008-10-23 7 views
3

J'ai trébuché sur mes disques d'objets photo plutôt anciens, et j'ai malheureusement découvert que l'entreprise (hemera) ne fournit plus de support pour cela. cela m'a laissé avec une pile de fichiers .hpi. Heureusement, j'ai trouvé this information sur l'extraction des composants jpg et png du fichier.Comment puis-je extraire les composants .jpg/.png d'un fichier .hpi?

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); 
$_ = <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 hexdump du fichier de test courant I accroché partir d'un CD est ici, si elle aide à tous:

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 

Répondre

4

Il semble que le regexp est erroné. Voilà pourquoi je l'ai écrit un petit programme C pour le faire pour moi:

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

Il 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 elle est suffisante pour toujours vous dire si quelque chose ne va pas, et la plupart du temps ce que c'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 "[email protected]" 
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 en option (est livré avec ImageMagick) va créer une nouvelle image PNG qui a le masque appliqué comme canal alpha. Notez que ce fichier sera environ 5 fois plus grand que les fichiers d'origine.

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

+0

fonctionne très bien! J'ai hâte de revenir à 2001 avec 50 000 images de personnes à grosse tête qui me dévisagent. – Owen

+0

Wow moyen d'aller le mile supplémentaire –

+0

Je l'ai utilisé pour trois DVD de données plein de plus de 150 000 images. – ypnos

5

J'ai rencontré un problème similaire en extrayant des images à partir d'un document MS Word. Voici le programme que j'ai écrit pour ça. Il extrait seulement PNGs, bien que:

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

Pas un programme-votre-propre solution, mais l'application this, qui est un logiciel gratuit pour un usage personnel, indique qu'il peut convertir des fichiers HPI.

+0

J'ai trouvé que, malheureusement, j'avais besoin d'une solution non Windows – Owen

+0

L'une des raisons pour lesquelles je garde quelques boîtes Windows autour, bien que et les jeux. –

+1

Je voudrais essayer d'exécuter l'application en utilisant 'wine'. – tzot

2

Pour ceux qui arrivent par Google ici, j'ai écrit un script Python qui permet de résoudre ce problème pour les images PNG seulement:

#!/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() 
0

Pour .jpeg et .mov fichiers il y a recoverjpeg, que je testé sur Linux (mais peut être compatible avec d'autres plates-formes).

Sur certains systèmes debian il est disponible par le biais apt get install recoverjpeg

Questions connexes