imagetools 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6ef91388db420d9917f632bdc0331075867547d3
4
+ data.tar.gz: 67fffc417243fb5651127df7c4804456eadb7ac4
5
+ SHA512:
6
+ metadata.gz: 24f098120824f57ff94074537e8a7e2fd974d5e7755ad8d3c903dc0bdc4e373aee64c4734c719035fc49f43c1824519a9e2e253375e5e999794b0ac7bc6aff66
7
+ data.tar.gz: 07755c99ae95407267fe811a8bf25dbb27c1774bd31714bb9708fa882a2c7a17cbd86ad67b33dd3b022996dff73827d3790a55b616c272cf7d08a82ddab6ade8
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /out/
10
+ /vendor/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
@@ -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 src@srcw.net. 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
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in imagetools.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ imagetools (0.1.0)
5
+ rmagick
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ minitest (5.11.3)
11
+ rake (10.5.0)
12
+ rmagick (2.16.0)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ bundler (~> 1.16)
19
+ imagetools!
20
+ minitest (~> 5.0)
21
+ rake (~> 10.0)
22
+
23
+ BUNDLED WITH
24
+ 1.16.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 src
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Imagetools
2
+
3
+ Image tools.
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ gem imagetools
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### imageconcat
14
+
15
+ ### imagefilter
16
+
17
+ ### iconcreator
18
+
19
+ ```
20
+ iconcreator -i <ORIGINAL_ICON_FILE> -o <OUTPUT_DIR>
21
+ ```
22
+
23
+
24
+
25
+ ## Usage
26
+
27
+ TODO: Write usage instructions here
28
+
29
+
30
+ ## License
31
+
32
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
33
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "imagetools"
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/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/build.sh ADDED
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+ # rmagick for sierra
3
+ export PKG_CONFIG_PATH=/usr/local/opt/imagemagick@6/lib/pkgconfig
4
+ #export PATH=/usr/local/Cellar/imagemagick@6/6.9.7-5/bin:$PATH
5
+
6
+ bundle_dir=./vendor/bundle
7
+ if [ -d "$bundle_dir" ] ; then
8
+ /bin/rm -rf "$bundle_dir"
9
+ bundle update
10
+ else
11
+ /bin/rm -rf "$bundle_dir"
12
+ bundle install --path "$bundle_dir"
13
+ fi
14
+
15
+
16
+
17
+
18
+
data/exe/iconcreator ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'imagetools/iconcreator'
4
+
5
+ Imagetools::Iconcreator.run(ARGV)
data/exe/imageconcat ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'imagetools/imageconcat'
4
+
5
+ Imagetools::Imageconcat.run(ARGV)
data/exe/imagefilter ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'imagetools/imagefilter'
4
+
5
+ Imagetools::Imagefilter.run(ARGV)
data/exe/imagetools ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "imagetools"
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+
3
+ export ANYENV_ROOT="$HOME/.anyenv"
4
+ if [ -d "$ANYENV_ROOT" ]; then
5
+ export PATH="$HOME/.anyenv/bin:/usr/local/bin:$PATH"
6
+ eval "$(anyenv init -)"
7
+ fi
8
+
9
+ #export PATH="$HOME/.rbenv/bin:$PATH:/opt/local/bin"
10
+ #if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi
11
+
12
+ cd `dirname $0`
13
+ #rbenv versions
14
+ #mogrify
15
+ bundle exec ruby exe/imagefilter "$@"
16
+
17
+
@@ -0,0 +1,36 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "imagetools/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "imagetools"
8
+ spec.version = Imagetools::VERSION
9
+ spec.authors = ["src"]
10
+ spec.email = ["src@srcw.net"]
11
+
12
+ spec.summary = %q{Image Tools.}
13
+ spec.description = %q{Image Tools.}
14
+ spec.homepage = ""
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ # end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ f.match(%r{^(test|spec|features)/})
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+ spec.add_dependency "rmagick"
33
+ spec.add_development_dependency "bundler", "~> 1.16"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "minitest", "~> 5.0"
36
+ end
@@ -0,0 +1,139 @@
1
+ # coding: utf-8
2
+ require "optparse"
3
+ require "fileutils"
4
+
5
+ module Imagetools
6
+ class Iconcreator
7
+
8
+ ICON_INFOS = [
9
+ ##### iPhone icons #####
10
+ ["20x20", "iphone", "2x"], # iPhone Notification iOS 7-11
11
+ ["20x20", "iphone", "3x"], #
12
+ ["29x29", "iphone", "2x"], # iPhone Spotlight iOS 5,6/Settings iOS 5-11
13
+ ["29x29", "iphone", "3x"], #
14
+ ["40x40", "iphone", "2x"], # iPhone Spotlight iOS 7-11
15
+ ["40x40", "iphone", "3x"], #
16
+ ["60x60", "iphone", "2x"], # iPhone App iOS 7-11
17
+ ["60x60", "iphone", "3x"], #
18
+ ##### iPad icons #####
19
+ ["20x20", "ipad", "1x"], # iPad Notification iOS 7-11
20
+ ["20x20", "ipad", "2x"], #
21
+ ["29x29", "ipad", "1x"], # iPad Settings iOS 6-11
22
+ ["29x29", "ipad", "2x"], #
23
+ ["40x40", "ipad", "1x"], # iPad Spotlight iOS 7-11
24
+ ["40x40", "ipad", "2x"], #
25
+ ["76x76", "ipad", "1x"], # iPad App iOS 7-11
26
+ ["76x76", "ipad", "2x"], #
27
+ ["83.5x83.5", "ipad", "2x"], # iPad Pro App iOS 9-11
28
+ ##### App Store #####
29
+ ["1024x1024", "ios-marketing", "1x"] # App Store iOS
30
+ ]
31
+
32
+ def self.run(argv)
33
+ opts = {}
34
+ opt = OptionParser.new(argv)
35
+ opt.banner = "Usage: #{opt.program_name} [-h|--help] <args>"
36
+ opt.version = VERSION
37
+ opt.separator('')
38
+ opt.separator("Options:")
39
+ opt.on_head('-h', '--help', 'Show this message') do |v|
40
+ puts opt.help
41
+ exit
42
+ end
43
+ opt.on('-v', '--verbose', 'Verbose message') {|v| opts[:v] = v}
44
+ opt.on('-i INPUTFILE', '--input=INPUTFILE', 'Original icon file') {|v| opts[:i] = v}
45
+ opt.on('-o OUTDIR', '--output=OUTDIR', 'Output dir') {|v| opts[:o] = v}
46
+ opt.parse!(argv)
47
+ opts[:i] ||= 'icon.png'
48
+ if !FileTest.file?(opts[:i])
49
+ puts opt.help
50
+ exit
51
+ end
52
+ opts[:o] ||= "./out"
53
+ command = Command.new(opts)
54
+ command.run
55
+ end
56
+
57
+ def self.realsize(point, scale)
58
+ unless point=~ /^([0-9.]+)x/
59
+ raise "invalid point #{point}"
60
+ end
61
+ point_value = $1.to_f
62
+ unless scale =~ /^(\d+)x/
63
+ raise "invalid scale #{point}"
64
+ end
65
+ scale_value = $1.to_i
66
+ (point_value * scale_value).to_i
67
+ end
68
+
69
+ def self.filename(point, scale)
70
+ "Icon-#{point}@#{scale}.png"
71
+ end
72
+
73
+ def initialize(opts)
74
+ @opts = opts
75
+ end
76
+
77
+ def run
78
+ puts "Create ios app icons"
79
+
80
+ outdir = @opts[:o]
81
+ inputfile = @opts[:i]
82
+ unless FileTest.directory?(outdir)
83
+ FileUtils.mkdir(outdir)
84
+ end
85
+
86
+ appicondir = outdir + '/AppIcon.appiconset'
87
+ if FileTest.directory?(appicondir)
88
+ FileUtils.rm_rf(appicondir)
89
+ FileUtils.mkdir(appicondir)
90
+ else
91
+ FileUtils.mkdir(appicondir)
92
+ end
93
+
94
+ filenames = []
95
+ ICON_INFOS.each_with_index do |icon_info, index|
96
+ point, idiom, scale = icon_info
97
+ # puts "point=#{point} idiom=#{idiom} scale=#{scale}"
98
+
99
+ realsize = self.class.realsize(point, scale)
100
+ filename = self.class.filename(point, scale)
101
+ filenames[index] = filename
102
+ path = appicondir + "/" + filename
103
+ cmd = "sips -Z #{realsize} #{inputfile} --out #{path} > /dev/null 2>&1"
104
+ puts cmd
105
+ system(cmd)
106
+ end
107
+
108
+ str = ""
109
+ str << "{\n"
110
+ str << " \"images\" : [\n"
111
+ ICON_INFOS.each_with_index do |icon_info, index|
112
+ point, idiom, scale = icon_info
113
+ filename = filenames[index]
114
+ str << " {\n"
115
+ str << " \"size\": \"#{point}\",\n"
116
+ str << " \"idiom\": \"#{idiom}\",\n"
117
+ str << " \"filename\": \"#{filename}\",\n"
118
+ str << " \"scale\": \"#{scale}\"\n"
119
+ if index < ICON_INFOS.size - 1
120
+ str << " },\n"
121
+ else
122
+ str << " }\n"
123
+ end
124
+ end
125
+ str << " ],\n"
126
+ str << " \"info\" : {\n"
127
+ str << " \"version\" : 1,\n"
128
+ str << " \"author\" : \"xcode\"\n"
129
+ str << " }\n"
130
+ str << "}\n"
131
+
132
+ contents_json = appicondir + '/Contents.json'
133
+ puts "Create #{contents_json}"
134
+ open(contents_json, 'w') do |f|
135
+ f.print(str)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,118 @@
1
+ # coding: utf-8
2
+ require 'rmagick'
3
+ require 'optparse'
4
+
5
+ module Imagetools
6
+ class Imageconcat
7
+
8
+ VERSION = "1.0"
9
+
10
+ def self.run(argv)
11
+ STDOUT.sync = true
12
+ opts = {}
13
+ opt = OptionParser.new(argv)
14
+ opt.version = VERSION
15
+ opt.banner = "Usage: #{opt.program_name} [-h|--help] <dir> or <image1 image2 image3 ...>"
16
+ opt.separator('')
17
+ opt.separator("Examples:")
18
+ opt.separator(" #{opt.program_name} ~/tmp # concat two recent IMG_*jpg images.")
19
+ opt.separator(" #{opt.program_name} image1.jpg image2.jpg image3.jpg # concat specified images.")
20
+ opt.separator('')
21
+ opt.separator("Options:")
22
+ opt.on_head('-h', '--help', 'Show this message') do |v|
23
+ puts opt.help
24
+ exit
25
+ end
26
+ opt.on('-v', '--verbose', 'Verbose message') {|v| opts[:v] = v}
27
+ opt.on('--dry-run', 'Message only') {|v| opts[:dry_run] = v}
28
+ opt.on('-o OUTNAME', '--output=OUTNAME', 'Output file') {|v| opts[:o] = v}
29
+ opt.on('-n NUM', '--number=NUM', 'Cancat image Number') {|v| opts[:n] = v.to_i}
30
+ opt.parse!(argv)
31
+ image_files = get_image_files(opts, argv)
32
+ if image_files.size < 2
33
+ puts opt.help
34
+ exit
35
+ end
36
+ command = Command.new(opts)
37
+ command.run(image_files)
38
+ end
39
+
40
+ def self.get_image_files(opts, argv)
41
+ image_files = []
42
+ # ディレクトリが処理対象かどうかを決める
43
+ dir = nil
44
+ if argv.size == 1
45
+ # 引き数が1個の場合は最初の引き数
46
+ path = File.expand_path(argv[0])
47
+ if FileTest.directory?(path)
48
+ dir = path
49
+ end
50
+ elsif argv.size == 0
51
+ # 引き数がない場合カレントディレクトリ
52
+ dir = File.expand_path('.')
53
+ end
54
+ if dir
55
+ concat_number = opts[:n] || 2
56
+ # ディレクトリが指定されていた場合、指定ディレクトリ内のIMG_ファイルの最新n個を対象とする
57
+ # 最新の基準は(ファイル名基準)
58
+ match_files = Dir.glob("#{dir}/IMG_*.{jpg,jpeg,png}", File::FNM_CASEFOLD).sort
59
+ # 後ろからn個を取得(小さい方の数とする)
60
+ count = [match_files.size, concat_number].min
61
+ image_files = match_files[-count..-1]
62
+ else
63
+ # それ以外は指定された引き数を全て対象とする
64
+ argv.each do |arg|
65
+ arg = File.expand_path(arg)
66
+ if FileTest.file?(arg) && (arg =~ /\.jpe?g$/i || arg =~ /\.png/i)
67
+ image_files << arg
68
+ end
69
+ end
70
+ end
71
+ image_files
72
+ end
73
+
74
+ def initialize(opts)
75
+ @opts = opts
76
+ end
77
+
78
+ def run(image_files)
79
+ dirname = File.dirname(image_files[-1])
80
+ output_name = "photo.jpg"
81
+ if @opts[:o]
82
+ output_name = @opts[:o]
83
+ end
84
+ output_path = File.join(dirname, output_name)
85
+ concat_images(image_files, output_path)
86
+ end
87
+
88
+ private
89
+ def concat_images(image_files, output_file)
90
+ puts image_files.join("+") + "=#{output_file}"
91
+
92
+ result_image_list = Magick::ImageList.new
93
+ image_files.each do |image_file|
94
+ #background_colorとflatten_imagesを組み合わせて背景色を指定
95
+ image_list = Magick::ImageList.new(image_file) {self.background_color = 'white'}
96
+ image = image_list.flatten_images
97
+ result_image_list << image
98
+ end
99
+
100
+ result = result_image_list.append(false)
101
+
102
+ width = result.columns
103
+ height = result.rows
104
+
105
+ padding = 10
106
+ if height > 1000
107
+ padding = 20
108
+ end
109
+
110
+ image_width = width / image_files.size
111
+ result = result.splice(image_width, 0, padding, 0) # 画像を10字に切る
112
+ if image_files.size > 2
113
+ result = result.splice(image_width * 2 + padding, 0, padding, 0) # 画像を10字に切るメソッドみたい
114
+ end
115
+ result.write output_file
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,174 @@
1
+ # coding: utf-8
2
+
3
+ require 'fileutils'
4
+ require 'optparse'
5
+
6
+ module Imagetools
7
+ class Imagefilter
8
+
9
+ SCREENSHOT_SEARCH = /s (\d+)-(\d+)-(\d+) (\d+)\.(\d+)\.(\d+).jpg/
10
+ SCREENSHOT_REPLACE = 's_\1\2\3_\4\5\6.jpg'
11
+ RESIZE_CMD = "mogrify -resize 1280x\\> "
12
+ COMPRESS_CMD = "jpegoptim --strip-all --max=90 "
13
+ EXTERNAL_CMDS = [RESIZE_CMD, COMPRESS_CMD]
14
+
15
+ PNG_SEARCH = /(.+)\.png/i
16
+ PNG_REPLACE = '\1.jpg'
17
+ JPG_SEARCH = /(.+)\.jpe?g/i
18
+ EXCLUDE_PAT = /^_/ # 先頭が"_"の場合は除外
19
+
20
+ def self.run(argv)
21
+ STDOUT.sync = true
22
+ opts = {}
23
+ opt = OptionParser.new(argv)
24
+ opt.banner = "Usage: #{opt.program_name} [-h|--help] <args>"
25
+ opt.version = VERSION
26
+ opt.separator('')
27
+ opt.separator('Parameters:')
28
+ param =<<EOM
29
+ RESIZE_CMD: #{RESIZE_CMD}
30
+ COMPRESS_CMD: #{COMPRESS_CMD}
31
+ EOM
32
+ opt.separator(param)
33
+ opt.separator('')
34
+ opt.separator("Options:")
35
+ opt.on_head('-h', '--help', 'Show this message') do |v|
36
+ puts opt.help
37
+ exit
38
+ end
39
+ # # 冗長メッセージ
40
+ opt.on('-v', '--verbose', 'Verbose message') {|v| opts[:v] = v}
41
+ opt.on('-n', '--dry-run', 'Message only') {|v| opts[:n] = v}
42
+ opt.on('-t', '--self-test', 'Run Self Test') {|v| opts[:t] = v}
43
+ opt.parse!(argv)
44
+ if opts[:t]
45
+ ret = selftest
46
+ exit(ret)
47
+ end
48
+ filepaths = self.filter_files(argv)
49
+ if filepaths.empty?
50
+ puts opt.help
51
+ exit
52
+ end
53
+ filepaths.each do |filepath|
54
+ command = Command.new(opts)
55
+ command.run(filepath)
56
+ end
57
+ end
58
+
59
+ def self.filter_files(argv)
60
+ filepaths = []
61
+ argv.each do |arg|
62
+ if FileTest.file?(arg)
63
+ path = File.expand_path(arg)
64
+ filepaths << path
65
+ end
66
+ end
67
+ filepaths
68
+ end
69
+
70
+ def self.replace_screenshot_filename(filename)
71
+ filename.sub!(SCREENSHOT_SEARCH, SCREENSHOT_REPLACE)
72
+ end
73
+
74
+ def self.replace_png2jpg(filename)
75
+ filename.sub!(PNG_SEARCH, PNG_REPLACE)
76
+ end
77
+
78
+ def self.match_exclude_image?(filename)
79
+ filename =~ EXCLUDE_PAT
80
+ end
81
+
82
+ def self.selftest
83
+ EXTERNAL_CMDS.each do |cmd|
84
+ args = cmd.split
85
+ cmd_name = args[0]
86
+ unless cmd_exists?(cmd)
87
+ puts "No command: #{cmd_name}"
88
+ return 127
89
+ end
90
+ end
91
+ return 0
92
+ end
93
+
94
+ def self.cmd_exists?(cmd)
95
+ # whichはコマンドが存在する場合のみ標準出力にパスを出力する
96
+ `which #{cmd}` != ""
97
+ end
98
+
99
+ def initialize(opts)
100
+ @opts = opts
101
+ end
102
+
103
+ def run(filepath)
104
+ if exclude_image?(filepath)
105
+ return
106
+ end
107
+ filepath = rename_screenshot(filepath)
108
+ filepath = png2jpg(filepath)
109
+ filepath = resize_jpg(filepath)
110
+ filepath = compress_jpg(filepath)
111
+ filepath
112
+ end
113
+
114
+ private
115
+ def exclude_image?(filepath)
116
+ fromname = File.basename(filepath)
117
+ if self.class.match_exclude_image?(fromname)
118
+ puts "exclude #{filepath}"
119
+ return true
120
+ end
121
+ false
122
+ end
123
+
124
+ def rename_screenshot(filepath)
125
+ fromname = File.basename(filepath)
126
+ toname = self.class.replace_screenshot_filename(fromname)
127
+ return filepath if toname.nil?
128
+
129
+ dir = File.dirname(filepath)
130
+ topath = File.join(dir, toname)
131
+ puts "rename: #{filepath} => #{topath}"
132
+ FileUtils.mv(filepath, topath) unless @opts[:n]
133
+ return topath
134
+ end
135
+
136
+ def png2jpg(filepath)
137
+ fromname = File.basename(filepath)
138
+ toname = self.class.replace_png2jpg(fromname)
139
+ return filepath if toname.nil?
140
+
141
+ dir = File.dirname(filepath)
142
+ topath = File.join(dir, toname)
143
+ puts "convert: #{filepath} => #{topath}"
144
+ # convert test.png -background "#ffff00" -flatten test.jpg
145
+ cmd = "convert \"#{filepath}\" -background \"#ffffff\" -flatten \"#{topath}\""
146
+ if system(cmd)
147
+ FileUtils.rm(filepath)
148
+ end
149
+ return topath
150
+ end
151
+
152
+ def resize_jpg(filepath)
153
+ fromname = File.basename(filepath)
154
+ unless fromname =~ JPG_SEARCH
155
+ return filepath
156
+ end
157
+ puts "resize: #{filepath}"
158
+ cmd = "#{RESIZE_CMD} \"#{filepath}\""
159
+ system(cmd)
160
+ return filepath
161
+ end
162
+
163
+ def compress_jpg(filepath)
164
+ fromname = File.basename(filepath)
165
+ unless fromname =~ JPG_SEARCH
166
+ return filepath
167
+ end
168
+ puts "compress: #{filepath}"
169
+ cmd = "#{COMPRESS_CMD} \"#{filepath}\""
170
+ system(cmd)
171
+ return filepath
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,3 @@
1
+ module Imagetools
2
+ VERSION = "0.1.0"
3
+ end
data/lib/imagetools.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "imagetools/version"
2
+ require "imagetools/imageconcat"
3
+ require "imagetools/imagefilter"
4
+ require "imagetools/iconcreator"
5
+
6
+ module Imagetools
7
+ # Your code goes here...
8
+ end
data/test.sh ADDED
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ #bundle exec rake test TEST=test/models/entry_test.rb TESTOPTS="--name=test_sample_2"
3
+ bundle exec rake test
4
+
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ bundle exec ruby exe/iconcreator "$@"
3
+
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ bundle exec ruby exe/imageconcat "$@"
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ bundle exec ruby exe/imagefilter "$@"
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: imagetools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - src
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rmagick
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.16'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.16'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: Image Tools.
70
+ email:
71
+ - src@srcw.net
72
+ executables:
73
+ - iconcreator
74
+ - imageconcat
75
+ - imagefilter
76
+ - imagetools
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - ".gitignore"
81
+ - ".travis.yml"
82
+ - CODE_OF_CONDUCT.md
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - bin/console
89
+ - bin/setup
90
+ - build.sh
91
+ - exe/iconcreator
92
+ - exe/imageconcat
93
+ - exe/imagefilter
94
+ - exe/imagetools
95
+ - hazel_imagefilter_template.sh
96
+ - imagetools.gemspec
97
+ - lib/imagetools.rb
98
+ - lib/imagetools/iconcreator.rb
99
+ - lib/imagetools/imageconcat.rb
100
+ - lib/imagetools/imagefilter.rb
101
+ - lib/imagetools/version.rb
102
+ - test.sh
103
+ - test_iconcreator.sh
104
+ - test_imageconcat.sh
105
+ - test_imagefilter.sh
106
+ homepage: ''
107
+ licenses:
108
+ - MIT
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.6.13
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Image Tools.
130
+ test_files: []