Python版图片合成脚本

Oct/13/2011 update script: remove urgly lambda, use os.path.splitext()

之前写过用Ruby+ImageMagick整合多张图片,因为现在转用python,所以又用python写了一个。

当然,这个脚本的前提也是需要安装ImageMagick,而且要把它的bin目录加到PATH里面。也就是说在命令行下面输入montage不会提示找不到程序。另外,你还要装Python环境。。。

这次写的Python版比较简单,没有写Usage,这里提一下:

把脚本文件搁到你要整合图片的目录,然后执行脚本。该目录所有图片就合成一个叫result.png的文件了。

运行时会提示用哪种方式连接。默认的是普通的拼接。那个photostyle是相册风格的,具体的自己试下就行了。

代码如下:

import os
imgTypes=('.jpg','jpeg','.png','.gif')
#isImg= lambda x: x.find('.') >0 and x.split('.')[1] in imgTypes
#imgFiles=[f for f in os.listdir(os.getcwd()) if isImg(f) and f.find('result') < 0]
imgFiles=[f for f in os.listdir(os.getcwd()) if os.path.splitext(f)[1].lower() in imgTypes and f.find('result') < 0]
imgStrings=reduce(lambda x,y: '%s %s'%(x,y), imgFiles)

photoStyle='montage %s -auto-orient -bordercolor Lavender -background white +polaroid -tile 1x -gravity center -background SkyBlue  -geometry "1x1<" result.jpg'%imgStrings
plainStyle='montage %s -tile 1x -geometry "1x1<" result.jpg'%imgStrings
choice=raw_input("1. default: plain\t2. photo style\nplz choose image merge type:")
if choice == '' or choice == '1':
    os.system(plainStyle)
else:
    os.system(photoStyle)

样图:

PhotoStyle:               PlainStyle:

otostyleotostyle

用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}`

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

沉迷写脚本-Ruby

最近疯狂使用Ruby写各种脚本,因为俺很痛恨手工重复劳动。
另外工作需要,也看了不少脚本,不过Python的居多,那个俺不是很懂。但是看代码还是可以看懂的。看懂了就想用Ruby来实现,因为一直觉得Ruby的语法更简洁漂亮。

刚才刚好看到个数字游戏的题(在这里看到的

题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?

然后那个人的解法不是很了解。但是有一点可以肯定,他不了解Ruby, 代码太不简洁了,完全没体现Ruby语言之美。他的算法说实话没看懂(俺数学不好。。。),不过我依据题目表面的意思做出来了,当然,这个执行效率肯定低些,毕竟是表面的。。。

#一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
#这是算的1000以内的,算1000就把下面的对应的改了就ok了。
a,b=[],[]
  1000.times do |x|
    1000.times do |y|
      a << x if(x+100==y**2)
      b << x if (x+268==y**2)
    end
  end
p a&b

题外话:在Ruby中,如果还用for和while的做枚举的人,都是对Ruby不了解的人!特别是用for做循环的,脑子进水了!

P.S. 网页版写个博客真费劲。代码就是不缩进!

Ubuntu Live USB 最高

今天又折腾Ubuntu,因为右上角的喇叭图标不见了。

然后网上找了个方法,于是我卸载了gnome-settings-daemon,期间提示有几个包同时卸载,当时没注意(这个是经验教训呀,以后删除东西的时候多留意两眼。。);更为悲剧的是我居然还重启了机器。

人间惨剧发生了。。在登录界面输入密码后,过了一会又会回到登录界面。

好在我之前处理Grub2 与Ubuntu的那些事的时候知道了chroot这个强大的东东,然后开始了折腾之旅:

  1. 首先用做好的Live USB进入系统,然后挂载根分区和boot分区,再是/sys /proc /dev /dev/pts。具体的可以参考前面那篇grub2的文章。
  2. 但是chroot进去的时候却提示
    chroot: cannot run command `/bin/bash': Exec format error
  3. 然后上网查了下,知道了是Live启动盘不一样导致了。终于想起来之前把启动盘重做成了32位的,而我的机器是64位的。。
  4. 只能回win7重做个64位的。。。两个系统就是方便呀~
  5. 为了能在chroot里面使用apt-get 需 要chroot能上网才行。当然,你的LiveUSB首先要能上网。把LiveUSB里面的dns配置拷到chroot里面:
    cp /etc/resolv.conf /mnt/etc/resolv.conf

    ,然后再进

    chroot /mnt
  6. 不过我总是不顺利呀,这次只安装了删掉的那个包(问题是那些同时删掉的都不记得是啥。。)。可想而知,还是不行
  7. 我就想,这肯定是gnome的问题了,那就重装gnome呗。又是一番遛狗,结果很简单:
    apt-get install ubuntu-desktop

    会把所有缺失的包都装上。重启后感受新生吧~~~

Ubuntu比Windows强太多了,虽然它不阻止你删除任何东西,甚至是/分区。但是通过chroot,很多看似很严重的问题都能解决。

另外那个喇叭图标消失的问题其实很简单:重新加载一次gnome-panel就行。如下命令顺序执行:

#重置gnome的面板设置,面板会消失,不必惊慌~
gconftool  --recursive-unset  /apps/panel<strong></strong>
#删除所有配置文件,你的所有针对上下面板的设置都会被删除
rm ~/.gconf/apps/panel
#重启panel,大功告成
pkill gnome-panel

另外我想说:折腾是学习的原动力!

用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

Grub2 与Ubuntu的那些事

Windows7与Ubuntu双启动的那些事 姊妹篇

之前那篇讲到我升级到Ubuntu 10.10,然后杯具的从Windows的启动菜单进不去了,出现grub rescue黑洞洞冷冰冰的界面:

error: the symbol ‘grub_xputs’ not found
grub rescue>

为了把Ubuntu救活,找了n多办法,还差点把Win7搞丢了。后来有些后怕就没动Ubuntu了,期间也尝试过几次,都未果。终于昨天心血来潮,好好研究了一番,终于在今天发现了问题的关键所在。而且最让人吐血的是最后找到的原因不是自己苦苦尝试的。。。好了,废话少说,听我慢慢道来。

先说下我的问题的根源,想看grub恢复方法的在后面有详细的介绍:

当我尝试过所有Ubuntu修复grub的方法后,还是提示grub_xputs。无奈在Ubuntu中文论坛发帖。然后继续找资料。刚好看到有人提到EasyBCD里面有个grub2模式。我记得我之前是的EasyBCD只有grub模式。然后发现EasyBCD确实多了个grub2选项,看来是2.0之后添加的。遂删除之前的条目,重新添加了grub2的条目,保存后重启,从启动项里面进入,grub列表终于出现了!这个跨年的问题终于解决,哈哈哈

Ubuntu出现grub rescue画面后最方便的解决方法就是使用对应的Live CD来处理。用U盘就能做 (省光盘就是低碳环保嘛),工具有好几个都不错:

  • Universal-USB-Installer:这个是官方推荐的工具:官方下载地址下面选USB,然后点右边的Show me how就可以看到下载了
  • unetbootin-windows:这个和上面那个差不多,不过会在启动后出现一个定制的菜单,更方便一些
  • LinuxLive USB Creator:图形化的工具,支持中文,可以安装作者定制的VirtualBox从Windows启动。适合新手。我用这个就10.04成功了,之后再没成功过。。而且那个VB虚拟机总出错。

从Live系统进入之后就可以对原有系统的grub重新安装了,Ubuntu forum里面有一篇非常棒的HOWTO介绍怎么操作的:HOWTO: Purge and Reinstall Grub 2 from the Live CD。还是啰嗦下:

我的ubuntu的 / 分区是sda7,/boot分区是 sda6,用livecd启动,在终端下(Application>Accessories>Terminal)输入

#切换到root权限
sudo –i
#挂载根目录 /
mount /dev/sda7 /mnt
#如果没 /boot 单独分区下面这步跳过
mount /dev/sda6 /mnt/boot
#从Live系统复制grub安装到被挂载的系统
grub-install --force --root-directory=/mnt /dev/sda6

注意:我因为要把grub安装到分区里面而不是MBR里面(就是grub-install那个命令的最后的参数是/dev/sda6,而不是/dev/sda或者/dev/sdb等),需使用了–force命令。不使用–force会提示如下信息

/usr/sbin/grub-setup: warn: Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea..
/usr/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists. However, blocklists are UNRELIABLE and its use is discouraged..
/usr/sbin/grub-setup: error: if you really want blocklists, use –force.

使用–force之后也会出,但是会有

Installation finished. No error reported

表示安装成功了。

如果你系统的grub.cfg文件损坏了或者不见了,那么还需要从Live系统进入到你出问题的系统你们更新一下这个文件。这时候要用到chroot

#下面的for循环是挂载你目标系统的各种必备设备
for i in /dev /dev/pts /proc /sys; do sudo mount -B $i /mnt$i; done
#然后就是进入挂载后的系统里面,也就是你出问题那个系统里面
chroot /mnt
#执行grub更新命令
grub-update
#成功后卸载挂载过的设备,如果没有单独的/boot分区就删除下面的/boot
for i in /dev/pts /dev /proc /sys /boot /; do sudo umount /mnt$i ; done

到此你的Ubuntu的grub就修复好了。那些个用grub rescue的命令的纯粹是找难受,虽然这方法我也用过。。太容易晕,也容易敲错;错了有可能很崩溃。。。

所以碰到rescue问题最好还是Live系统解决。主要是你需要了解linux分区的规则:再奉上一片关于分区的讲解,非常棒:Partitioning basics

杯具的面试及其它

应该说是去年了,去adobe二面。居然是技术面,之前完全没想到,然后就杯具了。
主要面试java,好久没用了,然后各种回答不上来。。最后那个面试官无奈了,看1小时的面试居然还差几十分钟,就给我出了个计算字符串中每个字母的个数的题。
然后我说不会用java写,用ruby行不?同意了,写了两种方法,基于String#scan和String#each_byte。最后他也没看懂。更无语的是我还把正则表达式的[Aa]写成了Aa,估计到时候拿我代码也运行不出来,唉。。

于是今天不甘心,重新写了个。比较满意


#char_count.rb
if ARGV.length != 1
    puts "argument error: usage: ruby char_count.rb string"
    exit
end

string = ARGV.shift
count = Hash.new (0)
('a'..'z').each do |char|
    count[char]=string.count(char)
end
('A'..'Z').each do |char|
    count[char.downcase]+=string.count(char)
end

#sort the out put in alphabetical order

count.sort.each do |element|
    if element[1]!= 0
        puts "Count of \"#{element[0]}/#{element[0].upcase}\" is #{element[1]} "
    end
end

P.S. 由于WP的博客被墙,翻墙不是每次都方便,于是想找个国内的。然后准备用Blogbus,而且它可以方便的搬家。搬完家之后发现我好几篇都“被审核”了!!马上对其印象差了很多!准备坚守这里了。。。

P.S.S 原来WordPress原生支持代码高亮的,一直不知道呀。。。 参见Posting Source code

用Ruby玩转PythonChallenge

前几天无意中知道了PythonChallenge这个网站,然后一发不可收拾.
开始用自己微薄的Ruby知识破解每一关,俺终于爱学习了。。就这样玩这个到了自己的生日。

今天建了一个Google的开源项目,专门保存这些资料。卡在第四关了。。。

项目地址:http://code.google.com/p/pythonchallenge4ruby

答案地址:http://code.google.com/p/pythonchallenge4ruby/wiki

Windows7与Ubuntu双启动的那些事

在经历了2次Ubuntu安装(10.04安装以及10.10升级)时WIN7进不去的事情后,我终于可以很淡定的表示,我不怕这些个启动问题了!

建议大家不要用grub写人MBR,用WIN7启动然后再进Ubuntu最保险!

这就需要你在安装Ubuntu分完区之后,设置好账号,出现的“准备开始安装”界面,不要直接点安装! 点击“高级”,选择/目录写入,不要选默认第一个的那个整个硬盘的选项。这样你的WIN7引导就不会被损坏。

话说我这次10.10升级后Ubuntu进不去了,提示 grub_xputs标识未找到。然后在grub_rescure下尝试未果后,然后只好用LinuxLive USBCreator做了个Ubuntu的LiveUSB,参考Ubuntu中文论坛的方法

然后问题就来了,出在grub-install root-directory的地方,我也依葫芦画瓢写了/dev/sda,这样就是悲剧的根源!因为这个命令是直接写到了/dev/sda的MBR中。重启后电脑黑屏了,没找到能启动的系统,连windows都进不去了- –

解决WIN7启动的那些事:WIN7 MBR和BCD文件修复

1. 因为之前对WIN7启动不太了解,这次总算清楚了:电脑开机后会先检查MBR,MBR然后会找到WIN7的隐藏的那个100M分区中的bootmgr;bootmgr会找同分区中的BCD文件启动系统启动菜单引导启动WIN7安装目录里面的winload.exe

2. 因为我有3张安装盘,在那里面转晕了,各种不好使。用系统自带的修复启动都不行。期间还试过bcdsect /nt60 SYS,都不行。这么折腾后我的BCD文件也被修改过了,查看100M那个系统保留分区里面的BCD文件的时间就知道了。

还好我用EASYBCD备份过BCD文件,那个和系统的是一样的,直接改名BCD直接覆盖就行。进入隐藏分区方法很多,比如WIN7 PE或者Linux LiveUSB,找到那个100M的分区,里面有BOOT目录和bootmgr文件。BOOT文件夹里面就有BCD文件。

3.然后启动电脑,还是不能进入WIN7。看来得恢复MBR。但是WIN7自带修复提示“windows无法自动修复此计算机。如果您最近将一个设备,如照相机或便携式音乐播放机,插入计算机,请将其拔出,然后重启,可我并没设备在计算机里”

4. 终于找到如何修复WIN7 mbr的方式。 请必须使用与你对应的WIN7版本的原版安装盘(主要保证X64/X32系统用X64/X32盘修复)启动。选择左下角的“修复计算机”->“启动命令提示符”->输入bootrec /FixMbr 回车。没有错误提示现在就可以重启电脑进入WIN7了。bootrec的使用见官方知识库 FixMbr修复MBR,FixBoot是修复BCD文件以及bootmgr,最好是自己平时用EasyBCD备份好,自己恢复,不然会有其他副作用。

成功后实在太高兴了~~~~狂吼了好几声,哈哈!

Ubuntu的问题到时候再说了,不想折腾了。从昨天晚上折腾到今天,还搭上WIN7。。。累了。。。