1 #!/usr/bin/perl 2 ## ----------------------------------------------------------------------- 3 ## 4 ## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved 5 ## 6 ## This program is free software; you can redistribute it and/or modify 7 ## it under the terms of the GNU General Public License as published by 8 ## the Free Software Foundation, Inc., 53 Temple Place Ste 330, 9 ## Boston MA 02111-1307, USA; either version 2 of the License, or 10 ## (at your option) any later version; incorporated herein by reference. 11 ## 12 ## ----------------------------------------------------------------------- 13 14 ## 15 ## lss16toppm: 16 ## Convert an LSS-16 image to PPM 17 ## 18 ## Usage: 19 ## 20 ## lss16toppm [-map] < file.lss > file.ppm 21 ## 22 ## The -map causes the color map to be output on stderr. 23 ## 24 25 eval { use bytes; }; 26 eval { binmode STDIN; }; 27 eval { binmode STDOUT; }; 28 29 $map = 0; 30 foreach $arg ( @ARGV ) { 31 if ( $arg eq '-map' ) { 32 $map = 1; 33 } else { 34 print STDERR "$0: Unknown option: $arg\n"; 35 exit 127; 36 } 37 } 38 39 if ( read(STDIN, $header, 56) != 56 ) { 40 print STDERR "$0: Short file\n"; 41 exit 1; 42 } 43 44 ($magic, $xsize, $ysize, @colorset) = unpack("Vvvc48", $header); 45 46 if ( $magic != 0x1413f33d ) { 47 print STDERR "$0: Invalid file format\n"; 48 exit 1; 49 } 50 51 %color = (); 52 for ( $i = 0 ; $i < 16 ; $i++ ) { 53 $r = int((shift @colorset) * 255 / 63 + 0.5); 54 $g = int((shift @colorset) * 255 / 63 + 0.5); 55 $b = int((shift @colorset) * 255 / 63 + 0.5); 56 57 $color{$i} = pack("ccc", $r, $g, $b); 58 59 if ( $map ) { 60 printf STDERR "#%02x%02x%02x=%d\n", $r, $g, $b, $i; 61 } 62 } 63 64 sub get_nybble() { 65 my($ch,$n); 66 if ( defined($nybble_buf) ) { 67 $n = $nybble_buf; 68 undef $nybble_buf; 69 } else { 70 if ( read(STDIN, $ch, 1) != 1 ) { 71 print STDERR "$0: Short read on input (file corrupt)\n"; 72 exit 1; 73 } 74 $ch = ord($ch); 75 $nybble_buf = $ch >> 4; 76 $n = $ch & 0xF; 77 } 78 return $n; 79 } 80 81 print "P6\n"; 82 print "$xsize $ysize\n"; 83 print "255\n"; 84 85 for ( $y = 0 ; $y < $ysize ; $y++ ) { 86 $x = 0; 87 $last = 0; 88 undef $nybble_buf; # Nybble buffer starts clear on each line 89 while ( $x < $xsize ) { 90 $n = get_nybble(); 91 92 if ( $n != $last ) { 93 print $color{$n}; 94 $last = $n; 95 $x++; 96 } else { 97 $c = get_nybble(); 98 if ( $c == 0 ) { 99 # Double-nybble run 100 $c = get_nybble(); 101 $c += get_nybble() << 4; 102 $c += 16; 103 } 104 # Truncate overlong runs 105 $c = $xsize-$x if ( $c > $xsize-$x ); 106 # Output run 107 print $color{$n} x $c; 108 $x += $c; 109 } 110 } 111 } 112