--- /dev/null
+#!/usr/bin/perl
+
+# unihex2png - program to turn a GNU Unifont hex glyph page of 256 code
+# points into a PNG file
+#
+# Synopsis: unihex2png [-i in_file.hex] [-o out_file.png]
+#
+#
+# Author: Paul Hardy, unifoundry <at> unifoundry.com, December 2007
+#
+# Perl conversion: Andrew Miller, August 2013
+#
+#
+# Copyright (C) 2007-2008 Paul Hardy
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+use Getopt::Long;
+use GD;
+
+$result = GetOptions (
+ "help|?",
+ "input|i=s" => \$input,
+ "output|o=s" => \$output,
+ "page|p=s" => \$page,
+ "rows|r=i" => \$charheight
+);
+
+if ($opt_help) {
+ print << "END";
+
+Turn a GNU Unifont hex glyph page of 256 code points into a PNG file
+
+Syntax:
+
+ unihex2png -i <Input_File> [-o <Output_File>] [-p <Page>] [-r <Rows>]
+
+ -i, --input the input hex file (read from STDIN if not specified)
+ -o, --output the output PNG file
+ -p, --page the Unicode page to convert - valid values are
+ 0 to 10FF (default is 0)
+ -r, --rows the height of the output glyphs in pixel rows -
+ valid values are 16, 24 and 32 (default is 16)
+ -?, --help display this help and exit
+
+
+Example:
+
+ unihex2png -i unifont.hex -o u83.png -p 83
+
+END
+ exit ()
+}
+
+#if (not $input) {
+# die ("No input file specified\n")
+#}
+
+if (not $output) {
+ die ("No output file specified\n")
+}
+
+if (not $page) {
+ $page = 0
+}
+
+$pagenum = hex ($page);
+
+if ($pagenum > 0x10FF) {
+ die ("Invalid page\n");
+}
+
+$charxoffset = 4;
+$gridxoffset = 48;
+$gridyoffset = 32;
+
+if (not $charheight) {
+ $charheight = 16;
+}
+
+if ($charheight == 16) {
+ $charyoffset = 7;
+ $boxsize = 32;
+ $xmax = 2;
+ $ymax = 1;
+ $charmaxwidth = 6;
+} elsif ($charheight == 24) {
+ $charyoffset = 4;
+ $boxsize = 32;
+ $xmax = 2;
+ $ymax = 2;
+ $charmaxwidth = 6;
+} elsif ($charheight == 32) {
+ $charyoffset = 4;
+ $boxsize = 40;
+ $xmax = 3;
+ $ymax = 3;
+ $charmaxwidth = 8;
+} else {
+ die ("Invalid height\n");
+}
+
+# Create box and set as tile pattern
+
+$box = new GD::Image ($boxsize, $boxsize);
+
+$black = $box->colorAllocate (0, 0, 0);
+$white = $box->colorAllocate (255, 255, 255);
+
+$box->filledRectangle (1, 1, $boxsize - 1, $boxsize - 1, $white);
+
+# Draw dots at 8 pixel boundaries
+ for ($count = 0; $count <= $xmax; $count++) {
+ $box->setPixel (($count * 8) + $charxoffset + 1, 0, $white);
+ $box->setPixel (($count * 8) + $charxoffset + 8, 0, $white);
+}
+
+for ($count = 0; $count <= $ymax; $count++) {
+ $box->setPixel (0, ($count * 8) + $charyoffset + 1, $white);
+ $box->setPixel (0, ($count * 8) + $charyoffset + 8, $white);
+}
+
+# Draw grid
+
+$im = new GD::Image ($boxsize * 16 + $gridxoffset, $boxsize * 16 + $gridyoffset);
+
+$black = $im->colorAllocate (0, 0, 0);
+$white = $im->colorAllocate (255, 255, 255);
+
+$im->fill (0, 0, $white);
+
+for ($xcount = 0; $xcount <= 16; $xcount++) {
+ for ($ycount = 0; $ycount <= 16; $ycount++) {
+ $im->copy ($box, $xcount * $boxsize + $gridxoffset - 1, $ycount * $boxsize + $gridyoffset - 1, 0, 0, $boxsize, $boxsize);
+ }
+}
+
+# Print plane
+$im->string (gdLargeFont, 8, 9, sprintf ('U+%02X', $pagenum >> 8), $black);
+
+# Print row headers
+for ($count = 0; $count <= 15; $count++) {
+ $im->string (gdLargeFont, 32, ($count * $boxsize) + (($boxsize - 16) / 2) + $gridyoffset, sprintf ('%X', $count), $black);
+}
+
+# Print column headers
+for ($count = 0; $count <= 15; $count++) {
+ $im->string (gdLargeFont, ($count * $boxsize) + (($boxsize - 24) / 2) + $gridxoffset, 9, sprintf ('%03X', (($pagenum & 0xFF) << 4) + $count), $black);
+}
+
+if ($input) {
+ open (HEXFILE, "$input") or die ('Cannot open file\n');
+} else {
+ *HEXFILE = *STDIN;
+}
+
+while (<HEXFILE>) {
+ chomp;
+ @data = split (':', $_);
+ $codepoint = hex ($data[0]);
+
+ # Calculate if codepoint is within page
+ if ($codepoint >> 8 == $pagenum) {
+ $char = $data[1];
+
+ # Calculate character width, column and row
+ $charwidth = length ($char) / $charheight;
+
+ if ($charwidth <= $charmaxwidth) {
+ $col = ($codepoint >> 4) & 0xF;
+ $row = $codepoint & 0xF;
+
+ for ($j = 0; $j < $charheight; $j++) {
+ # Get character row
+ $r = hex (substr ($char, $j * $charwidth, $charwidth));
+
+ # Draw character
+ for ($i = 0; $i < $charwidth * 4; $i++) {
+ if ($r & 1 << $i) {
+ $im->setPixel (($col * $boxsize) + ($charwidth * 4 - $i) + $charxoffset + $gridxoffset - 1, ($row * $boxsize) + $j + $charyoffset + $gridyoffset, $black);
+ }
+ }
+ }
+ }
+ }
+}
+# Only close input file handler if it isn't STDIN.
+if ($input) {
+ close HEXFILE;
+}
+
+# Save image
+open (PICTURE, ">$output") or die ("Cannot save image\n");
+binmode PICTURE;
+print PICTURE $im->png;
+close PICTURE;