swf_converter 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/autotest/discover.rb +1 -0
- data/check_memory.rb +41 -0
- data/examples/balloon.png +0 -0
- data/examples/balloon.swf +0 -0
- data/examples/balloon/150x150.png +0 -0
- data/examples/balloon/80x80.png +0 -0
- data/examples/rainy_day.png +0 -0
- data/examples/rainy_day.swf +0 -0
- data/lib/swf_converter.rb +26 -0
- data/lib/swf_converter/engine.rb +24 -0
- data/lib/swf_converter/engine/alphize.rb +132 -0
- data/lib/swf_converter/engine/alphize/blender.rb +80 -0
- data/lib/swf_converter/engine/alphize/runner.rb +18 -0
- data/lib/swf_converter/engine/alphize/swfs/black.swf +0 -0
- data/lib/swf_converter/engine/alphize/swfs/src/Preview.as +20 -0
- data/lib/swf_converter/engine/alphize/swfs/src/black.xml +13 -0
- data/lib/swf_converter/engine/alphize/swfs/src/build.sh +3 -0
- data/lib/swf_converter/engine/alphize/swfs/src/classes.swf +0 -0
- data/lib/swf_converter/engine/alphize/swfs/src/white.xml +13 -0
- data/lib/swf_converter/engine/alphize/swfs/white.swf +0 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/swf_converter/engine/alphize_spec.rb +126 -0
- data/spec/swf_converter/engine_spec.rb +40 -0
- data/spec/swf_converter_spec.rb +35 -0
- data/swf_converter.gemspec +12 -0
- metadata +82 -0
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/check_memory.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'swf_converter'
|
4
|
+
|
5
|
+
class MemoryCheckEngine < SwfConverter::Engine::Alphize
|
6
|
+
def blend(*args)
|
7
|
+
puts "About to blend"
|
8
|
+
super
|
9
|
+
puts "Blended"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Swf
|
14
|
+
include SwfConverter
|
15
|
+
|
16
|
+
attr_reader :swf_image_path
|
17
|
+
|
18
|
+
converts_swfs :with => MemoryCheckEngine, :size => [600, 600]
|
19
|
+
|
20
|
+
def initialize(swf_image_path)
|
21
|
+
@swf_image_path = swf_image_path
|
22
|
+
end
|
23
|
+
|
24
|
+
def local_swf_path
|
25
|
+
File.expand_path(File.join('..', 'examples', 'balloon.swf'), __FILE__)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
3.times do |major_iteration|
|
30
|
+
5.times do |minor_iteration|
|
31
|
+
file = Tempfile.new('check_memory')
|
32
|
+
swf = Swf.new(file.path)
|
33
|
+
puts swf.local_swf_path
|
34
|
+
swf.convert_swf!
|
35
|
+
file.close!
|
36
|
+
puts "Finished #{3 * major_iteration + minor_iteration}"
|
37
|
+
end
|
38
|
+
puts "Enter?";gets
|
39
|
+
end
|
40
|
+
puts "All done!";gets
|
41
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'swf_converter/engine/alphize'
|
2
|
+
|
3
|
+
module SwfConverter
|
4
|
+
module ClassMethods
|
5
|
+
attr_reader :swf_conversion_engine, :swf_conversion_options
|
6
|
+
|
7
|
+
def converts_swfs(options={})
|
8
|
+
options = options.dup
|
9
|
+
engine_class = options.delete(:with)
|
10
|
+
@swf_conversion_engine = engine_class.new if engine_class
|
11
|
+
@swf_conversion_engine.options = options
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def convert_swf!
|
16
|
+
self.class.swf_conversion_engine.convert!(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.included(base)
|
20
|
+
base.extend(ClassMethods)
|
21
|
+
base.converts_swfs :with => Engine::Alphize
|
22
|
+
end
|
23
|
+
|
24
|
+
class InvalidOptions < RuntimeError; end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'swf_converter'
|
2
|
+
|
3
|
+
require 'swf_converter/engine/alphize'
|
4
|
+
|
5
|
+
module SwfConverter
|
6
|
+
class Engine
|
7
|
+
attr_accessor :parent
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@options = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def options=(new_options)
|
15
|
+
validate_options!(new_options) if respond_to?(:validate_options!)
|
16
|
+
@options = new_options
|
17
|
+
end
|
18
|
+
|
19
|
+
def convert!(swf_parent)
|
20
|
+
raise NotImplementedError, "SwfConverter::Engine#convert! has no defined behavior. Subclass it and define your own."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
require 'swf_converter/engine'
|
6
|
+
require 'swf_converter/engine/alphize/blender'
|
7
|
+
require 'swf_converter/engine/alphize/runner'
|
8
|
+
|
9
|
+
module SwfConverter
|
10
|
+
class Engine
|
11
|
+
class Alphize < Engine
|
12
|
+
SWF_PATHS = {}.tap do |paths|
|
13
|
+
[:black, :white].each do |type|
|
14
|
+
paths[type] = File.expand_path("../alphize/swfs/#{type}.swf", __FILE__)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
include Runner
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@output_images = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def convert!(swf_parent)
|
25
|
+
images = {
|
26
|
+
:black => Tempfile.open('swf_converter_alphize_black.png'),
|
27
|
+
:white => Tempfile.open('swf_converter_alphize_white.png')
|
28
|
+
}
|
29
|
+
begin
|
30
|
+
write_opaque_images(swf_parent, images)
|
31
|
+
blend(swf_parent, images)
|
32
|
+
if swf_parent.respond_to?(:after_swf_conversion)
|
33
|
+
swf_parent.after_swf_conversion(@output_images)
|
34
|
+
end
|
35
|
+
ensure
|
36
|
+
images[:black].close!
|
37
|
+
images[:white].close!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
def write_opaque_images(swf_parent, images)
|
44
|
+
raw = Tempfile.open 'swf_converter_alphize_raw'
|
45
|
+
raw_path = e(raw.path)
|
46
|
+
size = @options[:size]
|
47
|
+
unless size
|
48
|
+
raise ":size option must be set to the original SWF dimensions"
|
49
|
+
end
|
50
|
+
# Each RGBA pixel takes a byte, so the filesize of one frame is the
|
51
|
+
# number of pixels (width * height) times the number of channels (4)
|
52
|
+
frame_filesize = size[0] * size[1] * 4
|
53
|
+
begin
|
54
|
+
images.each do |type, image|
|
55
|
+
wrapper_swf = e(SWF_PATHS[type])
|
56
|
+
params = e("FlashVars=includeSWF=file://#{swf_parent.local_swf_path}")
|
57
|
+
image_path = e(image.path)
|
58
|
+
run "create raw SWF dump on #{type}",
|
59
|
+
"dump-gnash #{wrapper_swf} -P #{params} " +
|
60
|
+
"-D #{raw_path} --max-advances 1 -j #{size[0]} -k #{size[1]} > /dev/null"
|
61
|
+
run "create opaque image from raw on #{type}",
|
62
|
+
"tail -c #{frame_filesize} #{raw_path} | convert -size #{size[0]}x#{size[1]} -depth 8 rgba:- " +
|
63
|
+
"-separate -swap 0,2 -combine png:#{image_path}"
|
64
|
+
end
|
65
|
+
ensure
|
66
|
+
raw.close!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def blend(swf_parent, images)
|
71
|
+
begin
|
72
|
+
blender = Blender.new(images)
|
73
|
+
if @options[:output_sizes]
|
74
|
+
blend_and_resize(swf_parent, blender)
|
75
|
+
else
|
76
|
+
output_path = prepare_path(swf_parent.swf_image_path)
|
77
|
+
blender.blend! output_path
|
78
|
+
@output_images[@options[:size]] = output_path
|
79
|
+
end
|
80
|
+
rescue Exception => e
|
81
|
+
raise ConversionError, "Could not blend opaque images: #{e.class}: #{e.message}", e.backtrace
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def blend_and_resize(swf_parent, blender)
|
86
|
+
original_image = Tempfile.new('swf_converter_alphize_original.png')
|
87
|
+
original_path = original_image.path
|
88
|
+
begin
|
89
|
+
blender.blend! original_path
|
90
|
+
@options[:output_sizes].each do |size|
|
91
|
+
resize(swf_parent, size, original_path)
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
original_image.close!
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def prepare_path(path)
|
99
|
+
FileUtils.mkdir_p(File.dirname(path))
|
100
|
+
path
|
101
|
+
end
|
102
|
+
|
103
|
+
def resize(swf_parent, size, original_path)
|
104
|
+
output_path = prepare_path(swf_parent.swf_image_path(size))
|
105
|
+
run "resize #{original_path} to #{size} at #{output_path}",
|
106
|
+
"convert #{original_path} -resize #{size[0]}x#{size[1]} #{output_path}"
|
107
|
+
@output_images[size] = output_path
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_options!(options)
|
111
|
+
if options[:size]
|
112
|
+
validate_size(options[:size], ":size option")
|
113
|
+
end
|
114
|
+
|
115
|
+
if options[:output_sizes]
|
116
|
+
options[:output_sizes].each_with_index do |size, n|
|
117
|
+
validate_size(size, "Element #{n} of :output_sizes option")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def validate_size(size, description)
|
123
|
+
unless size.is_a?(Array) && size.size == 2
|
124
|
+
raise ArgumentError, "#{description} must be a 2-dimensional array, but was #{size}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class ConversionError < StandardError;end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'swf_converter/engine/alphize/runner'
|
2
|
+
|
3
|
+
module SwfConverter
|
4
|
+
class Engine
|
5
|
+
class Alphize < Engine
|
6
|
+
TEMP_NAMES = [:negative, :alpha, :division]
|
7
|
+
|
8
|
+
class Blender
|
9
|
+
include Runner
|
10
|
+
|
11
|
+
def initialize(images)
|
12
|
+
@originals = images
|
13
|
+
end
|
14
|
+
|
15
|
+
def blend!(output_path)
|
16
|
+
# The strategy here is based on the following principle:
|
17
|
+
# original_image.alpha == (CHANNEL_MAX - image_on_white.red) + image_on_black.red
|
18
|
+
# (Applies to blue and green, too. Derived from the formulas applied
|
19
|
+
# by the original composition; not too hard to work out.)
|
20
|
+
# So, we will first get a grayscale version of an alpha mask by
|
21
|
+
# negating the image-on-white (create_negative!), then add it to the
|
22
|
+
# image-on-black to get the grayscale alpha mask (create_alpha!).
|
23
|
+
# The alpha mask image has white where the original image is opaque,
|
24
|
+
# and black where it is fully transparent, and gray where it is
|
25
|
+
# partially transparent. Once we have that image, since the RGB
|
26
|
+
# values in image-on-black were found by multiplying by the alpha
|
27
|
+
# value, we divide image-on-black by the grayscale alpha mask to get
|
28
|
+
# an opaque version of the image with the correct colors
|
29
|
+
# (create_division!), then apply that grayscale image as an alpha
|
30
|
+
# mask to save the final image (create_final!).
|
31
|
+
with_temps do |temps|
|
32
|
+
create_negative!(temps)
|
33
|
+
create_alpha!(temps)
|
34
|
+
create_division!(temps)
|
35
|
+
create_final!(output_path, temps)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def create_alpha!(temps)
|
42
|
+
run "create alpha mask for blending",
|
43
|
+
"convert #{@originals[:black].path} #{temps[:negative].path} " +
|
44
|
+
"-alpha Off -compose Plus -composite #{temps[:alpha].path}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def create_division!(temps)
|
48
|
+
run "create division image for blending",
|
49
|
+
"composite #{@originals[:black].path} #{temps[:alpha].path} " +
|
50
|
+
"-alpha Off -channel RGB -compose Divide #{temps[:division].path}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_final!(output_path, temps)
|
54
|
+
run "create final image for blending",
|
55
|
+
"convert #{temps[:division].path} #{temps[:alpha].path} " +
|
56
|
+
"-compose CopyOpacity -composite #{output_path}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_negative!(temps)
|
60
|
+
run "create negative image for blending",
|
61
|
+
"convert #{@originals[:white].path} " +
|
62
|
+
"-alpha Off -channel RGB -negate #{temps[:negative].path}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def with_temps
|
66
|
+
temps = (TEMP_NAMES.inject({}) do |hash, name|
|
67
|
+
hash[name] = Tempfile.open ["swf_converter_alphize_blender_#{name}", '.png']
|
68
|
+
hash
|
69
|
+
end)
|
70
|
+
begin
|
71
|
+
yield(temps)
|
72
|
+
ensure
|
73
|
+
temps.each { |name, temp| temp.close! }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SwfConverter
|
2
|
+
class Engine
|
3
|
+
class Alphize < Engine
|
4
|
+
module Runner
|
5
|
+
def e(*args)
|
6
|
+
Shellwords.escape(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(description, command)
|
10
|
+
unless system(command)
|
11
|
+
raise ConversionError, "Failed to #{description}: #{command.inspect}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Preview extends MovieClip {
|
2
|
+
var mytf:TextField;
|
3
|
+
|
4
|
+
function Preview(scope:MovieClip) {
|
5
|
+
var mc:MovieClip = scope.createEmptyMovieClip("mc", scope.getNextHighestDepth());
|
6
|
+
var my_listener:Object = new Object();
|
7
|
+
|
8
|
+
my_listener.onLoadComplete = function(target_mc:MovieClip) {
|
9
|
+
mc.opaqueBackground = 0x0000FF;
|
10
|
+
}
|
11
|
+
|
12
|
+
var my_loader:MovieClipLoader = new MovieClipLoader();
|
13
|
+
my_loader.addListener(my_listener);
|
14
|
+
my_loader.loadClip(scope.includeSWF, mc);
|
15
|
+
}
|
16
|
+
|
17
|
+
function onLoad() {
|
18
|
+
var preview:Preview = new Preview(_root);
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<movie width="600" height="600" framerate="12">
|
3
|
+
<background color="#000000"/>
|
4
|
+
<clip import="classes.swf" />
|
5
|
+
|
6
|
+
<frame>
|
7
|
+
<library>
|
8
|
+
<clip id="app" class="Preview" />
|
9
|
+
</library>
|
10
|
+
|
11
|
+
<place id="app" name="myApp" depth="0" height="500" width="500" x="0" y="0" />
|
12
|
+
</frame>
|
13
|
+
</movie>
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<movie width="600" height="600" framerate="12">
|
3
|
+
<background color="#FFFFFF"/>
|
4
|
+
<clip import="classes.swf" />
|
5
|
+
|
6
|
+
<frame>
|
7
|
+
<library>
|
8
|
+
<clip id="app" class="Preview" />
|
9
|
+
</library>
|
10
|
+
|
11
|
+
<place id="app" name="myApp" depth="0" height="500" width="500" x="0" y="0" />
|
12
|
+
</frame>
|
13
|
+
</movie>
|
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
$:.unshift File.expand_path('..', __FILE__)
|
2
|
+
|
3
|
+
require 'swf_converter/engine'
|
4
|
+
|
5
|
+
class Swf
|
6
|
+
include SwfConverter
|
7
|
+
end
|
8
|
+
|
9
|
+
class OtherSwf
|
10
|
+
include SwfConverter
|
11
|
+
end
|
12
|
+
|
13
|
+
class VanillaSwf
|
14
|
+
include SwfConverter
|
15
|
+
end
|
16
|
+
|
17
|
+
class DummyEngine < SwfConverter::Engine; end
|
18
|
+
class OtherDummyEngine < SwfConverter::Engine; end
|
19
|
+
|
20
|
+
class ValidatingEngine < SwfConverter::Engine
|
21
|
+
def validate_options!(new_options)
|
22
|
+
unless new_options[:sizes]
|
23
|
+
raise SwfConverter::InvalidOptions, "CustomEngine requires sizes option"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class SupposedlyConvertingEngine < SwfConverter::Engine
|
29
|
+
def convert!(swf_parent)
|
30
|
+
# supposedly convert
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Matchers.define :match_image do |file2|
|
35
|
+
require 'RMagick'
|
36
|
+
|
37
|
+
match do |file1|
|
38
|
+
signatures = [file1, file2].map do |file_or_path|
|
39
|
+
is_file = file_or_path.is_a? File
|
40
|
+
if is_file
|
41
|
+
file = file_or_path
|
42
|
+
else
|
43
|
+
file = File.open(file_or_path, 'r')
|
44
|
+
end
|
45
|
+
|
46
|
+
image = Magick::Image::from_blob(file.read)[0]
|
47
|
+
file.close unless is_file
|
48
|
+
signature = image.signature
|
49
|
+
image.destroy!
|
50
|
+
signature
|
51
|
+
end
|
52
|
+
|
53
|
+
signatures[0] == signatures[1]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def example_path(subpath)
|
58
|
+
File.expand_path(File.join('..', '..', 'examples', subpath), __FILE__)
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'swf_converter/engine/alphize'
|
3
|
+
|
4
|
+
require 'tempfile'
|
5
|
+
require 'tmpdir'
|
6
|
+
|
7
|
+
describe SwfConverter::Engine::Alphize do
|
8
|
+
before(:each) do
|
9
|
+
@engine = SwfConverter::Engine::Alphize.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "size option" do
|
13
|
+
it "should be settable" do
|
14
|
+
@engine.options = {:size => [300, 500]}
|
15
|
+
@engine.options[:size].should == [300, 500]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should require a 2-dimensional array" do
|
19
|
+
lambda { @engine.options = {:size => [300, 300]} }.should_not raise_error
|
20
|
+
lambda { @engine.options = {:size => [7, 8]} }.should_not raise_error
|
21
|
+
lambda { @engine.options = {:size => 300} }.should raise_error
|
22
|
+
lambda { @engine.options = {:size => [300]} }.should raise_error
|
23
|
+
lambda { @engine.options = {:size => [300, 300, 300]} }.should raise_error
|
24
|
+
lambda { @engine.options = {:size => [300, 300, 300, 300]} }.should raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "output_sizes option" do
|
29
|
+
it "should be settable" do
|
30
|
+
@engine.options = {:output_sizes => [[300, 300]]}
|
31
|
+
@engine.options[:output_sizes].should == [[300, 300]]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should require all elements to be 2-dimensional arrays" do
|
35
|
+
lambda { @engine.options = {:output_sizes => [[300, 300]]} }.should_not raise_error
|
36
|
+
lambda { @engine.options = {:output_sizes => [[300, 300], [7, 8]]} }.should_not raise_error
|
37
|
+
lambda { @engine.options = {:output_sizes => [[300, 300], [7, 8], [1026, 1993]]} }.should_not raise_error
|
38
|
+
lambda { @engine.options = {:output_sizes => 300} }.should raise_error
|
39
|
+
lambda { @engine.options = {:output_sizes => [300]} }.should raise_error
|
40
|
+
lambda { @engine.options = {:output_sizes => [[300]]} }.should raise_error
|
41
|
+
lambda { @engine.options = {:output_sizes => [300, 300]} }.should raise_error
|
42
|
+
lambda { @engine.options = {:output_sizes => [[150, 150], [300]]} }.should raise_error
|
43
|
+
lambda { @engine.options = {:output_sizes => [[300, 300], [150, 150], [10, 26, 1993]]} }.should raise_error
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "with a size of 600x600 set" do
|
48
|
+
before(:each) do
|
49
|
+
@engine.options = {:size => [600, 600]}
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should convert the balloon to a single 600x600 image" do
|
53
|
+
output_file = Tempfile.new 'balloon.png'
|
54
|
+
begin
|
55
|
+
parent = mock('balloon', :local_swf_path => example_path('balloon.swf'),
|
56
|
+
:swf_image_path => output_file.path)
|
57
|
+
@engine.convert! parent
|
58
|
+
output_file.should match_image(example_path('balloon.png'))
|
59
|
+
ensure
|
60
|
+
output_file.close!
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should create the destination directory for the balloon if does not exist" do
|
65
|
+
dir = File.join(Dir.tmpdir, 'swf_converter_alphize_spec_tmpdir')
|
66
|
+
Dir.delete(dir) if Dir.exist?(dir)
|
67
|
+
output_file_path = File.join(dir, 'balloon.png')
|
68
|
+
output_file = nil
|
69
|
+
begin
|
70
|
+
parent = mock('balloon', :local_swf_path => example_path('balloon.swf'),
|
71
|
+
:swf_image_path => output_file_path)
|
72
|
+
@engine.convert! parent
|
73
|
+
output_file = File.open(output_file_path)
|
74
|
+
output_file.should match_image(example_path('balloon.png'))
|
75
|
+
ensure
|
76
|
+
File.delete(output_file_path) if File.exist?(output_file_path)
|
77
|
+
Dir.delete(dir) if Dir.exist?(dir)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should convert the rainy day to a single 600x600 image" do
|
82
|
+
output_file = Tempfile.new 'rainy_day.png'
|
83
|
+
begin
|
84
|
+
parent = mock('rainy_day', :local_swf_path => example_path('rainy_day.swf'),
|
85
|
+
:swf_image_path => output_file.path)
|
86
|
+
@engine.convert! parent
|
87
|
+
output_file.should match_image(example_path('rainy_day.png'))
|
88
|
+
ensure
|
89
|
+
output_file.close!
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "and 80x80 and 150x150 output sizes set" do
|
94
|
+
before(:each) do
|
95
|
+
@engine.options[:output_sizes] = [
|
96
|
+
[80, 80],
|
97
|
+
[150, 150]
|
98
|
+
]
|
99
|
+
|
100
|
+
@thumbnails = {
|
101
|
+
80 => Tempfile.new('balloon80.png'),
|
102
|
+
150 => Tempfile.new('balloon150.png')
|
103
|
+
}
|
104
|
+
|
105
|
+
@parent = mock('balloon_thumbnails', :local_swf_path => example_path('balloon.swf'))
|
106
|
+
@parent.stub!(:swf_image_path).with([80, 80]).and_return(@thumbnails[80].path)
|
107
|
+
@parent.stub!(:swf_image_path).with([150, 150]).and_return(@thumbnails[150].path)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should convert the balloon to 80x80 and 150x150 thumbnails" do
|
111
|
+
@engine.convert! @parent
|
112
|
+
@thumbnails[80].should match_image(example_path('balloon/80x80.png'))
|
113
|
+
@thumbnails[150].should match_image(example_path('balloon/150x150.png'))
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should run an after hook if set" do
|
117
|
+
@parent.should_receive(:after_swf_conversion).with({
|
118
|
+
[80, 80] => @thumbnails[80].path,
|
119
|
+
[150, 150] => @thumbnails[150].path
|
120
|
+
})
|
121
|
+
@engine.convert! @parent
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'swf_converter/engine'
|
3
|
+
|
4
|
+
describe SwfConverter::Engine do
|
5
|
+
describe "#options" do
|
6
|
+
it "should return the options set" do
|
7
|
+
engine = SwfConverter::Engine.new
|
8
|
+
engine.options = {:foo => :bar}
|
9
|
+
engine.options.should == {:foo => :bar}
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should allow a subclass to validate options on set" do
|
13
|
+
lambda {
|
14
|
+
engine = ValidatingEngine.new
|
15
|
+
engine.options = {:foo => :bar}
|
16
|
+
}.should raise_error(SwfConverter::InvalidOptions)
|
17
|
+
|
18
|
+
lambda {
|
19
|
+
engine = ValidatingEngine.new
|
20
|
+
engine.options = {:foo => :bar, :sizes => [150, 300]}
|
21
|
+
}.should_not raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#convert!" do
|
26
|
+
it "should raise an error if not implemented by subclass" do
|
27
|
+
parent = mock('engine_conversion_parent')
|
28
|
+
|
29
|
+
lambda {
|
30
|
+
engine = SwfConverter::Engine.new
|
31
|
+
engine.convert!(parent)
|
32
|
+
}.should raise_error(NotImplementedError)
|
33
|
+
|
34
|
+
lambda {
|
35
|
+
engine = SupposedlyConvertingEngine.new
|
36
|
+
engine.convert!(parent)
|
37
|
+
}.should_not raise_error
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'swf_converter'
|
3
|
+
|
4
|
+
describe SwfConverter do
|
5
|
+
it "should have alphize set by default" do
|
6
|
+
VanillaSwf.swf_conversion_engine.should be_a SwfConverter::Engine::Alphize
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should allow class to set its own engine" do
|
10
|
+
Swf.converts_swfs :with => DummyEngine
|
11
|
+
OtherSwf.converts_swfs :with => OtherDummyEngine
|
12
|
+
|
13
|
+
Swf.swf_conversion_engine.should be_a DummyEngine
|
14
|
+
OtherSwf.swf_conversion_engine.should be_a OtherDummyEngine
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should allow class to set options" do
|
18
|
+
Swf.converts_swfs :with => DummyEngine, :foo => :bar
|
19
|
+
Swf.swf_conversion_engine.options.should == {:foo => :bar}
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#convert_swf!" do
|
23
|
+
it "should call engine#convert" do
|
24
|
+
engine_class = mock('swf_engine_requiring_conversion_class')
|
25
|
+
engine = mock('swf_engine_requiring_conversion')
|
26
|
+
engine.stub!(:options=)
|
27
|
+
engine_class.stub!(:new).and_return(engine)
|
28
|
+
Swf.converts_swfs :with => engine_class
|
29
|
+
swf = Swf.new
|
30
|
+
engine.should_receive(:convert!).with(swf)
|
31
|
+
swf.convert_swf!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'swf_converter'
|
3
|
+
s.version = '0.0.3'
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.author = 'Matchu'
|
6
|
+
s.email = ['matchu1993@gmail.com']
|
7
|
+
s.summary = 'Converts SWFs to PNGs'
|
8
|
+
s.description = "Include SwfConverter on a class to get #convert_swf!, which writes PNGs from that object's SWF file. Work in progress."
|
9
|
+
s.require_path = 'lib'
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
end
|
12
|
+
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: swf_converter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.3
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matchu
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-22 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: "Include SwfConverter on a class to get #convert_swf!, which writes PNGs from that object's SWF file. Work in progress."
|
18
|
+
email:
|
19
|
+
- matchu1993@gmail.com
|
20
|
+
executables: []
|
21
|
+
|
22
|
+
extensions: []
|
23
|
+
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- Gemfile
|
28
|
+
- autotest/discover.rb
|
29
|
+
- check_memory.rb
|
30
|
+
- examples/balloon.png
|
31
|
+
- examples/balloon.swf
|
32
|
+
- examples/balloon/150x150.png
|
33
|
+
- examples/balloon/80x80.png
|
34
|
+
- examples/rainy_day.png
|
35
|
+
- examples/rainy_day.swf
|
36
|
+
- lib/swf_converter.rb
|
37
|
+
- lib/swf_converter/engine.rb
|
38
|
+
- lib/swf_converter/engine/alphize.rb
|
39
|
+
- lib/swf_converter/engine/alphize/blender.rb
|
40
|
+
- lib/swf_converter/engine/alphize/runner.rb
|
41
|
+
- lib/swf_converter/engine/alphize/swfs/black.swf
|
42
|
+
- lib/swf_converter/engine/alphize/swfs/src/Preview.as
|
43
|
+
- lib/swf_converter/engine/alphize/swfs/src/black.xml
|
44
|
+
- lib/swf_converter/engine/alphize/swfs/src/build.sh
|
45
|
+
- lib/swf_converter/engine/alphize/swfs/src/classes.swf
|
46
|
+
- lib/swf_converter/engine/alphize/swfs/src/white.xml
|
47
|
+
- lib/swf_converter/engine/alphize/swfs/white.swf
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
- spec/swf_converter/engine/alphize_spec.rb
|
50
|
+
- spec/swf_converter/engine_spec.rb
|
51
|
+
- spec/swf_converter_spec.rb
|
52
|
+
- swf_converter.gemspec
|
53
|
+
has_rdoc: true
|
54
|
+
homepage:
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
requirements: []
|
75
|
+
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 1.6.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 3
|
80
|
+
summary: Converts SWFs to PNGs
|
81
|
+
test_files: []
|
82
|
+
|