Domanda

Mi sono imbattuto nei miei piuttosto piuttosto antichi dischi di oggetti fotografici e ho scoperto tristemente che la compagnia (hemera) non lo supporta più. questo mi ha lasciato con un mucchio di file .hpi. Fortunatamente, ho trovato queste informazioni sull'estrazione dei componenti jpg e png di il file.

Sfortunatamente, non sono stato in grado di farlo funzionare. Qualcuno può capire cosa c'è che non va in questo codice? Sarei felice con una soluzione PHP o Python se Perl non fa per te. :)

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

Mi sono imbattuto nei miei piuttosto piuttosto antichi dischi di oggetti fotografici e ho scoperto tristemente che la compagnia (hemera) non lo supporta più. questo mi ha lasciato con un mucchio di file .hpi. Fortunatamente, ho trovato queste informazioni sull'estrazione dei componenti jpg e png di il file.

Sfortunatamente, non sono stato in grado di farlo funzionare. Qualcuno può capire cosa c'è che non va in questo codice? Sarei felice con una soluzione PHP o Python se Perl non fa per te. :)

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

Il hexdump del file di test corrente che ho strappato da un CD è qui, se aiuta affatto:

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

Il hexdump del file di test corrente che ho strappato da un CD è qui, se aiuta affatto:

<*>
È stato utile?

Soluzione

Sembra che il regexp sia sbagliato. Ecco perché ho scritto un piccolo programma C per farlo per me:

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

Funziona con i parametri della riga di comando input.hpi output.jpg output.png. La gestione degli errori non è corretta al 100%, ma è abbastanza buona da dirti sempre se qualcosa non va, e il più delle volte di cosa si tratta. Per file di grandi dimensioni, dovrai ingrandire MAX_SIZE.

Ecco uno script di shell che puoi chiamare con * .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

Il comando composito opzionale (fornito con ImageMagick) creerà una nuova immagine PNG con la maschera applicata come canale alfa. Nota che questo file sarà circa 5 volte più grande dei file originali.

Nota che alcuni file HPI sono forniti senza maschera. In questo caso, il mio programma continuerà a funzionare, ma fornirà un file PNG vuoto.

Altri suggerimenti

Ho avuto un problema simile durante l'estrazione di immagini da un documento MS Word. Ecco il programma che ho scritto per questo. Estrae solo PNG, tuttavia:

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

Non una soluzione personalizzata, ma questa applicazione, che è freeware per uso personale, afferma che può convertire file hpi.

Per chi arriva da Google qui, ho scritto uno script Python che risolve questo problema solo per le immagini 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()

Per i file .jpeg e .mov c'è recoverjpeg , che ho testato su Linux (ma potrebbe essere compatibile con altre piattaforme).

Su alcuni sistemi debian è disponibile tramite apt get install recoverjpeg

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top