lgtm_hd 0.1.3 → 0.1.4
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 +4 -4
- data/.travis.yml +6 -0
- data/README.md +6 -2
- data/bin/lgtm_hd +2 -3
- data/lgtm_hd.gemspec +2 -0
- data/lib/lgtm_hd.rb +4 -122
- data/lib/lgtm_hd/cli.rb +13 -22
- data/lib/lgtm_hd/configuration.rb +8 -8
- data/lib/lgtm_hd/meme_generator.rb +118 -0
- data/lib/lgtm_hd/utilities.rb +5 -0
- data/lib/lgtm_hd/version.rb +1 -1
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 690ffa92888775481986a81d37f5283cb85b5736
|
4
|
+
data.tar.gz: 9004f97a6135757b9206b11af5189f6af79c5d8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3be3ee8b19592dbcf5be3d03df690a0f24bab103b318ea0953d2c9fa571fe50ed8d03a1536c4141c85ce5b86b115d5a4e646a6a63ca402a4bf36a8a19856464d
|
7
|
+
data.tar.gz: 977302599a8bd739e8e7ee0900a7d19542850ee017e0bae2e41484316642844d690b89498ddcf082869b164780e13964a2ae3a6ad2176246c983cda752e4d508
|
data/.travis.yml
CHANGED
@@ -2,3 +2,9 @@ language: ruby
|
|
2
2
|
rvm:
|
3
3
|
- 2.2.3
|
4
4
|
before_install: gem install bundler -v 1.10.6
|
5
|
+
addons:
|
6
|
+
code_climate:
|
7
|
+
repo_token: f8de4766221c1d212d7c884d1415314f1c55a24c1a58e16db530efbf155d1ad3
|
8
|
+
# regular test configuration
|
9
|
+
after_success:
|
10
|
+
- bundle exec codeclimate-test-reporter
|
data/README.md
CHANGED
@@ -23,10 +23,14 @@ Source | Happy Taeyeon!
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
$ lgtm_hd [transform] <
|
26
|
+
$ lgtm_hd [transform] <source_uri> <output_folder> [--clipboard] [--interactive]
|
27
27
|
$ lgtm_hd http://domain.com/image.jpg /path/lgtm.jpg
|
28
28
|
|
29
|
-
|
29
|
+
|
30
|
+
--clipboard will let the OS copy content of the file for direct pasting to Github comment box
|
31
|
+
--interactive is for lazy people who can\'t bother to type
|
32
|
+
Default command is transform so you can just leave the command empty.
|
33
|
+
|
30
34
|
|
31
35
|
## Features
|
32
36
|
|
data/bin/lgtm_hd
CHANGED
data/lgtm_hd.gemspec
CHANGED
@@ -33,6 +33,8 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "bundler", "~> 1.10"
|
34
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
35
35
|
spec.add_development_dependency "rspec", "3.6.0"
|
36
|
+
spec.add_development_dependency "simplecov"
|
37
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
36
38
|
spec.add_runtime_dependency "commander", "4.4.3"
|
37
39
|
spec.add_runtime_dependency "clipboard", "1.1.1"
|
38
40
|
spec.add_runtime_dependency "os", "1.0.0"
|
data/lib/lgtm_hd.rb
CHANGED
@@ -1,123 +1,5 @@
|
|
1
|
+
require "lgtm_hd/version"
|
1
2
|
require "lgtm_hd/configuration"
|
2
|
-
require "
|
3
|
-
require "
|
4
|
-
|
5
|
-
module LgtmHD
|
6
|
-
|
7
|
-
class MemeGenerator
|
8
|
-
attr_accessor :input_image_URI, :output_image_URI
|
9
|
-
|
10
|
-
# TODO make options list for this class
|
11
|
-
# TODO pass BLOB data into this class instead of paths
|
12
|
-
def initialize(input_image_URI, output_image_URI)
|
13
|
-
@input_image_URI = input_image_URI
|
14
|
-
@output_image_URI = output_image_URI
|
15
|
-
|
16
|
-
@img = MiniMagick::Image.open(@input_image_URI)
|
17
|
-
@caption_position = :caption_position_bottom
|
18
|
-
end
|
19
|
-
|
20
|
-
##
|
21
|
-
# Used to create a new Image object data-copy. Not used to "paint" or
|
22
|
-
# that kind of thing.
|
23
|
-
#
|
24
|
-
# @param caption_text [String] Specify the caption for your LGTM meme
|
25
|
-
# @return [MiniMagick::Image] The drawn image
|
26
|
-
#
|
27
|
-
def draw (caption_text = "LGTM")
|
28
|
-
if @img.respond_to? (:combine_options) then
|
29
|
-
@img.combine_options do |c|
|
30
|
-
c.gravity captionPosition()
|
31
|
-
c.draw "text 0,0 " << "#{caption_text}"
|
32
|
-
c.font captionFont
|
33
|
-
c.pointsize captionFontSize
|
34
|
-
c.density imageDensity
|
35
|
-
c.fill captionColor
|
36
|
-
c.resize imageMaxSize().reduce() {|w,h| w << 'x' << h} # syntax: convert -resize $wx$h
|
37
|
-
end
|
38
|
-
@img.contrast
|
39
|
-
end
|
40
|
-
yield @img if block_given?
|
41
|
-
end
|
42
|
-
|
43
|
-
def export
|
44
|
-
@img.write(@output_image_URI)
|
45
|
-
yield @output_image_URI if block_given?
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def imageMaxSize
|
52
|
-
[Configuration::OUTPUT_MAX_WIDTH.to_s, Configuration::OUTPUT_MAX_HEIGHT.to_s]
|
53
|
-
end
|
54
|
-
|
55
|
-
##
|
56
|
-
# @return [String] the position of image
|
57
|
-
# Could be either :caption_position_top or :caption_position_bottom
|
58
|
-
#
|
59
|
-
def captionPosition ()
|
60
|
-
if not [:caption_position_top, :caption_position_bottom].include? (@caption_position)
|
61
|
-
@caption_position = :caption_position_top
|
62
|
-
end
|
63
|
-
return {:caption_position_top => "north center",
|
64
|
-
:caption_position_bottom => "south center"}[@caption_position]
|
65
|
-
end
|
66
|
-
|
67
|
-
def captionFont
|
68
|
-
'' << LgtmHD.root << Configuration::FONT_PATH
|
69
|
-
end
|
70
|
-
|
71
|
-
def captionFontSize
|
72
|
-
Configuration::CAPTION_FONT_SIZE_DEFAULT
|
73
|
-
end
|
74
|
-
|
75
|
-
def imageDensity
|
76
|
-
Configuration::OUTPUT_DENSITY
|
77
|
-
end
|
78
|
-
|
79
|
-
##
|
80
|
-
# Decide foreground color depending on background color
|
81
|
-
# https://en.wikipedia.org/wiki/Rec._601
|
82
|
-
#
|
83
|
-
# We use this method that include magic numbers .241, .691, .068 accroding to
|
84
|
-
# the provided wikipedia link
|
85
|
-
# Math.Sqrt(
|
86
|
-
# c.R * c.R * .241 +
|
87
|
-
# c.G * c.G * .691 +
|
88
|
-
# c.B * c.B * .068)
|
89
|
-
#
|
90
|
-
# Magic cut off number is 130.
|
91
|
-
# Under 130 is too dark, so the foreground color is white
|
92
|
-
# Above is too bright so the foreground color is black
|
93
|
-
#
|
94
|
-
# @return [String] the foreground color of caption
|
95
|
-
#
|
96
|
-
def captionColor
|
97
|
-
# Copy current image data instead of working directly on working file
|
98
|
-
img = MiniMagick::Image.read(@img.to_blob)
|
99
|
-
|
100
|
-
# cutoff's x is always 0 as we only support top or bottom right now
|
101
|
-
cutoff_y = @caption_position == :caption_position_bottom ? (img.height/2).round : 0
|
102
|
-
img.crop("#{img.width}x#{img.height/2}+0+#{cutoff_y}")
|
103
|
-
|
104
|
-
# Since we are getting
|
105
|
-
img = img.resize('1x1')
|
106
|
-
rgb = img.get_pixels[0][0] # Only 1x1 pixel remember? ^_^
|
107
|
-
color = {}
|
108
|
-
['r','g','b'].zip(rgb) { |k,v| color[k] = v }
|
109
|
-
|
110
|
-
magic_color_value = color['r'] * color['r'] * 0.241
|
111
|
-
magic_color_value += color['g'] * color['g'] * 0.691
|
112
|
-
magic_color_value += color['b'] * color['b'] * 0.068
|
113
|
-
magic_color_value = Math.sqrt(magic_color_value)
|
114
|
-
|
115
|
-
return (magic_color_value.round > 130) ? "#000000" : "#FFFFFF"
|
116
|
-
end
|
117
|
-
|
118
|
-
end # End of Class
|
119
|
-
|
120
|
-
def self.root
|
121
|
-
File.expand_path '../..', __FILE__
|
122
|
-
end
|
123
|
-
end # End of Module
|
3
|
+
require "lgtm_hd/utilities"
|
4
|
+
require "lgtm_hd/meme_generator"
|
5
|
+
require "lgtm_hd/cli"
|
data/lib/lgtm_hd/cli.rb
CHANGED
@@ -1,15 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'commander'
|
3
3
|
require 'os'
|
4
|
-
require 'net/http'
|
5
|
-
require 'tempfile'
|
6
4
|
require 'clipboard'
|
7
5
|
require 'uri'
|
8
6
|
|
9
|
-
require 'lgtm_hd'
|
10
|
-
require 'lgtm_hd/version'
|
11
|
-
require 'lgtm_hd/configuration'
|
12
|
-
|
13
7
|
module LgtmHD
|
14
8
|
class CLI
|
15
9
|
include Commander::Methods
|
@@ -21,7 +15,7 @@ module LgtmHD
|
|
21
15
|
default_command :transform
|
22
16
|
|
23
17
|
command :transform do |c|
|
24
|
-
c.syntax = 'lgtm_hd
|
18
|
+
c.syntax = 'lgtm_hd <source_uri> <output_path> [--clipboard] [--interactive]'
|
25
19
|
c.summary = 'Generate a LGTM image from source_uri (local path or URL) into output folder'
|
26
20
|
c.description = ''
|
27
21
|
c.example '', 'lgtm_hd export http://domain.com/image.png /path/to/lgtm.png'
|
@@ -32,37 +26,34 @@ module LgtmHD
|
|
32
26
|
to_clipboard = options.clipboard
|
33
27
|
|
34
28
|
# ARGS validation!
|
35
|
-
if args.length == 2
|
29
|
+
if args.length == 2
|
36
30
|
source_uri = args[0]
|
37
31
|
output_uri = args[1]
|
38
|
-
|
39
32
|
elsif options.interactive # Interactive mode!
|
40
33
|
say "-- LGTM Interactive mode --"
|
41
34
|
source_uri = ask('Source (URL or Path/to/file): ')
|
42
|
-
output_uri = ask('Output Folder
|
43
|
-
# TODO accept relative path "~/.."
|
35
|
+
output_uri = ask('Output Folder: ')
|
44
36
|
to_clipboard = agree("Copy to clipboard afterward? [Y/N]")
|
45
37
|
else
|
46
|
-
|
38
|
+
say "usage: lgtm_hd <source_uri> <output_path> [--clipboard] [--interactive]"
|
39
|
+
raise ArgumentError, "Too few or too many arguments provided, need 2: source and output URIs"
|
47
40
|
end
|
48
41
|
|
49
42
|
|
50
43
|
# Validate the inputs
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
44
|
+
output_folder = File.expand_path(output_uri)
|
45
|
+
output_file = File.join(output_folder,
|
46
|
+
LgtmHD::Configuration::OUTPUT_PREFIX +
|
47
|
+
Time.now.strftime('%Y-%m-%d_%H-%M-%S') +
|
48
|
+
File.extname(source_uri))
|
49
|
+
raise "Source is not proper URIs (URL or Path/to/file)" unless source_uri =~ URI::regexp || File.exist?(source_uri)
|
50
|
+
raise "Output is invalid path or directory" unless File.exist?(output_folder) && File.directory?(output_folder)
|
55
51
|
|
56
|
-
unless File.exist?(output_uri) and File.directory?(output_uri) then
|
57
|
-
raise "Output is not a directory or valid path"
|
58
|
-
end
|
59
52
|
|
60
|
-
file_ext = File.extname(source_uri)
|
61
|
-
output_uri = File.join(output_uri, "" << LgtmHD::Configuration::OUTPUT_PREFIX << Time.now.strftime('%Y-%m-%d_%H-%M-%S') << file_ext)
|
62
53
|
|
63
54
|
# Do stuff with our LGTM meme
|
64
55
|
say "- Reading and inspecting source"
|
65
|
-
meme_generator = MemeGenerator.new(source_uri,
|
56
|
+
meme_generator = MemeGenerator.new(input_image_uri:source_uri, output_image_uri:output_file)
|
66
57
|
say "- Rendering output"
|
67
58
|
meme_generator.draw
|
68
59
|
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module LgtmHD
|
2
2
|
module Configuration
|
3
3
|
# Program configurations
|
4
|
-
PROGRAM_NAME
|
5
|
-
DESCRIPTION
|
4
|
+
PROGRAM_NAME = "lgtm_hd".freeze
|
5
|
+
DESCRIPTION = "Generating images from user input with LGTM text on it, or fetching images from LGTM.in based on user's query. Finally put the image to clipboard.".freeze
|
6
6
|
|
7
7
|
# Output Image configurations
|
8
|
-
OUTPUT_PREFIX
|
9
|
-
OUTPUT_MAX_WIDTH
|
10
|
-
OUTPUT_MAX_HEIGHT
|
11
|
-
OUTPUT_DENSITY
|
8
|
+
OUTPUT_PREFIX = "lgtm_hd_".freeze
|
9
|
+
OUTPUT_MAX_WIDTH = 500.freeze
|
10
|
+
OUTPUT_MAX_HEIGHT = 500.freeze
|
11
|
+
OUTPUT_DENSITY = 90.freeze # or 120 point per inch
|
12
12
|
|
13
13
|
# Caption configurations
|
14
|
-
FONT_PATH
|
15
|
-
CAPTION_FONT_SIZE_DEFAULT
|
14
|
+
FONT_PATH = "/fonts/impact.ttf".freeze
|
15
|
+
CAPTION_FONT_SIZE_DEFAULT = 96.freeze
|
16
16
|
|
17
17
|
end
|
18
18
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require "mini_magick"
|
2
|
+
|
3
|
+
module LgtmHD
|
4
|
+
class MemeGenerator
|
5
|
+
|
6
|
+
# TODO make options list for this class
|
7
|
+
# TODO pass BLOB data into this class instead of paths
|
8
|
+
def initialize(input_image_uri:, output_image_uri:)
|
9
|
+
@input_image_uri = input_image_uri
|
10
|
+
@output_image_uri = output_image_uri
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Used to create a new Image object data-copy. Not used to "paint" or
|
15
|
+
# that kind of thing.
|
16
|
+
#
|
17
|
+
# @param caption_text [String] Specify the caption for your LGTM meme
|
18
|
+
# @return [MiniMagick::Image] The drawn image
|
19
|
+
#
|
20
|
+
def draw(caption_text = "LGTM")
|
21
|
+
img = image
|
22
|
+
img.combine_options do |c|
|
23
|
+
c.gravity caption_position
|
24
|
+
c.draw "text 0,0 " << caption_text
|
25
|
+
c.font caption_font
|
26
|
+
c.pointsize caption_font_size
|
27
|
+
c.density image_density
|
28
|
+
c.fill caption_color
|
29
|
+
c.resize image_max_size().reduce() {|w,h| "#{w}x#{h}"} # syntax: convert -resize $wx$h
|
30
|
+
img.contrast
|
31
|
+
end
|
32
|
+
yield img if block_given?
|
33
|
+
end
|
34
|
+
|
35
|
+
def export
|
36
|
+
image.write(@output_image_uri)
|
37
|
+
yield @output_image_uri if block_given?
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def image
|
44
|
+
@image ||= MiniMagick::Image.open(@input_image_uri)
|
45
|
+
end
|
46
|
+
|
47
|
+
def image_max_size
|
48
|
+
[Configuration::OUTPUT_MAX_WIDTH, Configuration::OUTPUT_MAX_HEIGHT]
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# @return [String] the position of image
|
53
|
+
# Could be either :caption_position_top or :caption_position_bottom
|
54
|
+
# Default value is top
|
55
|
+
#
|
56
|
+
def caption_position
|
57
|
+
if not [:caption_position_top, :caption_position_bottom].include? (@caption_position)
|
58
|
+
@caption_position = :caption_position_bottom
|
59
|
+
end
|
60
|
+
return {:caption_position_top => "north center",
|
61
|
+
:caption_position_bottom => "south center"}[@caption_position]
|
62
|
+
end
|
63
|
+
|
64
|
+
def caption_font
|
65
|
+
File.join(LgtmHD::gem_root, Configuration::FONT_PATH)
|
66
|
+
end
|
67
|
+
|
68
|
+
def caption_font_size
|
69
|
+
Configuration::CAPTION_FONT_SIZE_DEFAULT
|
70
|
+
end
|
71
|
+
|
72
|
+
def image_density
|
73
|
+
Configuration::OUTPUT_DENSITY
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Decide foreground color depending on background color
|
78
|
+
# https://en.wikipedia.org/wiki/Rec._601
|
79
|
+
#
|
80
|
+
# We use this method that include magic numbers .241, .691, .068 accroding to
|
81
|
+
# the provided wikipedia link
|
82
|
+
# Math.Sqrt(
|
83
|
+
# c.R * c.R * .241 +
|
84
|
+
# c.G * c.G * .691 +
|
85
|
+
# c.B * c.B * .068)
|
86
|
+
#
|
87
|
+
# Magic cut off number is 130.
|
88
|
+
# Under 130 is too dark, so the foreground color is white
|
89
|
+
# Above is too bright so the foreground color is black
|
90
|
+
#
|
91
|
+
# @return [String] the foreground color of caption
|
92
|
+
#
|
93
|
+
def caption_color
|
94
|
+
# Copy current image data instead of working directly on working file
|
95
|
+
# because ImageMagick apply change directly to the temporary working file instead of keep changes in memory
|
96
|
+
# Might need to invest a bit further to ensure this, as for now, lazy..
|
97
|
+
temp_img = MiniMagick::Image.read(image.to_blob)
|
98
|
+
|
99
|
+
# cutoff's x is always 0 as we only support top or bottom right now
|
100
|
+
cutoff_y = @caption_position == :caption_position_bottom ? (temp_img.height/2).round : 0
|
101
|
+
temp_img.crop("#{temp_img.width}x#{temp_img.height/2}+0+#{cutoff_y}")
|
102
|
+
|
103
|
+
# Since we are getting
|
104
|
+
temp_img = temp_img.resize('1x1')
|
105
|
+
rgb = temp_img.get_pixels[0][0] # Only 1x1 pixel remember? ^_^
|
106
|
+
color = {}
|
107
|
+
['r','g','b'].zip(rgb) { |k,v| color[k] = v }
|
108
|
+
|
109
|
+
magic_color_value = color['r'] * color['r'] * 0.241
|
110
|
+
magic_color_value += color['g'] * color['g'] * 0.691
|
111
|
+
magic_color_value += color['b'] * color['b'] * 0.068
|
112
|
+
magic_color_value = Math.sqrt(magic_color_value)
|
113
|
+
|
114
|
+
(magic_color_value.round > 130) ? "#000000" : "#FFFFFF"
|
115
|
+
end
|
116
|
+
|
117
|
+
end # End of Class
|
118
|
+
end # End of module
|
data/lib/lgtm_hd/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lgtm_hd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Huy Dinh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,34 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 3.6.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: simplecov
|
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: codeclimate-test-reporter
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: commander
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,6 +162,8 @@ files:
|
|
134
162
|
- lib/lgtm_hd.rb
|
135
163
|
- lib/lgtm_hd/cli.rb
|
136
164
|
- lib/lgtm_hd/configuration.rb
|
165
|
+
- lib/lgtm_hd/meme_generator.rb
|
166
|
+
- lib/lgtm_hd/utilities.rb
|
137
167
|
- lib/lgtm_hd/version.rb
|
138
168
|
homepage: http://github.com/phradion/lgtm_hd
|
139
169
|
licenses:
|