用Ruby+ImageMagick整合多张图片

嗯,其实这个的起因是新浪微博只能贴一张图片。然后又有很多人整合了贴上去,所以我也想试试:P

直接用RMagick应该是可以直接做的,但是考虑到RMagick的方法太过复杂,所以使用了这么个组合方式。其实RMagick就是ImageMagick的ruby实现罢了。

言归正传:非常简单的代码,不过俺还是写了好久,Ruby的方法还是不熟悉呃,每次写都需要看RubyDoc。。。

使用方法:把脚本扔到一堆图片(支持jpg,png,gif)的文件夹里面,双击运行,搞定;或者在脚本后面加需要处理的图片的路径。最后会生成一个result.jpg文件。

TODO:

  • 考虑是否需要按图片尺寸来从小到大排列;如果图片太大就转换所有图片到差不多尺寸,然后从小到大排列……
  • 用RMagick重写该脚本
  • 既然是TO-DO,就看以后有心情弄不了
require 'pathname'
dir=nil
file_str=""

def usage
  puts "Usage: #{__FILE__} [path_with_image_files]"
  puts "Example 1: #{__FILE__}"
  puts "Example 2: #{__FILE__} D:\\funimg"
end

if ARGV.length ==0
  dir= Pathname.new(File.dirname(__FILE__)).realpath
  Dir.chdir(dir)
elsif ARGV.length ==1
  dir=ARGV.first
  begin
    Dir.chdir dir
  rescue Errno::ENOENT
    puts "Cannot find the directory you specified!"
    usage
    exit 1
  end
else
  usage
  exit 1
end

Dir.glob("*.{jpeg,jpg,png,gif}") do |fn|
  basename=fn.split('.')[0]
  extname= File.extname(fn)
  if extname != 'png'
    `convert #{fn} -quality 100 #{basename}.png`
    File.delete(fn)
  end
  file_str << "#{basename}.png "
end

#start to append all images
`convert #{file_str} -gravity Center -quality 80 -append result.jpg`

Update: 其实用ImageMagick的montage命令更好用:

`montage #{file_str} -auto-orient -bordercolor Lavender -background black +polaroid -tile 1x -gravity center -background SkyBlue  -geometry "1x1<" #{result_img}`

或者

`montage #{file_str} -tile 1x -geometry "1x1<" #{result_img}`

都不错。可以自己试试效果。第一个是相册风格的,第二个是直接拼接的。

Advertisements

用Ruby替换魔兽世界toc文件版本号

玩魔兽世界的同学都知道,当WoW升级后,插件也需要升级。但是有些插件其实没有影响,只是需要把toc文件里面的版本号改成新的就好。这几天刚好国服从3.2.2升级到了3.3.5,这样toc里面的版本号就需要从30200改成30300 (虽然有些改了也用不了)

然后我就想到用ruby实现这个应该不难,早上起来就开始写了。其实很简单,只是自己对ruby的应用还不纯熟。。。现在终于完工了

代码如下:

# toc_ver.rb
# change version number of toc to what you wanted
if ARGV.length != 2 || ARGV.last !~ /[0-9]{5}/ || !File.directory?(ARGV.first)
 puts "Error: two arguments should be used. If your path contains spaces, using quotes" if ARGV.length !=2
 puts "Error: specified directory not found" if File.directory?(ARGV.first)
 puts "Error: version number should be 5 digits" if ARGV.last !~ /[0-9]{5}/
 puts usage=<<USAGE
Usage: toc_ver.rb path_of_Addons version_number
Example: toc_ver.rb "E:\\World of Warcaft\\Interface\\Addons" 30300
USAGE
exit
end

Dir.chdir(ARGV.first)
tocfiles= File.join("**","*.toc")
Dir.glob(tocfiles) do |filename|
#save the file lines in an array; substitution; overwrite the original file
file_array=File.readlines(filename).each {|line| line.gsub!(/## Interface: [0-9]{5}/, "## Interface: #{ARGV.last}") }
 File.open(filename,'w') do |file|
 file_array.each {|line| file.puts(line)}
 end
end

把上面代码保存为toc_ver.rb使用方法: toc_ver.rb [Addons的路径] [要修改的版本号]。
如 toc_ver.rb “E:\World of Warcaft\Interface\Addons” 30300
注意,如果路径有空格的话需要加引号。

浪费的时间主要是想:打开一个文件,然后读入每行。找到要修改的行,替换。
这种想法是不行的,不能对一个文件同时读+修改。所以我还是先把每行读到一股数组,修改完之后再把数组写入。可以参见Stackedoverflow的讨论。那个正确答案是错的,File.read返回的是File对象而不是String