words_to_image 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +22 -0
- data/Rakefile +7 -0
- data/collage.gemspec +40 -0
- data/config/defaults.rb +8 -0
- data/config/flickr_init.rb +4 -0
- data/lib/words_to_image/collage.rb +53 -0
- data/lib/words_to_image/dictionary.rb +23 -0
- data/lib/words_to_image/flickr.rb +15 -0
- data/lib/words_to_image/image.rb +55 -0
- data/lib/words_to_image/processor.rb +41 -0
- data/spec/fixtures/sample_dict +15 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/words_to_image/collage_spec.rb +33 -0
- data/spec/words_to_image/dictionary_spec.rb +44 -0
- data/spec/words_to_image/flickr_spec.rb +38 -0
- data/spec/words_to_image/image_spec.rb +69 -0
- data/spec/words_to_image/processor_spec.rb +56 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cca0cf3ff67d38ada24d0e54af212cb0d441b0b6
|
4
|
+
data.tar.gz: e083dc22715bb2b12551fe524c6e476ad9403385
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 71428f5b5562691eba5ac2afcae5507109ea5586d844e95b3472d98cc1d4b50a4866e6d144791edb0a53e6fe8ffb0e1b05be6a076b0d0a1550de8305482598cc
|
7
|
+
data.tar.gz: a1634ec4b5725c5b85c58fa7d1e8bc417861ea88e5f20e9406f8f64dc85e3b4cdcb7d89555f8939844255db69545c1a7fb245a442e56d17bd8cb752244262754
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
*.jpg
|
23
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Alona Mekhovova
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Wokds To Image
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
---------------> don't forget an instruction for ImageMagick
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'words_to_image'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install words_to_image
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
data/Rakefile
ADDED
data/collage.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib/words_to_image', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "words_to_image"
|
7
|
+
spec.version = "0.0.2"
|
8
|
+
spec.authors = ["Alona Mekhovova"]
|
9
|
+
spec.email = ["alona.tarasova@gmail.com"]
|
10
|
+
spec.summary = "A collage maker based on flickr search results"
|
11
|
+
spec.description = %q{
|
12
|
+
command line application that
|
13
|
+
|
14
|
+
* accepts a list of search keywords as arguments
|
15
|
+
* queries the Flickr API for the top-rated image for each keyword
|
16
|
+
* downloads the results
|
17
|
+
* crops them rectangularly
|
18
|
+
* assembles a collage grid from ten images and
|
19
|
+
* writes the result to a user-supplied filename
|
20
|
+
|
21
|
+
If given less than ten keywords, or if any keyword fails to
|
22
|
+
result in a match, retrieve random words from a dictionary
|
23
|
+
source such as `/usr/share/dict/words`. Repeat as necessary
|
24
|
+
until you have gathered ten images.
|
25
|
+
}
|
26
|
+
spec.homepage = ""
|
27
|
+
spec.license = "MIT"
|
28
|
+
|
29
|
+
spec.files = `git ls-files -z`.split("\x0")
|
30
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
31
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
32
|
+
spec.require_paths = ["config", "lib/words_to_image"]
|
33
|
+
|
34
|
+
spec.add_runtime_dependency "flickraw"
|
35
|
+
spec.add_runtime_dependency "mini_magick"
|
36
|
+
|
37
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
38
|
+
spec.add_development_dependency "rake"
|
39
|
+
spec.add_development_dependency "rspec"
|
40
|
+
end
|
data/config/defaults.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'defaults'
|
2
|
+
|
3
|
+
module WordsToImage
|
4
|
+
class Collage
|
5
|
+
def initialize(path, max_row_width, images_count)
|
6
|
+
@path = valid_path(path)
|
7
|
+
@img_per_row = [(max_row_width / 150).to_i, images_count].min
|
8
|
+
@rows_count = (images_count / @img_per_row.to_f).ceil
|
9
|
+
|
10
|
+
@images_connected = 0
|
11
|
+
get_collage_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def +( image )
|
15
|
+
img = MiniMagick::Image.new(@path)
|
16
|
+
second_image = MiniMagick::Image.new(image.filename)
|
17
|
+
|
18
|
+
img = img.composite(second_image) do |i|
|
19
|
+
i.compose "Over"
|
20
|
+
i.geometry "+#{horizontal_offset}+#{vertical_offset}"
|
21
|
+
end
|
22
|
+
img.write(@path)
|
23
|
+
|
24
|
+
@images_connected += 1
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def get_collage_file
|
30
|
+
`convert -size #{@img_per_row * 150}x#{@rows_count * 150} canvas:white #{@path}`
|
31
|
+
end
|
32
|
+
|
33
|
+
def horizontal_offset
|
34
|
+
(@images_connected % @img_per_row) * 150
|
35
|
+
end
|
36
|
+
|
37
|
+
def vertical_offset
|
38
|
+
(@images_connected / @img_per_row) * 150
|
39
|
+
end
|
40
|
+
|
41
|
+
def valid_path(path)
|
42
|
+
dir, base = File.split(path)
|
43
|
+
|
44
|
+
base += ".jpg" unless base[/\.\w+$/]
|
45
|
+
|
46
|
+
raise "Directory unwritable" unless File.writable?(dir)
|
47
|
+
|
48
|
+
"#{dir}/#{base}"
|
49
|
+
rescue => e
|
50
|
+
raise ArgumentError, "invalid result file path: #{e.message}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module WordsToImage
|
2
|
+
class Dictionary
|
3
|
+
def initialize(path)
|
4
|
+
@path = path
|
5
|
+
end
|
6
|
+
|
7
|
+
def get_word
|
8
|
+
words.delete(words.sample)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def words
|
13
|
+
@words ||= read_content
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_content
|
17
|
+
contents = File.read(@path)
|
18
|
+
contents.split
|
19
|
+
rescue => e
|
20
|
+
raise IOError, "Dictionary file unreadable: #{e.message}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "flickraw"
|
2
|
+
require "flickr_init"
|
3
|
+
|
4
|
+
module WordsToImage
|
5
|
+
class Flickr
|
6
|
+
def self.fetch(keyword)
|
7
|
+
photo = flickr.photos.search(text: keyword, media: :photos, per_page: 1, sort: "interestingness-desc").first
|
8
|
+
return if photo.nil?
|
9
|
+
|
10
|
+
FlickRaw.url_q OpenStruct.new(photo.to_hash)
|
11
|
+
rescue => e
|
12
|
+
raise "problem connecting to flickr API: #{e.message}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'mini_magick'
|
2
|
+
|
3
|
+
module WordsToImage
|
4
|
+
class Image
|
5
|
+
def initialize(path)
|
6
|
+
@path = path
|
7
|
+
@square_size = 150 #px
|
8
|
+
end
|
9
|
+
|
10
|
+
def squarize!
|
11
|
+
img = MiniMagick::Image.new(filename)
|
12
|
+
|
13
|
+
w_original, h_original = [img[:width].to_f, img[:height].to_f]
|
14
|
+
|
15
|
+
# check proportions
|
16
|
+
if w_original < h_original
|
17
|
+
bigger_side = (h_original * @square_size / w_original).to_i
|
18
|
+
remove = "0x#{ ((bigger_side - @square_size)/2.0).to_i }"
|
19
|
+
else
|
20
|
+
bigger_side = (w_original * @square_size / h_original).to_i
|
21
|
+
remove = "#{ ((bigger_side - @square_size)/2.0).to_i }x0"
|
22
|
+
end
|
23
|
+
op_resize = [bigger_side, bigger_side].join("x")
|
24
|
+
|
25
|
+
img.resize(op_resize)
|
26
|
+
img.shave(remove)
|
27
|
+
|
28
|
+
self
|
29
|
+
rescue => e
|
30
|
+
raise IOError, "failed to modify an image: #{e.message}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def download
|
34
|
+
open(URI.parse(@path)) { |image|
|
35
|
+
File.open(filename, "wb") do |file|
|
36
|
+
file.puts image.read
|
37
|
+
end
|
38
|
+
}
|
39
|
+
|
40
|
+
self
|
41
|
+
rescue => e
|
42
|
+
raise IOError, "image download error: #{e.message}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def filename
|
46
|
+
@filename ||= "img_#{Time.now.to_f}#{@path[/\.\w+$/]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete!
|
50
|
+
File.delete(filename)
|
51
|
+
rescue
|
52
|
+
puts "! could not delete temporary file: #{filename}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'defaults'
|
2
|
+
|
3
|
+
module WordsToImage
|
4
|
+
class Processor
|
5
|
+
def initialize(local_settings={})
|
6
|
+
@images_count = local_settings[:images_count] || DEFAULT_SETTINGS[:images_count]
|
7
|
+
@dictionary_path = local_settings[:dictionary_path] || DEFAULT_SETTINGS[:dictionary_path]
|
8
|
+
@result_path = local_settings[:result_path] || DEFAULT_SETTINGS[:result_path]
|
9
|
+
@max_row_width = [local_settings[:max_row_width] || DEFAULT_SETTINGS[:max_row_width], 150].max
|
10
|
+
|
11
|
+
@images, @words = [], []
|
12
|
+
@dictionary = Dictionary.new(@dictionary_path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_images(keywords=[])
|
16
|
+
while !collection_complete?
|
17
|
+
keyword = keywords.shift || @dictionary.get_word
|
18
|
+
raise ArgumentError, "not enough words to complete a collage" unless keyword
|
19
|
+
|
20
|
+
next unless image = Flickr.fetch( keyword )
|
21
|
+
@images << image
|
22
|
+
@words << keyword
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_collage
|
27
|
+
@result = Collage.new(@result_path, @max_row_width, @images.count)
|
28
|
+
|
29
|
+
@images.each do |path|
|
30
|
+
image = Image.new(path).download.squarize!
|
31
|
+
@result += image
|
32
|
+
image.delete!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def collection_complete?
|
38
|
+
@images.count == @images_count
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WordsToImage::Collage do
|
4
|
+
let(:collage) { WordsToImage::Collage.new('path', 333, 5) }
|
5
|
+
let(:image) {double("mini_magick image")}
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow_any_instance_of(WordsToImage::Collage).to receive(:get_collage_file)
|
9
|
+
allow(MiniMagick::Image).to receive(:new).and_return(image)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it "should fix the path given" do
|
14
|
+
expect(collage.instance_variable_get(:"@path")).to eq("./path.jpg")
|
15
|
+
end
|
16
|
+
|
17
|
+
context "inexisting path" do
|
18
|
+
it "should raise an error" do
|
19
|
+
expect {
|
20
|
+
WordsToImage::Collage.new('/inexisting/directory/file', 333, 5)
|
21
|
+
}.to raise_error(ArgumentError, /Directory unwritable/)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#+" do
|
27
|
+
it "should connect an image to collage" do
|
28
|
+
expect(image).to receive(:composite).and_return(double("image", write: {}))
|
29
|
+
|
30
|
+
collage + WordsToImage::Image.new('path')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WordsToImage::Dictionary do
|
4
|
+
SAMPLE_PATH = 'spec/fixtures/sample_dict'
|
5
|
+
|
6
|
+
describe "#get_word" do
|
7
|
+
let(:dictionary) { WordsToImage::Dictionary.new(SAMPLE_PATH) }
|
8
|
+
|
9
|
+
it "should return one word from the set" do
|
10
|
+
words = File.read(SAMPLE_PATH).split
|
11
|
+
|
12
|
+
words.count.times do
|
13
|
+
expect(words).to include(dictionary.get_word)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return words in random order" do
|
18
|
+
dict2 = WordsToImage::Dictionary.new(SAMPLE_PATH)
|
19
|
+
|
20
|
+
words = (1..5).map { dictionary.get_word }
|
21
|
+
words2 = (1..5).map { dict2.get_word }
|
22
|
+
|
23
|
+
expect(words).not_to eq words2
|
24
|
+
end
|
25
|
+
|
26
|
+
context "no words left" do
|
27
|
+
before do
|
28
|
+
allow(dictionary).to receive(:read_content).and_return([])
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return nil" do
|
32
|
+
expect(dictionary.get_word).to be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "file unreadable" do
|
37
|
+
let(:inexisting_dict) { WordsToImage::Dictionary.new('/inexisting/path') }
|
38
|
+
|
39
|
+
it "should raise an exception with verbose description" do
|
40
|
+
expect{inexisting_dict.get_word}.to raise_error(IOError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WordsToImage::Flickr do
|
4
|
+
describe ".fetch" do
|
5
|
+
context "image found" do
|
6
|
+
before do
|
7
|
+
photo_info = {id: 123, server: 456, title: "Pure beauty"}
|
8
|
+
|
9
|
+
allow(flickr.photos).to receive("search").and_return([photo_info])
|
10
|
+
allow(FlickRaw).to receive("url_q").with(OpenStruct).and_return("http://image_url")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should fetch an image using flickr API" do
|
14
|
+
expect(WordsToImage::Flickr.fetch("weihnachten")).to eq "http://image_url"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "nothing found" do
|
19
|
+
before do
|
20
|
+
allow(flickr.photos).to receive("search").and_return([])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return nil if nothing fetched" do
|
24
|
+
expect(WordsToImage::Flickr.fetch("weihnachten")).to be_nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "fetch is impossible" do
|
29
|
+
before do
|
30
|
+
allow(flickr.photos).to receive("search").and_raise(StandardError, "no internet")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise an error" do
|
34
|
+
expect{WordsToImage::Flickr.fetch("weihnachten")}.to raise_error(RuntimeError, "problem connecting to flickr API: no internet")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WordsToImage::Image do
|
4
|
+
let(:image) { WordsToImage::Image.new('http://image.jpg') }
|
5
|
+
let(:image_file) { double("image file", shave: nil, resize: nil) }
|
6
|
+
before do
|
7
|
+
allow(MiniMagick::Image).to receive(:new).and_return(image_file)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#squarize!" do
|
11
|
+
context "initially square image" do
|
12
|
+
before do
|
13
|
+
allow(image_file).to receive(:[]).with(:width).and_return(300)
|
14
|
+
allow(image_file).to receive(:[]).with(:height).and_return(300)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should resize the image" do
|
18
|
+
expect(image_file).to receive(:resize).with("150x150")
|
19
|
+
|
20
|
+
image.squarize!
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should NOT crop the image" do
|
24
|
+
expect(image_file).to receive(:shave).with("0x0")
|
25
|
+
|
26
|
+
image.squarize!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "image has landscape layout" do
|
31
|
+
before do
|
32
|
+
allow(image_file).to receive(:[]).with(:width).and_return(400)
|
33
|
+
allow(image_file).to receive(:[]).with(:height).and_return(300)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should resize the image by longer part" do
|
37
|
+
expect(image_file).to receive(:resize).with("200x200")
|
38
|
+
|
39
|
+
image.squarize!
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should crop the image horizontally" do
|
43
|
+
expect(image_file).to receive(:shave).with("25x0")
|
44
|
+
|
45
|
+
image.squarize!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "image has portrait layout" do
|
50
|
+
before do
|
51
|
+
allow(image_file).to receive(:[]).with(:width).and_return(200)
|
52
|
+
allow(image_file).to receive(:[]).with(:height).and_return(400)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should resize the image by longer part" do
|
56
|
+
expect(image_file).to receive(:resize).with("300x300")
|
57
|
+
|
58
|
+
image.squarize!
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should crop the image vertically" do
|
62
|
+
expect(image_file).to receive(:shave).with("0x75")
|
63
|
+
|
64
|
+
image.squarize!
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WordsToImage::Processor do
|
4
|
+
let(:processor) { WordsToImage::Processor.new }
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "should set all default configs" do
|
8
|
+
WordsToImage::DEFAULT_SETTINGS.each_pair do |setting, value|
|
9
|
+
expect(processor.instance_variable_get(:"@#{setting}")).to eq value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should setup the user input vars with higher prio" do
|
14
|
+
local_settings = {
|
15
|
+
images_count: 3,
|
16
|
+
dictionary_path: 'other path',
|
17
|
+
result_path: 'my secret place'
|
18
|
+
}
|
19
|
+
|
20
|
+
processor1 = WordsToImage::Processor.new(local_settings)
|
21
|
+
local_settings.each_pair do |setting, value|
|
22
|
+
expect(processor1.instance_variable_get(:"@#{setting}")).to eq value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#get_images" do
|
28
|
+
let(:processor) { WordsToImage::Processor.new(images_count: 5) }
|
29
|
+
|
30
|
+
before do
|
31
|
+
allow(WordsToImage::Flickr).to receive(:fetch).and_return("http://image_url")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should fetch enough images using keywords" do
|
35
|
+
processor.get_images(["word1", "word2", "word3", "word4", "word5"])
|
36
|
+
|
37
|
+
expect(processor.instance_variable_get(:"@images").count).to eq 5
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use the dictionary it additional words needed" do
|
41
|
+
expect_any_instance_of(WordsToImage::Dictionary).to receive(:get_word).exactly(3).times.and_return("random word")
|
42
|
+
|
43
|
+
processor.get_images(["word1", "word2"])
|
44
|
+
end
|
45
|
+
|
46
|
+
context "not enough words available" do
|
47
|
+
before do
|
48
|
+
allow_any_instance_of(WordsToImage::Dictionary).to receive(:words).and_return([])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should raise an error" do
|
52
|
+
expect{processor.get_images}.to raise_error(ArgumentError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: words_to_image
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alona Mekhovova
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: flickraw
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mini_magick
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: "\n command line application that\n\n * accepts a list of search
|
84
|
+
keywords as arguments\n * queries the Flickr API for the top-rated image for
|
85
|
+
each keyword\n * downloads the results\n * crops them rectangularly\n *
|
86
|
+
assembles a collage grid from ten images and\n * writes the result to a user-supplied
|
87
|
+
filename\n\n If given less than ten keywords, or if any keyword fails to\n result
|
88
|
+
in a match, retrieve random words from a dictionary\n source such as `/usr/share/dict/words`.
|
89
|
+
Repeat as necessary\n until you have gathered ten images.\n "
|
90
|
+
email:
|
91
|
+
- alona.tarasova@gmail.com
|
92
|
+
executables: []
|
93
|
+
extensions: []
|
94
|
+
extra_rdoc_files: []
|
95
|
+
files:
|
96
|
+
- ".gitignore"
|
97
|
+
- Gemfile
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- collage.gemspec
|
102
|
+
- config/defaults.rb
|
103
|
+
- config/flickr_init.rb
|
104
|
+
- lib/words_to_image/collage.rb
|
105
|
+
- lib/words_to_image/dictionary.rb
|
106
|
+
- lib/words_to_image/flickr.rb
|
107
|
+
- lib/words_to_image/image.rb
|
108
|
+
- lib/words_to_image/processor.rb
|
109
|
+
- spec/fixtures/sample_dict
|
110
|
+
- spec/spec_helper.rb
|
111
|
+
- spec/words_to_image/collage_spec.rb
|
112
|
+
- spec/words_to_image/dictionary_spec.rb
|
113
|
+
- spec/words_to_image/flickr_spec.rb
|
114
|
+
- spec/words_to_image/image_spec.rb
|
115
|
+
- spec/words_to_image/processor_spec.rb
|
116
|
+
homepage: ''
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- config
|
124
|
+
- lib/words_to_image
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 2.4.6
|
138
|
+
signing_key:
|
139
|
+
specification_version: 4
|
140
|
+
summary: A collage maker based on flickr search results
|
141
|
+
test_files:
|
142
|
+
- spec/fixtures/sample_dict
|
143
|
+
- spec/spec_helper.rb
|
144
|
+
- spec/words_to_image/collage_spec.rb
|
145
|
+
- spec/words_to_image/dictionary_spec.rb
|
146
|
+
- spec/words_to_image/flickr_spec.rb
|
147
|
+
- spec/words_to_image/image_spec.rb
|
148
|
+
- spec/words_to_image/processor_spec.rb
|