meme_captain 0.0.9 → 0.1.0
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.
- data/ChangeLog +14 -0
- data/README.md +38 -13
- data/bin/memecaptain +3 -1
- data/config.ru +23 -2
- data/lib/meme_captain.rb +2 -0
- data/lib/meme_captain/image_list.rb +1 -0
- data/lib/meme_captain/image_list/fetch.rb +1 -1
- data/lib/meme_captain/image_list/fetch_error.rb +17 -0
- data/lib/meme_captain/meme.rb +52 -55
- data/lib/meme_captain/meme_data.rb +1 -2
- data/lib/meme_captain/server.rb +88 -27
- data/lib/meme_captain/source_fetch_fail.rb +28 -0
- data/lib/meme_captain/text_pos.rb +45 -0
- data/lib/meme_captain/version.rb +1 -1
- data/meme_captain.gemspec +5 -0
- data/public/css/screen.css +66 -0
- data/public/js/fabric.min.js +7 -0
- data/spec/meme_captain_spec.rb +13 -0
- data/views/index.erb +307 -112
- metadata +40 -7
- data/public/1.gif +0 -0
data/ChangeLog
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
0.1.0 2012-02-07
|
|
2
|
+
|
|
3
|
+
Redesign web interface.
|
|
4
|
+
|
|
5
|
+
Avoid repeated failures fetching the same source image from the web
|
|
6
|
+
interface / API.
|
|
7
|
+
|
|
8
|
+
ruby interface now supports adding any number of text strings to
|
|
9
|
+
an image.
|
|
10
|
+
|
|
11
|
+
Add custom text positioning and sizing to web interface, API and
|
|
12
|
+
ruby interface. Web interface has text positioning widget using
|
|
13
|
+
fabric.js and canvas.
|
|
14
|
+
|
|
1
15
|
0.0.9 2012-01-19
|
|
2
16
|
|
|
3
17
|
Design and markup improvements on the site.
|
data/README.md
CHANGED
|
@@ -1,21 +1,48 @@
|
|
|
1
|
-
Ruby gem to create meme images (images with text added
|
|
1
|
+
Ruby gem to create meme images (images with text added).
|
|
2
2
|
|
|
3
3
|
Runs locally and has no web dependencies.
|
|
4
4
|
|
|
5
5
|
Works with animated gifs.
|
|
6
6
|
|
|
7
|
+
Create a simple top and bottom text meme:
|
|
8
|
+
|
|
7
9
|
```ruby
|
|
8
10
|
require 'open-uri'
|
|
9
11
|
|
|
10
12
|
require 'meme_captain'
|
|
11
13
|
|
|
12
14
|
open('http://memecaptain.com/troll_face.jpg', 'rb') do |f|
|
|
13
|
-
i = MemeCaptain.
|
|
15
|
+
i = MemeCaptain.meme_top_bottom(f, 'test', '1 2 3')
|
|
16
|
+
i.display
|
|
17
|
+
i.write('out.jpg')
|
|
18
|
+
end
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Advanced usage with text sizing and positioning and RMagick attributes:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'open-uri'
|
|
25
|
+
|
|
26
|
+
require 'meme_captain'
|
|
27
|
+
|
|
28
|
+
open('http://memecaptain.com/cool_story_bro.jpg', 'rb') do |f|
|
|
29
|
+
i = MemeCaptain.meme(f, [
|
|
30
|
+
MemeCaptain::TextPos.new('the quick brown fox', 0.70, 0.1, 0.25, 0.5,
|
|
31
|
+
:fill => 'green'),
|
|
32
|
+
MemeCaptain::TextPos.new('jumped over the lazy dog', 100, 400, 200, 100,
|
|
33
|
+
:font => 'Impact-Regular'),
|
|
34
|
+
MemeCaptain::TextPos.new('test', 10, 10, 50, 25)
|
|
35
|
+
])
|
|
14
36
|
i.display
|
|
15
37
|
i.write('out.jpg')
|
|
16
38
|
end
|
|
17
39
|
```
|
|
18
40
|
|
|
41
|
+
Text box sizes and positions can be specified as pixels (the origin is the top
|
|
42
|
+
left corner of the image) or as floats which are percentages of the image
|
|
43
|
+
width and height. The x and y coordinates of a text box are the coordinates
|
|
44
|
+
of its top left corner.
|
|
45
|
+
|
|
19
46
|
Also includes a Sinatra app that exposes the API over HTTP which is currently
|
|
20
47
|
running http://memecaptain.com/
|
|
21
48
|
|
|
@@ -24,36 +51,34 @@ You can use the memecaptain.com API if you prefer it to using the gem.
|
|
|
24
51
|
Simplest API:
|
|
25
52
|
|
|
26
53
|
```
|
|
27
|
-
http://memecaptain.com/i?u=<url encoded source image url>&
|
|
54
|
+
http://memecaptain.com/i?u=<url encoded source image url>&t1=<url encoded top text>&t2=<url encoded bottom text>
|
|
28
55
|
```
|
|
29
56
|
|
|
30
57
|
Example:
|
|
31
58
|
|
|
32
59
|
```
|
|
33
|
-
http://memecaptain.com/i?u=http%3A%2F%2Fmemecaptain.com%2Fyao_ming.jpg&
|
|
60
|
+
http://memecaptain.com/i?u=http%3A%2F%2Fmemecaptain.com%2Fyao_ming.jpg&t1=sure+i%27ll+test&t2=the+api
|
|
34
61
|
```
|
|
35
62
|
|
|
36
|
-

|
|
37
64
|
|
|
38
65
|
If you want better error messages, use this which will return JSON:
|
|
39
66
|
|
|
40
67
|
```
|
|
41
|
-
http://memecaptain.com/g?u=<url encoded source image url>&
|
|
68
|
+
http://memecaptain.com/g?u=<url encoded source image url>&t1=<url encoded top text>&t2=<url encoded bottom text>
|
|
42
69
|
```
|
|
43
70
|
|
|
44
71
|
Example:
|
|
45
72
|
|
|
46
73
|
```
|
|
47
|
-
http://memecaptain.com/g?u=http%3A%2F%2Fmemecaptain.com%2Fyao_ming.jpg&
|
|
74
|
+
http://memecaptain.com/g?u=http%3A%2F%2Fmemecaptain.com%2Fyao_ming.jpg&t1=sure+i%27ll+test&t2=the+api
|
|
48
75
|
```
|
|
49
76
|
|
|
50
|
-
Note: tempUrl is deprecated and will now always be the same as permUrl. It is
|
|
51
|
-
left for compability with older clients.
|
|
52
|
-
|
|
53
|
-
|
|
54
77
|
```json
|
|
55
78
|
{
|
|
56
|
-
|
|
57
|
-
tempUrl: "http://memecaptain.com/tmp/de55f7a78c6559d4a24ef3e72e2de89992b82695.jpeg"
|
|
79
|
+
imageUrl: "http://memecaptain.com/c7757f.jpg"
|
|
58
80
|
}
|
|
59
81
|
```
|
|
82
|
+
|
|
83
|
+
Optional parameters t1x, t1y, t1w, t1h, t2x, t2y, t2w, t2h can be added to
|
|
84
|
+
position and size text (see example above).
|
data/bin/memecaptain
CHANGED
|
@@ -50,7 +50,9 @@ unless ARGV.empty?
|
|
|
50
50
|
].include? k
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
meme_options = Hash[meme_options] if meme_options.is_a?(Array)
|
|
54
|
+
|
|
55
|
+
output_image = MemeCaptain.meme_top_bottom(
|
|
54
56
|
input_io, options[:top_text], options[:bottom_text], meme_options)
|
|
55
57
|
|
|
56
58
|
input_io.close
|
data/config.ru
CHANGED
|
@@ -3,6 +3,7 @@ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
|
3
3
|
require 'mongo'
|
|
4
4
|
require 'mongo_mapper'
|
|
5
5
|
require 'rack'
|
|
6
|
+
require 'rack/rewrite'
|
|
6
7
|
|
|
7
8
|
require 'meme_captain'
|
|
8
9
|
|
|
@@ -18,8 +19,28 @@ MemeCaptain::MemeData.ensure_index :meme_id
|
|
|
18
19
|
|
|
19
20
|
MemeCaptain::MemeData.ensure_index [
|
|
20
21
|
[:source_url, 1],
|
|
21
|
-
[:
|
|
22
|
-
[:bottom_text, 1],
|
|
22
|
+
[:texts, 1],
|
|
23
23
|
]
|
|
24
24
|
|
|
25
|
+
MemeCaptain::SourceFetchFail.ensure_index :url
|
|
26
|
+
|
|
27
|
+
use Rack::Rewrite do
|
|
28
|
+
rewrite %r{/([gi])\?(.+)}, lambda { |match, rack_env|
|
|
29
|
+
result = match[0]
|
|
30
|
+
|
|
31
|
+
if match[2].index('tt=') or match[2].index('tb=')
|
|
32
|
+
q = Rack::Utils.parse_query(match[2])
|
|
33
|
+
if q.key?('tt') or q.key?('tb')
|
|
34
|
+
q['t1'] = q.delete('tt') if q.key?('tt')
|
|
35
|
+
q['t2'] = q.delete('tb') if q.key?('tb')
|
|
36
|
+
new_q = q.map { |k,v|
|
|
37
|
+
"#{Rack::Utils.escape(k)}=#{Rack::Utils.escape(v)}" }.join('&')
|
|
38
|
+
result = "#{match[1]}?#{new_q}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
result
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
|
|
25
46
|
run MemeCaptain::Server
|
data/lib/meme_captain.rb
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module MemeCaptain
|
|
2
|
+
|
|
3
|
+
module ImageList
|
|
4
|
+
|
|
5
|
+
# Error for source image fetch failures.
|
|
6
|
+
class FetchError < StandardError
|
|
7
|
+
|
|
8
|
+
def initialize(response_code)
|
|
9
|
+
@response_code = response_code
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
attr_accessor :response_code
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
data/lib/meme_captain/meme.rb
CHANGED
|
@@ -6,19 +6,12 @@ module MemeCaptain
|
|
|
6
6
|
|
|
7
7
|
# Create a meme image.
|
|
8
8
|
#
|
|
9
|
-
# Input can be an IO object or a blob of data.
|
|
9
|
+
# Input can be an IO object or a blob of data. text_poss is an enumerable
|
|
10
|
+
# of TextPos objects containing text, position and style options.
|
|
10
11
|
#
|
|
11
12
|
# Options:
|
|
12
|
-
# max_lines - maximum number of text lines per caption
|
|
13
|
-
# min_pointsize - minimum point size
|
|
14
13
|
# super_sample - work this many times larger before shrinking
|
|
15
|
-
|
|
16
|
-
# text_width_pct - float percentage of image width for each caption
|
|
17
|
-
#
|
|
18
|
-
# Any other options will be set on the Draw objects for the text and
|
|
19
|
-
# can be used to control text fill, stroke, etc. See RMagick annotate
|
|
20
|
-
# attributes.
|
|
21
|
-
def meme(input, top_text, bottom_text, options={})
|
|
14
|
+
def meme(input, text_poss, options={})
|
|
22
15
|
img = Magick::ImageList.new
|
|
23
16
|
if input.respond_to?(:read)
|
|
24
17
|
img.from_blob(input.read)
|
|
@@ -26,27 +19,7 @@ module MemeCaptain
|
|
|
26
19
|
img.from_blob(input)
|
|
27
20
|
end
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
:max_lines => 16,
|
|
31
|
-
:min_pointsize => 12,
|
|
32
|
-
:super_sample => 2.0,
|
|
33
|
-
:text_height_pct => 0.25,
|
|
34
|
-
:text_width_pct => 0.9,
|
|
35
|
-
|
|
36
|
-
# Draw options
|
|
37
|
-
:fill => 'white',
|
|
38
|
-
:font => 'Impact',
|
|
39
|
-
:stroke => 'black',
|
|
40
|
-
:stroke_width => 8,
|
|
41
|
-
}.merge(options)
|
|
42
|
-
|
|
43
|
-
max_lines = options.delete(:max_lines)
|
|
44
|
-
super_sample = options.delete(:super_sample)
|
|
45
|
-
min_pointsize = options.delete(:min_pointsize) * super_sample
|
|
46
|
-
|
|
47
|
-
text_width = img.page.width * options.delete(:text_width_pct) * super_sample
|
|
48
|
-
text_height = img.page.height * options.delete(:text_height_pct) *
|
|
49
|
-
super_sample
|
|
22
|
+
super_sample = options[:super_sample] || 2.0
|
|
50
23
|
|
|
51
24
|
text_layer = Magick::Image.new(
|
|
52
25
|
img.page.width * super_sample, img.page.height * super_sample) {
|
|
@@ -54,38 +27,54 @@ module MemeCaptain
|
|
|
54
27
|
self.density = 72.0 * super_sample
|
|
55
28
|
}
|
|
56
29
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
30
|
+
text_poss.each do |text_pos|
|
|
31
|
+
caption = Caption.new(text_pos.text)
|
|
60
32
|
|
|
61
|
-
|
|
33
|
+
if caption.drawable?
|
|
34
|
+
wrap_tries = (1..text_pos.max_lines).map { |num_lines|
|
|
35
|
+
caption.wrap(num_lines).upcase.annotate_quote
|
|
36
|
+
}.uniq
|
|
62
37
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
[Caption.new(bottom_text), Magick::SouthGravity],
|
|
66
|
-
].select { |x| x[0].drawable? }.each do |caption, gravity|
|
|
67
|
-
wrap_tries = (1..max_lines).map { |num_lines|
|
|
68
|
-
caption.wrap(num_lines).upcase.annotate_quote
|
|
69
|
-
}.uniq
|
|
38
|
+
text_x = (text_pos.x.is_a?(Float) ?
|
|
39
|
+
img.page.width * text_pos.x : text_pos.x) * super_sample
|
|
70
40
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
text_width, text_height, wrap_try, min_pointsize)
|
|
41
|
+
text_y = (text_pos.y.is_a?(Float) ?
|
|
42
|
+
img.page.height * text_pos.y : text_pos.y) * super_sample
|
|
74
43
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
44
|
+
text_width = (text_pos.width.is_a?(Float) ?
|
|
45
|
+
img.page.width * text_pos.width : text_pos.width) * super_sample
|
|
46
|
+
|
|
47
|
+
text_height = (text_pos.height.is_a?(Float) ?
|
|
48
|
+
img.page.height * text_pos.height : text_pos.height) * super_sample
|
|
49
|
+
|
|
50
|
+
min_pointsize = text_pos.min_pointsize * super_sample
|
|
78
51
|
|
|
79
|
-
|
|
52
|
+
draw = Magick::Draw.new {
|
|
53
|
+
text_pos.draw_options.each { |k,v| self.send("#{k}=", v) }
|
|
54
|
+
}
|
|
80
55
|
|
|
81
|
-
|
|
82
|
-
draw.pointsize = choice.pointsize
|
|
56
|
+
draw.extend Draw
|
|
83
57
|
|
|
84
|
-
|
|
85
|
-
|
|
58
|
+
choices = wrap_tries.map do |wrap_try|
|
|
59
|
+
pointsize, metrics = draw.calc_pointsize(text_width, text_height,
|
|
60
|
+
wrap_try, min_pointsize)
|
|
86
61
|
|
|
87
|
-
|
|
88
|
-
|
|
62
|
+
CaptionChoice.new(pointsize, metrics, wrap_try, text_width,
|
|
63
|
+
text_height)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
choice = choices.max
|
|
67
|
+
|
|
68
|
+
draw.pointsize = choice.pointsize
|
|
69
|
+
|
|
70
|
+
draw.annotate text_layer, text_width, text_height, text_x, text_y,
|
|
71
|
+
choice.text
|
|
72
|
+
|
|
73
|
+
draw.stroke = 'none'
|
|
74
|
+
|
|
75
|
+
draw.annotate text_layer, text_width, text_height, text_x, text_y,
|
|
76
|
+
choice.text
|
|
77
|
+
end
|
|
89
78
|
end
|
|
90
79
|
|
|
91
80
|
text_layer.resize!(1.0 / super_sample)
|
|
@@ -99,4 +88,12 @@ module MemeCaptain
|
|
|
99
88
|
|
|
100
89
|
end
|
|
101
90
|
|
|
91
|
+
# Shortcut to generate a typical meme with text at the top and bottom.
|
|
92
|
+
def meme_top_bottom(input, top_text, bottom_text, options={})
|
|
93
|
+
meme(input, [
|
|
94
|
+
TextPos.new(top_text, 0.05, 0, 0.9, 0.25, options),
|
|
95
|
+
TextPos.new(bottom_text, 0.05, 0.75, 0.9, 0.25, options)
|
|
96
|
+
])
|
|
97
|
+
end
|
|
98
|
+
|
|
102
99
|
end
|
data/lib/meme_captain/server.rb
CHANGED
|
@@ -15,22 +15,51 @@ module MemeCaptain
|
|
|
15
15
|
|
|
16
16
|
get '/' do
|
|
17
17
|
@u = params[:u]
|
|
18
|
-
|
|
19
|
-
@
|
|
18
|
+
|
|
19
|
+
@t1 = params[:t1]
|
|
20
|
+
@t1x = params[:t1x]
|
|
21
|
+
@t1y = params[:t1y]
|
|
22
|
+
@t1w = params[:t1w]
|
|
23
|
+
@t1h = params[:t1h]
|
|
24
|
+
|
|
25
|
+
@t2 = params[:t2]
|
|
26
|
+
@t2x = params[:t2x]
|
|
27
|
+
@t2y = params[:t2y]
|
|
28
|
+
@t2w = params[:t2w]
|
|
29
|
+
@t2h = params[:t2h]
|
|
20
30
|
|
|
21
31
|
@root_url = url('/')
|
|
22
32
|
|
|
23
33
|
erb :index
|
|
24
34
|
end
|
|
25
35
|
|
|
36
|
+
def convert_metric(metric, default)
|
|
37
|
+
case
|
|
38
|
+
when metric.to_s.empty?; default
|
|
39
|
+
when metric.index('.'); metric.to_f
|
|
40
|
+
else; metric.to_i
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
26
44
|
def normalize_params(p)
|
|
27
45
|
result = {
|
|
28
46
|
'u' => p[:u],
|
|
47
|
+
|
|
29
48
|
# convert to empty string if null
|
|
30
|
-
'
|
|
31
|
-
'
|
|
49
|
+
't1' => p[:t1].to_s,
|
|
50
|
+
't2' => p[:t2].to_s,
|
|
32
51
|
}
|
|
33
52
|
|
|
53
|
+
result['t1x'] = convert_metric(p[:t1x], 0.05)
|
|
54
|
+
result['t1y'] = convert_metric(p[:t1y], 0)
|
|
55
|
+
result['t1w'] = convert_metric(p[:t1w], 0.9)
|
|
56
|
+
result['t1h'] = convert_metric(p[:t1h], 0.25)
|
|
57
|
+
|
|
58
|
+
result['t2x'] = convert_metric(p[:t2x], 0.05)
|
|
59
|
+
result['t2y'] = convert_metric(p[:t2y], 0.75)
|
|
60
|
+
result['t2w'] = convert_metric(p[:t2w], 0.9)
|
|
61
|
+
result['t2h'] = convert_metric(p[:t2h], 0.25)
|
|
62
|
+
|
|
34
63
|
# if the id of an existing meme is passed in as the source url, use the
|
|
35
64
|
# source image of that meme for the source image
|
|
36
65
|
if result['u'][%r{^[a-f0-9]+\.(?:gif|jpg|png)$}]
|
|
@@ -48,23 +77,54 @@ module MemeCaptain
|
|
|
48
77
|
|
|
49
78
|
if existing = MemeData.first(
|
|
50
79
|
:source_url => norm_params[:u],
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
|
|
81
|
+
'texts.0.text' => norm_params[:t1],
|
|
82
|
+
'texts.0.x' => norm_params[:t1x],
|
|
83
|
+
'texts.0.y' => norm_params[:t1y],
|
|
84
|
+
'texts.0.w' => norm_params[:t1w],
|
|
85
|
+
'texts.0.h' => norm_params[:t1h],
|
|
86
|
+
|
|
87
|
+
'texts.1.text' => norm_params[:t2],
|
|
88
|
+
'texts.1.x' => norm_params[:t2x],
|
|
89
|
+
'texts.1.y' => norm_params[:t2y],
|
|
90
|
+
'texts.1.w' => norm_params[:t2w],
|
|
91
|
+
'texts.1.h' => norm_params[:t2h]
|
|
53
92
|
)
|
|
54
93
|
existing
|
|
55
94
|
else
|
|
56
95
|
if same_source = MemeData.find_by_source_url(norm_params[:u])
|
|
57
96
|
source_fs_path = same_source.source_fs_path
|
|
58
97
|
else
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
98
|
+
if source_fetch_fail = SourceFetchFail.find_by_url(norm_params[:u])
|
|
99
|
+
source_fetch_fail.requested!
|
|
100
|
+
halt 500, 'Error loading source image url'
|
|
101
|
+
else
|
|
102
|
+
source_img = ImageList::SourceImage.new
|
|
103
|
+
begin
|
|
104
|
+
source_img.fetch! norm_params[:u]
|
|
105
|
+
rescue => error
|
|
106
|
+
SourceFetchFail.new(
|
|
107
|
+
:attempt_count => 1,
|
|
108
|
+
:orig_ip => request.ip,
|
|
109
|
+
:response_code => error.respond_to?(:response_code) ?
|
|
110
|
+
error.response_code : nil,
|
|
111
|
+
:url => norm_params[:u]
|
|
112
|
+
).save!
|
|
113
|
+
halt 500, 'Error loading source image url'
|
|
114
|
+
end
|
|
115
|
+
source_img.prepare! settings.source_img_max_side, settings.watermark
|
|
116
|
+
source_fs_path = source_img.cache(norm_params[:u], 'source_cache')
|
|
117
|
+
end
|
|
63
118
|
end
|
|
64
119
|
|
|
65
120
|
open(source_fs_path, 'rb') do |source_io|
|
|
66
|
-
|
|
67
|
-
norm_params[:
|
|
121
|
+
t1 = TextPos.new(norm_params[:t1], norm_params[:t1x],
|
|
122
|
+
norm_params[:t1y], norm_params[:t1w], norm_params[:t1h])
|
|
123
|
+
|
|
124
|
+
t2 = TextPos.new(norm_params[:t2], norm_params[:t2x],
|
|
125
|
+
norm_params[:t2y], norm_params[:t2w], norm_params[:t2h])
|
|
126
|
+
|
|
127
|
+
meme_img = MemeCaptain.meme(source_io, [t1, t2])
|
|
68
128
|
meme_img.extend ImageList::Cache
|
|
69
129
|
|
|
70
130
|
# convert non-animated gifs to png
|
|
@@ -95,8 +155,20 @@ module MemeCaptain
|
|
|
95
155
|
|
|
96
156
|
:source_url => norm_params[:u],
|
|
97
157
|
:source_fs_path => source_fs_path,
|
|
98
|
-
|
|
99
|
-
:
|
|
158
|
+
|
|
159
|
+
:texts => [{
|
|
160
|
+
:text => norm_params[:t1],
|
|
161
|
+
:x => norm_params[:t1x],
|
|
162
|
+
:y => norm_params[:t1y],
|
|
163
|
+
:w => norm_params[:t1w],
|
|
164
|
+
:h => norm_params[:t1h],
|
|
165
|
+
}, {
|
|
166
|
+
:text => norm_params[:t2],
|
|
167
|
+
:x => norm_params[:t2x],
|
|
168
|
+
:y => norm_params[:t2y],
|
|
169
|
+
:w => norm_params[:t2w],
|
|
170
|
+
:h => norm_params[:t2h],
|
|
171
|
+
}],
|
|
100
172
|
|
|
101
173
|
:request_count => 0,
|
|
102
174
|
|
|
@@ -117,22 +189,11 @@ module MemeCaptain
|
|
|
117
189
|
begin
|
|
118
190
|
meme_data = gen(params)
|
|
119
191
|
|
|
120
|
-
meme_url = url("/#{meme_data.meme_id}")
|
|
121
|
-
|
|
122
|
-
template_query = [
|
|
123
|
-
[:u, meme_data.meme_id],
|
|
124
|
-
[:tt, meme_data.top_text],
|
|
125
|
-
[:tb, meme_data.bottom_text],
|
|
126
|
-
].map { |k,v|
|
|
127
|
-
"#{Rack::Utils.escape(k)}=#{Rack::Utils.escape(v)}" }.join('&')
|
|
128
|
-
|
|
129
192
|
[200, { 'Content-Type' => 'application/json' }, {
|
|
130
|
-
'
|
|
131
|
-
'permUrl' => meme_url,
|
|
132
|
-
'templateUrl' => url("/?#{template_query}"),
|
|
193
|
+
'imageUrl' => url("/#{meme_data.meme_id}")
|
|
133
194
|
}.to_json]
|
|
134
195
|
rescue => error
|
|
135
|
-
[500, { 'Content-Type' => 'text/plain' },
|
|
196
|
+
[500, { 'Content-Type' => 'text/plain' }, 'Error generating image']
|
|
136
197
|
end
|
|
137
198
|
end
|
|
138
199
|
|