imaginizer 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b57552f3d3613d48fbe96a2d8271158d4c2e938
4
- data.tar.gz: 8addcc75730714e0c81e484fb1925177d1e311a3
3
+ metadata.gz: 82ba111cb40bc4ffde4bb54212a371ce849b7876
4
+ data.tar.gz: ec933dd1678bf6ee211d9989fb5fac39e4c8ad16
5
5
  SHA512:
6
- metadata.gz: 02d32e79e10a528aef27923c23bed3dfcb034a5faff8f0828e3241e6eb6a2bbed90bbe328b1ae1e000b7e44f2050c59a6373d8c9f21585d9f5cbb78e041bff9b
7
- data.tar.gz: 92340345dffea0b3bbaabba3dc067361954a1a731ee60d010949bf5acba3a3847002c58676584c408e1b4b69bbbd8afff4a4d011bbc899e812fa8e49e4d13ce5
6
+ metadata.gz: 286af7a8402b9a6b55737b36bc39be6ddf5b371bb02741f65660bdc10f371e85af9e44921b5d5dc5dfa40abec54ecd0f660733f8bacde92414aa9ab93e25295e
7
+ data.tar.gz: 378ccaf62c45a887f1f1cf7d8ab9c8855d46dd546caf6fce19429ee42ed0275044827a4f70d2b3ca4bd82715dd778d68bbb9f626700d63550a561c68624a863e
data/README.md CHANGED
@@ -11,7 +11,7 @@ You need [Imagemagick](http://www.imagemagick.org) with [Freetype](http://freety
11
11
 
12
12
  To check if you have it installed, run this command:
13
13
 
14
- check=`cosnvert -list CONFIGURE 2> /dev/null|grep DELEGATES|grep freetype|wc -l`; if [ $check -eq 1 ]; then echo "Imagemagick/Freetype IS installed"; else echo "Imagemagick/Freetype IS NOT installed"; fi
14
+ check=`convert -list CONFIGURE 2> /dev/null|grep DELEGATES|grep freetype|wc -l`; if [ $check -eq 1 ]; then echo "Imagemagick/Freetype IS installed"; else echo "Imagemagick/Freetype IS NOT installed"; fi
15
15
 
16
16
  To install:
17
17
 
@@ -9,9 +9,9 @@ end
9
9
 
10
10
  require 'imaginizer/parser'
11
11
 
12
- options = ImaginizerParser.parse ARGV
12
+ options = Imaginizer::Parser.parse ARGV
13
13
  output = options.delete :output
14
14
  puts "Creating images with #{options}:"
15
15
  images = Imaginizer.create_images options
16
16
  puts "Images created at #{images.map &:image_path}"
17
- ImaginizerParser.output images, output
17
+ Imaginizer::Parser.output images, output
@@ -1,137 +1,24 @@
1
- require 'mini_magick'
1
+ require 'imaginizer/image'
2
2
 
3
3
  module Imaginizer
4
4
  def self.create_images(options = {})
5
5
  sizes = options.delete(:sizes) { [] }
6
- sizes.map do |size|
7
- width, height = size.split 'x'
8
- create_image options.merge(width: width, height: height)
9
- end
6
+ sizes.map {|size| create_image size, options}
10
7
  end
11
8
 
12
- def self.create_image(options = {})
13
- Image.create image_path(options) do |image|
9
+ def self.create_image(size, options = {})
10
+ Image.create size, image_path(size) do |image|
14
11
  image.make_jpeg
15
- image.resize options[:width], options[:height]
16
- image.set_background options[:bg] if options[:bg]
17
- image.overlay_image options[:fg] if options[:fg]
12
+ image.resize
13
+ image.set_background options[:background] if options[:background]
14
+ image.set_foreground options[:foreground] if options[:foreground]
18
15
  image.set_title options[:title] if options[:title]
19
16
  image.set_subtitle options[:subtitle] if options[:subtitle]
20
17
  image.set_footer options[:footer] if options[:footer]
21
18
  end
22
19
  end
23
20
 
24
- def self.image_path(options)
25
- basename = options.values_at(:width, :height).join('_')
26
- "/tmp/#{basename}.jpg"
27
- end
28
-
29
- class Image
30
- attr_accessor :image_data, :image_path
31
-
32
- def initialize(source_path = nil)
33
- @image_data = MiniMagick::Image.open source_path || empty_image_path
34
- end
35
-
36
- def self.create(image_path)
37
- new.tap do |image|
38
- image.image_path = image_path
39
- yield image
40
- image.image_data.write image_path
41
- end
42
- end
43
-
44
- [:height, :width, :format].each do |method|
45
- define_method method do
46
- image_data[method]
47
- end
48
- end
49
-
50
- def size
51
- "#{width}x#{height}"
52
- end
53
-
54
- def make_jpeg
55
- @image_data.format 'jpg'
56
- end
57
-
58
- def resize(w, h)
59
- @image_data.resize "#{w}x#{h}!" if w and h
60
- end
61
-
62
- def crop(options = {})
63
- return if options.none?
64
- w = options[:width] || width
65
- h = options[:height] || height
66
- x_offset = (width - w)/2
67
- y_offset = (height- h)/2
68
- @image_data.crop "#{w}x#{h}+#{x_offset}+#{y_offset}"
69
- end
70
-
71
- def blur(radius_x_sigma)
72
- @image_data.combine_options {|c| c.blur radius_x_sigma} if radius_x_sigma
73
- end
74
-
75
- def set_background(options = {})
76
- overlay_image options.merge(blur: '0x15', fill: true)
77
- end
78
-
79
- def set_title(options = {})
80
- overlay_text options.merge(uppercase: true)
81
- end
82
-
83
- def set_subtitle(options = {})
84
- overlay_text options.merge(style: 'italic')
85
- end
86
-
87
- def set_footer(options = {})
88
- overlay_box options.fetch(:box, {height: options[:size]})
89
- overlay_text options.merge(style: 'bold', uppercase: true, gravity: 'south')
90
- end
91
-
92
- def overlay_text(options = {})
93
- return unless text = options[:text]
94
- text.upcase! if options[:uppercase]
95
- @image_data.combine_options do |c|
96
- c.fill 'white'
97
- c.font font_path(options[:style])
98
- c.gravity options.fetch(:gravity, 'center')
99
- c.pointsize options[:size] if options[:size]
100
- c.draw "text 0,0 '#{options[:text]}'"
101
- end
102
- end
103
-
104
- def overlay_box(options = {})
105
- return if options.none?
106
- x2 = width
107
- y2 = height
108
- x1 = x2 - (options[:width] || x2)
109
- y1 = y2 - (options[:height] || y2)
110
- @image_data.combine_options do |c|
111
- c.fill 'graya(0%, 0.5)'
112
- c.draw "rectangle #{x1}, #{y1}, #{x2}, #{y2}"
113
- end
114
- end
115
-
116
- def overlay_image(options = {})
117
- return unless options[:img]
118
- image = Image.new options[:img]
119
- image.blur options[:blur]
120
- image.crop height: options[:height]
121
- image.resize width, height if options[:fill]
122
- @image_data = @image_data.composite image.image_data
123
- end
124
-
125
- private
126
-
127
- def empty_image_path
128
- File.expand_path '../assets/1x1.jpg', __FILE__
129
- end
130
-
131
- def font_path(style)
132
- style ||= 'regular'
133
- font_file = "../assets/RobotoCondensed-#{style.capitalize}.ttf"
134
- File.expand_path font_file, __FILE__
135
- end
21
+ def self.image_path(size)
22
+ "/tmp/#{size}.jpg"
136
23
  end
137
24
  end
@@ -0,0 +1,196 @@
1
+ require 'mini_magick'
2
+
3
+ class Imaginizer::Image
4
+ attr_accessor :image_data, :image_path, :image_size
5
+
6
+ def initialize(source_path = nil)
7
+ @image_data = MiniMagick::Image.open source_path || empty_image_path
8
+ end
9
+
10
+ def self.create(size, image_path)
11
+ new.tap do |image|
12
+ image.image_size = size
13
+ image.image_path = image_path
14
+ yield image
15
+ image.image_data.write image_path
16
+ end
17
+ end
18
+
19
+ def make_jpeg
20
+ @image_data.format 'jpg'
21
+ end
22
+
23
+ def resize
24
+ @image_data.resize "#{image_width}x#{image_height}!"
25
+ end
26
+
27
+ def set_background(options = {})
28
+ v = values_for :background
29
+ overlay_image options.merge(blur: '0x15', fill: true, x: v[:x],
30
+ y: v[:y], h: v[:h])
31
+ end
32
+
33
+ def set_foreground(options = {})
34
+ v = values_for :foreground
35
+ overlay_image options.merge(h: v[:h], w: v[:w]) unless v[:skip]
36
+ end
37
+
38
+ def set_title(options = {})
39
+ set_text :title, options do |v|
40
+ {style: 'bold', uppercase: true, x: v[:x], y: v[:y], size: v[:size]}
41
+ end
42
+ end
43
+
44
+ def set_subtitle(options = {})
45
+ set_text :subtitle, options do |v|
46
+ {style: 'italic', size: 14, x: v[:x], y: v[:y]}
47
+ end
48
+ end
49
+
50
+ def set_footer(options = {})
51
+ overlay_box values_for(:footer)
52
+ set_text :footer, options do |v|
53
+ {style: 'bold', uppercase: true, x: v[:x], y: v[:y], size: v[:size]}
54
+ end
55
+ end
56
+
57
+ protected
58
+
59
+ def blur(radius_x_sigma)
60
+ @image_data.combine_options {|c| c.blur radius_x_sigma} if radius_x_sigma
61
+ end
62
+
63
+ def crop(options = {})
64
+ return if options.none?
65
+ w = options[:w] || width
66
+ h = options[:h] || height
67
+ x_offset = (width - w)/2
68
+ y_offset = (height- h)/2
69
+ @image_data.crop "#{w}x#{h}+#{x_offset}+#{y_offset}"
70
+ end
71
+
72
+ private
73
+
74
+ def values_for(property)
75
+ {medium_rectangle: {
76
+ width: 300,
77
+ height: 250,
78
+ background: {y: 125, h: 125},
79
+ foreground: {h: 125},
80
+ title: {y: 23, second_line_y: 57, size: 40},
81
+ subtitle: {y: 84},
82
+ footer: {h: 30, size: 25, y: 111}
83
+ },
84
+ rectangle: {
85
+ width: 180,
86
+ height: 150,
87
+ foreground: {skip: true},
88
+ title: {y: -39, second_line_y: -12, size: 34},
89
+ subtitle: {y: 13},
90
+ footer: {h: 28, size: 16, y: 63}
91
+ },
92
+ wide_skyscraper: {
93
+ width: 160,
94
+ height: 600,
95
+ background: {y: 250, h: 125},
96
+ foreground: {h: 250},
97
+ title: {y: -23, second_line_y: 0, size: 30},
98
+ subtitle: {y: 33},
99
+ footer: {h: 94, size: 26, y: 242, second_line_y: 263}
100
+ },
101
+ leaderboard: {
102
+ width: 728,
103
+ height: 90,
104
+ background: {x: 228},
105
+ foreground: {w: 228},
106
+ title: {x: 120, y: -24, size: 42},
107
+ subtitle: {x: 120, y: 5},
108
+ footer: {w: 500, h: 29, size: 26, x: 120, y: 30}
109
+ }
110
+ }[@image_size].fetch property, {}
111
+ end
112
+
113
+ [:height, :width, :format].each do |method|
114
+ define_method method do
115
+ image_data[method]
116
+ end
117
+ end
118
+
119
+ def size
120
+ "#{width}x#{height}"
121
+ end
122
+
123
+ def image_width
124
+ values_for :width
125
+ end
126
+
127
+ def image_height
128
+ values_for :height
129
+ end
130
+
131
+ def set_text(size, options = {})
132
+ values = values_for size
133
+ size_options = options.merge yield(values)
134
+ if values[:second_line_y]
135
+ line1, line2 = word_wrap options[:text]
136
+ overlay_text size_options.merge(text: line1)
137
+ overlay_text size_options.merge(text: line2, y: values[:second_line_y])
138
+ else
139
+ overlay_text size_options
140
+ end
141
+ end
142
+
143
+ def word_wrap(text)
144
+ text.delete("\n").sub(/(.{1,9})(\s+|$)/, "\\1\n").strip.split("\n")
145
+ end
146
+
147
+ def overlay_text(options = {})
148
+ return unless text = options[:text]
149
+ text.upcase! if options[:uppercase]
150
+ @image_data.combine_options do |c|
151
+ c.fill 'white'
152
+ c.font font_path(options[:style])
153
+ c.gravity 'center'
154
+ c.pointsize options[:size] if options[:size]
155
+ c.draw "text #{options[:x] || 0},#{options[:y] || 0} '#{options[:text]}'"
156
+ end
157
+ end
158
+
159
+ def overlay_box(options = {})
160
+ return if options.none?
161
+ x2 = width
162
+ y2 = height
163
+ x1 = x2 - (options[:w] || x2)
164
+ y1 = y2 - (options[:h] || y2)
165
+ @image_data.combine_options do |c|
166
+ c.fill 'graya(0%, 0.5)'
167
+ c.draw "rectangle #{x1}, #{y1}, #{x2}, #{y2}"
168
+ end
169
+ end
170
+
171
+ def overlay_image(options = {})
172
+ return unless options[:img]
173
+ image = self.class.new options[:img]
174
+ image.blur options[:blur]
175
+
176
+ image.crop options
177
+ image.resize image_size if options[:fill]
178
+ overlay_x = options[:x] || 0
179
+ overlay_y = options[:y] || 0
180
+ @image_data = @image_data.composite image.image_data do |c|
181
+ c.geometry "#{image.width}x#{image.height}+#{overlay_x}+#{overlay_y}"
182
+ end
183
+ end
184
+
185
+
186
+
187
+ def empty_image_path
188
+ File.expand_path '../../assets/1x1.jpg', __FILE__
189
+ end
190
+
191
+ def font_path(style)
192
+ style ||= 'regular'
193
+ font_file = "../../assets/RobotoCondensed-#{style.capitalize}.ttf"
194
+ File.expand_path font_file, __FILE__
195
+ end
196
+ end
@@ -1,5 +1,11 @@
1
+ # coding: utf-8
1
2
  require 'optparse'
2
- class ImaginizerParser
3
+
4
+ class Imaginizer::Parser
5
+ def self.valid_sizes
6
+ [:medium_rectangle, :rectangle, :wide_skyscraper, :leaderboard]
7
+ end
8
+
3
9
  def self.parse(args)
4
10
  options = default_values
5
11
 
@@ -9,49 +15,38 @@ class ImaginizerParser
9
15
  opts.separator ''
10
16
  opts.separator 'Specific options:'
11
17
 
12
- opts.on('-d', '--dimension WxH', String, 'Image width x height') do |d|
18
+ opts.on('-d', '--dimension [IAB_SIZE]', valid_sizes,
19
+ %Q(Sizes to create #{valid_sizes} – multiple values accepted)) do |d|
13
20
  options[:sizes] << d
14
21
  end
15
- default_sizes = options.delete(:default_sizes)
16
- options[:sizes] = default_sizes if options[:sizes].empty?
17
22
 
18
- opts.on('-b', '--background path', String, 'Background image') do |path|
19
- options[:bg][:img] = path
23
+ opts.on('-b', '--background path', String,
24
+ %q(Background image – either a local path or a URL)) do |path|
25
+ options[:background][:img] = path
20
26
  end
21
27
 
22
- opts.on('-f', '--foreground path', String, 'Foreground image') do |path|
23
- options[:fg][:img] = path
28
+ opts.on('-f', '--foreground path', String,
29
+ %q(Foreground image – either a local path or a URL)) do |path|
30
+ options[:foreground][:img] = path
24
31
  end
25
32
 
26
- opts.on('--foreground-height N', String, 'Foreground image height') do |n|
27
- options[:fg][:height] = n
28
- end
29
-
30
- opts.on('-t', '--title text', String, 'Overlay title') do |text|
33
+ opts.on('-t', '--title text', String,
34
+ %q(Title to overlay – maximum 15 characters)) do |text|
31
35
  options[:title][:text] = text
32
36
  end
33
37
 
34
- opts.on('--title-size N', Integer, 'Title size') do |size|
35
- options[:title][:size] = size
36
- end
37
-
38
- opts.on('-s', '--subtitle text', String, 'Overlay subtitle') do |text|
38
+ opts.on('-s', '--subtitle text', String,
39
+ %q(Subtitle to overlay – maximum 15 characters)) do |text|
39
40
  options[:subtitle][:text] = text
40
41
  end
41
42
 
42
- opts.on('--subtitle-size N', Integer, 'Subtitle size') do |size|
43
- options[:subtitle][:size] = size
44
- end
45
-
46
- opts.on('-r', '--footer text', String, 'Overlay footer') do |text|
43
+ opts.on('-r', '--footer text', String,
44
+ %q(Footer to overlay – maximum 20 characters)) do |text|
47
45
  options[:footer][:text] = text
48
46
  end
49
47
 
50
- opts.on('--footer-size N', Integer, 'Footer size') do |size|
51
- options[:footer][:size] = size
52
- end
53
-
54
- opts.on('-o', '--output [OUTPUT]', [:image, :html], 'What to show') do |o|
48
+ opts.on('-o', '--output [OUTPUT]', [:image, :html],
49
+ %q(Output type – either an image or an HTML page)) do |o|
55
50
  options[:output] = o
56
51
  end
57
52
 
@@ -70,6 +65,8 @@ class ImaginizerParser
70
65
  end
71
66
 
72
67
  opt_parser.parse!(args)
68
+
69
+ options[:sizes] = self.valid_sizes if options[:sizes].empty?
73
70
  options
74
71
  end
75
72
 
@@ -77,12 +74,11 @@ class ImaginizerParser
77
74
  {}.tap do |opts|
78
75
  opts[:output] = :html
79
76
  opts[:sizes] = []
80
- opts[:default_sizes] = ['300x250', '180x150', '160x600', '728x90']
81
- opts[:title] = {text: 'Sample title', size: 40}
82
- opts[:subtitle] = {text: 'Sample subtitle', size: 14}
83
- opts[:footer] = {text: 'Sample footer', size: 25}
84
- opts[:bg] = {img: 'http://lorempixel.com/300/300/abstract'}
85
- opts[:fg] = {img: 'http://lorempixel.com/300/300/people', height: 100}
77
+ opts[:title] = {text: 'Title max 18 chars'}
78
+ opts[:subtitle] = {text: 'This subtitle is 30 characters'}
79
+ opts[:footer] = {text: 'A footer w/ 20 chars'}
80
+ opts[:background] = {img: 'http://lorempixel.com/300/300/abstract'}
81
+ opts[:foreground] = {img: 'http://lorempixel.com/300/300/people'}
86
82
  end
87
83
  end
88
84
 
@@ -98,13 +94,17 @@ class ImaginizerParser
98
94
  <html>
99
95
  <head>
100
96
  <meta charset="UTF-8" />
97
+ <style>
98
+ body {background-color: #ccc}
99
+ figure {float: left}
100
+ </style>
101
101
  <title>Imaginizer output</title>
102
102
  </head>
103
103
  <body>
104
104
  #{images.map do |image|
105
105
  '<figure>' +
106
106
  '<img src="' + image.image_path + '" />' +
107
- '<figcaption>Size: ' + image.size + '</figcaption>' +
107
+ '<figcaption>Size: ' + image.image_size.to_s + '</figcaption>' +
108
108
  '</figure>'
109
109
  end.join}
110
110
  </body>
@@ -1,3 +1,3 @@
1
1
  module Imaginizer
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imaginizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claudio Baccigalupo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-22 00:00:00.000000000 Z
12
+ date: 2013-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mini_magick
@@ -123,6 +123,7 @@ files:
123
123
  - lib/assets/RobotoCondensed-Bold.ttf
124
124
  - lib/assets/RobotoCondensed-Italic.ttf
125
125
  - lib/assets/RobotoCondensed-Regular.ttf
126
+ - lib/imaginizer/image.rb
126
127
  - lib/imaginizer/parser.rb
127
128
  - lib/imaginizer/version.rb
128
129
  - lib/imaginizer.rb