Skip to content

Instantly share code, notes, and snippets.

@ChuckM
Created August 23, 2016 06:14
Show Gist options
  • Save ChuckM/f38847cb1343279c61d5a33d6bdf324d to your computer and use it in GitHub Desktop.
Save ChuckM/f38847cb1343279c61d5a33d6bdf324d to your computer and use it in GitHub Desktop.
Trying to pull a font out of a bitmap
#!/usr/bin/env perl
use strict;
use warnings;
use Graphics::Magick;
use Data::Dumper;
use Getopt::Long;
my $code;
my $font = "reg-bold-italic-full.png";
my $make_font;
GetOptions(
'code+' => \$code,
'font=s' => \$font,
'make=s' => \$make_font,
);
my $row_offset = shift;
my $col_offset = shift;
my $gm = Graphics::Magick->new;
$gm->read($font);
my ($width, $height) = $gm->[0]->Get('columns', 'rows');
$row_offset = 0 if not defined $row_offset;
$col_offset = 0 if not defined $col_offset;
my $char_width = $width / 80;
my $char_height = $height / 25;
print "Image is $width by $height pixels\n";
print "Computed character box: [$char_width, $char_height]\n";
my $base_x = 0;
my $base_y = 0;
my $min_val = 300;
my $max_val = -1;
for (my $row = 0; $row < $height; $row += 1) {
for (my $col = 0; $col < $width; $col += 1) {
my $x = $col;
my $y = $row;
my ($pixel) = $gm->[0]->Get("pixel[$x,$y]");
my ($g) = $pixel =~ /\d+,(\d+),\d+/;
$g = ($g >> 8) & 0xff;
$min_val = $g if ($g < $min_val);
$max_val = $g if ($g > $max_val);
}
}
print "For the image, min, max => $min_val, $max_val\n";
my $rng = ($max_val - $min_val);
my $scale = 255.0 / $rng;
printf "Dynamic range : %d, scaling %f\n", $rng, $scale;
if (defined $make_font) {
if ($make_font eq "r") {
all_font($gm, 1, 0, "regular-font.c");
} elsif ($make_font eq "b") {
all_font($gm, 1, 8 * $char_height + 1, "bold-font.c");
}
}
print "\t{ \n" if defined $code;
for (my $row = 0; $row < $char_height; $row += 1) {
print "\t" if defined $code;
for (my $col = 0; $col < $char_width; $col += 1) {
my $x = $col + $base_x + $col_offset * $char_width;
my $y = $row + $base_y + $row_offset * $char_height;
my ($pixel) = $gm->[0]->Get("pixel[$x,$y]");
my ($g) = $pixel =~ /\d+,(\d+),\d+/;
$g = ($g >> 8) & 0xff;
if (defined $code) {
printf("0x%x", $g);
if ($col < 9) {
print ", ";
} else {
print "},";
}
} else {
printf "0x%02X ", $g;
}
}
print "\n";
}
#
#
#
#
my $num_chars = 7;
for (my $dash = 0; $dash < ($num_chars * $char_width) + 1; $dash += 1) {
if (($dash % $char_width) == 0) {
print "+";
}
print "-";
}
print "\n";
for (my $row = 0; $row < $char_height; $row += 1) {
for (my $col = 0; $col < (7 * $char_width) + 1; $col += 1) {
my $x = $col + $base_x + $col_offset * $char_width;
my $y = $row + $base_y + $row_offset * $char_height;
my ($pixel) = $gm->[0]->Get("pixel[$x,$y]");
my ($g) = $pixel =~ /\d+,(\d+),\d+/;
if (($col % $char_width) == 0) {
print "|";
}
$g = ($g >> 8) & 0xff;
if ($g < 127) {
print "*";
} else {
print " ";
}
}
print "\n";
}
for (my $dash = 0; $dash < ($num_chars * $char_width) + 1; $dash += 1) {
if (($dash % $char_width) == 0) {
print "+";
}
print "-";
}
print "\n";
sub all_font {
my ($img, $bx, $by, $file) = @_;
my $cw = $char_width;
my $ch = $char_height - 3;
print "Generating font into $file\n";
open (my $fh, ">", $file);
print $fh "#include <stdint.h>\n";
print $fh "\n/* program generated font code */\n";
print $fh "#define CHAR_WIDTH $cw\n";
print $fh "#define CHAR_HEIGHT $ch\n";
print $fh "const uint8_t font_glyphs[256][CHAR_HEIGHT][CHAR_WIDTH] = {\n";
for (my $row = 0; $row < 8; $row += 1) {
for (my $col = 0; $col < 32; $col += 1) {
code_glyph($fh, $img, $row, $col, $ch, $cw, $bx, $by);
}
}
print $fh "};\n";
close $fh;
}
sub code_glyph {
my ($fh, $img, $ro, $co, $ch, $cw, $bx, $by) = @_;
my @pic;
print $fh "\t{\n";
for (my $row = 0; $row < $ch; $row += 1) {
my $y = $by + $row + $ro * $char_height;
print $fh "\t\t{";
@pic = ();
for (my $col = 0; $col < $cw; $col += 1) {
my $x = $bx + $col + $co * $cw;
my ($pixel) = $img->[0]->Get("pixel[$x,$y]");
my ($g) = $pixel =~ /\d+,(\d+),\d+/;
$g = ($g >> 8) & 0xff;
my $v = (($g - $min_val) < 0) ? 0 : $g - $min_val;
$v = ($v * $scale) > 255 ? 255 : $v * $scale;
$v = 255 - $v;
if ($v < 64) {
push @pic, " ";
} elsif ($v < 128) {
push @pic, "-";
} elsif ($v < 192) {
push @pic, "*";
} else {
push @pic, "@";
}
printf $fh ("0x%02x", $v);
if ($col < ($char_width - 1)) {
print $fh ", ";
} else {
print $fh "},";
}
}
print $fh "/* " . join("", @pic) . " */\n";
}
print $fh "\t},\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment