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