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 | } |
---|