imagetools 1.3.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b165e7e85d7d0854577ab7a1f452ff4b3df9d87ea82890dcdda5f0550f969046
4
- data.tar.gz: e38ddf3c06d47997399fada92f2130460cfadb5558bb0f460b555e07684cb3cb
3
+ metadata.gz: f1abcb0bf228739f0993edc336151eec2bdbdbc2bfc8a46d6c1b5ce47e5d5836
4
+ data.tar.gz: c03694b434386645be24daeb97ee5b12ae03588401afc1b3d207ddd44e9dd3ba
5
5
  SHA512:
6
- metadata.gz: f16f40fdcb563715da0064a6c5a2ef9bd61ff2469f70d7e25760156b081ef950b8c5ea3608bcf773e96ba59b91314216ff7b995bfd94b6c784b10d3a2d61c9a0
7
- data.tar.gz: bea91193b72e52fda2954c19939dbf92ae479bec2a3029c6d4156f2d19714b01e343301ce8f205a1c27d9ece7a95b538f700379dc37cedc48c9b353fba1fda26
6
+ metadata.gz: 15ac47a208ab77856ea2382ea5792ff67f02382f7402a111c439ea6b36290d5bcba24e77e51c5fd03eac7f42aa0ccab2da499054f10ba9fed2fe10892e8a5604
7
+ data.tar.gz: 6aae7f1b2acdf083467c39db9fd69f35e44326853cac81670077fd235246f75b06ae49637fcd50cf3013eacb53e751a750cd5a1e222fa754a842620a734a21cf
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.5
1
+ 3.0.2
data/Gemfile.lock CHANGED
@@ -1,15 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- imagetools (1.3.1)
5
- rmagick (= 3.2.0)
4
+ imagetools (1.5.1)
5
+ rmagick
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- minitest (5.14.4)
10
+ minitest (5.15.0)
11
11
  rake (13.0.6)
12
- rmagick (3.2.0)
12
+ rmagick (4.2.4)
13
13
 
14
14
  PLATFORMS
15
15
  ruby
@@ -21,4 +21,4 @@ DEPENDENCIES
21
21
  rake (~> 13.0)
22
22
 
23
23
  BUNDLED WITH
24
- 2.1.4
24
+ 2.3.8
data/exe/imageblog ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'imagetools/imageblog'
4
+
5
+ Imagetools::Imageblog.run(ARGV)
data/imagetools.gemspec CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.bindir = "exe"
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
- spec.add_dependency "rmagick", "3.2.0"
32
+ spec.add_dependency "rmagick"
33
33
  spec.add_development_dependency "bundler", "~> 2.0"
34
34
  spec.add_development_dependency "rake", "~> 13.0"
35
35
  spec.add_development_dependency "minitest", "~> 5.0"
@@ -0,0 +1,148 @@
1
+ # coding: utf-8
2
+ # imagehugo: hugo用の画像処理。リネームとサムネイル&アイキャッチ画像の生成。
3
+
4
+ require 'imagetools/version'
5
+ require 'imagetools/imagefilter'
6
+ require 'rmagick'
7
+ require 'optparse'
8
+ require 'fileutils'
9
+
10
+ module Imagetools
11
+ class ImageItem
12
+ attr_accessor :srcfile, :dstfile, :outfile
13
+ def to_s
14
+ "#{srcfile}=>#{dstfile}=>#{outfile}"
15
+ end
16
+ end
17
+
18
+ class Imageblog
19
+ def self.run(argv)
20
+ STDOUT.sync = true
21
+ opts = {}
22
+ opt = OptionParser.new(argv)
23
+ opt.version = VERSION
24
+ opt.banner = "Usage: #{opt.program_name} [-h|--help] <dir> or <image1 image2 image3 ...>"
25
+ opt.separator('')
26
+ opt.separator("Examples:")
27
+ opt.separator(" #{opt.program_name} ~/tmp # concat two recent IMG_*jpg images.")
28
+ opt.separator(" #{opt.program_name} image1.jpg image2.jpg image3.jpg # concat specified images.")
29
+ opt.separator('')
30
+ opt.separator("Options:")
31
+ opt.on_head('-h', '--help', 'Show this message') do |v|
32
+ puts opt.help
33
+ exit
34
+ end
35
+ opt.on('-v', '--verbose', 'Verbose message') {|v| opts[:v] = v}
36
+ opt.on('--dry-run', 'Message only') {|v| opts[:dry_run] = v}
37
+ opt.on('-o OUTDIR', '--output=OUTDIR', 'Output dir') {|v| opts[:o] = v}
38
+ opt.on('-n NUM', '--number=NUM', 'Process image number') {|v| opts[:n] = v.to_i}
39
+ opt.on('-b BASENAME', '--base=BASENAME', 'Output file basename') {|v| opts[:b] = v}
40
+ opt.parse!(argv)
41
+ opts[:b] ||= Time.now.strftime("%Y%m%d")
42
+ dir, image_files = get_image_files(opts, argv)
43
+ if image_files.size == 0
44
+ puts opt.help
45
+ exit
46
+ end
47
+ command = Imageblog.new(opts)
48
+ command.run(dir, image_files)
49
+ end
50
+
51
+ def self.get_image_files(opts, argv)
52
+ image_files = []
53
+ # ディレクトリが処理対象かどうかを決める
54
+ dir = nil
55
+ if argv.size == 1
56
+ # 引き数が1個の場合は最初の引き数
57
+ path = File.expand_path(argv[0])
58
+ if FileTest.directory?(path)
59
+ dir = path
60
+ end
61
+ elsif argv.size == 0
62
+ # 引き数がない場合カレントディレクトリ
63
+ dir = File.expand_path('.')
64
+ end
65
+ if dir
66
+ concat_number = opts[:n] || 2
67
+ # ディレクトリが指定されていた場合、指定ディレクトリ内のIMG_ファイルの最新n個を対象とする
68
+ # 最新の基準は(ファイル名基準)
69
+ match_files = Dir.glob("#{dir}/*.{jpg,jpeg,png}", File::FNM_CASEFOLD).sort
70
+ # match_files.sort {|a, b|
71
+ # File.mtime(a) <=> File.mtime(b)
72
+ # }
73
+ # 後ろからn個を取得(小さい方の数とする)
74
+ count = [match_files.size, concat_number].min
75
+ image_files = match_files[-count..-1]
76
+ else
77
+ # それ以外は指定された引き数を全て対象とする
78
+ argv.each do |arg|
79
+ arg = File.expand_path(arg)
80
+ dir = File.dirname(arg)
81
+ if FileTest.file?(arg) && (arg =~ /\.jpe?g$/i || arg =~ /\.png/i)
82
+ image_files << arg
83
+ end
84
+ end
85
+ end
86
+ return dir, image_files
87
+ end
88
+
89
+ def initialize(opts)
90
+ @opts = opts
91
+ end
92
+
93
+
94
+ def run(dir, image_files)
95
+ outdir = dir
96
+ if @opts[:o]
97
+ outdir = @opts[:o]
98
+ end
99
+ rename_images(image_files, outdir)
100
+ # concat_images(image_files, output_path)
101
+ end
102
+
103
+ private
104
+ def rename_images(image_files, outdir)
105
+ # サムネイルはhoge_0.jpg
106
+ # アイキャッチはhoge_1.jpg hoge_2.jpg以降が通常の画像
107
+ items = []
108
+ thumbnal_item = nil # hoge_0.jpgとする
109
+ image_files.each_with_index do |image_file, index|
110
+ item = ImageItem.new
111
+ item.srcfile = image_file
112
+
113
+ src_basename = File.basename(image_file)
114
+ extname = File.extname(src_basename)
115
+ dst_basename = @opts[:b]
116
+
117
+ item.dstfile = File.join(outdir, "#{dst_basename}_#{index + 1}#{extname}")
118
+ if index == 0
119
+ thumbnal_item = ImageItem.new
120
+ thumbnal_item.srcfile = image_file
121
+ thumbnal_item.dstfile = File.join(outdir, "#{dst_basename}_0#{extname}")
122
+ end
123
+ items << item
124
+ end
125
+ items.each do |item|
126
+ FileUtils.cp(item.srcfile, item.dstfile)
127
+ end
128
+ FileUtils.cp(thumbnal_item.srcfile, thumbnal_item.dstfile)
129
+
130
+ #フィルタ実行
131
+ config = Config.new
132
+ config.init_default
133
+ opts = {}
134
+ filter = Imagefilter.new(opts, config)
135
+ items.each do |item|
136
+ item.outfile = filter.run(item.dstfile)
137
+ end
138
+
139
+
140
+ # サムネイル
141
+ config.resize_width = 400
142
+ filter = Imagefilter.new(opts, config)
143
+ thumbnal_item.outfile = filter.run(thumbnal_item.dstfile)
144
+
145
+ end
146
+ end
147
+ end
148
+
@@ -26,7 +26,7 @@ module Imagetools
26
26
  opt.on('-v', '--verbose', 'Verbose message') {|v| opts[:v] = v}
27
27
  opt.on('--dry-run', 'Message only') {|v| opts[:dry_run] = v}
28
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}
29
+ opt.on('-n NUM', '--number=NUM', 'Concat image number') {|v| opts[:n] = v.to_i}
30
30
  opt.parse!(argv)
31
31
  image_files = get_image_files(opts, argv)
32
32
  if image_files.size < 2
@@ -89,14 +89,20 @@ module Imagetools
89
89
  def concat_images(image_files, output_file)
90
90
  puts image_files.join("+") + "=#{output_file}"
91
91
 
92
+ # 結果の画像リスト
92
93
  result_image_list = Magick::ImageList.new
94
+
93
95
  image_files.each do |image_file|
94
- #background_colorとflatten_imagesを組み合わせて背景色を指定
96
+ # 個別画像の背景色を白に変換
97
+ # 一気に行く方法がないので、ImageListを作成しbackground_colorとflatten_imagesを組み合わる。
95
98
  image_list = Magick::ImageList.new(image_file) {self.background_color = 'white'}
96
99
  image = image_list.flatten_images
100
+
101
+ # 結果の画像リストに追加
97
102
  result_image_list << image
98
103
  end
99
-
104
+
105
+ #append(false)で横方向に結合
100
106
  result = result_image_list.append(false)
101
107
 
102
108
  width = result.columns
@@ -9,20 +9,45 @@ module Imagetools
9
9
  class Config
10
10
  FILENAME_SEARCH = 's (\d+)-(\d+)-(\d+) (\d+)\.(\d+)\.(\d+)'
11
11
  FILENAME_REPLACE = 's_\1\2\3_\4\5\6'
12
+ RESIZE_WIDTH = 1280
13
+
14
+ def self.create_from_yaml(yaml)
15
+ config = Config.new
16
+ config.filename_search1 = config_value(yaml, "filename", "search1", false)
17
+ config.filename_replace1 = config_value(yaml, "filename", "replace1", false)
18
+ config.filename_search2 = config_value(yaml, "filename", "search2", false)
19
+ config.filename_replace2 = config_value(yaml, "filename", "replace2", false)
20
+ config.filename_search3 = config_value(yaml, "filename", "search3", false)
21
+ config.filename_replace3 = config_value(yaml, "filename", "replace3", false)
22
+ config.resize_width = config_value(yaml, "resize", "width", false)
23
+ config.init_default
24
+ config
25
+ end
26
+
27
+
28
+ def self.config_value(yaml, section, key, require)
29
+ return nil unless yaml
30
+ return nil unless yaml[section]
31
+ value = yaml[section][key]
32
+ if require && (value.nil? || value.empty?)
33
+ raise RuntimeError, "#{section}:#{key}: is empty"
34
+ end
35
+ value
36
+ end
12
37
 
13
- def initialize(yaml)
14
- @yaml = yaml
15
- @filename_search1 = config_value("filename", "search1", false) || FILENAME_SEARCH
16
- @filename_replace1 = config_value("filename", "replace1", false) || FILENAME_REPLACE
17
- @filename_search2 = config_value("filename", "search2", false)
18
- @filename_replace2 = config_value("filename", "replace2", false)
19
- @filename_search3 = config_value("filename", "search3", false)
20
- @filename_replace3 = config_value("filename", "replace3", false)
38
+ def initialize
21
39
  end
22
40
 
23
- attr_reader :filename_search1, :filename_replace1,
24
- :filename_search2, :filename_replace2,
25
- :filename_search3, :filename_replace3
41
+ def init_default
42
+ @filename_search1 ||= FILENAME_SEARCH
43
+ @filename_replace1 ||= FILENAME_REPLACE
44
+ @resize_width ||= RESIZE_WIDTH
45
+ end
46
+
47
+ attr_accessor :filename_search1, :filename_replace1,
48
+ :filename_search2, :filename_replace2,
49
+ :filename_search3, :filename_replace3
50
+ attr_accessor :resize_width
26
51
 
27
52
  def filename_patterns
28
53
  [
@@ -31,16 +56,6 @@ module Imagetools
31
56
  [@filename_search3, @filename_replace3],
32
57
  ]
33
58
  end
34
-
35
- private
36
- def config_value(section, key, require)
37
- return nil unless @yaml
38
- value = @yaml[section][key]
39
- if require && (value.nil? || value.empty?)
40
- raise RuntimeError, "#{section}:#{key}: is empty"
41
- end
42
- value
43
- end
44
59
  end
45
60
 
46
61
  class Imagefilter
@@ -49,8 +64,7 @@ module Imagetools
49
64
 
50
65
  CONVERT_CMD = "convert"
51
66
  DWEBP_CMD = "dwebp"
52
- # RESIZE_CMD = "mogrify -resize 1280x\\> "
53
- RESIZE_CMD = "mogrify -background white -resize 1280x\\> "
67
+ RESIZE_CMD = "mogrify -background white -resize %dx\\> "
54
68
  ROTATE_CMD = "exiftran -ai "
55
69
  COMPRESS_CMD = "jpegoptim --strip-all --max=90 "
56
70
  EXTERNAL_CMDS = [RESIZE_CMD, ROTATE_CMD, COMPRESS_CMD]
@@ -61,6 +75,9 @@ module Imagetools
61
75
  PNG_SEARCH = /(.+)\.png/i
62
76
  PNG_REPLACE = '\1.jpg'
63
77
  JPG_SEARCH = /(.+)\.jpe?g/i
78
+ HEIC_SEARCH = /(.+)\.heic/i
79
+ HEIC_REPLACE = '\1.jpg'
80
+
64
81
  EXCLUDE_PAT = /^_/ # 先頭が"_"の場合は除外
65
82
 
66
83
  def self.run(argv)
@@ -96,7 +113,7 @@ EOM
96
113
  if FileTest.file?(config_file)
97
114
  yaml = YAML.load_file(config_file)
98
115
  end
99
- config = Config.new(yaml)
116
+ config = Config.create_from_yaml(yaml)
100
117
  if opts[:t]
101
118
  ret = selftest
102
119
  exit(ret)
@@ -142,6 +159,10 @@ EOM
142
159
  filename.sub(PNG_SEARCH, PNG_REPLACE)
143
160
  end
144
161
 
162
+ def self.replace_heic2jpg(filename)
163
+ filename.sub(HEIC_SEARCH, HEIC_REPLACE)
164
+ end
165
+
145
166
  def self.match_exclude_image?(filename)
146
167
  filename =~ EXCLUDE_PAT
147
168
  end
@@ -172,10 +193,10 @@ EOM
172
193
  if exclude_image?(filepath)
173
194
  return
174
195
  end
175
-
176
196
  filepath = rename_image(filepath)
177
197
  filepath = webp2png(filepath)
178
198
  filepath = png2jpg(filepath)
199
+ filepath = heic2jpg(filepath)
179
200
  filepath = resize_jpg(filepath)
180
201
  filepath = rotate_jpg(filepath)
181
202
  filepath = compress_jpg(filepath)
@@ -239,13 +260,31 @@ EOM
239
260
  return topath
240
261
  end
241
262
 
263
+ def heic2jpg(filepath)
264
+ fromname = File.basename(filepath)
265
+ toname = self.class.replace_heic2jpg(fromname)
266
+ # puts "heic2jpg #{fromname}=>#{toname}"
267
+ return filepath if fromname == toname
268
+
269
+ dir = File.dirname(filepath)
270
+ topath = File.join(dir, toname)
271
+ puts "convert: #{filepath} => #{topath}"
272
+ # convert ~/Desktop/test.heic -o ~/Desktop/test.jpg
273
+ cmd = "#{CONVERT_CMD} \"#{filepath}\" \"#{topath}\""
274
+ if system(cmd)
275
+ FileUtils.rm(filepath)
276
+ end
277
+ return topath
278
+ end
279
+
242
280
  def resize_jpg(filepath)
243
281
  fromname = File.basename(filepath)
244
282
  unless fromname =~ JPG_SEARCH
245
283
  return filepath
246
284
  end
247
285
  puts "resize: #{filepath}"
248
- cmd = "#{RESIZE_CMD} \"#{filepath}\""
286
+ resize_cmd = sprintf(RESIZE_CMD, @config.resize_width)
287
+ cmd = "#{resize_cmd} \"#{filepath}\""
249
288
  system(cmd)
250
289
  return filepath
251
290
  end
@@ -1,3 +1,3 @@
1
1
  module Imagetools
2
- VERSION = "1.3.1"
2
+ VERSION = "1.5.1"
3
3
  end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/test_imageblog.sh ADDED
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ bundle exec ruby exe/imageblog "$@"
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imagetools
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - src
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-10 00:00:00.000000000 Z
11
+ date: 2022-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rmagick
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 3.2.0
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 3.2.0
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +72,7 @@ email:
72
72
  executables:
73
73
  - iconcreator
74
74
  - iconextractor
75
+ - imageblog
75
76
  - imageburst
76
77
  - imageconcat
77
78
  - imagefilter
@@ -102,6 +103,7 @@ files:
102
103
  - build.sh
103
104
  - exe/iconcreator
104
105
  - exe/iconextractor
106
+ - exe/imageblog
105
107
  - exe/imageburst
106
108
  - exe/imageconcat
107
109
  - exe/imagefilter
@@ -113,6 +115,7 @@ files:
113
115
  - lib/imagetools.rb
114
116
  - lib/imagetools/iconcreator.rb
115
117
  - lib/imagetools/iconextractor.rb
118
+ - lib/imagetools/imageblog.rb
116
119
  - lib/imagetools/imageburst.rb
117
120
  - lib/imagetools/imageconcat.rb
118
121
  - lib/imagetools/imagefilter.rb
@@ -142,12 +145,19 @@ files:
142
145
  - sample/demo/demo/Base.lproj/Main.storyboard
143
146
  - sample/demo/demo/Info.plist
144
147
  - sample/demo/demo/ViewController.swift
148
+ - sample/hugo_dst/1200x400.png
149
+ - sample/hugo_dst/1200x800.png
150
+ - sample/hugo_dst/600x200.png
151
+ - sample/hugo_src/0000.png
152
+ - sample/hugo_src/0001.png
153
+ - sample/hugo_src/0002.png
145
154
  - sample/icon.png
146
155
  - sample/icon.sketch
147
156
  - sample_iconcreator.sh
148
157
  - test.sh
149
158
  - test_iconcreator.sh
150
159
  - test_iconextractor.sh
160
+ - test_imageblog.sh
151
161
  - test_imageburst.sh
152
162
  - test_imageconcat.sh
153
163
  - test_imagefilter.sh
@@ -156,7 +166,7 @@ homepage: ''
156
166
  licenses:
157
167
  - MIT
158
168
  metadata: {}
159
- post_install_message:
169
+ post_install_message:
160
170
  rdoc_options: []
161
171
  require_paths:
162
172
  - lib
@@ -171,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
181
  - !ruby/object:Gem::Version
172
182
  version: '0'
173
183
  requirements: []
174
- rubygems_version: 3.1.6
175
- signing_key:
184
+ rubygems_version: 3.2.22
185
+ signing_key:
176
186
  specification_version: 4
177
187
  summary: Image Tools.
178
188
  test_files: []