スポンサーサイト

Tags :
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

AppleScriptでJPEG画像がプログレッシブかどうかを判定する

AdobeのPhotoshopフォーラムに投稿されていたのを見て、ちょっと考えてみました。

ApplescriptでプログレッシブJPEGはわかりますか?
(Adobe Forums: フォーラム: Photoshop (Japan))

PhotoshopのAppleScriptリファレンスを眺めてみたり、保存した画像のXMPメタデータにそれらしい情報が含まれていないか見てみたんですが、Photoshopを使った解決法が見つからなかったので、Photoshopを使わない別の方法でやってみます。

通常この手の処理はバイナリデータを先頭から読んでいってマーカーの値が出てきたらそれを判別して……みたいな感じになりますが、AppleScriptでバイナリデータを扱うのはちょっと面倒そうなので、Unix系のOSで使える出来合いのライブラリに処理を投げてしまったほうが手取り早く、確実だと思います。

で、今回使用してみたのは『libjpeg』ライブラリに含まれる『rdjpgcom』コマンドで、シェルを使ってJPEG画像に関する情報を取り出す事ができます。このコマンドをAppleScriptの『do shell script』で呼び出してやります。

そのためにはMacに『libjpeg』をインストールしてやる必要がありますが、下のサイトでコンパイル済みのインストーラ形式のものが公開されています。

http://ethan.tira-thompson.org/Mac_OS_X_Ports.html
(@ITで紹介されていたものですが、インストーラの素性は保証できないので、利用は自身の判断で…今回必要なのは『rdjpgcom』コマンドだけなので、『libjpeg』本体は無くても良いようですが。)

上記インストーラでは『rdjpgcom』コマンドは『/usr/local/bin』にインストールされます。

このコマンドの使い方は、例えばデスクトップにある画像、ファイル名『baseline.jpg』の情報を見る場合、ターミナルで、
rdjpgcom -verbose /User/hogehoge/Desktop/baseline.jpg
のように -verbose オプションを付けてファイルのパスを渡してやれば、
JPEG image is 1280w * 1024h, 3 color components, 8 bits per sample
JPEG process: Baseline
のような形で返ってきます。

『rdjpgcom』コマンドは、JPEG画像以外のファイルを処理した場合、標準エラー出力に『Not a JPEG file』の文字列を返してくるので、メッセージを『try~on error』で拾えます。

AppleScriptから使う場合はこんな感じでしょうか。
on open drop
	repeat with aFile in drop
		tell application "Finder"
			set fPath to POSIX path of aFile as string
			set scpt to "/usr/local/bin/rdjpgcom -verbose " & quoted form of fPath
			try
				set rslt to do shell script scpt as string
				if rslt is not "" then
					display dialog name of aFile & return & word 3 of paragraph 2 of rslt
				else
					display dialog "不明"
				end if
			on error errStr
				display dialog errStr
			end try
		end tell
	end repeat
end open
上記のスクリプトではAppleScirpt側で、シェルから返ってきた文字列が入る変数rsltから『Progressive』『Baseline』を取り出していますが、
rdjpgcom -verbose /User/hogehoge/Desktop/baseline.jpg | grep process | awk '{ print $3 }'
のようにgrepとawkを通してやれば、シェル側で
Baseline
の文字列だけを取り出せます。(この場合、JPEG以外のファイルを処理すると何も返ってきません。)

結局AppleScriptでは出来てないじゃん!とか言われそうですが、Finderなどの処理を自動化しつつ、手に負えない処理はシェルや他の言語に丸投げするのがグルー(糊)な言語としてのAppleScriptの正しい使い方だと思っているので。
スポンサーサイト

AppleScript & Photoshopで2つの画像の差異がある部分を着色表示する

久しぶりの更新になります。

AppleScriptを使って、Photoshopで表示している2つの画像の差異がある部分(値が同じでないピクセル)を、着色表示してみます。印刷会社などで導入されている『デジタル検版』の様な感じで表示します。

やっている事は、

・下準備として画像がレイヤを持っている場合はそれを統合して一枚モノの画像にしておき
・2つの画像をレイヤで重ね
・画像モードを『16bit/チャンネルのRGB』に変換
・上のレイヤの描画モードを『差の絶対値』にして下のレイヤと統合
・差を目立たせる為にトーンカーブでライト側を一杯まで引っ張る(入力4、出力255)
・画像を2値化してから反転
・赤く着色して元の画像に重ねて表示

という一連の動作をAppleScriptで実行しています。


例えば、オリジナル画像(Image1)と、オレンジの種を消した画像(Image2)をPhotoshopで表示しておき、AppleScriptを実行すると、差異のあるピクセルを色付けした状態で表示します。(下の画像は比較し易いように並べたものです)



こちらはオリジナル画像(Image1)に対してトーンカーブで中間域の濃度をCMYK値で5%上げた画像(Image2)の場合。

こんな感じで色付け表示します。画像の色調をトーンカーブ等で調整した際、どの辺りまで影響が出るのかを確認する事ができます。

『DIFF_THRESHOLD』の値は、どれくらいの色の差があれば色付けするのかを決めるしきい値で、スクリプト1行目の値を上の画像のように220にしておくとCMYKの値でおよそ5%以上の差があれば色付けするようになり、値が小さい程わずかな色の差で反応するようになります。

スクリプト中でRGBに変換する前に『16bit/チャンネル』にしていますが、これは2つのレイヤーの画像のCMYK値が同じだったとしても、『8bit/チャンネル』のままだとRGBの変換後に僅かな数値の違いが出てしまうためです。


で、今回色んな画像で試してみて、ちょっと意外だった事が。



上の例は、左のオリジナル画像を『JPEGフォーマット(画質は最高の12)』で保存したものと、『EPS JPEGエンコーディング(最高画質)』で保存して、それぞれオリジナルと比べてどれだけ変化しているのかを見てみたんですが、どうもEPS JPEGエンコーディングの方が色が変化したピクセルが多い(=劣化が大きい)ようで、色々な画像で試してみたんですがどれも同じ傾向でした。まあ目で見た限りでは見分けは付かないんですが、てっきり同等のものだと勝手に思い込んでいたので自分にとっては『プチ驚愕の事実』でした。

以下が今回のAppleScript。スクリプトを実行するときは『比較したい2つの画像のみ』を表示しておきます。
■動作確認
MacOSX 10.5.8
Photoshop CS4
property DIFF_THRESHOLD : 50

tell application "Adobe Photoshop CS4"
	activate
	set doc1 to document 1
	set doc2 to document 2
	set current document to doc1
	
	tell doc1
		flatten
		select all
		copy
	end tell
	
	set current document to doc2
	
	tell doc2
		flatten
		paste
		set bits per channel to sixteen
		change mode to RGB
		set imgLay1 to background layer
		set name of imgLay1 to "Image 1"
		set imgLay2 to layer 1
		set name of imgLay2 to "Image 2"
		set blend mode of imgLay2 to difference
		duplicate imgLay1
		duplicate imgLay2
		move 2nd layer to after 3rd layer
		tell layer 1
			merge
			select all
			adjust using curves with options {class:curves, curve points:{{0, 0}, {4, 255}}}
			adjust using threshold adjustment with options {class:threshold adjustment, level:DIFF_THRESHOLD}
			adjust using inversion
		end tell
		make new art layer with properties {blend mode:lighten}
		fill selection with contents {class:RGB color, red:255, green:64, blue:64}
		merge layer 1
		set name of layer 1 to "Diff"
		set opacity of layer 1 to 70
		set blend mode of layer 2 to normal
	end tell
	
end tell

画像のクリッピングパスをもう一方の同じファイル名の画像にコピーするAppleScript

地味な実用系スクリプト。

時々、入稿されてきたRGB画像が数百点にのぼり、しかもその画像を結構な短納期でキリヌキと色調補正&CMYK変換をしなければならない事があって、そんな場合はキリヌキを(海外の協力会社などに)外注し、同時進行で色調補正の作業をするんですが、後で仕上がってきたキリヌキ画像のクリッピングパスを、手元で色調補正していた画像に反映させてやる必要が出てきます。その作業を自動化するためのAppleScriptです。

実は、たけうちとおるさんのサイトにそのまんまの機能のAppleScriptがあったんですが、自分の作業環境だと意図しない動作をするようだったので、少しチェックをきつめにするようにして書きました。

■使い方
あらかじめ『キリヌキ済み(クリッピングパスがある)画像』と『キリヌキ前の画像』のフォルダを作り、その中に(対になる様)画像を整理して入れておきます。(必ずしも数が合っている必要はありませんが、後でチェックする事になるので始めのうちに揃えておいた方が良いでしょう。)

スクリプトを実行し、『キリヌキ済み(コピー元)』と『キリヌキ前』のフォルダの場所を聞いて来るので、それぞれを選択してやるとPhotoshopでの処理が始まり、キリヌキ済み画像のクリッピングパスをキリヌキ前の同名の画像に適用して行きます。

下記の様な、正しく処理出来なかったファイルは『赤ラベル』が付いて確認作業がしやすいようになっています。
・双方のフォルダで一致するファイル名のものが無かった。
・コピー元の画像にクリッピングパスが無かった。
・コピー先の画像には既にクリッピングパスがあった。
・Photoshopで開けなかった。
・…etc.

■動作確認
MacOSX 10.5.8
Photoshop CS4
tell application "Adobe Photoshop CS4"
	set ru to ruler units of settings
	set ruler units of settings to cm units
end tell

tell application "Finder"
	set srcFold to (choose folder with prompt "クリッピングあり画像(コピー元)のフォルダを選択") as string
	set srcFold to srcFold as string
	set destFold to (choose folder with prompt "クリッピングなし画像(適用先)のフォルダを選択") as string
	repeat with theFile in list folder destFold without invisibles
		set theFile to (destFold & theFile) as alias
		if not class of ((properties of theFile) as record) is folder then my setLabel(theFile, 2)
	end repeat
	set destFold to destFold as string
	repeat with theFile in list folder srcFold without invisibles
		set srcFile to (srcFold & theFile) as alias
		if not class of ((properties of srcFile) as record) is folder then
			try
				set destFile to (destFold & theFile) as alias
				my mergePath(srcFile, destFile)
				
			on error
				--コピー先のファイルを開けない(存在しない)場合もコピー元に赤ラベルを付ける
				my setLabel(srcFile, 2)
			end try
		end if
	end repeat
end tell

tell application "Adobe Photoshop CS4"
	set ruler units of settings to ru
end tell

activate me
beep
if my chkLabel(srcFold) or my chkLabel(destFold) then
	display dialog "処理に問題のある画像があります。" & return & "双方のフォルダの『赤いラベル』のファイルをチェックして下さい。" with icon 0
else
	display dialog "終了しました。"
end if


on mergePath(srcFile, destFile)
	tell application "Adobe Photoshop CS4"
		activate
		open srcFile showing dialogs never
		set srcDoc to current document
		set pathItem to path items in srcDoc whose kind is clipping
		
		if (count pathItem) is 0 then
			my setLabel(srcFile, 2)
			close srcDoc
			return
		end if
		
		--クリッピングパスが存在せず下の行の処理に失敗すると以降の記述が実行されない場合がある?(エラーは出ず再現条件不明)
		set cp to entire path of path items in srcDoc whose kind is clipping
		close srcDoc
		my setLabel(srcFile, 4)
		
		open destFile showing dialogs never
		set destDoc to current document
		if (count (path items in destDoc whose kind is clipping)) is 0 then
			make new path item in destDoc with properties {entire path:cp, name:"Clipping", kind:clipping}
			my setLabel(destFile, 4)
			close destDoc saving yes
		else
			close destDoc
		end if
		
	end tell
end mergePath


on setLabel(theFile, col)
	tell application "Finder"
		set label index of theFile to col
	end tell
end setLabel


on chkLabel(theFolder)
	tell application "Finder"
		repeat with theFile in list folder theFolder without invisibles
			set theFile to (theFolder & theFile) as alias
			if label index of theFile is 2 then return true
		end repeat
		return false
	end tell
end chkLabel

Twitterで『あの人』が自分をfollowしているかどうかを調べるAppleScript

ここんとこ仕事が立て込んでたので放置してしまいました。ちょっと軽めのネタを。

Twitterやってると突然、『follow整理します!』みたいな感じのPOSTが流れて来て、そんな時に自分のfollowerが減ってたりすると、『えっ?…オレ?』とか思ったりして、特に相手がお気に入りの人だったりするとちょっと気になったりするもんです。また、結構前にfollowしたけどfollow返されてたっけ?みたいに思ってもtwitterからの『followされました』メールをいちいちチェックするのも面倒です。

相手にremoveされたかを知るには、『りむったー』とか『Qwitter』等のサービスを利用すればremoveされた際に通知を受け取る事が出来ますが、そもそも一度もfollowされてない相手には関係がありません。

そこで、Twitter APIに用意されている『ユーザ間のfriend関係』を調べる機能を利用して『相手にfollowされてるかどうかを調べる』AppleScriptを書きました。この手のサービスやuser.jsも有りそうですが、探すヒマがあったら自分で書く、みたいな感じで。あと、高機能なTwitterクライアント使ってる人には必要無いかも知れません。

スクリプト中の『あなたのユーザ名』『パスワード』の部分を書き換えて実行し、気になる『あの人』のユーザ名を入力するとfollowされてるかどうかを表示します。





■動作確認
MacOSX 10.5.8
property user : "あなたのユーザ名"
property pass : "パスワード"

tell application "Finder"
	set friend to text returned of (display dialog "『あの人』のユーザ名を入力してください。" default answer "") as string
	try
		--set scpt to "curl --user \"" & user & ":" & pass & "\" -L \"http://twitter.com/friendships/exists.json?user_a=" & friend & "&user_b=" & user & "\""
		set scpt to "curl -L \"http://api.twitter.com/1/friendships/exists.json?user_a=" & friend & "&user_b=" & user & "\""
		set ret to do shell script scpt
	on error
		my myError()
	end try
	
	set mes to "『" & friend & "』さんは、あなたをfollowして"
	if ret is "true" then
		display dialog mes & "います。" buttons "OK" default button 1
	else if ret is "false" then
		display dialog mes & "いません。" buttons "OK" default button 1 with icon 2
	else
		my myError()
	end if
end tell

on myError()
	activate me
	display dialog "ユーザ名を正しく入力してください。" buttons "OK" default button 1
	error number -128
end myError

AppleScriptのシンタックスをハイライトするJavaScriptを少し改良

ウチのblogではAppleScriptとかJavaSciptのソースコードをいろいろ書き散らして晒してますが、ソースコードの構文を色分け表示するのに、AppleScriptの場合は自作のJavaScriptを使ってハイライト表示させています。(AppleScript以外のソースコードは、『SyntaxHighlighter』を利用)

で、今回ちょっと不具合があったのを直したついでに少し改良して、スクリプトエディタでの表示と同じ様に、主要な構文がボールドの文字で表示出来る様にしたのと、あとリストのラベル名やAppleEventが含まれるコードもできるだけスクリプトエディタでの色分けに合わせる様にしました。ソースコードのクリップボードへのコピーをする部分は、flashを使った外部のライブラリ『Zero Clipboard』を使っています。

<pre class="applescript">~</pre>でAppleScriptのソースを囲むとこんな感じに表示する様になってます。
on «event appSscrW» theObject given «class eveE»:theEvent
	set theValue to «class conT» of theObject as number
	(«class delY» of theEvent)
	set theValue to theValue + («class delY» of theEvent)
	set theEvent to theEvent
	set «class conT» of theObject to theValue
	tell window of theObject
		set contents of «class texF» "seconds" to contents of «class sliI» "secondsSlider"
		set secsToPlay to contents of «class texF» "seconds"
	end tell
end «event appSscrW»


on create_thumb(tgt_file, dest_file)
	tell application "Adobe Photoshop CS4"
		activate
		open tgt_file showing dialogs never
		set theDoc to current document
		tell theDoc
			if width > height then
				resize image width thumb_size as pixels resolution 72 resample method bicubic
			else
				resize image height thumb_size as pixels resolution 72 resample method bicubic
			end if
			change mode to RGB
			convert to profile "sRGB IEC61966-2.1" intent relative colorimetric with blackpoint compensation and dithering
			set save_opts to {class:JPEG save options, embed color profile:false, quality:10}
			save in file dest_file as JPEG with options save_opts appending no extension with copying
			close without saving
		end tell
	end tell
end create_thumb


(*  via MacWiki http://macwiki.sourceforge.jp/wiki/index.php/AppleScriptTips *)
set chars to {¬
	{uc:"A", lc:"a", ucj:"A", lcj:"a"}, {uc:"B", lc:"b", ucj:"B", lcj:"b"}, ¬
	{uc:"C", lc:"c", ucj:"C", lcj:"c"}, {uc:"D", lc:"d", ucj:"D", lcj:"d"}, ¬
	{uc:"E", lc:"e", ucj:"E", lcj:"e"}, {uc:"F", lc:"f", ucj:"F", lcj:"f"}, ¬
	{uc:"G", lc:"g", ucj:"G", lcj:"g"}, {uc:"H", lc:"h", ucj:"H", lcj:"h"}, ¬
	{uc:"I", lc:"i", ucj:"I", lcj:"i"}, {uc:"J", lc:"j", ucj:"J", lcj:"j"}, ¬
	{uc:"K", lc:"k", ucj:"K", lcj:"k"}, {uc:"L", lc:"l", ucj:"L", lcj:"l"}, ¬
	{uc:"M", lc:"m", ucj:"M", lcj:"m"}, {uc:"N", lc:"n", ucj:"N", lcj:"n"}, ¬
	{uc:"O", lc:"o", ucj:"O", lcj:"o"}, {uc:"P", lc:"p", ucj:"P", lcj:"p"}, ¬
	{uc:"Q", lc:"q", ucj:"Q", lcj:"q"}, {uc:"R", lc:"r", ucj:"R", lcj:"r"}, ¬
	{uc:"S", lc:"s", ucj:"S", lcj:"s"}, {uc:"T", lc:"t", ucj:"T", lcj:"t"}, ¬
	{uc:"U", lc:"u", ucj:"U", lcj:"u"}, {uc:"V", lc:"v", ucj:"V", lcj:"v"}, ¬
	{uc:"W", lc:"w", ucj:"W", lcj:"w"}, {uc:"X", lc:"x", ucj:"X", lcj:"x"}, ¬
	{uc:"Y", lc:"y", ucj:"Y", lcj:"y"}, {uc:"Z", lc:"z", ucj:"Z", lcj:"z"}}
set theText to "AppleScript アップルスクリプト AppleScript"
set newText to ""
repeat with aChar in every character of theText
	repeat with c in chars
		if aChar as string is uc of c then set aChar to lc of c -- tr/A-Z/a-z/
		-- if aChar as string is lc of c then set aChar to uc of c -- tr/a-z/A-Z/
	end repeat
	set newText to newText & aChar
end repeat
-- display dialog newText
クォートされた文字列を赤くしてるのは、ウチのblogにあるAppleScriptのコードはシェルとか他の言語に処理を投げてるのが多いので、その部分を目立つ様にするためです。

AppleScriptはアプリケーションの数だけ、それこそ無限にプロパティやメソッド等の予約語があるので、完璧に構文を正しく表示するのは難しいですが、基本的にこのJavaScriptでは『変数名とハンドラ名と記号と数字とコメントとクォートされた文字列以外はすべて予約語』として扱ってます。(で、イレギュラーなものを個別に登録して処理。)

変数名やハンドラかどうかは一旦コードを頭からスキャンして判断してるので、コードの一部を載せた様な場合いきなり変数名が出て来ても対応出来ず、スクリプトエディタでコンパイルが通る形のものでないときちんと処理出来ないという弱点はあります。

まあ、今後Adobeはアプリの新機能をAppleScriptでサポートしなくなるというのもあって、AppleScript書く事が少なくなってるので出番はあまり無いかも知れません。
Profile
choco
Author : choco

印刷・製版の現場を経て、広告制作会社でPhotoshopを使ったビジュアル制作を担当。

→現在は車載機器開発ベンダにて、組み込み3Dデータ作成やUIデザインなどを行っています。

Categories
Favorites


Search
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。