2013 December 2

HPI Image Extractor

Topics

The catalog and CDs from Hemera Photo-Objects

The various Hemera Photo-Objects libraries aren’t much use to designers anymore, since the image format is proprietary and the browser software obsolete. But it turns out the file format is basically a container for a JPG of the image and a PNG of the mask.

Ed Halley offered a short Perl script to extract the image and mask from an HPI, but the code is apparently a little out of date and wouldn’t run on my OS X 10.9 Ā«MavericksĀ» system. So I tweaked it a bit, and now I can use my Photo-Objects again. I’m posting it here in case anyone else has the same problem:

#!/usr/bin/perl

# HPI image converter script
# based on a similar script by Ed Halley
# at http://www.halley.cc/ed/linux/interop/hemera.html

# get the name of the folder with HPI images from user
print "\nEnter the path of the folder holding your HPI images:\n\n";
my $source_dir = <STDIN>;
chomp $source_dir;

# open the HPI source directory
opendir(DIR, $source_dir) or die "cannot open directory";

# get the name of the destination folder for PNG/JPG images
print "\nEnter the path of the destination folder for the PNG/JPG images:\n\n";
my $destination_dir = <STDIN>;
chomp $destination_dir;

# put all .hpi files into an array
@docs = grep(/\.hpi$/,readdir(DIR));

# for each .hpi file,
foreach $file (@docs) {
  # get the name of the file for later use
  my $name = $1 if $file =~ /^(.+).hpi$/;

  # open the file for reading
  open(my $hpi, "<", "$source_dir/$file")
    or die "cannot open < $file: $!";

  # perform all actions in binary mode
  binmode($hpi);

  # reset the file input separator within the local block
  local $/;
  $_ = <$hpi>;
  close($hpi);

  # match the JPG portion to $j and the PNG (mask) portion to $p
  ($j, $p) = m|^.{32}(.*)(\211PNG.*)$|s;

  # write the JPG
  open(my $jpg, ">", $destination_dir . '/' . $name . '.jpg');
  binmode($jpg);
  print $jpg $j;
  close $jpg;

  # write the PNG mask
  open(my $png, ">", $destination_dir . '/' . $name . '.png');
  binmode($png);
  print $png $p;
  close $png;
}

print "\nConversion complete!\n\n";