Home | History | Annotate | Download | only in utils
      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