Advertisement
howtophil

imageWaterfall.pl

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