-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscreengif.rb
executable file
·126 lines (107 loc) · 4.17 KB
/
screengif.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env ruby
require 'rmagick'
include Magick
require 'screengif/draw_progressbar.rb'
require 'screengif/options.rb'
require 'screengif/util.rb'
module Screengif
def self.call_ffmpeg(input_file, options, verbose)
ffmpeg_loglevel = verbose ? 'verbose' : 'warning'
if options.framerate
ffmpeg_framerate = "-r #{options.framerate}"
end
if options.max_width || options.max_height
options.max_width ||= "-1"
options.max_height ||= "-1"
ffmpeg_resize = "-vf scale=#{options.max_width}:#{options.max_height} -sws_flags lanczos"
end
# TODO: error handling
return `ffmpeg -i '#{input_file}' -loglevel #{ffmpeg_loglevel} #{ffmpeg_framerate} #{ffmpeg_resize} -f image2pipe -vcodec ppm - `
end
def self.call_gifsicle(data)
$stderr.puts "Filtering output through gifsicle" if $verbose
# TODO: error handling
result = ''
# popen is for system calls that require setting STDIN
IO.popen('gifsicle --loop --optimize=3 --multifile -', 'r+') do |f|
f.write(data)
f.close_write
result = f.read
end
return result
end
def self.handle_input(input_file, options, optionparser)
if (input_file)
$stderr.puts "Running ffmpeg with #{input_file}" if $verbose
input = Screengif::call_ffmpeg(input_file, options, $verbose)
elsif !$stdin.tty? # we are being piped to
$stderr.puts "Reading input from STDIN." if $verbose
input = STDIN.read
else
$stderr.puts "No input file available."
puts optionparser
exit 1
end
return input
end
def self.handle_output(output_file, output, optionparser)
if (output_file)
File.open(output_file, 'w') do |f|
f.puts output
end
elsif !STDOUT.tty?
$stderr.puts "Sending output to STDOUT" if $verbose
puts output
else
$stderr.puts "Error: No output destination available."
puts optionparser
exit 1
end
end
def self.start
options,optionparser = Screengif::Options.parse(ARGV)
$startTime = Time.now
input = handle_input(options.input_file, options, optionparser)
canvas = ImageList.new.from_blob(input)
if (!options.no_coalesce)
$stderr.puts "Beginning imagemagick coalescing..." if $verbose
canvas = canvas.coalesce()
$stderr.puts "Coalescing completed" if $verbose
end
statusPrinter = Screengif::StatusPrinter.new($stderr)
canvas.each_with_index do |img,index|
statusPrinter.printText("Processing image: #{index+1}/#{canvas.length}")
img.delay = (index + 1 == canvas.length) ? options.delay_last : options.delay
img.format = 'GIF'
if options.fuzz.to_i > 0
# when run as a gem, setting img.fuzz="5%" throws a wierd error; so we do this instead
# img.fuzz = "#{img.fuzz}%"
img.fuzz = QuantumRange * options.fuzz.to_i / 100.0
end
unless options.nocontrast
img = img.contrast(true)
img = img.white_threshold(QuantumRange * 0.99)
# img = img.level(QuantumRange * 0.05, QuantumRange * 0.95)
end
Screengif::DrawProgressbar.draw(img, (index.to_f+1)/canvas.length) if (options.progressbar)
canvas[index] = img
end
statusPrinter.done
# see http://stackoverflow.com/questions/958681/how-to-deal-with-memory-leaks-in-rmagick-in-ruby
GC.start
# Reduce down to 256 colors (as required by GIF), disable dithering (equivalent to +dither)
$stderr.puts "Beginning quantization... (takes a while)" if $verbose
canvas = canvas.quantize(256, RGBColorspace, NoDitherMethod)
$stderr.puts "Quantization completed." if $verbose
$stderr.puts "Beginning rmagick OptimizePlusLayer..." if $verbose
canvas = canvas.optimize_layers(OptimizePlusLayer)
$stderr.puts "Beginning rmagick OptimizeTransLayer..." if $verbose
canvas = canvas.optimize_layers(OptimizeTransLayer)
$stderr.puts "Rmagick processing completed. Outputting results..." if $verbose
output = canvas.to_blob
GC.start
output = Screengif::call_gifsicle(output) unless (options.no_gifsicle)
handle_output(options.output_file, output, optionparser)
Screengif::ConversionStats.print(options.input_file, options.output_file, input, output)
end
end