Wie kann ich extrahieren Sie die .jpg / .png Komponenten einer .hpi-Datei?

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

  •  03-07-2019
  •  | 
  •  

Frage

Ich stolperte über meine eher alte Fotoplatten-Objekte, und leider das Unternehmen (hemera) fanden heraus, mehr für sie keine Unterstützung bieten. das hat mich mit einem ganzen Haufen von .hpi Dateien links. Glücklicherweise fand ich diese Informationen auf Extrahieren der jpg und png Komponenten die Datei.

Leider habe ich es nicht zu arbeiten in der Lage zu bekommen. Kann jemand herausfinden, was mit diesem Code falsch? Ich würde mit einem PHP oder Python-Lösung freuen, wenn Perl ist nicht Ihr Ding. :)

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

Die hexdump der aktuellen Testdatei verhakt off ich eine CD hier ist, wenn es überhaupt hilft:

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
War es hilfreich?

Lösung

Es scheint, die regexp falsch ist. Deshalb habe ich ein kleines C-Programm schrieb es für mich zu tun:

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

Es arbeitet mit den Kommandozeilenparameter input.hpi output.jpg output.png. Die Fehlerbehandlung ist nicht 100% richtig, aber es ist gut genug, um immer zu sagen, wenn etwas falsch ist, und die meiste Zeit, was es ist. Für große Dateien, müssen Sie MAX_SIZE vergrößern.

Hier ist ein Shell-Skript, das Sie mit * .hpi nennen kann:

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

Der optionale Verbundbefehl (kommt mit ImageMagick) ein neuen PNG-Bild erzeugen, das die Maske als Alphakanal angewandt wird. Beachten Sie, dass diese Datei wird etwa 5-mal größer als die Originaldateien.

Beachten Sie, dass einige HPI-Dateien ohne Maske kommen. In diesem Fall wird immer noch mein Programm arbeiten, aber eine leere PNG-Datei geben.

Andere Tipps

Ich hatte ein ähnliches Problem, Bilder von einem MS Word-Dokument zu extrahieren. Hier ist das Programm, das ich für das schrieb. Es ist nur extrahiert PNGs, aber:

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

Nicht eine Programm-your-own-Lösung, aber diese Anwendung, die ist Freeware für den persönlichen Gebrauch, heißt es, dass es hpi-Dateien umwandeln kann.

Für jene von Google Ankunft hier habe ich einen Python-Skript geschrieben, das dieses Problem für PNG-Bilder löst nur:

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

Für .jpeg und .mov Dateien gibt es recoverjpeg , die ich auf Linux getestet (aber kann mit anderen Plattformen kompatibel sein).

Auf einigen Debian-Systemen es verfügbar ist durch apt get install recoverjpeg

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top