A simple image to sound conversion python script.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 

123 lignes
4.3 KiB

#!/usr/bin/env python
from PIL import Image, ImageOps
import wave, math, array, argparse, sys, timeit
def parser():
parser = argparse.ArgumentParser()
# Specified command options and its helps message
parser.add_argument ("INPUT_FILE", help="Name of the image to be converted.")
parser.add_argument ("-r", "--rotate", help="Rotate image 90 degrees for more sexy spectograph looks and sound", action='store_true')
parser.add_argument ("-i", "--invert", help="Invert image colors.", action='store_true')
parser.add_argument ("-o", "--output", help="Name of the output wav file. Default value: out.wav).")
parser.add_argument ("-b", "--bottom", help="Bottom frequency range. Default value: 200.", type=int)
parser.add_argument ("-t", "--top", help="Top frequency range. Default value: 20000.", type=int)
parser.add_argument ("-p", "--pixels", help="Pixels per second. Default value: 30.", type=int)
parser.add_argument ("-s", "--sampling", help="Sample rate. Default value: 44100.", type=int)
# Create "arguments" object based on user input
arguments = parser.parse_args()
# Default values
min_freq = 200
max_freq = 20000
sample_rate = 44100
pixels = 30
output = "out.wav"
rotate = False
invert = False
# Check arguments values
if arguments.output:
output = arguments.output
if arguments.bottom:
min_freq = arguments.bottom
if arguments.top:
max_freq = arguments.top
if arguments.pixels:
pixels = arguments.pixels
if arguments.sampling:
sample_rate = arguments.sampling
if arguments.rotate:
rotate = True
if arguments.invert:
invert = True
print ("------------------------------------ Simple Image To Sound Script ------------------------------------\n")
print ('Input file: %s.' % arguments.INPUT_FILE)
print ('Frequency range: %d - %d.' % (min_freq, max_freq))
print ('Pixels per second: %d.' % pixels)
print ('Sampling rate: %d.' % sample_rate)
print ('Rotate Image: %s.' % ('Yes' if rotate else 'No'))
return (arguments.INPUT_FILE, output, min_freq, max_freq, pixels, sample_rate, rotate, invert)
def convert (INPUT_FILE, output, min_freq, max_freq, pixels, sample_rate, rotate, invert):
image = Image.open (INPUT_FILE).convert ('L')
# rotate image if requested
if rotate:
image = image.rotate (90)
# invert image if requested
if invert:
image = ImageOps.invert (image)
output = wave.open (output, 'w')
output.setparams ((1, 2, sample_rate, 0, 'NONE', 'not compressed'))
freq_range = max_freq - min_freq
interval = freq_range / image.size[1]
samples = sample_rate // pixels
data = array.array ('h')
# Converting process start
time_start = timeit.default_timer()
for x in range (image.size[0]):
row = []
for y in range (image.size[1]):
yinv = image.size[1] - y - 1
amplitude = image.getpixel ((x,y))
if (amplitude > 0):
row.append (gen_wave (yinv * interval + min_freq, amplitude, samples, sample_rate))
for i in range(samples):
for j in row:
try:
data[i + x * samples] += j[i]
except (IndexError):
data.insert (i + x * samples, j[i])
except (OverflowError):
if j[i] > 0:
data[i + x * samples] = 32767
else:
data[i + x * samples] = -32768
sys.stdout.write ("Conversion progress: %d%% \r" % (float(x) / image.size[0] * 100))
sys.stdout.flush()
output.writeframes (data.tobytes())
output.close()
# Converting process end
time_end = timeit.default_timer()
print ("Conversion progress: 100%")
print ("Success. Completed in %d seconds." % int(time_end - time_start))
def gen_wave (frequency, amplitude, samples, sample_rate):
cycles = samples * frequency / sample_rate
wave = []
for i in range(samples):
x = math.sin (float (cycles) * 2 * math.pi * i / float (samples)) * float (amplitude)
wave.append (int (math.floor (x)))
return wave
if __name__ == '__main__':
input_choice = parser()
convert (*input_choice)