daily_image 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +26 -0
- data/README.md +96 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/daily_image +145 -0
- data/bin/setup +8 -0
- data/daily_image.gemspec +35 -0
- data/lib/daily_image/config.rb +49 -0
- data/lib/daily_image/image.rb +205 -0
- data/lib/daily_image/poem.rb +41 -0
- data/lib/daily_image/version.rb +3 -0
- data/lib/daily_image.rb +30 -0
- data/tmp/daily_2018-09-14.jpg +0 -0
- data/tmp/daily_2018-09-17.jpg +0 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1efdea98fc3b59bc85431e1c8384ce8d0095cc22ff54d11021ef6918df677ae3
|
4
|
+
data.tar.gz: 804765d2e0540898e7853407fb3a23bcd7cd51128b8d30e57cd5f24a8daed6f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 34ba4f064cb456f6747f40fb7355e5e8922612736ef322d3fa129911b4289144eee46df4b7185746f5bcb248ed260ed3c14d61189722e90c2ab27ea59333d461
|
7
|
+
data.tar.gz: 219c852823562df7adb6f7b59efb75c773fe030afeb4e6b1825db5227eafc6df0133e113902adc8975e15225975305f2a46cbdff0a27b3af11ebcffb6366cdda
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at lanyuejin1108@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
daily_image (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ffi (1.9.25)
|
10
|
+
minitest (5.11.3)
|
11
|
+
rake (10.5.0)
|
12
|
+
ruby-vips (2.0.13)
|
13
|
+
ffi (~> 1.9)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
bundler (~> 1.16)
|
20
|
+
daily_image!
|
21
|
+
minitest (~> 5.0)
|
22
|
+
rake (~> 10.0)
|
23
|
+
ruby-vips (~> 2.0.13)
|
24
|
+
|
25
|
+
BUNDLED WITH
|
26
|
+
1.16.1
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# DailyImage
|
2
|
+
|
3
|
+
日签 Or 日历,生成一张当日的图片。Just For Fun!👏
|
4
|
+
|
5
|
+
## 使用
|
6
|
+
|
7
|
+
如果需要在项目中使用,在你的gemfile中添加以下代码
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'daily_image'
|
11
|
+
```
|
12
|
+
|
13
|
+
然后执行下面的命令
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
或者,你可以直接安装使用
|
18
|
+
|
19
|
+
$ gem install daily_image
|
20
|
+
|
21
|
+
## 使用
|
22
|
+
|
23
|
+
### 配置使用
|
24
|
+
|
25
|
+
当你需要项目使用时,可以通过下面方式修改默认配置:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
|
29
|
+
# 初始项目配置
|
30
|
+
DailyImage.configure do |config|
|
31
|
+
config[:bg_color] = [255, 255, 255] # 背景颜色
|
32
|
+
config[:frame_color] = [151, 158, 160] # 边框颜色
|
33
|
+
config[:text_color] = [100, 145, 170] # 文字颜色
|
34
|
+
config[:date_color] = [100, 145, 170] # 中间日期颜色
|
35
|
+
config[:unused_color] = [200, 205, 215] # 进度条未使用颜色
|
36
|
+
config[:used_color] = [100, 145, 170] # 进度条已使用颜色
|
37
|
+
config[:out_frame_offset] = 15 # 外层边框偏移量
|
38
|
+
config[:in_frame_offset] = 50 # 下半部分内层边框偏移量
|
39
|
+
config[:font] = 'Hiragino Sans GB' # 文字默认字体
|
40
|
+
end
|
41
|
+
|
42
|
+
# 调用方法
|
43
|
+
DailyImage.draw_image(output_path) # 默认图片存放地址,包所在的目录
|
44
|
+
|
45
|
+
# 例子
|
46
|
+
DailyImage.draw_image('./')
|
47
|
+
```
|
48
|
+
|
49
|
+
### 命令行
|
50
|
+
|
51
|
+
如果是直接安装,可以通过命令行直接调用。**当然,还是需要安装ruby以及对应的依赖**
|
52
|
+
|
53
|
+
```shell
|
54
|
+
$ bundle exec daily_image -h
|
55
|
+
Usage: daily_image [options]
|
56
|
+
|
57
|
+
Specific options:
|
58
|
+
-b, --bg_color BG_COLOR the image's background color
|
59
|
+
-r, --frame_color FRAME_COLOR the image's frame color
|
60
|
+
-t, --text_color TEXT_COLOR the image's text color
|
61
|
+
-d, --date_color DATE_COLOR the middle date's text color
|
62
|
+
-n, --unused_color UNUSED_COLOR unused color of the progress bar
|
63
|
+
-u, --used_color USED_COLOR used color of the progress bar
|
64
|
+
-o OUT_FRAME_OFFSET, the outside frame offset
|
65
|
+
--out_offset
|
66
|
+
-i, --in_offset IN_FRAME_OFFSET the inside frame offset
|
67
|
+
-f, --font FONT the text font
|
68
|
+
-s, --output OUTPUT the output path, save the new image
|
69
|
+
|
70
|
+
Common options:
|
71
|
+
-h, --help Show the help message
|
72
|
+
-v, --version Show version
|
73
|
+
|
74
|
+
```
|
75
|
+
|
76
|
+
## 示例
|
77
|
+
|
78
|
+

|
79
|
+
|
80
|
+
## 感谢🙏
|
81
|
+
|
82
|
+
站在巨人的肩膀上
|
83
|
+
|
84
|
+
1. 画图使用了 [ruby-vips](https://github.com/jcupitt/ruby-vips)
|
85
|
+
|
86
|
+
2. 诗词来自于 [一言·古诗词 API](https://github.com/xenv/gushici)
|
87
|
+
|
88
|
+
## 如何贡献
|
89
|
+
|
90
|
+
1. Fork it
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
92
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
94
|
+
5. Create new Pull Request
|
95
|
+
|
96
|
+
欢迎贡献相关代码或是反馈使用时遇到的问题👏,另外请记得为你的代码编写测试。
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "daily_image"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/daily_image
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "optparse"
|
5
|
+
require "json"
|
6
|
+
require "daily_image"
|
7
|
+
|
8
|
+
class DailyImageOptparser
|
9
|
+
|
10
|
+
class Parser
|
11
|
+
attr_accessor :bg_color,
|
12
|
+
:frame_color,
|
13
|
+
:text_color,
|
14
|
+
:date_color,
|
15
|
+
:unused_color,
|
16
|
+
:used_color,
|
17
|
+
:font,
|
18
|
+
:out_frame_offset,
|
19
|
+
:in_frame_offset,
|
20
|
+
:output_path
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
end
|
24
|
+
|
25
|
+
def define_options(parser)
|
26
|
+
parser.banner = "Usage: daily_image [options]"
|
27
|
+
parser.separator ""
|
28
|
+
parser.separator "Specific options:"
|
29
|
+
|
30
|
+
bg_color_option(parser)
|
31
|
+
frame_color_option(parser)
|
32
|
+
text_color_option(parser)
|
33
|
+
date_color_option(parser)
|
34
|
+
unused_color_option(parser)
|
35
|
+
used_color_option(parser)
|
36
|
+
out_frame_offset_option(parser)
|
37
|
+
in_frame_offset_option(parser)
|
38
|
+
font_option(parser)
|
39
|
+
output_path_option(parser)
|
40
|
+
|
41
|
+
parser.separator ""
|
42
|
+
parser.separator "Common options:"
|
43
|
+
|
44
|
+
parser.on_tail("-h", "--help", "Show the help message") do
|
45
|
+
puts parser
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
# Another typical switch to print the version.
|
49
|
+
parser.on_tail("-v", "--version", "Show version") do
|
50
|
+
puts DailyImage::VERSION
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def bg_color_option(parser)
|
58
|
+
parser.on("-b", "--bg_color BG_COLOR", "the image's background color") do |bg_color|
|
59
|
+
self.bg_color = bg_color
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def frame_color_option(parser)
|
64
|
+
parser.on("-r", "--frame_color FRAME_COLOR", "the image's frame color") do |frame_color|
|
65
|
+
self.frame_color = frame_color
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def text_color_option(parser)
|
70
|
+
parser.on("-t", "--text_color TEXT_COLOR", "the image's text color") do |text_color|
|
71
|
+
self.text_color = text_color
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def date_color_option(parser)
|
76
|
+
parser.on("-d", "--date_color DATE_COLOR", "the middle date's text color") do |date_color|
|
77
|
+
self.date_color = date_color
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def unused_color_option(parser)
|
82
|
+
parser.on("-n", "--unused_color UNUSED_COLOR", "unused color of the progress bar") do |unused_color|
|
83
|
+
self.unused_color = unused_color
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def used_color_option(parser)
|
88
|
+
parser.on("-u", "--used_color USED_COLOR", "used color of the progress bar") do |used_color|
|
89
|
+
self.used_color = used_color
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def out_frame_offset_option(parser)
|
94
|
+
parser.on("-o", "--out_offset OUT_FRAME_OFFSET", "the outside frame offset") do |out_offset|
|
95
|
+
self.out_frame_offset = out_offset
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def in_frame_offset_option(parser)
|
100
|
+
parser.on("-i", "--in_offset IN_FRAME_OFFSET", "the inside frame offset") do |in_offset|
|
101
|
+
self.in_frame_offset = in_offset
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def font_option(parser)
|
106
|
+
parser.on("-f", "--font FONT", "the text font") do |font|
|
107
|
+
self.font = font
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def output_path_option(parser)
|
112
|
+
parser.on("-s", "--output OUTPUT", "the output path, save the new image") do |output|
|
113
|
+
self.output_path = output
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
attr_reader :parser, :options
|
120
|
+
def parse(args)
|
121
|
+
@options = Parser.new
|
122
|
+
@args = OptionParser.new do |parser|
|
123
|
+
@options.define_options(parser)
|
124
|
+
parser.parse!(args)
|
125
|
+
end
|
126
|
+
@options
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
parser = DailyImageOptparser.new
|
131
|
+
options = parser.parse(ARGV)
|
132
|
+
|
133
|
+
DailyImage.configure do |config|
|
134
|
+
config.bg_color = JSON.parse(options.bg_color) if options.bg_color
|
135
|
+
config.frame_color = JSON.parse(options.frame_color) if options.frame_color
|
136
|
+
config.text_color = JSON.parse(options.text_color) if options.text_color
|
137
|
+
config.date_color = JSON.parse(options.date_color) if options.date_color
|
138
|
+
config.unused_color = JSON.parse(options.unused_color) if options.unused_color
|
139
|
+
config.used_color = JSON.parse(options.used_color) if options.used_color
|
140
|
+
config.out_frame_offset = options.out_frame_offset.to_i if options.out_frame_offset
|
141
|
+
config.in_frame_offset = options.in_frame_offset.to_i if options.in_frame_offset
|
142
|
+
config.font = options.font if options.font
|
143
|
+
end
|
144
|
+
|
145
|
+
DailyImage.draw_image(options.output_path)
|
data/bin/setup
ADDED
data/daily_image.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "daily_image/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "daily_image"
|
8
|
+
spec.version = DailyImage::VERSION
|
9
|
+
spec.authors = ["renyijiu"]
|
10
|
+
spec.email = ["lanyuejin1108@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{A gem generate a daily image. Just For Fun 😊}
|
13
|
+
spec.description = %q{A gem generate a daily image. Just For Fun 😊}
|
14
|
+
spec.homepage = "https://github.com/renyijiu/daily_image"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
22
|
+
"public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
f.match(%r{^(test|spec|features)/})
|
27
|
+
end
|
28
|
+
spec.bindir = "bin"
|
29
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
33
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
34
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
35
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "singleton"
|
2
|
+
|
3
|
+
module DailyImage
|
4
|
+
class Config
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
# 背景颜色
|
8
|
+
attr_accessor :bg_color
|
9
|
+
|
10
|
+
# 边框颜色
|
11
|
+
attr_accessor :frame_color
|
12
|
+
|
13
|
+
# 文字颜色
|
14
|
+
attr_accessor :text_color
|
15
|
+
|
16
|
+
# 中间日期颜色
|
17
|
+
attr_accessor :date_color
|
18
|
+
|
19
|
+
# 进度条未使用颜色
|
20
|
+
attr_accessor :unused_color
|
21
|
+
|
22
|
+
# 进度条已使用颜色
|
23
|
+
attr_accessor :used_color
|
24
|
+
|
25
|
+
# 文字默认字体
|
26
|
+
attr_accessor :font
|
27
|
+
|
28
|
+
# 外层边框偏移量
|
29
|
+
attr_accessor :out_frame_offset
|
30
|
+
|
31
|
+
# 下半部分内层边框偏移量
|
32
|
+
attr_accessor :in_frame_offset
|
33
|
+
|
34
|
+
def configuration
|
35
|
+
@config ||= {}.tap do |config|
|
36
|
+
config[:bg_color] = bg_color || [255, 255, 255]
|
37
|
+
config[:frame_color] = frame_color || [151, 158, 160]
|
38
|
+
config[:text_color] = text_color || [100, 145, 170]
|
39
|
+
config[:date_color] = date_color || [100, 145, 170]
|
40
|
+
config[:unused_color] = unused_color || [200, 205, 215]
|
41
|
+
config[:used_color] = used_color || [100, 145, 170]
|
42
|
+
config[:out_frame_offset] = out_frame_offset || 15
|
43
|
+
config[:in_frame_offset] = in_frame_offset || 50
|
44
|
+
config[:font] = font || 'Hiragino Sans GB'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
|
2
|
+
module DailyImage
|
3
|
+
class Image
|
4
|
+
|
5
|
+
def initialize(width = 600, height = 800)
|
6
|
+
@width = width
|
7
|
+
@height = height
|
8
|
+
end
|
9
|
+
|
10
|
+
def draw_image
|
11
|
+
image = Vips::Image.black(@width, @height)
|
12
|
+
image = draw_top_half(image)
|
13
|
+
|
14
|
+
draw_down_half(image)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def config
|
20
|
+
@config ||= DailyImage.config
|
21
|
+
end
|
22
|
+
|
23
|
+
# 画出上半部分
|
24
|
+
def draw_top_half(image)
|
25
|
+
image = draw_background(image)
|
26
|
+
image = draw_frame(image)
|
27
|
+
image = draw_day(image)
|
28
|
+
image = draw_date(image)
|
29
|
+
image = draw_week(image)
|
30
|
+
image = draw_progress_txt(image)
|
31
|
+
|
32
|
+
draw_progress(image)
|
33
|
+
end
|
34
|
+
|
35
|
+
# 画出下半部分
|
36
|
+
def draw_down_half(image)
|
37
|
+
image = draw_down_frame(image)
|
38
|
+
|
39
|
+
draw_poem(image)
|
40
|
+
end
|
41
|
+
|
42
|
+
# 设置背景颜色
|
43
|
+
def draw_background(image)
|
44
|
+
image + config[:bg_color]
|
45
|
+
end
|
46
|
+
|
47
|
+
# 画出外边框
|
48
|
+
def draw_frame(image)
|
49
|
+
[0, 1, 2, 3, 4, 10, 11].each do |offset|
|
50
|
+
offset += config[:out_frame_offset]
|
51
|
+
|
52
|
+
width = @width - 2 * offset
|
53
|
+
height = @height - 2 * offset
|
54
|
+
|
55
|
+
image = image.draw_rect(config[:frame_color], offset, offset, width, height, fill: false)
|
56
|
+
end
|
57
|
+
|
58
|
+
image
|
59
|
+
end
|
60
|
+
|
61
|
+
# 画出中间日期
|
62
|
+
def draw_day(image)
|
63
|
+
day = Date.today.day.to_s
|
64
|
+
|
65
|
+
# 生成字体图片
|
66
|
+
text = generate_text_image(day, dpi: 1000, text_color: config[:date_color])
|
67
|
+
|
68
|
+
# 计算字体放置位置
|
69
|
+
x = (image.width - text.width) / 2
|
70
|
+
y = (image.height * 0.2).to_i
|
71
|
+
|
72
|
+
image.draw_image text, x, y, mode: :set
|
73
|
+
end
|
74
|
+
|
75
|
+
# 画出左上角日期
|
76
|
+
def draw_date(image)
|
77
|
+
date = Date.today.to_s
|
78
|
+
text = generate_text_image(date, dpi: 150)
|
79
|
+
|
80
|
+
# 计算放置位置
|
81
|
+
x = (image.width * 0.1).to_i
|
82
|
+
y = (image.height * 0.09).to_i
|
83
|
+
|
84
|
+
image.draw_image text, x, y, mode: :set
|
85
|
+
end
|
86
|
+
|
87
|
+
# 画出右上角信息
|
88
|
+
def draw_week(image)
|
89
|
+
week_arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
90
|
+
week = week_arr[Date.today.cwday]
|
91
|
+
|
92
|
+
text = generate_text_image(week, dpi: 140)
|
93
|
+
|
94
|
+
# 计算放置位置
|
95
|
+
x = (image.width * 0.75).to_i
|
96
|
+
y = (image.height * 0.09).to_i
|
97
|
+
|
98
|
+
image.draw_image text, x, y, mode: :set
|
99
|
+
end
|
100
|
+
|
101
|
+
# 画出进度描述信息
|
102
|
+
def draw_progress_txt(image)
|
103
|
+
day = Date.today.yday
|
104
|
+
percent = (percent_of_year * 100).round(2)
|
105
|
+
text = "第 #{day} 天,进度已消耗 #{percent}%"
|
106
|
+
|
107
|
+
# 获取文字图片
|
108
|
+
text_image = generate_text_image(text)
|
109
|
+
|
110
|
+
x = (@width - text_image.width) / 2
|
111
|
+
y = @height * 0.44
|
112
|
+
|
113
|
+
image.draw_image text_image, x, y, mode: :set
|
114
|
+
end
|
115
|
+
|
116
|
+
# 画出年进度信息
|
117
|
+
def draw_progress(image)
|
118
|
+
height = 30
|
119
|
+
|
120
|
+
unused_width = @width - 2 * config[:in_frame_offset]
|
121
|
+
used_width = (unused_width * percent_of_year).to_i
|
122
|
+
|
123
|
+
x = config[:in_frame_offset]
|
124
|
+
y = (@height * 0.5).to_i
|
125
|
+
|
126
|
+
# 画出整年的进度条
|
127
|
+
image = image.draw_rect(config[:unused_color], x, y, unused_width, height, fill: true)
|
128
|
+
|
129
|
+
# 画出已进行的进度条
|
130
|
+
image.draw_rect(config[:used_color], x, y, used_width, height, fill: true)
|
131
|
+
end
|
132
|
+
|
133
|
+
# 画出下半部分边框
|
134
|
+
def draw_down_frame(image)
|
135
|
+
width = (@width - 2 * config[:in_frame_offset]).to_i
|
136
|
+
height = (@height * 0.49 - 2 * config[:in_frame_offset]).to_i
|
137
|
+
|
138
|
+
x = config[:in_frame_offset]
|
139
|
+
y = (@height * 0.51 + config[:in_frame_offset]).to_i
|
140
|
+
|
141
|
+
image.draw_rect(config[:frame_color], x, y, width, height, fill: false)
|
142
|
+
end
|
143
|
+
|
144
|
+
def draw_poem(image)
|
145
|
+
_, res = DailyImage::Poem.new.txt
|
146
|
+
|
147
|
+
title = res['origin'] || '无题'
|
148
|
+
content = res['content'] || '唯有梦想与爱情,不可辜负。'
|
149
|
+
author = "--- #{res['author'] || '佚名'}"
|
150
|
+
|
151
|
+
image = draw_poem_title(image, title)
|
152
|
+
image = draw_poem_content(image, content)
|
153
|
+
draw_poem_author(image, author)
|
154
|
+
end
|
155
|
+
|
156
|
+
def draw_poem_title(image, title)
|
157
|
+
text = generate_text_image(title, dpi: 110)
|
158
|
+
|
159
|
+
x = ((@width - text.width) / 2).to_i
|
160
|
+
y = (@height * 0.65).to_i
|
161
|
+
|
162
|
+
image.draw_image text, x, y, mode: :set
|
163
|
+
end
|
164
|
+
|
165
|
+
def draw_poem_content(image, content)
|
166
|
+
text = generate_text_image(content, dpi: 135)
|
167
|
+
|
168
|
+
x = ((@width - text.width) / 2).to_i
|
169
|
+
y = (@height * 0.75).to_i
|
170
|
+
|
171
|
+
image.draw_image text, x, y, mode: :set
|
172
|
+
end
|
173
|
+
|
174
|
+
def draw_poem_author(image, author)
|
175
|
+
text = generate_text_image(author)
|
176
|
+
|
177
|
+
x = (@width - text.width - config[:in_frame_offset] - 10).to_i
|
178
|
+
y = (@height * 0.85).to_i
|
179
|
+
|
180
|
+
image.draw_image text, x, y, mode: :set
|
181
|
+
end
|
182
|
+
|
183
|
+
# 计算当天时间在一年的百分比
|
184
|
+
def percent_of_year
|
185
|
+
days = Date.new(Date.today.year, 12, 31).yday
|
186
|
+
current_days = Date.today.yday
|
187
|
+
|
188
|
+
(current_days.to_f / days).round(4)
|
189
|
+
end
|
190
|
+
|
191
|
+
# 生成字体图片
|
192
|
+
def generate_text_image(text, opts={})
|
193
|
+
dpi = opts.fetch(:dpi, 100)
|
194
|
+
text_color = opts.fetch(:text_color, config[:text_color])
|
195
|
+
bg_color = opts.fetch(:bg_color, config[:bg_color])
|
196
|
+
font = opts.fetch(:font, config[:font])
|
197
|
+
|
198
|
+
text_image = Vips::Image.text text, dpi: dpi, font: font
|
199
|
+
text_image = text_image.embed 0, 0, text_image.width, text_image.height, extend: :mirror
|
200
|
+
|
201
|
+
text_image.ifthenelse(text_color, bg_color, blend: true)
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
#
|
5
|
+
# 使用 一言·古诗词 API, 获取一条古诗词
|
6
|
+
#
|
7
|
+
# API返回结果:
|
8
|
+
# {
|
9
|
+
# content: "陌上风光浓处。第一寒梅先吐。",
|
10
|
+
# origin: "十样花·陌上风光浓处",
|
11
|
+
# author: "李弥逊",
|
12
|
+
# category: "古诗文-植物-梅花"
|
13
|
+
# }
|
14
|
+
#
|
15
|
+
module DailyImage
|
16
|
+
class Poem
|
17
|
+
|
18
|
+
API_URL = "https://api.gushi.ci/all.json"
|
19
|
+
|
20
|
+
def txt
|
21
|
+
get(API_URL)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def get(url, params={})
|
27
|
+
uri = URI(url)
|
28
|
+
uri.query = URI.encode_www_form(params)
|
29
|
+
|
30
|
+
res = Net::HTTP.get_response(uri)
|
31
|
+
format_res(res)
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_res(res)
|
35
|
+
return [false, {}] unless res.is_a?(Net::HTTPSuccess)
|
36
|
+
|
37
|
+
[true, JSON.parse(res.body)]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
data/lib/daily_image.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "date"
|
2
|
+
require "vips"
|
3
|
+
require "daily_image/version"
|
4
|
+
require "daily_image/poem"
|
5
|
+
require "daily_image/image"
|
6
|
+
require "daily_image/config"
|
7
|
+
|
8
|
+
module DailyImage
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def configure
|
12
|
+
config = DailyImage::Config.instance
|
13
|
+
yield config
|
14
|
+
end
|
15
|
+
|
16
|
+
def config
|
17
|
+
DailyImage::Config.instance.configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
def draw_image(output_path = nil)
|
21
|
+
output_path ||= Dir.pwd
|
22
|
+
output_file = File.join(output_path, "daily_#{Date.today}.jpeg")
|
23
|
+
|
24
|
+
image = DailyImage::Image.new.draw_image
|
25
|
+
|
26
|
+
image.write_to_file(output_file, Q: 100)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
Binary file
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: daily_image
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- renyijiu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-09-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
description: "A gem generate a daily image. Just For Fun \U0001F60A"
|
56
|
+
email:
|
57
|
+
- lanyuejin1108@gmail.com
|
58
|
+
executables:
|
59
|
+
- console
|
60
|
+
- daily_image
|
61
|
+
- setup
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".gitignore"
|
66
|
+
- ".travis.yml"
|
67
|
+
- CODE_OF_CONDUCT.md
|
68
|
+
- Gemfile
|
69
|
+
- Gemfile.lock
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/daily_image
|
74
|
+
- bin/setup
|
75
|
+
- daily_image.gemspec
|
76
|
+
- lib/daily_image.rb
|
77
|
+
- lib/daily_image/config.rb
|
78
|
+
- lib/daily_image/image.rb
|
79
|
+
- lib/daily_image/poem.rb
|
80
|
+
- lib/daily_image/version.rb
|
81
|
+
- tmp/daily_2018-09-14.jpg
|
82
|
+
- tmp/daily_2018-09-17.jpg
|
83
|
+
homepage: https://github.com/renyijiu/daily_image
|
84
|
+
licenses: []
|
85
|
+
metadata:
|
86
|
+
allowed_push_host: https://rubygems.org
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.7.6
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: "A gem generate a daily image. Just For Fun \U0001F60A"
|
107
|
+
test_files: []
|