howtophil

imageWaterfall.pl

Feb 6th, 2024 (edited)
1,908
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.02 KB | None | 0 0
  1. #!/usr/bin/perl
  2. #--------------------------------------------------------------------------
  3. # This script is a modification of a pre-existing script.
  4. # The modifications are by Phillip J Rhoades.
  5. #
  6. # It is based on this script: https://github.com/plurSKI/imageSpectrogram
  7. # http://www.devrand.org/2013/04/image-to-spectrogram.html by Gavin Black
  8. #
  9. # The original script created "hidden" spectrogram images.
  10. #
  11. # The modifications are for creating waterfall images in fldigi
  12. # and similar programs. Since I've made quite a few changes, I've
  13. # renamed the perl script to denote its different purpose.
  14. #
  15. # Please use waterfallpre.sh to "prep" images for transformation
  16. # into waterfall sstv images. Or use GIMP (Ph*t*sh*p, whatever).
  17. # I find gray scale images work best. Fiddle with the contrast
  18. # and brightness and make a few test runs.
  19. #
  20. # ./waterfallpre.sh "imagename.jpg" 150
  21. #
  22. # This will generate 150-imagename.jpg
  23. #
  24. # 10 pixels wide is about 100hz in the fldigi waterfall.
  25. # So, you'll want to keep images 200ish or fewer pixels
  26. # wide in most cases.
  27. #
  28. # I'm not your dad though, so do as you like.
  29. #
  30. # After your image is ready run:
  31. #
  32. # ./imageWaterfall.pl "150-imagename.jpg" <output_file> <sound_frequency_center>
  33. #
  34. # You will then have a wav file which will create a lossy image
  35. # in the fldigi (and similar programs) waterfall display
  36. # when received. Amaze your friends! Be the King Geek and The Dork God!
  37. #
  38. #--------------------------------------------------------------------------
  39.  
  40. use strict;
  41. use Audio::Wav;
  42. use Math::Complex;
  43. use GD;
  44. use constant TWO_PI => pi() * 2;
  45.  
  46.  
  47. my $wav = Audio::Wav->new();
  48. my $sample_rate = 44100;
  49. my $bits_sample = 16;
  50. my $freq_Center = $ARGV[2] || 1500;
  51. my $y = 1;
  52. print "$freq_Center";
  53.  
  54. if( $#ARGV < 0 )
  55. {
  56.   print "Usage: $0 input_file <output_file> <sound_frequency_center>\n";
  57.   exit 0;
  58. }
  59.  
  60. # Start writing the wave with the proper arguments
  61. write_out(( $#ARGV < 1) ? "$ARGV[0].wav" : $ARGV[1], $ARGV[0]);
  62.  
  63.  
  64. sub write_out
  65. {
  66.    # Set up the wave file
  67.    my $filename = shift;
  68.    my $write = $wav->write($filename, {
  69.       bits_sample => $bits_sample,
  70.       sample_rate => $sample_rate,
  71.       channels    => 1,
  72.    });
  73.  
  74.    # Set up the picture to read from
  75.    my $imageName = shift;
  76.    my $srcimage;
  77.    open FILE, $imageName or die "Couldn't open: $imageName\n";
  78.    close(FILE);
  79.    my $ucImage = uc $imageName;
  80.    if( $ucImage =~ m/.JPG/ || $ucImage =~ m/.JPEG/ )
  81.    {
  82.       $srcimage = GD::Image->newFromJpeg($imageName);
  83.    } elsif ( $ucImage =~ m/.PNG/ ) {
  84.       $srcimage = GD::Image->newFromPng($imageName);
  85.    } elsif ( $ucImage =~ m/.GIF/ ) {
  86.       $srcimage = GD::Image->newFromGif($imageName);
  87.    } else {
  88.       print "Unsupported filetype\nMust be png, jpg, jpeg, bmp, or gif\n";
  89.       exit -1;
  90.    }
  91.    my ($srcW,$srcH) = $srcimage->getBounds();
  92.  
  93.    # Step through each pixel
  94.    #for( my $x = 0; $x < $srcW; $x ++ )
  95.    #for( my $x = 0; $x < $srcH; $x ++ )
  96.    for( my $x = $srcH; $x > 0; $x -- )
  97.    {
  98.       my @t = ();
  99.       #for( my $y = 0; $y < $srcH; $y ++ )
  100.       for( my $y = $srcW; $y > 0; $y -- )
  101.       {
  102.          my $index = $srcimage->getPixel($y,$x);
  103.          my ($r,$g,$b) = $srcimage->rgb($index);
  104.  
  105.          # Set the frequency and 'color' for this pixel.  Ignore if black
  106.          if( $r > 10 || $g > 10 && $b > 10 )
  107.          {
  108.             #my $c = 4.25 - 4.25*($r + $g + $b)/(256*3);
  109.             my $c = 4.25 - 4.25*($r + $g + $b)/(256*3);
  110.             if( $c < 0.75 )
  111.             {
  112.                 $c = 0.75;
  113.             }
  114.             #print "$c\n";
  115.  
  116.             #push( @t, int(2000 - ( $y + 1)/( $srcH + 1) * 1800) );
  117.             #push( @t, int(2000 - ( $y + 1)/( $srcH + 1) * ( ( $srcH * 10 ) - $srcH ) ) );
  118.             #push( @t, int( ( $freq_Center + ( $srcH * 5 ) - ( $srcH / 2) ) - ( $y + 1)/( $srcH + 1) * ( ( $srcH * 10 ) - $srcH ) ) );
  119.             push( @t, int( ( $freq_Center - ( $srcW * 5 ) + ( $srcW / 2) ) + ( $y + 1)/( $srcW + 1) * ( ( $srcW * 10 ) - $srcW ) ) );
  120.             #push( @t, int(($y/$srcH)+1000) );
  121.             push( @t, $c );
  122.          }
  123.       }
  124.  
  125.       # Ugly way to show a status percentage
  126.       my $status = int(100*$x/$srcH);
  127.       my $lowstatus = 100 - $status;
  128.       my $statusDec = int(10000*$x/$srcH) - 100 * $status;
  129.       my $lowstatusDec = 100 - $statusDec;
  130.       print "\b\b\b\b\b\b\b\b\b\b\b\b$lowstatus.$lowstatusDec%   ";
  131.       $| = 1;
  132.       # Add a .23 second set of sine waves
  133.       add_sine($write, .23, @t);
  134.    }
  135.  
  136.    # Finish up
  137.    print "\b\b\b\b\b\b\b\b\b\b\b\b\b100%   \n";
  138.    $write->finish();
  139.  
  140. }
  141.  
  142. sub add_sine {
  143.    my ($write,$length,@freqs) = @_;
  144.    my $max_no = (2 ** $bits_sample) / 2;
  145.    $length *= $sample_rate;
  146.  
  147.    for my $pos (0..$length) {
  148.        my $count = 0;
  149.        my $val = 0;
  150.        for( $count = 0; $count < @freqs.length; $count += 2)
  151.        {
  152.           my $time = ($pos / $sample_rate) * @freqs[$count];
  153.           $val += sin(TWO_PI * $time)*10/(10 ** @freqs[$count + 1]);
  154.        }
  155.        $val /= $count+1;
  156.        my $samp = $val * $max_no;
  157.        $write->write($samp);
  158.    }
  159. }
  160.  
Advertisement
Add Comment
Please, Sign In to add comment