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 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
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
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)
@@ -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 { |k,v| self.send("#{k}=", v) }
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
- text_layer.resize!(1.0 / super_sample)
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
@@ -0,0 +1,12 @@
1
+ require 'pp'
2
+
3
+ module MemeCaptain
4
+
5
+ module_function
6
+
7
+ # Format an object like pp would would and return the formatted string.
8
+ def pretty_format(o)
9
+ PP.pp o, dump = ''
10
+ end
11
+
12
+ end