Perl, 134 characters
All linebreaks may be removed.
@s=unpack"C*",~"P\xdbLI\xc3a`[\@AB\xe0t\xc8df";
$_=<>;for$s(6,3,0){print map$s[hex$&]&1<<$_+$s?$_%2?"_":"|":" ",
0..2while/./g;print$/}
Explanation
@s
stores the bits for each segment. The entries are in order from 0 to F (thanks to hex()
) and the bits map to segments in this order:
6 7 x
3 4 5
0 1 2
with 0
being the LSB. (Bit 6 is unused). The values are stored packed in the string bit-inverted so there are a lot more printable characters; the ~
operator flips the bits and unpack gives me numbers (perl’s bitwise operators are much clumsier when it comes to strings).
With the data in hand I read the input and proceed to loop over it three times; the only difference between the three loops is the bitmask required. For each character of input three characters of output are printed. The character to be printed is
$s[ hex $& ] & (1 << ($_ + $s) )
? ($_ % 2 ? "_" : "|" )
: " "
where @s
is the lookup table, $s
is the shift in effect depending on the row, and $_
is whether we’re printing the 1st, 2nd, or 3rd character in the row. If the right bit in the lookup table entry is false it prints a space; otherwise it prints a “|” on the sides or a “_” in the middle.