2011年05月07日

[Python] 画像の縦横比を見て回転させ縮小するプログラム Ver7

マルチプロセッシングはどうにも上手くいかないので、Ver5[記事]をベースに改良。
アホみたいに2回もループしているのを1つにまとめたり、縮小する必要が無いのに、画像を再圧縮しているのを止めた。

多少冗長な箇所があるけど、もう一回並列化にチャレンジするために残しておく。

コード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# 引数で指定したフォルダの画像ファイルを
# 出力先フォルダに縮小・回転しながらコピーする

from __future__ import print_function
import os, sys,glob
import shutil
from PIL import Image

# 出力先フォルダ指定。
TARGET_DIR = u'C:\\Photo'
#COWON A3向け
#max_size = (800, 480)
#PSP向け
#max_size = (480, 270)
#Ziio向け
max_size = (480, 800)
#対象拡張子
ext_dic = ['.jpg','.jpeg','.png','.bmp']
#ファイル名のprefix
DEST_PREFIX = 's_'
#JPEG品質
JPEG_QUALITY = 75

def makeOutputDirectory(outputDirPath):
	if os.path.isdir(outputDirPath) == False:
		os.makedirs(outputDirPath)

def isTarget(ext):
	return True if ext.lower() in ext_dic else False

class ProgressBar:
	def __init__(self,totalNum):
		self.totalNum = totalNum
		self.counter = 0
		self.chr = u"*"
		self.width = 40
	def addCounter(self,incrementNum):
		self.counter += incrementNum
	def show(self):
		pbar_chrs = self.chr * (self.width * self.counter / self.totalNum)
		percentage = 100 * self.counter / self.totalNum
		meter = u'\r|{0}{1}| {2}/{3}個 ({4}%)'.format(pbar_chrs,u' ' * (self.width - len(pbar_chrs)),self.counter,self.totalNum, percentage)
		sys.stdout.write(meter)
		sys.stdout.flush()

def createTargetImagePath( path,targetBaseDirectory ):

	targetPath = []
	names = os.listdir(path)
	targetDirectory = targetBaseDirectory

	for name in names:
		srcname = os.path.join(path, name)
		try:
			if os.path.isdir(srcname):
				targetDirectory = os.path.join(targetBaseDirectory, name)
				targetPath += createTargetImagePath( srcname,targetDirectory )
			else:
				root, ext = os.path.splitext(srcname)
				if isTarget(ext) == True:
					targetPath.append((srcname,os.path.join(targetDirectory,DEST_PREFIX + name)))
		except (IOError, os.error), why:
			print(u"Can't copy",srcname,u':',str(why))
	return (targetPath)

def shrinkImage(srcFileName, dstFileName):

	sourceImage = Image.open(srcFileName)
	
	if sourceImage.size[0] > max_size[0] or sourceImage.size[1] > max_size[1] or sourceImage.format == 'BMP':
		destImage = sourceImage
		# BMPの場合、JPEGにする
		if sourceImage.format == 'BMP':
			destImage = destImage.convert('RGB')
			root,ext = os.path.splitext(dstFileName)
			dstFileName = root + '.jpg'
		else:
			format = sourceImage.format
		
		if max_size[0] > max_size[1]:
			#横が長いディスプレイの場合は縦長の画像を回転させる。
			if destImage.size[0] < destImage.size[1]:
				destImage = destImage.rotate(270)
		else:
			#縦が長いディスプレイの場合は横長の画像を回転させる。
			if destImage.size[0] > destImage.size[1]:
				destImage = destImage.rotate(270)
		destImage.thumbnail(max_size, Image.ANTIALIAS)
		destImage.save(dstFileName,quality=JPEG_QUALITY)
	else:
		# 画面に収まらないor BMP形式以外の場合は、再圧縮する必要ないので普通のコピーにする
		shutil.copy(srcFileName,dstFileName)
	

def copyImageTree(targetList,progress):

	for target in targetList:
		srcname = target[0]
		dstname = target[1]
		try:
			makeOutputDirectory(os.path.dirname(dstname))
			shrinkImage(srcname,dstname)
			progress.addCounter(1)
			progress.show()
		except (IOError, os.error), why:
			print(u"Cant' copy",srcname,'to',dstname,u':',str(why))
	
if __name__=='__main__':
	#引数がおかしい場合
	if len(sys.argv) < 2:
		print(u'Usage: # Python ',sys.argv[0],u' [souceimagedirectorypath]...')
		raw_input()
		quit()
		
	targetPathList = []
	for x in range(1,len(sys.argv)):
		sourcePath = os.path.dirname(unicode(sys.argv[x],"mbcs") + '\\')

		if os.path.isdir(sourcePath) == False:	#存在しないPathを指定した場合
			print(u'[',sourcePath,u']: Src directory does not exist.')
			raw_input()
			quit()
		elif os.path.isdir(TARGET_DIR) == False:	#存在しないPathを指定した場合
			print(u'[',TARGET_DIR,u']: Dest directory does not exist.')
			raw_input()
			quit()
		elif sourcePath == TARGET_DIR:	#入力先と出力先が同じ場合
			print(u'The input destination is the same as the output destination.')
			raw_input()
			quit()
		else:
			targetPathList +=  createTargetImagePath(sourcePath,(TARGET_DIR + '\\' + os.path.basename(sourcePath)))
	
	if len(targetPathList) == 0:
		print(u'File does not exist.')
		quit()

	progress = ProgressBar(len(targetPathList))
	copyImageTree(targetPathList,progress)

2011/5/8 20:46 追記

os.mkdir()だと、階層構造のフォルダが作成できなかったので、os.makedirs()に変更。
IronPythonだと作ってくれるのに・・・。

タグ:Python
posted by MINE at 23:58 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック