Program to convert an LSS-16 image to PPM.
authorhpa <hpa>
Tue, 10 Apr 2001 04:09:23 +0000 (04:09 +0000)
committerhpa <hpa>
Tue, 10 Apr 2001 04:09:23 +0000 (04:09 +0000)
lss16toppm [new file with mode: 0755]

diff --git a/lss16toppm b/lss16toppm
new file mode 100755 (executable)
index 0000000..513aa9e
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/perl
+#
+# Convert an LSS-16 image to PPM
+#
+# Usage:
+#
+#      lss16toppm [-map] < file.lss > file.ppm
+#
+# The -map causes the color map to be output on stderr.
+#
+
+$map = 0;
+foreach $arg ( @ARGV ) {
+    if ( $arg eq '-map' ) {
+       $map = 1;
+    } else {
+       print STDERR "$0: Unknown option: $arg\n";
+       exit 127;
+    }
+}
+
+if ( read(STDIN, $header, 56) != 56 ) {
+    print STDERR "$0: Short file\n";
+    exit 1;
+}
+
+($magic, $xsize, $ysize, @colorset) = unpack("Vvvc48", $header);
+
+if ( $magic != 0x1413f33d ) {
+    print STDERR "$0: Invalid file format\n";
+    exit 1;
+}
+
+%color = ();
+for ( $i = 0 ; $i < 16 ; $i++ ) {
+    $r = int((shift @colorset) * 255 / 63 + 0.5);
+    $g = int((shift @colorset) * 255 / 63 + 0.5);
+    $b = int((shift @colorset) * 255 / 63 + 0.5);
+
+    $color{$i} = pack("ccc", $r, $g, $b);
+
+    if ( $map ) {
+       printf STDERR "#%02x%02x%02x=%d\n", $r, $g, $b, $i;
+    }
+}
+
+sub get_nybble() {
+    my($ch,$n);
+    if ( defined($nybble_buf) ) {
+       $n = $nybble_buf;
+       undef $nybble_buf;
+    } else {
+       if ( read(STDIN, $ch, 1) != 1 ) {
+           print STDERR "$0: Short read on input (file corrupt)\n";
+           exit 1;
+       }
+       $ch = ord($ch);
+       $nybble_buf = $ch >> 4;
+       $n = $ch & 0xF;
+    }
+    return $n;
+}
+
+print "P6\n";
+print "$xsize $ysize\n";
+print "255\n";
+
+for ( $y = 0 ; $y < $ysize ; $y++ ) {
+    $x = 0;
+    $last = 0;
+    undef $nybble_buf;         # Nybble buffer starts clear on each line
+    while ( $x < $xsize ) {
+       $n = get_nybble();
+
+       if ( $n != $last ) {
+           print $color{$n};
+           $last = $n;
+           $x++;
+       } else {
+           $c = get_nybble();
+           if ( $c == 0 ) {
+               # Double-nybble run
+               $c = get_nybble();
+               $c += get_nybble() << 4;
+               $c += 16;
+           }
+           # Truncate overlong runs
+           $c = $xsize-$x if ( $c > $xsize-$x );
+           # Output run
+           while ( $c ) {
+               print $color{$n};
+               $c--;
+               $x++;
+           }
+       }
+    }
+}