klear 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +71 -27
- data/bin/klear +15 -11
- data/lib/klear.rb +1 -0
- data/lib/klear/animation_order.rb +26 -0
- data/lib/klear/file_generator.rb +80 -64
- data/lib/klear/version.rb +1 -1
- data/spec/fixtures/animation_order/a.png +0 -0
- data/spec/fixtures/animation_order/b.png +0 -0
- data/spec/fixtures/animation_order/frame_1.png +0 -0
- data/spec/fixtures/animation_order/frame_10.png +0 -0
- data/spec/fixtures/animation_order/frame_100.png +0 -0
- data/spec/fixtures/animation_order/frame_12.png +0 -0
- data/spec/fixtures/animation_order/frame_2.png +0 -0
- data/spec/fixtures/animation_order/x.png +0 -0
- data/spec/lib/klear/animation_order_spec.rb +68 -0
- data/spec/lib/klear/file_generator_spec.rb +3 -4
- metadata +79 -41
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -29,7 +29,8 @@ Format is ZIP so a .kle file is just a zip-file containing files and folders.
|
|
29
29
|
**Directory Layout**
|
30
30
|
|
31
31
|
+ *DIR* 'META-INF' (mandatory)
|
32
|
-
+ 'kle.yml', YAML file containing meta-data describing aspects like
|
32
|
+
+ 'kle.yml', YAML file containing meta-data describing aspects like
|
33
|
+
framerate & more
|
33
34
|
+ 'MANIFEST.MF' containing meta-data about the klear file itself (e.g.
|
34
35
|
format version)
|
35
36
|
+ *DIR* 'frames' (mandatory)
|
@@ -44,11 +45,17 @@ Format is ZIP so a .kle file is just a zip-file containing files and folders.
|
|
44
45
|
|
45
46
|
### Workflow
|
46
47
|
|
47
|
-
The initial source of a kle is a sequence of PNGs + metadata. Those are used
|
48
|
+
The initial source of a kle is a sequence of PNGs + metadata. Those are used
|
49
|
+
to generate a .kle file incl. the file 'frames.bin'. The metadata is stored in
|
50
|
+
'META-INF/kle.yml' and describes aspects like fps.
|
48
51
|
|
49
|
-
If a kle file does not have frame.bin in its cache directory it can be
|
52
|
+
If a kle file does not have frame.bin in its cache directory it can be
|
53
|
+
regenerated. This is also useful for future format changes together with the
|
54
|
+
manifest to detect if a frames.bin is deprecated and needs to be regenerated.
|
50
55
|
|
51
|
-
The source sequence of PNGs is stored in the KLE-file as well
|
56
|
+
The source sequence of PNGs is stored in the KLE-file as well. Having the source
|
57
|
+
PNGs included with the archives allows for resampling of `frames.bin` and other
|
58
|
+
manipulations later on.
|
52
59
|
|
53
60
|
## Command Line Usage
|
54
61
|
|
@@ -62,52 +69,74 @@ dumps archive content info to stdout.
|
|
62
69
|
|
63
70
|
*Notice: file generation depends on jruby because of its usage of Java JAI*
|
64
71
|
|
65
|
-
Klear files are zipped directory structures which are generated from a set of
|
72
|
+
Klear files are zipped directory structures which are generated from a set of
|
73
|
+
images. The pixel values directly map to motor position and light intensity.
|
74
|
+
On top of that, the klear file contains some additional meta info and cache
|
75
|
+
date to speed up its loading at runtime. Generating a klear file from a images
|
76
|
+
sequence in a directory goes like:
|
66
77
|
|
67
78
|
$ rvm jruby exec ./bin/klear.rb generate image_sequence_dir outfile.kle
|
68
79
|
|
69
|
-
and of course, more documentation needs to come
|
70
|
-
|
80
|
+
and of course, more documentation needs to come.
|
71
81
|
|
72
82
|
## File Format Details
|
73
83
|
|
74
84
|
### PNGs
|
75
85
|
|
76
|
-
Each single PNG represents exactly one frame and is stored with 16-bit /
|
86
|
+
Each single PNG represents exactly one frame and is stored with 16-bit /
|
87
|
+
channel. The size of the PNGs is determined by the number of columns and rows,
|
88
|
+
where each tile is 10px x 10px in size. A Column represents the state of a
|
89
|
+
blade at a frame (a certain point in time). The number of columns represents
|
90
|
+
the number of blades. A Row represents one aspect across all blades, e.g. an
|
91
|
+
outermost light or the state of the motor.
|
77
92
|
|
78
|
-
|
93
|
+
**Example**
|
79
94
|
|
80
|
-
!Waves_00129.png
|
95
|
+
![Waves_00129.png](spec/fixtures/kle_generate/Waves/Waves_00129.png)
|
81
96
|
|
82
97
|
* We have 11 rows and 14 columns (blades)
|
83
|
-
*
|
84
|
-
*
|
85
|
-
Define the direction - what is a point of reference?)
|
86
|
-
* The
|
98
|
+
* (as a convention) buttom row describes the motor state
|
99
|
+
* Other rows describe the state of the lights from one direction to the
|
100
|
+
other (TODO: Define the direction - what is a point of reference?)
|
101
|
+
* The PNG is 140px by 110px in size.
|
87
102
|
|
88
103
|
### Sequence of PNGs
|
89
104
|
|
90
|
-
The order of the sequence is
|
91
|
-
|
92
|
-
The number of columns and rows must be the same for all PNGs.
|
105
|
+
The order of the sequence is determined by the **intuitiv** numerial order of the file names. This is done by extracting digits from the filenames and than sort them numerial. This is different than the directory listing order in some cases where the frame number is embedded in the filename or is not padded with a leading zero. When no frame numbe is present in the filenames the sorting is in normal alphabetical order.
|
93
106
|
|
94
107
|
*Examples*
|
95
108
|
|
96
109
|
* `A.png, B.png, X.png` is valid sequence of 3 PNGs
|
97
|
-
* `Test_0001.png, Test_0002.png,
|
110
|
+
* `Test_0001.png, Test_0002.png, Test_1000.png` is a valid sequence
|
111
|
+
|
112
|
+
A sequence does not need to be consecutive (it can have gaps e.g.
|
113
|
+
`01.png,10.png` is valid and the existence of e.g. 05.png is not enforced).
|
98
114
|
|
99
|
-
|
115
|
+
*Sequence Order:*
|
116
|
+
|
117
|
+
ls -1 (shell order) | intuitive Animation Order
|
118
|
+
----------------------+-------------------------------------
|
119
|
+
frame_1.png | frame_1.png
|
120
|
+
frame_10.png | frame_2.png
|
121
|
+
frame_100.png | frame_10.png
|
122
|
+
frame_12.png | frame_12.png
|
123
|
+
frame_2.png | frame_100.png
|
124
|
+
|
125
|
+
The number of columns and rows must be the same for all PNGs.
|
100
126
|
|
101
127
|
### kle.yml
|
102
128
|
|
103
|
-
Contains information about how to use the frames:
|
129
|
+
Contains information fields about how to use the frames:
|
104
130
|
|
105
131
|
* Number of columns and rows (geometry)
|
106
132
|
* Frames per second
|
107
133
|
* recommended gamma value
|
108
|
-
*
|
134
|
+
* pixel scale for the input PNGs
|
135
|
+
* descriptor (optional)
|
109
136
|
|
110
|
-
The geometry is determined automatically by reading the first png in the png
|
137
|
+
The geometry is determined automatically by reading the first png in the png
|
138
|
+
sequence and dividing width and height by 10 respectively. This relies on one
|
139
|
+
tile in the png being 10x10px in size.
|
111
140
|
|
112
141
|
*Example:*
|
113
142
|
<pre>
|
@@ -119,6 +148,18 @@ The geometry is determined automatically by reading the first png in the png seq
|
|
119
148
|
fps: 25
|
120
149
|
</pre>
|
121
150
|
|
151
|
+
## Klear file version 1.1 format update
|
152
|
+
|
153
|
+
*Kle-Version: 1.1*
|
154
|
+
<pre>
|
155
|
+
pixel_scale:
|
156
|
+
- 30
|
157
|
+
- 30
|
158
|
+
</pre>
|
159
|
+
|
160
|
+
In version 1.1 the pixel_scale attribute is added which was fixed to 10px pixel before. The pixel scale defines the amout of pixels per axis, default value is 10px. This means a 10x10 pixel square in the input PNG stands for one axis. For easier visibility now pixel scale can be manually overwridden. For installations with few axises, for example 10 by 2, it might be reasonable to define pixel scale as 30. This would result in a PNG size of 300 by 60 pixel, which is much easier to review on the computer screen than a 10 by 2 pixel image.
|
161
|
+
|
162
|
+
|
122
163
|
### MANIFEST.MF
|
123
164
|
|
124
165
|
The manifest contains meta information about the file and file format itself:
|
@@ -132,15 +173,18 @@ The manifest contains meta information about the file and file format itself:
|
|
132
173
|
<pre>
|
133
174
|
Manifest-Version: 1.0
|
134
175
|
|
135
|
-
Kle-Version: 1.
|
136
|
-
Created-By:
|
176
|
+
Kle-Version: 1.1
|
177
|
+
Created-By: bin/klear (0.1.5)
|
137
178
|
</pre>
|
138
179
|
|
139
180
|
### frames.bin
|
140
181
|
|
141
|
-
The frames.bin binary file contains the extracted 16-bit values sampled from
|
182
|
+
The frames.bin binary file contains the extracted 16-bit values sampled from
|
183
|
+
each tile of the PNGs. It contains all frames and each frame contains all
|
184
|
+
columns and rows.
|
142
185
|
|
143
|
-
Each 16-bit value is saved as unsigned 16 bit integer big endian (network byte
|
186
|
+
Each 16-bit value is saved as unsigned 16 bit integer big endian (network byte
|
187
|
+
order) and uses 2 bytes in frames.bin.
|
144
188
|
|
145
189
|
A PNG with 11 rows and 14 columns uses `14 x 11 x 2 bytes = 308 bytes`.
|
146
190
|
|
@@ -166,4 +210,4 @@ which results in a binary big endian (network) byte order sequence like:
|
|
166
210
|
|
167
211
|
0xBA1D 0xAFEF 0xA381 0xC753 0xC821 0xC27D 0x6981 0x97E5 0xB8E3
|
168
212
|
|
169
|
-
|
213
|
+
*(note: row 1 is the motor state by convention)*
|
data/bin/klear
CHANGED
@@ -8,22 +8,25 @@ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
|
8
8
|
require 'klear'
|
9
9
|
|
10
10
|
def usage
|
11
|
-
puts
|
11
|
+
puts <<-HELP
|
12
12
|
klear usage (version: #{Klear::VERSION} - #{Klear::DATE})
|
13
13
|
|
14
14
|
klear --help
|
15
15
|
* this help
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
klear
|
21
|
-
*
|
16
|
+
|
17
|
+
klear [OPTIONS] generate <path to PNG files folder> <klear-file>
|
18
|
+
* Generates klear file from png_folder
|
19
|
+
|
20
|
+
klear [OPTIONS] regenerate <klear-file>
|
21
|
+
* Regenerates klear file's cache
|
22
|
+
|
23
|
+
klear info <klear-file>
|
24
|
+
* Produces report on a klear file.
|
22
25
|
|
23
26
|
OPTIONS
|
24
|
-
--
|
25
|
-
|
26
|
-
|
27
|
+
--silent:[true/false] : default false
|
28
|
+
--overwrite : force overwriting of existing files
|
29
|
+
HELP
|
27
30
|
|
28
31
|
exit
|
29
32
|
end
|
@@ -37,11 +40,12 @@ Defaults = {
|
|
37
40
|
Applix.main(ARGV, Defaults) do
|
38
41
|
prolog do |_, opts|
|
39
42
|
opts[:help] and usage
|
43
|
+
$silent = opts[:silent]
|
40
44
|
@app = Klear::FileGenerator.new(opts)
|
41
45
|
end
|
42
46
|
|
43
47
|
handle(:generate) do |*args, opts|
|
44
|
-
(
|
48
|
+
(2 <= args.size) or usage
|
45
49
|
@app.generate(*args)
|
46
50
|
end
|
47
51
|
|
data/lib/klear.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Klear::AnimationOrder
|
2
|
+
|
3
|
+
def glob pattern, &blk
|
4
|
+
filenames = sort(Dir.glob(pattern))
|
5
|
+
blk.nil? or filenames.each {|fname| blk.call(fname)}
|
6
|
+
filenames
|
7
|
+
end
|
8
|
+
|
9
|
+
def sort(filenames)
|
10
|
+
filenames.sort do |a, b|
|
11
|
+
begin
|
12
|
+
frame_number_from_string(a) <=> frame_number_from_string(b)
|
13
|
+
rescue ArgumentError => e
|
14
|
+
a <=> b
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def frame_number_from_string(filename)
|
20
|
+
Integer(filename.tr('^0-9', '').sub(/^0+(\d)/, '\1'))
|
21
|
+
rescue ArgumentError => e
|
22
|
+
raise e, "no frame number in filename: '#{filename}' - #{e}"
|
23
|
+
end
|
24
|
+
|
25
|
+
extend(self)
|
26
|
+
end
|
data/lib/klear/file_generator.rb
CHANGED
@@ -1,31 +1,26 @@
|
|
1
|
-
# TODO maybe use Zip::ZipOutputStream for generating the zip first in-memory?
|
2
|
-
# TODO extract java/jruby specific stuff
|
3
|
-
|
4
1
|
class Klear::FileGenerator
|
5
2
|
|
6
3
|
Defaults = {
|
7
4
|
overwrite: false,
|
5
|
+
fps: 25,
|
6
|
+
gamma: 1.0,
|
7
|
+
pixel_scale: [10, 10],
|
8
8
|
}
|
9
9
|
|
10
10
|
def initialize options = {}
|
11
11
|
@options = Defaults.merge(options)
|
12
|
+
@fps = @options[:fps]
|
13
|
+
@gamma = @options[:gamma]
|
14
|
+
|
15
|
+
@raw_frame_values = []
|
12
16
|
@png_path = nil
|
13
17
|
@kle_path = nil
|
14
|
-
@fps = 25
|
15
|
-
if @options.has_key? :fps
|
16
|
-
@fps = @options[:fps]
|
17
|
-
end
|
18
|
-
@gamma = 1.0
|
19
|
-
if @options.has_key? :gamma
|
20
|
-
@gamma = @options[:gamma]
|
21
|
-
end
|
22
18
|
@geometry = nil
|
23
|
-
@raw_frame_values = []
|
24
19
|
@kle_file = nil
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
end
|
21
|
+
|
22
|
+
def pixel_scale
|
23
|
+
@options[:pixel_scale]
|
29
24
|
end
|
30
25
|
|
31
26
|
def overwrite?
|
@@ -33,33 +28,33 @@ class Klear::FileGenerator
|
|
33
28
|
end
|
34
29
|
|
35
30
|
def load
|
36
|
-
Zip::ZipFile.open(@kle_path) {
|
37
|
-
@kle_file = kle
|
38
|
-
}
|
31
|
+
Zip::ZipFile.open(@kle_path) {|kle| @kle_file = kle}
|
39
32
|
end
|
40
33
|
|
41
|
-
def write
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
34
|
+
def write(path)
|
35
|
+
# TODO: maybe use Zip::ZipOutputStream to generate zip file in-memory?
|
36
|
+
Zip::ZipFile.open(path, Zip::ZipFile::CREATE) do |klear|
|
37
|
+
@kle_file = klear
|
38
|
+
add_pngs(@kle_file)
|
39
|
+
recache
|
46
40
|
|
47
41
|
# Meta
|
48
|
-
|
49
|
-
|
42
|
+
klear.mkdir('META-INF')
|
43
|
+
klear.file.open("META-INF/MANIFEST.MF", "w") do |fd|
|
50
44
|
fd.write <<-MANIFEST
|
51
45
|
Manifest-Version: 1.0
|
52
46
|
|
53
|
-
Kle-Version: 1.
|
47
|
+
Kle-Version: 1.1
|
54
48
|
Created-By: #{__FILE__} (#{Klear::VERSION})
|
55
49
|
Generated-At: #{Time.now}
|
56
50
|
|
57
51
|
MANIFEST
|
58
52
|
end
|
59
53
|
|
60
|
-
|
54
|
+
klear.file.open("META-INF/kle.yml", "w") do |fd|
|
61
55
|
fd.write({
|
62
56
|
"geometry" => @geometry,
|
57
|
+
"pixel_scale" => pixel_scale,
|
63
58
|
"gamma" => @gamma,
|
64
59
|
"fps" => @fps
|
65
60
|
}.to_yaml)
|
@@ -77,7 +72,7 @@ Generated-At: #{Time.now}
|
|
77
72
|
raise "'#{@kle_path}' :: already exists! (use --overwrite to force it)"
|
78
73
|
end
|
79
74
|
end
|
80
|
-
write
|
75
|
+
write(@kle_path)
|
81
76
|
report
|
82
77
|
end
|
83
78
|
|
@@ -94,79 +89,100 @@ Output KleFile : '#{@kle_path}'
|
|
94
89
|
* geometry : #{@geometry}
|
95
90
|
|
96
91
|
REPORT
|
97
|
-
puts report if
|
92
|
+
puts report if !$silent
|
98
93
|
end
|
99
94
|
|
100
95
|
def regenerate theKleFile
|
101
96
|
@kle_path = theKleFile
|
102
97
|
load
|
103
|
-
|
98
|
+
recache
|
104
99
|
end
|
105
100
|
|
106
101
|
private
|
107
102
|
|
108
|
-
def add_pngs
|
109
|
-
|
110
|
-
|
111
|
-
puts " * adding png file '#{file}' to '#{@kle_path}'" if
|
112
|
-
|
103
|
+
def add_pngs(klear)
|
104
|
+
klear.mkdir('frames')
|
105
|
+
Klear::AnimationOrder.glob("#{@png_path}/*.png") do |file|
|
106
|
+
puts " * adding png file '#{file}' to '#{@kle_path}'" if !$silent
|
107
|
+
klear.add("frames/#{File.basename(file)}", file)
|
113
108
|
end
|
114
109
|
end
|
115
110
|
|
116
|
-
def
|
117
|
-
puts "regenerating cache..." if
|
111
|
+
def recache
|
112
|
+
puts "regenerating cache..." if !$silent
|
118
113
|
if @kle_file.dir.entries("/").include?("cache")
|
119
114
|
@kle_file.dir.rmdir('cache')
|
120
115
|
end
|
121
116
|
@kle_file.dir.mkdir('cache')
|
122
117
|
if @raw_frame_values.empty?
|
123
|
-
analyze_images
|
118
|
+
@raw_frame_values = analyze_images(@kle_file)
|
124
119
|
end
|
125
|
-
@kle_file.file.open("cache/frames.bin", "wb")
|
120
|
+
@kle_file.file.open("cache/frames.bin", "wb") do |os|
|
126
121
|
arr = BinData::Array.new(:type => :uint16be)
|
127
122
|
arr.assign @raw_frame_values
|
128
123
|
arr.write(os)
|
129
|
-
|
124
|
+
end
|
130
125
|
@kle_file.commit
|
131
126
|
end
|
132
127
|
|
128
|
+
# TODO: extract java/jruby specific stuff
|
133
129
|
if RUBY_PLATFORM.match /java/i
|
134
130
|
include Java
|
135
131
|
import 'javax.media.jai.JAI'
|
136
132
|
import 'com.sun.media.jai.codec.ByteArraySeekableStream'
|
137
133
|
|
138
|
-
def analyze_images
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
image =
|
143
|
-
|
144
|
-
|
134
|
+
def analyze_images(klear)
|
135
|
+
bytes = []
|
136
|
+
klear.dir.entries("/frames").each do |png|
|
137
|
+
puts "analyzing image file '#{png}'" if !$silent
|
138
|
+
image = load_image(klear.file.read("/frames/#{png}"))
|
139
|
+
bytes.concat(analyze_image(image, pixel_scale))
|
140
|
+
end
|
141
|
+
bytes
|
145
142
|
end
|
146
143
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
144
|
+
def load_image(ruby_bytes)
|
145
|
+
istream = ByteArraySeekableStream.new(ruby_bytes.to_java_bytes)
|
146
|
+
image = JAI.create("stream", istream)
|
147
|
+
|
148
|
+
if @geometry.nil? # first loaded image defines the geometry
|
149
|
+
xs, ys = *pixel_scale
|
150
|
+
@geometry = {columns: image.width / xs, rows: image.height / ys}
|
151
|
+
puts "Determined geometry: #{@geometry.inspect}" if !$silent
|
152
|
+
|
153
|
+
if(image.width.modulo(xs) != 0) or (image.height.modulo(ys) != 0)
|
154
|
+
raise "image size / pixel scale mismatch: #{@geometry} - #{p@ixel_scale}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
image
|
159
|
+
end
|
160
|
+
|
161
|
+
def analyze_image(image, pixel_scale)
|
162
|
+
#@geometry ||= (
|
163
|
+
# puts "Determined geometry: #{@geometry.inspect}" if !$silent
|
164
|
+
# {columns: image.width / 10, rows: image.height / 10}
|
165
|
+
#)
|
166
|
+
|
167
|
+
xs, ys = *pixel_scale
|
168
|
+
xc, yc = image.width / xs, image.height / ys
|
153
169
|
|
154
170
|
raster = image.getData
|
155
171
|
bytes = []
|
156
|
-
(0
|
157
|
-
(0
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
#puts "value at (col #{col}, #{@geometry[:rows] - row - 1}) - pixel-coords: (#{
|
162
|
-
bytes <<
|
163
|
-
|
164
|
-
|
172
|
+
(0...yc).to_a.reverse!.each do |row|
|
173
|
+
(0...xc).each do |col|
|
174
|
+
yi = (row + 0.5) * ys # 5 + 10 * (row)
|
175
|
+
xi = (col + 0.5) * xs # 5 + 10 * (col)
|
176
|
+
val = raster.getPixel(xi, yi, nil)[0].to_i
|
177
|
+
#puts "value at (col #{col}, #{@geometry[:rows] - row - 1}) - pixel-coords: (#{xi}, #{yi}) => #{val}"
|
178
|
+
bytes << val
|
179
|
+
end
|
180
|
+
end
|
165
181
|
bytes
|
166
182
|
end
|
167
183
|
|
168
184
|
else # NOT JAVA!
|
169
|
-
def analyze_images
|
185
|
+
def analyze_images(*_)
|
170
186
|
raise "use JRUBY to run this script with #analyse_images support"
|
171
187
|
end
|
172
188
|
end
|
data/lib/klear/version.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Klear::AnimationOrder do
|
4
|
+
let(:ao) { subject }
|
5
|
+
|
6
|
+
it 'globs animation from directory' do
|
7
|
+
ao_dir = "#{RSpec.configuration.fixtures}/animation_order"
|
8
|
+
expect(ao.glob("#{ao_dir}/frame_*.png")).to eq(%W(
|
9
|
+
#{ao_dir}/frame_1.png
|
10
|
+
#{ao_dir}/frame_2.png
|
11
|
+
#{ao_dir}/frame_10.png
|
12
|
+
#{ao_dir}/frame_12.png
|
13
|
+
#{ao_dir}/frame_100.png
|
14
|
+
))
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'globs files without frame number' do
|
18
|
+
ao_dir = "#{RSpec.configuration.fixtures}/animation_order"
|
19
|
+
expect(ao.glob("#{ao_dir}/?.png")).to eq(%W(
|
20
|
+
#{ao_dir}/a.png
|
21
|
+
#{ao_dir}/b.png
|
22
|
+
#{ao_dir}/x.png
|
23
|
+
))
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'raises exception on non numbered frames' do
|
27
|
+
expect{ao.frame_number_from_string('a.png')}.to raise_error(
|
28
|
+
/no frame number in filename: 'a.png'/
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'extracts leading number' do
|
33
|
+
expect(ao.frame_number_from_string('23_a.png')).to eq(23)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'extracts trailing number' do
|
37
|
+
expect(ao.frame_number_from_string('tmp/frames/frame_0.png')).to eq(0)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'extracts zero padded leading number' do
|
41
|
+
expect(ao.frame_number_from_string('0023_a.png')).to eq(23)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'extracts zero padded trailing number' do
|
45
|
+
expect(ao.frame_number_from_string('a_0023.png')).to eq(23)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'is no confused by trailing zeros' do
|
49
|
+
expect(ao.frame_number_from_string('1000')).to eq(1000)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
it 'sorts plain numbers' do
|
54
|
+
expect(ao.sort(%w(1 2 3 4))).to eq(%w(1 2 3 4))
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'handles zero padded numbers' do
|
58
|
+
expect(ao.sort(%w(03 02 01 04))).to eq(%w(01 02 03 04))
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'sorts numerical' do
|
62
|
+
expect(ao.sort(%w(100 1 2 10))).to eq(%w(1 2 10 100))
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'sorts numerical when number is in string' do
|
66
|
+
expect(ao.sort(%w(f1 f100 f2 f20))).to eq(%w(f1 f2 f20 f100))
|
67
|
+
end
|
68
|
+
end
|
@@ -3,15 +3,15 @@ require 'tmpdir'
|
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
5
|
describe Klear::FileGenerator do
|
6
|
-
|
7
|
-
|
6
|
+
unless RUBY_PLATFORM.match /java/i
|
7
|
+
pending 'porting tests from jruby'
|
8
|
+
else
|
8
9
|
context 'default options' do
|
9
10
|
let(:fg) { Klear::FileGenerator.new }
|
10
11
|
it 'defaults to not overwrite' do
|
11
12
|
expect(fg.overwrite?).to be(false)
|
12
13
|
end
|
13
14
|
end
|
14
|
-
|
15
15
|
|
16
16
|
it "reads a directory with pngs and produces a valid kle file" do
|
17
17
|
fg = Klear::FileGenerator.new :fps => 33, :gamma => 2.4
|
@@ -85,5 +85,4 @@ describe Klear::FileGenerator do
|
|
85
85
|
FileUtils.rmtree tmpDir
|
86
86
|
end
|
87
87
|
end # JAVA
|
88
|
-
|
89
88
|
end
|
metadata
CHANGED
@@ -1,130 +1,148 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: klear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- art+com/dirk luesebrink
|
8
|
-
autorequire:
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
date: 2013-11-12 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: applix
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
none: false
|
15
22
|
requirement: !ruby/object:Gem::Requirement
|
16
23
|
requirements:
|
17
24
|
- - '>='
|
18
25
|
- !ruby/object:Gem::Version
|
19
26
|
version: '0'
|
20
|
-
|
27
|
+
none: false
|
21
28
|
prerelease: false
|
29
|
+
type: :runtime
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rubyzip
|
22
32
|
version_requirements: !ruby/object:Gem::Requirement
|
23
33
|
requirements:
|
24
34
|
- - '>='
|
25
35
|
- !ruby/object:Gem::Version
|
26
36
|
version: '0'
|
27
|
-
|
28
|
-
name: rubyzip
|
37
|
+
none: false
|
29
38
|
requirement: !ruby/object:Gem::Requirement
|
30
39
|
requirements:
|
31
40
|
- - '>='
|
32
41
|
- !ruby/object:Gem::Version
|
33
42
|
version: '0'
|
34
|
-
|
43
|
+
none: false
|
35
44
|
prerelease: false
|
45
|
+
type: :runtime
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bindata
|
36
48
|
version_requirements: !ruby/object:Gem::Requirement
|
37
49
|
requirements:
|
38
50
|
- - '>='
|
39
51
|
- !ruby/object:Gem::Version
|
40
52
|
version: '0'
|
41
|
-
|
42
|
-
name: bindata
|
53
|
+
none: false
|
43
54
|
requirement: !ruby/object:Gem::Requirement
|
44
55
|
requirements:
|
45
56
|
- - '>='
|
46
57
|
- !ruby/object:Gem::Version
|
47
58
|
version: '0'
|
48
|
-
|
59
|
+
none: false
|
49
60
|
prerelease: false
|
61
|
+
type: :runtime
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - '>='
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
55
|
-
|
56
|
-
name: rspec
|
69
|
+
none: false
|
57
70
|
requirement: !ruby/object:Gem::Requirement
|
58
71
|
requirements:
|
59
72
|
- - '>='
|
60
73
|
- !ruby/object:Gem::Version
|
61
74
|
version: '0'
|
62
|
-
|
75
|
+
none: false
|
63
76
|
prerelease: false
|
77
|
+
type: :development
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: guard
|
64
80
|
version_requirements: !ruby/object:Gem::Requirement
|
65
81
|
requirements:
|
66
82
|
- - '>='
|
67
83
|
- !ruby/object:Gem::Version
|
68
84
|
version: '0'
|
69
|
-
|
70
|
-
name: guard
|
85
|
+
none: false
|
71
86
|
requirement: !ruby/object:Gem::Requirement
|
72
87
|
requirements:
|
73
88
|
- - '>='
|
74
89
|
- !ruby/object:Gem::Version
|
75
90
|
version: '0'
|
76
|
-
|
91
|
+
none: false
|
77
92
|
prerelease: false
|
93
|
+
type: :development
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: guard-rspec
|
78
96
|
version_requirements: !ruby/object:Gem::Requirement
|
79
97
|
requirements:
|
80
98
|
- - '>='
|
81
99
|
- !ruby/object:Gem::Version
|
82
100
|
version: '0'
|
83
|
-
|
84
|
-
name: guard-rspec
|
101
|
+
none: false
|
85
102
|
requirement: !ruby/object:Gem::Requirement
|
86
103
|
requirements:
|
87
104
|
- - '>='
|
88
105
|
- !ruby/object:Gem::Version
|
89
106
|
version: '0'
|
90
|
-
|
107
|
+
none: false
|
91
108
|
prerelease: false
|
92
|
-
|
93
|
-
requirements:
|
94
|
-
- - '>='
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
109
|
+
type: :development
|
97
110
|
- !ruby/object:Gem::Dependency
|
98
111
|
name: rb-fsevent
|
99
|
-
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
113
|
requirements:
|
101
114
|
- - ~>
|
102
115
|
- !ruby/object:Gem::Version
|
103
116
|
version: 0.9.1
|
104
|
-
|
105
|
-
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
107
119
|
requirements:
|
108
120
|
- - ~>
|
109
121
|
- !ruby/object:Gem::Version
|
110
122
|
version: 0.9.1
|
123
|
+
none: false
|
124
|
+
prerelease: false
|
125
|
+
type: :development
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
113
|
-
|
127
|
+
name: ruby-debug
|
128
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
129
|
requirements:
|
115
130
|
- - '>='
|
116
131
|
- !ruby/object:Gem::Version
|
117
132
|
version: '0'
|
118
|
-
|
119
|
-
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirement: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - '>='
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
|
-
|
126
|
-
|
127
|
-
|
139
|
+
none: false
|
140
|
+
prerelease: false
|
141
|
+
type: :development
|
142
|
+
description: " \n create and manage choreographies for motors and lights on the\
|
143
|
+
\ Manta Rhei.\n klear is the kinetic-light-engine archive format and is used\
|
144
|
+
\ by the\n kinetic-light-engine runtime to drive the Manta Rhei installation.\n\
|
145
|
+
\ "
|
128
146
|
email:
|
129
147
|
- dirk.luesebrink@artcom.de
|
130
148
|
executables:
|
@@ -140,6 +158,7 @@ files:
|
|
140
158
|
- bin/klear
|
141
159
|
- klear.gemspec
|
142
160
|
- lib/klear.rb
|
161
|
+
- lib/klear/animation_order.rb
|
143
162
|
- lib/klear/choreography.rb
|
144
163
|
- lib/klear/file.rb
|
145
164
|
- lib/klear/file_generator.rb
|
@@ -148,6 +167,14 @@ files:
|
|
148
167
|
- lib/klear/frames.rb
|
149
168
|
- lib/klear/motors.rb
|
150
169
|
- lib/klear/version.rb
|
170
|
+
- spec/fixtures/animation_order/a.png
|
171
|
+
- spec/fixtures/animation_order/b.png
|
172
|
+
- spec/fixtures/animation_order/frame_1.png
|
173
|
+
- spec/fixtures/animation_order/frame_10.png
|
174
|
+
- spec/fixtures/animation_order/frame_100.png
|
175
|
+
- spec/fixtures/animation_order/frame_12.png
|
176
|
+
- spec/fixtures/animation_order/frame_2.png
|
177
|
+
- spec/fixtures/animation_order/x.png
|
151
178
|
- spec/fixtures/black_to_white_linear.kle
|
152
179
|
- spec/fixtures/kle_generate/Waves/Waves_00129.png
|
153
180
|
- spec/fixtures/kle_generate/Waves/Waves_00130.png
|
@@ -419,6 +446,7 @@ files:
|
|
419
446
|
- spec/fixtures/test.kle
|
420
447
|
- spec/fixtures/test_without_gamma_and_fps.kle
|
421
448
|
- spec/fixtures/wave.kle
|
449
|
+
- spec/lib/klear/animation_order_spec.rb
|
422
450
|
- spec/lib/klear/choreography_spec.rb
|
423
451
|
- spec/lib/klear/file_generator_spec.rb
|
424
452
|
- spec/lib/klear/file_spec.rb
|
@@ -430,8 +458,7 @@ files:
|
|
430
458
|
- spec/spec_helper.rb
|
431
459
|
homepage: http://www.artcom.de/en/projects/project/detail/manta-rhei/
|
432
460
|
licenses: []
|
433
|
-
|
434
|
-
post_install_message:
|
461
|
+
post_install_message:
|
435
462
|
rdoc_options: []
|
436
463
|
require_paths:
|
437
464
|
- lib
|
@@ -440,18 +467,28 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
440
467
|
- - '>='
|
441
468
|
- !ruby/object:Gem::Version
|
442
469
|
version: '0'
|
470
|
+
none: false
|
443
471
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
444
472
|
requirements:
|
445
473
|
- - '>='
|
446
474
|
- !ruby/object:Gem::Version
|
447
475
|
version: '0'
|
476
|
+
none: false
|
448
477
|
requirements: []
|
449
|
-
rubyforge_project:
|
450
|
-
rubygems_version:
|
451
|
-
signing_key:
|
452
|
-
specification_version:
|
478
|
+
rubyforge_project:
|
479
|
+
rubygems_version: 1.8.24
|
480
|
+
signing_key:
|
481
|
+
specification_version: 3
|
453
482
|
summary: create and manage choreographies for motors and lights on the Manta Rhei
|
454
483
|
test_files:
|
484
|
+
- spec/fixtures/animation_order/a.png
|
485
|
+
- spec/fixtures/animation_order/b.png
|
486
|
+
- spec/fixtures/animation_order/frame_1.png
|
487
|
+
- spec/fixtures/animation_order/frame_10.png
|
488
|
+
- spec/fixtures/animation_order/frame_100.png
|
489
|
+
- spec/fixtures/animation_order/frame_12.png
|
490
|
+
- spec/fixtures/animation_order/frame_2.png
|
491
|
+
- spec/fixtures/animation_order/x.png
|
455
492
|
- spec/fixtures/black_to_white_linear.kle
|
456
493
|
- spec/fixtures/kle_generate/Waves/Waves_00129.png
|
457
494
|
- spec/fixtures/kle_generate/Waves/Waves_00130.png
|
@@ -723,6 +760,7 @@ test_files:
|
|
723
760
|
- spec/fixtures/test.kle
|
724
761
|
- spec/fixtures/test_without_gamma_and_fps.kle
|
725
762
|
- spec/fixtures/wave.kle
|
763
|
+
- spec/lib/klear/animation_order_spec.rb
|
726
764
|
- spec/lib/klear/choreography_spec.rb
|
727
765
|
- spec/lib/klear/file_generator_spec.rb
|
728
766
|
- spec/lib/klear/file_spec.rb
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 2ce4d5cdafe23e6dff8a591fbb74ab16316acff8
|
4
|
-
data.tar.gz: db86b996953818cadb54ae3217a6d911b097d83a
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 996c00baae0b8081d085affe62d9d0b07e460148d01698fec8365e0e5be65d8e4699947cfbe7c2018c8cea23a6f3217b8732444db9cf5ffa6598e9cd801a4c66
|
7
|
-
data.tar.gz: 44b5b2ad67c6db67bc7fdf9590064a9f3e506a9612c15c0711b0ee15a4fbdaf62148104b85bde55f1d2d35eb534acda1ea259d87a635d8bb46dc54f5af8c80e5
|