imageWaterfall.pl
howtophil |
PRO |
02/07/24 12:12:15 AM UTC (Edited) |
0 ⭐ |
9276 👁️ |
Never ⏰ |
[audio, perl, image, waterfall, ham, waterfall image]
#!/usr/bin/perl
#--------------------------------------------------------------------------
# This script is a modification of a pre-existing script.
# The modifications are by Phillip J Rhoades.
# [email protected]
#
# It is based on this script: https://github.com/plurSKI/imageSpectrogram
# http://www.devrand.org/2013/04/image-to-spectrogram.html by Gavin Black
#
# The original script created "hidden" spectrogram images.
#
# The modifications are for creating waterfall images in fldigi
# and similar programs. Since I've made quite a few changes, I've
# renamed the perl script to denote its different purpose.
#
# Please use waterfallpre.sh to "prep" images for transformation
# into waterfall sstv images. Or use GIMP (Ph*t*sh*p, whatever).
# I find gray scale images work best. Fiddle with the contrast
# and brightness and make a few test runs.
#
# ./waterfallpre.sh "imagename.jpg" 150
#
# This will generate 150-imagename.jpg
#
# 10 pixels wide is about 100hz in the fldigi waterfall.
# So, you'll want to keep images 200ish or fewer pixels
# wide in most cases.
#
# I'm not your dad though, so do as you like.
#
# After your image is ready run:
#
# ./imageWaterfall.pl "150-imagename.jpg" <output_file> <sound_frequency_center>
#
# You will then have a wav file which will create a lossy image
# in the fldigi (and similar programs) waterfall display
# when received. Amaze your friends! Be the King Geek and The Dork God!
#
#--------------------------------------------------------------------------
use strict;
use Audio::Wav;
use Math::Complex;
use GD;
use constant TWO_PI => pi() * 2;
my $wav = Audio::Wav->new();
my $sample_rate = 44100;
my $bits_sample = 16;
my $freq_Center = $ARGV[2] || 1500;
my $y = 1;
print "$freq_Center";
if( $#ARGV < 0 )
{
print "Usage: $0 input_file <output_file> <sound_frequency_center>\n";
exit 0;
}
# Start writing the wave with the proper arguments
write_out(( $#ARGV < 1) ? "$ARGV[0].wav" : $ARGV[1], $ARGV[0]);
sub write_out
{
# Set up the wave file
my $filename = shift;
my $write = $wav->write($filename, {
bits_sample => $bits_sample,
sample_rate => $sample_rate,
channels => 1,
});
# Set up the picture to read from
my $imageName = shift;
my $srcimage;
open FILE, $imageName or die "Couldn't open: $imageName\n";
close(FILE);
my $ucImage = uc $imageName;
if( $ucImage =~ m/.JPG/ || $ucImage =~ m/.JPEG/ )
{
$srcimage = GD::Image->newFromJpeg($imageName);
} elsif ( $ucImage =~ m/.PNG/ ) {
$srcimage = GD::Image->newFromPng($imageName);
} elsif ( $ucImage =~ m/.GIF/ ) {
$srcimage = GD::Image->newFromGif($imageName);
} else {
print "Unsupported filetype\nMust be png, jpg, jpeg, bmp, or gif\n";
exit -1;
}
my ($srcW,$srcH) = $srcimage->getBounds();
# Step through each pixel
#for( my $x = 0; $x < $srcW; $x ++ )
#for( my $x = 0; $x < $srcH; $x ++ )
for( my $x = $srcH; $x > 0; $x -- )
{
my @t = ();
#for( my $y = 0; $y < $srcH; $y ++ )
for( my $y = $srcW; $y > 0; $y -- )
{
my $index = $srcimage->getPixel($y,$x);
my ($r,$g,$b) = $srcimage->rgb($index);
# Set the frequency and 'color' for this pixel. Ignore if black
if( $r > 10 || $g > 10 && $b > 10 )
{
#my $c = 4.25 - 4.25*($r + $g + $b)/(256*3);
my $c = 4.25 - 4.25*($r + $g + $b)/(256*3);
if( $c < 0.75 )
{
$c = 0.75;
}
#print "$c\n";
#push( @t, int(2000 - ( $y + 1)/( $srcH + 1) * 1800) );
#push( @t, int(2000 - ( $y + 1)/( $srcH + 1) * ( ( $srcH * 10 ) - $srcH ) ) );
#push( @t, int( ( $freq_Center + ( $srcH * 5 ) - ( $srcH / 2) ) - ( $y + 1)/( $srcH + 1) * ( ( $srcH * 10 ) - $srcH ) ) );
push( @t, int( ( $freq_Center - ( $srcW * 5 ) + ( $srcW / 2) ) + ( $y + 1)/( $srcW + 1) * ( ( $srcW * 10 ) - $srcW ) ) );
#push( @t, int(($y/$srcH)+1000) );
push( @t, $c );
}
}
# Ugly way to show a status percentage
my $status = int(100*$x/$srcH);
my $lowstatus = 100 - $status;
my $statusDec = int(10000*$x/$srcH) - 100 * $status;
my $lowstatusDec = 100 - $statusDec;
print "\b\b\b\b\b\b\b\b\b\b\b\b$lowstatus.$lowstatusDec% ";
$| = 1;
# Add a .23 second set of sine waves
add_sine($write, .23, @t);
}
# Finish up
print "\b\b\b\b\b\b\b\b\b\b\b\b\b100% \n";
$write->finish();
}
sub add_sine {
my ($write,$length,@freqs) = @_;
my $max_no = (2 ** $bits_sample) / 2;
$length *= $sample_rate;
for my $pos (0..$length) {
my $count = 0;
my $val = 0;
for( $count = 0; $count < @freqs.length; $count += 2)
{
my $time = ($pos / $sample_rate) * @freqs[$count];
$val += sin(TWO_PI * $time)*10/(10 ** @freqs[$count + 1]);
}
$val /= $count+1;
my $samp = $val * $max_no;
$write->write($samp);
}
}
Comments
0 B
|👍
/👎
0 B
|👍
/👎