meme_captain 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +62 -2
- data/Gemfile +3 -0
- data/README.md +6 -1
- data/config.ru +4 -0
- data/doc/lightweight_front_end.md +64 -0
- data/doc/setup.md +13 -0
- data/lib/meme_captain/image_list/fetch.rb +2 -0
- data/lib/meme_captain/meme.rb +16 -4
- data/lib/meme_captain/memebg.rb +62 -0
- data/lib/meme_captain/norm_params.rb +92 -0
- data/lib/meme_captain/pretty_format.rb +12 -0
- data/lib/meme_captain/server.rb +134 -74
- data/lib/meme_captain/upload.rb +30 -0
- data/lib/meme_captain/version.rb +1 -1
- data/lib/meme_captain.rb +4 -1
- data/meme_captain.gemspec +2 -0
- data/public/css/screen.css +14 -0
- data/public/favicon.ico +0 -0
- data/public/js/fabric.min.js +3 -3
- data/public/js/jquery-1.7.2.min.js +4 -0
- data/public/js/meme_captain.js +403 -0
- data/public/source_images.json +65 -1
- data/public/thumbs.jpg +0 -0
- data/public/thumbs_1330486916.jpg +0 -0
- data/public/thumbs_1333591668.jpg +0 -0
- data/public/thumbs_1334189407.jpg +0 -0
- data/public/thumbs_1334973608.jpg +0 -0
- data/script/thumb_sprites.rb +57 -14
- data/spec/caption_choice_spec.rb +53 -0
- data/spec/caption_spec.rb +45 -0
- data/spec/image_list/fetch_spec.rb +33 -0
- data/spec/meme_captain_spec.rb +8 -2
- data/spec/memebg_spec.rb +14 -0
- data/spec/norm_params_spec.rb +223 -0
- data/spec/pretty_format_spec.rb +9 -0
- data/spec/text_pos_spec.rb +29 -0
- data/views/index.erb +14 -335
- metadata +150 -161
- data/lib/meme_captain/file_body.rb +0 -15
data/ChangeLog
CHANGED
@@ -1,3 +1,64 @@
|
|
1
|
+
0.1.1 2012-04-26
|
2
|
+
|
3
|
+
Update jQuery and fabric.js to latest versions.
|
4
|
+
|
5
|
+
Disable border on image links for IE.
|
6
|
+
|
7
|
+
Disable text positioning for browsers that don't support canvas.
|
8
|
+
|
9
|
+
Add new source images to the site: annoying Facebook girl and you're
|
10
|
+
gonna have a bad time.
|
11
|
+
|
12
|
+
Add new source images to the site: bad luck Brian, laundry room viking,
|
13
|
+
paranoid parrot, conspiracy Keanu, socially awesome awkward penguin
|
14
|
+
and you should feel bad.
|
15
|
+
|
16
|
+
Increase default stroke width to 8 pixels.
|
17
|
+
|
18
|
+
Add new source images to the site: condescending Wonka and first world
|
19
|
+
problems.
|
20
|
+
|
21
|
+
Add unsharp mask step to make text sharper.
|
22
|
+
|
23
|
+
Scale stroke width by supersample.
|
24
|
+
|
25
|
+
Make search result thumbnail size relative to image size.
|
26
|
+
|
27
|
+
Add share on Reddit link.
|
28
|
+
|
29
|
+
Add templateUrl to JSON response and template link to page.
|
30
|
+
|
31
|
+
Add favicon.ico to site.
|
32
|
+
|
33
|
+
Fix 404 error on empty u parameter.
|
34
|
+
|
35
|
+
Add new source images to the site: Ron Swanson and the more you know.
|
36
|
+
|
37
|
+
Add setup document.
|
38
|
+
|
39
|
+
Follow redirects when fetching source images.
|
40
|
+
|
41
|
+
Highlight form fields when they are populated or preloaded.
|
42
|
+
|
43
|
+
Add source image upload support to site.
|
44
|
+
|
45
|
+
Generalize and document thumb sprites script.
|
46
|
+
|
47
|
+
Add docs for setting up lightweight third-party sites.
|
48
|
+
|
49
|
+
Add JSONP support for lightweight third-party sites to use.
|
50
|
+
|
51
|
+
Use Magick::Image.destroy! to reduce memory leaking.
|
52
|
+
|
53
|
+
Handle odd image formats like BMP.
|
54
|
+
|
55
|
+
Add debug logging.
|
56
|
+
|
57
|
+
Write more rspecs.
|
58
|
+
|
59
|
+
Add new source images to the site: bad joke eel, Neil DeGrasse Tyson,
|
60
|
+
Obama not bad and impaired duck.
|
61
|
+
|
1
62
|
0.1.0 2012-02-07
|
2
63
|
|
3
64
|
Redesign web interface.
|
@@ -45,8 +106,7 @@
|
|
45
106
|
Add new source images to the site: all the things 2, cool story bro,
|
46
107
|
aw yeah, Boromir, Ned Stark.
|
47
108
|
|
48
|
-
0.0.8
|
49
|
-
2011-11-23
|
109
|
+
0.0.8 2011-11-23
|
50
110
|
|
51
111
|
Start change log.
|
52
112
|
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -76,9 +76,14 @@ http://memecaptain.com/g?u=http%3A%2F%2Fmemecaptain.com%2Fyao_ming.jpg&t1=sure+i
|
|
76
76
|
|
77
77
|
```json
|
78
78
|
{
|
79
|
-
imageUrl: "http://memecaptain.com/c7757f.jpg"
|
79
|
+
imageUrl: "http://memecaptain.com/c7757f.jpg",
|
80
|
+
templateUrl: "http://memecaptain.com/?u=c7757f.jpg"
|
80
81
|
}
|
81
82
|
```
|
82
83
|
|
83
84
|
Optional parameters t1x, t1y, t1w, t1h, t2x, t2y, t2w, t2h can be added to
|
84
85
|
position and size text (see example above).
|
86
|
+
|
87
|
+
If you want to host a customized version of the memecaptain.com web interface
|
88
|
+
on your own web server but use the memecaptain.com backend see
|
89
|
+
[lightweight front end](https://github.com/mmb/meme_captain/blob/master/doc/lightweight_front_end.md).
|
data/config.ru
CHANGED
@@ -3,12 +3,14 @@ $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
|
3
3
|
require 'mongo'
|
4
4
|
require 'mongo_mapper'
|
5
5
|
require 'rack'
|
6
|
+
require 'rack/contrib/jsonp'
|
6
7
|
require 'rack/rewrite'
|
7
8
|
|
8
9
|
require 'meme_captain'
|
9
10
|
|
10
11
|
use Rack::ConditionalGet
|
11
12
|
use Rack::Sendfile
|
13
|
+
use Rack::JSONP
|
12
14
|
|
13
15
|
use Rack::Static, :urls => %w{/tmp}, :root => 'public'
|
14
16
|
|
@@ -22,6 +24,8 @@ MemeCaptain::MemeData.ensure_index [
|
|
22
24
|
[:texts, 1],
|
23
25
|
]
|
24
26
|
|
27
|
+
MemeCaptain::Upload.ensure_index :upload_id
|
28
|
+
|
25
29
|
MemeCaptain::SourceFetchFail.ensure_index :url
|
26
30
|
|
27
31
|
use Rack::Rewrite do
|
@@ -0,0 +1,64 @@
|
|
1
|
+
If you want to host your own custom Meme Captain site but do not want to set
|
2
|
+
up the ruby backend you can use the memecaptain.com backend. In this scenario,
|
3
|
+
the HTML, Javscript and CSS are hosted on your web server and the meme images
|
4
|
+
are created on and hosted on memecaptain.com.
|
5
|
+
|
6
|
+
This is an option if you are on shared hosting and do not have access to
|
7
|
+
ruby or MongoDB or do not want to deal with setting them up.
|
8
|
+
|
9
|
+
Download the files at these locations and save them in your document root:
|
10
|
+
|
11
|
+
* http://memecaptain.com/
|
12
|
+
* http://memecaptain.com/css/screen.css
|
13
|
+
* http://memecaptain.com/js/fabric.min.js
|
14
|
+
* http://memecaptain.com/js/meme_captain.js
|
15
|
+
* http://memecaptain.com/source_images.json
|
16
|
+
|
17
|
+
The css in js should go in css and js directories in your document root so
|
18
|
+
that they match the url paths.
|
19
|
+
|
20
|
+
Find this line in js/meme_captain.js
|
21
|
+
|
22
|
+
```
|
23
|
+
genUrl = '/g',
|
24
|
+
```
|
25
|
+
|
26
|
+
and change it to
|
27
|
+
|
28
|
+
```
|
29
|
+
genUrl = 'http://memecaptain.com/g',
|
30
|
+
```
|
31
|
+
|
32
|
+
# Changing the Default Source Images
|
33
|
+
|
34
|
+
The source image thumbnails that show up on the page are driven by a JSON
|
35
|
+
description and a single image that contain CSS sprites. The JSON and image
|
36
|
+
must be regenerated to change them.
|
37
|
+
|
38
|
+
The rmagick ruby gem must be installed:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
gem install rmagick
|
42
|
+
```
|
43
|
+
|
44
|
+
Get and run the script:
|
45
|
+
|
46
|
+
```sh
|
47
|
+
wget https://raw.github.com/mmb/meme_captain/master/script/thumb_sprites.rb
|
48
|
+
RUBYOPT='r rubygems'
|
49
|
+
ruby thumb_sprites.rb -u URL_ROOT -s SOURCE_URL_PREFIX SOURCE_IMAGE_PATH/*
|
50
|
+
```
|
51
|
+
|
52
|
+
SOURCE_IMAGE_PATH is the directory where the source images are stored.
|
53
|
+
URL_ROOT is the root url of the Meme Captain installation. SOURCE_URL_PREFIX
|
54
|
+
is the part between the root url and the image filenames in the image urls.
|
55
|
+
|
56
|
+
For example if the images are stored in /var/www/meme.com/source and the
|
57
|
+
url root is http://meme.com/, use:
|
58
|
+
|
59
|
+
```sh
|
60
|
+
ruby thumb_sprites.rb -u http://meme.com/ -s source/ /var/www/meme.com/source/*
|
61
|
+
```
|
62
|
+
|
63
|
+
Copy the generated source_images.json and thumbs_xxx.jpg files to the Meme
|
64
|
+
Captain document root.
|
data/doc/setup.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Requirements
|
2
|
+
|
3
|
+
* a Ruby/Rack web application environment (such as
|
4
|
+
[Passenger](http://www.modrails.com/))
|
5
|
+
|
6
|
+
* Ruby gem dependencies (see the gemspec)
|
7
|
+
|
8
|
+
* [MongoDB](http://www.mongodb.org/)
|
9
|
+
|
10
|
+
You will most likely need a dedicated or virtual private server to run
|
11
|
+
MongoDB as most shared hosting does not support it. See the lightweight front
|
12
|
+
end document for how host the static HTML/CSS/Javascript only and use
|
13
|
+
memecaptain.com for the backend.
|
@@ -11,6 +11,8 @@ module MemeCaptain
|
|
11
11
|
def fetch!(url)
|
12
12
|
curl = Curl::Easy.perform(url) do |c|
|
13
13
|
c.useragent = 'Meme Captain http://memecaptain.com/'
|
14
|
+
c.follow_location = true
|
15
|
+
c.max_redirects = 3
|
14
16
|
end
|
15
17
|
unless curl.response_code == 200
|
16
18
|
raise FetchError.new(curl.response_code)
|
data/lib/meme_captain/meme.rb
CHANGED
@@ -24,7 +24,6 @@ module MemeCaptain
|
|
24
24
|
text_layer = Magick::Image.new(
|
25
25
|
img.page.width * super_sample, img.page.height * super_sample) {
|
26
26
|
self.background_color = 'none'
|
27
|
-
self.density = 72.0 * super_sample
|
28
27
|
}
|
29
28
|
|
30
29
|
text_poss.each do |text_pos|
|
@@ -50,7 +49,15 @@ module MemeCaptain
|
|
50
49
|
min_pointsize = text_pos.min_pointsize * super_sample
|
51
50
|
|
52
51
|
draw = Magick::Draw.new {
|
53
|
-
text_pos.draw_options.each
|
52
|
+
text_pos.draw_options.each do |k,v|
|
53
|
+
# options that need to be scaled by super sample
|
54
|
+
if [
|
55
|
+
:stroke_width
|
56
|
+
].include?(k)
|
57
|
+
v *= super_sample
|
58
|
+
end
|
59
|
+
self.send("#{k}=", v)
|
60
|
+
end
|
54
61
|
}
|
55
62
|
|
56
63
|
draw.extend Draw
|
@@ -77,15 +84,20 @@ module MemeCaptain
|
|
77
84
|
end
|
78
85
|
end
|
79
86
|
|
80
|
-
|
87
|
+
if super_sample != 1
|
88
|
+
text_layer.resize!(1.0 / super_sample)
|
89
|
+
text_layer = text_layer.unsharp_mask
|
90
|
+
end
|
81
91
|
|
82
92
|
img.each do |frame|
|
83
93
|
frame.composite!(text_layer, -frame.page.x, -frame.page.y,
|
84
94
|
Magick::OverCompositeOp)
|
85
95
|
frame.strip!
|
86
96
|
end
|
87
|
-
img
|
88
97
|
|
98
|
+
text_layer.destroy!
|
99
|
+
|
100
|
+
img
|
89
101
|
end
|
90
102
|
|
91
103
|
# Shortcut to generate a typical meme with text at the top and bottom.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'RMagick'
|
2
|
+
|
3
|
+
module MemeCaptain
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# Public: Generate a pie slice meme background.
|
8
|
+
#
|
9
|
+
# size - The side length in pixels of the generated image.
|
10
|
+
# colors - An Array of color strings (any values that RMagick accepts).
|
11
|
+
# num_rays - The Fixnum of rays to create.
|
12
|
+
# block - An optiona block passed to Draw.new for specifying additional
|
13
|
+
# draw options
|
14
|
+
#
|
15
|
+
# Examples
|
16
|
+
#
|
17
|
+
# memebg(400, %w{red orange yellow green blue indigo violet}, 20) {
|
18
|
+
# # draw options
|
19
|
+
# # self.stroke = 'white'
|
20
|
+
# }.display
|
21
|
+
#
|
22
|
+
# Returns a Magick::Image of the meme background.
|
23
|
+
def memebg(size, colors, num_rays, &block)
|
24
|
+
# make circle 5% too big to avoid empty space at corners from rounding
|
25
|
+
# errors
|
26
|
+
circle_radius = Math.sqrt(2 * ((size / 2.0) ** 2)) * 1.05
|
27
|
+
|
28
|
+
side_len = 2 * circle_radius
|
29
|
+
|
30
|
+
start_x = side_len
|
31
|
+
start_y = circle_radius
|
32
|
+
|
33
|
+
center = "#{circle_radius},#{circle_radius}"
|
34
|
+
|
35
|
+
img = Magick::Image.new(side_len, side_len)
|
36
|
+
|
37
|
+
color_cycle = colors.cycle
|
38
|
+
|
39
|
+
(1..num_rays).each do |ray_index|
|
40
|
+
ray_radius = 2 * Math::PI / num_rays * ray_index
|
41
|
+
|
42
|
+
end_x = circle_radius + (Math.cos(ray_radius) * circle_radius)
|
43
|
+
end_y = circle_radius - (Math.sin(ray_radius) * circle_radius)
|
44
|
+
|
45
|
+
svg = "M#{center} L#{start_x},#{start_y} A#{center} 0 0,0 #{end_x},#{end_y} z"
|
46
|
+
|
47
|
+
draw = Magick::Draw.new {
|
48
|
+
instance_eval(&block) if block_given?
|
49
|
+
self.fill = color_cycle.next
|
50
|
+
}
|
51
|
+
|
52
|
+
draw.path svg
|
53
|
+
draw.draw img
|
54
|
+
|
55
|
+
start_x = end_x
|
56
|
+
start_y = end_y
|
57
|
+
end
|
58
|
+
|
59
|
+
img.crop! Magick::CenterGravity, size, size
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module MemeCaptain
|
2
|
+
|
3
|
+
# Normalize query string parameters.
|
4
|
+
#
|
5
|
+
# Provide defaults, do some basic validation and convert some parameters
|
6
|
+
# to floats or integers.
|
7
|
+
class NormParams
|
8
|
+
|
9
|
+
def initialize(params={})
|
10
|
+
@u = ''
|
11
|
+
|
12
|
+
@t1 = ''
|
13
|
+
@t2 = ''
|
14
|
+
|
15
|
+
@t1x = 0.05
|
16
|
+
@t1y = 0
|
17
|
+
@t1w = 0.9
|
18
|
+
@t1h = 0.25
|
19
|
+
|
20
|
+
@t2x = 0.05
|
21
|
+
@t2y = 0.75
|
22
|
+
@t2w = 0.9
|
23
|
+
@t2h = 0.25
|
24
|
+
|
25
|
+
load params
|
26
|
+
end
|
27
|
+
|
28
|
+
# Load query string parameters.
|
29
|
+
#
|
30
|
+
# Do some basic validation and convert some parameters to floats or
|
31
|
+
# integers.
|
32
|
+
def load(params)
|
33
|
+
params.select { |k,v|
|
34
|
+
[
|
35
|
+
:u,
|
36
|
+
:t1,
|
37
|
+
:t2,
|
38
|
+
].include? k.to_sym }.each do |k,v|
|
39
|
+
send "#{k}=", v.to_s
|
40
|
+
end
|
41
|
+
|
42
|
+
params.select { |k,v|
|
43
|
+
[
|
44
|
+
:t1x,
|
45
|
+
:t1y,
|
46
|
+
:t1w,
|
47
|
+
:t1h,
|
48
|
+
|
49
|
+
:t2x,
|
50
|
+
:t2y,
|
51
|
+
:t2w,
|
52
|
+
:t2h,
|
53
|
+
].include?(k.to_sym) and !v.to_s.empty? }.each do |k,v|
|
54
|
+
send "#{k}=", convert_metric(v)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return a sorted string representation of the fields.
|
59
|
+
def signature
|
60
|
+
instance_variables.sort.map { |v|
|
61
|
+
name = v[1..-1] # remove @
|
62
|
+
"#{name}#{instance_variable_get(v)}"
|
63
|
+
}.join
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_accessor :u
|
67
|
+
|
68
|
+
attr_accessor :t1
|
69
|
+
attr_accessor :t2
|
70
|
+
|
71
|
+
attr_accessor :t1x
|
72
|
+
attr_accessor :t1y
|
73
|
+
attr_accessor :t1w
|
74
|
+
attr_accessor :t1h
|
75
|
+
|
76
|
+
attr_accessor :t2x
|
77
|
+
attr_accessor :t2y
|
78
|
+
attr_accessor :t2w
|
79
|
+
attr_accessor :t2h
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Convert a metric string to a float or integer.
|
84
|
+
#
|
85
|
+
# Expects a string.
|
86
|
+
def convert_metric(metric)
|
87
|
+
metric.index('.') ? metric.to_f : metric.to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|