AppleScript名:指定画像をTIFF形式で保存 |
— Created 2017-02-05 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" set aFile to POSIX path of (choose file of type {"public.image"} with prompt "Select Image A") set aImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile set fRes to retUUIDfilePath(aFile, "tif") of me set sRes to saveNSImageAtPathAsTIFF(imgRes, fRes) of me on retUUIDfilePath(aPath, aEXT) set aUUIDstr to (current application’s NSUUID’s UUID()’s UUIDString()) as string set aPath to ((current application’s NSString’s stringWithString:aPath)’s stringByDeletingLastPathComponent()’s stringByAppendingPathComponent:aUUIDstr)’s stringByAppendingPathExtension:aEXT return aPath end retUUIDfilePath –NSImageを指定パスにTIFF形式で保存 on saveNSImageAtPathAsTIFF(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSTIFFFileType) |properties|:(missing value)) set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean return aRes –true/false end saveNSImageAtPathAsTIFF |
タグ: 10.12savvy
画像にステガノグラフィーで埋め込まれた文字列を取り出す
オープンソースのステガノグラフィーのプログラム「ISStego」(By Isaac Stevao Sena氏)を用いて、JPEG画像に埋め込んだ文字情報を取り出すAppleScriptです。
ISStegoは普通にObjective-Cで書かれたGUIベースのアプリケーションだったので、そのままではAppleScriptから呼び出せませんでした。
そこで、中身をそのままそっくり移し替えた新規フレームワーク「stegLib.framework」をでっちあげてビルドし、AppleScriptから呼び出してみました。
JPEG画像にUTF-8の文字情報(日本語文字列)を埋め込んで別のPNG画像に書き出し、書き出した画像からUTF-8の文字情報を取り出す実験を行ってみました。エンコードもデコードもうまく行っているようなので、うまく処理できていると思います。
ステガノグラフィーについて初めて聞いたのは20年ぐらい前のことと記憶していますが、こんなに手軽に使えるようになっていたとは驚きです。
▲Original Image
▲Information Embedded Image
AppleScript名:画像にステガノグラフィーで埋め込まれた文字列を取り出す |
— Created 2015-10-21 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "stegLib" –https://github.com/isena/ISStego set aFile to POSIX path of (choose file of type {"public.png"}) set aFilePath to current application’s NSString’s stringWithString:aFile set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL set aDecodedData to current application’s ISStegoDecoder’s alloc()’s init()’s decodeStegoImage:aImage |error|:(missing value) set resStr to (current application’s NSString’s alloc()’s initWithData:aDecodedData encoding:(current application’s NSUTF8StringEncoding)) as string –> "長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software" |
画像にステガノグラフィーで情報を埋め込む
オープンソースのステガノグラフィー(steganography)のプログラム「ISStego」(By Isaac Stevao Sena氏)を用いて、JPEG画像に文字情報を埋め込むAppleScriptです。
ISStegoは普通にObjective-Cで書かれたGUIベースのアプリケーションだったので、そのままではAppleScriptから呼び出せませんでした。
そこで、中身をそのままそっくり移し替えた新規フレームワーク「stegLib.framework」をでっちあげてビルドし、AppleScriptから呼び出してみました。
JPEG画像にUTF-8の文字情報(日本語文字列)を埋め込んで別のPNG画像に書き出し、書き出した画像からUTF-8の文字情報を取り出す実験を行ってみました。エンコードもデコードもうまく行っているようなので、うまく処理できていると思います。
ステガノグラフィー(steganography)について初めて聞いたのは20年ぐらい前のことと記憶していますが、こんなに手軽に使えるようになっていたとは驚きです。
Twitterにプログラムを投稿するのに、(140文字制限を回避するため)文字を画像化して投稿しているのを見て、「そこまでやるなら、画像にプログラムの文字データを埋め込めばいいのに」と思い、「ステガノグラフィーで埋め込めばいいんじゃないか?」ということで、埋め込めるようになったのですが、肝心のTwitterクライアントから画像をダウンロードする手段がなかったのがダメダメでした(Webブラウザ経由ならOKです)。
▲Original Image
▲Information Embedded Image
AppleScript名:画像にステガノグラフィーで情報を埋め込む |
— Created 2015-10-21 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "stegLib" –https://github.com/isena/ISStego set aFile to POSIX path of (choose file of type {"public.jpeg"}) set encString to "長野谷隆昌/ぴよまるソフトウェア/Piyomaru Software" set aFilePath to current application’s NSString’s stringWithString:aFile set aExt to "png" set newPath to aFilePath’s stringByDeletingPathExtension() set newPath2 to newPath’s stringByAppendingString:"_stego" set newPath3 to newPath2’s stringByAppendingPathExtension:aExt set aURL to current application’s |NSURL|’s fileURLWithPath:aFilePath set aImage to current application’s NSImage’s alloc()’s initWithContentsOfURL:aURL set strData to current application’s NSString’s stringWithString:encString set aEncimage to current application’s ISStegoEncoder’s alloc()’s init()’s stegoImageForImage:aImage |data|:strData |error|:(missing value) my saveImageRepAtPathAsPNG(aEncimage, newPath3) –画像を指定パスにPNG形式で保存 on saveImageRepAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)) return (myNewImageData’s writeToFile:newPath atomically:true) as boolean end saveImageRepAtPathAsPNG |
拡張子でUTIを指定しつつchoose file of type
choose fileコマンドを拡張して、選択対象をUTIではなくファイル拡張子で指定できるようにしたAppleScriptです。
もともと、Classic Mac OSの時代からファイルのタイプを指し示す識別子としてFile Type(”PICT”とか”MooV”とか)が存在していましたが、OS X 10.6あたりで廃止になり、ウヤムヤのまま部分的に延命してきたものの、macOS 10.13でファイルシステムにAPFSを採用(File Typeなどの情報がFile System上に存在しない)したことにより、完全に使用不能になりました。
ファイルの区別に利用してきた情報としては、File type以外にも、
拡張子(複数の書き方をすることがある。.jpgとか.jpegとか)
ファイルkind(ローカライズされている)
type identifier(UTIのこと)
が存在しています。
「すべての画像」「プレーンテキスト全般」といったざっくりとした指定が可能なUTIは、AppleScript側にあまり機能が解放されておらず、あまり利用できていなかったのですが、macOS 10.10でCocoaの機能が利用できるようになってからはUTIの利用もすすんできました。
ただ、それなりに調べる作業も必要だったり、ツールを併用する必要もあったりするので、ファイル拡張子からUTIをScriptで調べて指定できたほうが便利な場合もあるのでは? と考え、このようなルーチン(+命令拡張)を書いてみたものです。
AppleScript名:拡張子でUTIを指定しつつchoose file of type |
— Created 2018-1-20 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use framework "Foundation" use scripting additions use BridgePlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html set aFile to choose file of type {"jpg", "png"} with prompt "This is a message" set bFile to choose file of type {"scpt", "scptd"} with prompt "With default locaion" default location (path to desktop) on choose file of type extList with prompt aMes as string : "" default location aLoc : missing value set utiList to {} repeat with i in extList set the end of utiList to retFileFormatUTI(i) of me end repeat if aLoc = missing value then continue choose file of type utiList with prompt aMes else continue choose file of type utiList with prompt aMes default location aLoc end if end choose file on retFileFormatUTI(aExt as string) load framework return (current application’s SMSForder’s UTIForExtension:aExt) as string end retFileFormatUTI |
指定UTIでUTIを入れたリストをフィルタリング
AppleScript名:指定UTIでUTIを入れたリストをフィルタリング |
— Created 2017-11-03 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" property NSPredicate : a reference to current application’s NSPredicate property NSArray : a reference to current application’s NSArray set aList to {"public.jpeg", "com.compuserve.gif", "public.svg-image", "public.plain-text", "com.apple.iwork.keynote.key", "com.apple.iwork.pages.pages", "com.apple.iwork.numbers.numbers", "com.microsoft.word.doc", "com.microsoft.excel.xls", "com.microsoft.powerpoint.ppt", "com.apple.mail.email", "com.apple.applescript.script", "com.apple.applescript.text", "public.html", "com.apple.property-list", "public.zip-archive", "public.au-audio", "com.apple.m4a-audio", "com.apple.m4v-video"} set aRes to filterUTIList(aList, "public.text") –> {"public.plain-text", "com.apple.applescript.script", "com.apple.applescript.text", "public.html"} set bRes to filterUTIList(aList, "public.image") –> {"public.jpeg", "com.compuserve.gif", "public.svg-image"} set cRes to filterUTIList(aList, "public.audiovisual-content") –> {"public.au-audio", "com.apple.m4a-audio", "com.apple.m4v-video"} on filterUTIList(aUTIList, aUTIstr) set anArray to NSArray’s arrayWithArray:aUTIList set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr) set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list return bRes end filterUTIList |
指定拡張子のUTI文字列を取得する
AppleScript名:指定拡張子のUTI文字列を取得する |
— Created 2016-10-24 by Takaaki Naganoya — Modified 2016-10-25 by Shane Stanley — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AVFoundation" use BridgePlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html set aRes to retFileFormatUTI("mov") of me –> "com.apple.quicktime-movie" set aRes to retFileFormatUTI("mp4") of me –> "public.mpeg-4" set aRes to retFileFormatUTI("m4v") of me –> "com.apple.m4v-video" set aRes to retFileFormatUTI("m4a") of me –> "com.apple.m4a-audio" set aRes to retFileFormatUTI("3gp") of me –> "public.3gpp" set aRes to retFileFormatUTI("3gp2") of me –> "public.3gpp2" set aRes to retFileFormatUTI("caf") of me –> "com.apple.coreaudio-format" set aRes to retFileFormatUTI("wav") of me –> "com.microsoft.waveform-audio" set aRes to retFileFormatUTI("aif") of me –> "public.aifc-audio" set aRes to retFileFormatUTI("aifc") of me –> "public.aifc-audio" set aRes to retFileFormatUTI("amr") of me –> "org.3gpp.adaptive-multi-rate-audio" set aRes to retFileFormatUTI("mp3") of me –> "public.mp3" set aRes to retFileFormatUTI("au") of me –> "public.au-audio" set aRes to retFileFormatUTI("ac3") of me –> "public.ac3-audio" on retFileFormatUTI(aExt as string) load framework return (current application’s SMSForder’s UTIForExtension:aExt) as list of string or string end retFileFormatUTI |
指定ファイルのUTI情報を取得
AppleScript名:指定ファイルのUTI情報を取得 |
— Created 2017-10-25 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "MagicKit" –https://github.com/aidansteele/magickit set aFile to POSIX path of (choose file) set aRes to (current application’s GEMagicKit’s magicForFileAtPath:aFile) set aaRes to aRes’s |description|() as string –> "ISO Media, MPEG v4 system, version 2" set aMime to (aRes’s mimeType()) as string –> "video/mp4; charset=binary" set utiList to (aRes’s uniformTypeHierarchy()) as list –> {"com.apple.quicktime-movie", "public.movie", "public.audiovisual-content", "public.data", "public.content", "public.item"} set aDesc to (aRes’s |description|()) as string –> "ISO Media, Apple QuickTime movie" |
calcColorDomainLib
AppleScript名:calcColorDomainLib |
— Created 2018-01-08 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSColor : a reference to current application’s NSColor set {rCol, gCol, bCol} to choose color set cName to retColorDomainName(rCol, gCol, bCol, 65535) of me set cValue to retColorDomainValue(rCol, gCol, bCol, 65535) of me return {cName, cValue} on retColorDomainName(rCol as integer, gCol as integer, bCol as integer, aColorMax) set aCol to makeNSColorFromRGBAval(rCol, gCol, bCol, aColorMax, aColorMax) of me return retColorDomainNameFronNSColor(aCol) of me end retColorDomainName on retColorDomainNameFronNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 set colName to "" if satVal = 0.0 then if brightVal ≤ 0.2 then set colName to "black" else if (brightVal > 0.95) then set colName to "white" else set colName to "gray" end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colName to "red" else if hueVal ≤ (45.0 / 360) then set colName to "orange" else if hueVal < (70.0 / 360) then set colName to "yellow" else if hueVal < (150.0 / 360) then set colName to "green" else if hueVal < (190.0 / 360) then set colName to "light blue" –cyan else if (hueVal < 250.0 / 360.0) then set colName to "blue" else if (hueVal < 290.0 / 360.0) then set colName to "purple" else set colName to "pink" –magenta end if end if return colName end retColorDomainNameFronNSColor on retColorDomainValue(rCol as integer, gCol as integer, bCol as integer, aColorMax) set aCol to makeNSColorFromRGBAval(rCol, gCol, bCol, aColorMax, aColorMax) of me return retColorDomainValueFromNSColor(aCol) of me end retColorDomainValue on retColorDomainValueFromNSColor(aCol) set hueVal to aCol’s hueComponent() set satVal to aCol’s saturationComponent() set brightVal to aCol’s brightnessComponent() if satVal ≤ 0.01 then set satVal to 0.0 if satVal = 0.0 then if brightVal ≤ 0.2 then set colVal to {0, 0, 0} –Black else if (brightVal > 0.95) then set colVal to {65535, 65535, 65535} –White else set colVal to {32768, 32768, 32768} –Gray end if else if hueVal ≤ (15.0 / 360) or hueVal ≥ (330 / 360) then set colVal to {65535, 0, 0} –red else if hueVal ≤ (45.0 / 360) then set colVal to {65535, 32768, 0} –orange else if hueVal < (70.0 / 360) then set colVal to {65533, 63639, 2654} –yellow else if hueVal < (150.0 / 360) then set colVal to {4626, 35488, 17789} –green else if hueVal < (190.0 / 360) then set colVal to {0, 60802, 65535} –cyan, light blue else if (hueVal < 250.0 / 360.0) then set colVal to {0, 0, 65535} –blue else if (hueVal < 290.0 / 360.0) then set colVal to {32768, 0, 32768} –purple else set colVal to {65535, 0, 65535} –magenta, pink end if end if return colVal end retColorDomainValueFromNSColor on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer) set aRedCocoa to (redValue / aMaxVal) as real set aGreenCocoa to (greenValue / aMaxVal) as real set aBlueCocoa to (blueValue / aMaxVal) as real set aAlphaCocoa to (alphaValue / aMaxVal) as real set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa return aColor end makeNSColorFromRGBAval |
Camel Case化
AppleScript名:Camel Case化 |
— Created 2015-12-24 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" camelCase("this is a pen") of me –> "thisIsAPen." on camelCase(aPhrase) set firstWord to current application’s NSString’s stringWithString:(word 1 of aPhrase) set firstWord to firstWord’s |lowercaseString|() set restOfPhrase to current application’s NSString’s stringWithString:(text from word 2 to -1 of aPhrase) set restOfPhrase to restOfPhrase’s capitalizedString()’s stringByReplacingOccurrencesOfString:space withString:"" set newPhrase to firstWord’s stringByAppendingString:restOfPhrase return (newPhrase’s stringByFoldingWithOptions:(current application’s NSDiacriticInsensitiveSearch) locale:(missing value)) as text end camelCase |
文字エンコーディングを自動判別してファイル読み込み v1.2.1
指定のテキストファイル(日本語テキストを想定)を、文字エンコーディングを自動判定して読み込むAppleScriptです。
これまで、日本語テキストファイルの文字エンコーディングを自動判定するのにテキストエディタをAppleScriptからコントロールして使っていましたが、それだと並列処理するAppleScriptの中で使用できないし、テキストエディタがない環境では実行することができません(ダウンロードすればいいだけの話ですが)。
さまざまな日本語テキストエディタのソースコードをながめて、文字コードの自動判定ロジックがわかってきたので、AppleScriptで実装してみました。さらに、独自の「文字化け判定ロジック」を考えたので、それを併用しています。
Step 1 伝統的な判定(勝ち抜け方式)
伝統的な文字コードの判定を順次行います。この、判定を行う順序が重要です。最初にISO2022JPのチェック、ついでEUC、UTF-8、シフトJISと、順次コード判定を行います。勝ち抜け方式で、妥当な文字エンコーディングとみなしたらそこで評価を打ち切ります。
Step 2 総当たり判定(全部評価してから考える)
UTF-16BE/LE/無印Unicodeについては、それぞれの文字エンコーディングで実際に評価してみて、文字化けしないものを採用します。独自ロジックにより文字化け状態をプログラム的に判断するのと、そのエンコーディングで読み込んだ結果をNSLinguisticTaggerで評価し、「ja」(日本語)と判定するかどうかの確認をすべてのエンコーディングで行なっています。
以上の2ステップでだいたい日本語テキストのエンコーディング自動判定ができています。
もし、寿司屋の湯のみ茶碗のように漢字で魚の名前を羅列した日本語テキストがUTF-16BEとかで書かれていたりすると自動判定できない可能性もありますが、青空文庫の日本語テキストやWebに掲載されているテクニカルな記事(アルファベットやカタカナの使用比率が高い)でテストしてみたところ、問題なく判定できています(実際に魚の名前のテキストを作って読み込んでみましたが、とくに問題はありませんでした)。
だいたい、日本語として意味をなしているようなテキストであれば、文字コードの自動判定はできているように思います。ただ、世間は広いので、本Scriptのロジックで判定できないようなケースもあるかもしれません。そのような時にはコメント欄やフォーラムへの報告をお願いいたします(対応するかどうかは別として。知り合いのテキストエディタ作者の方は、無償で公開しているソフトに文句を言われて「すぐに対応しろ!」だのと散々言われたそうで、、、、、、、)。
AppleScript名:文字エンコーディングを自動判別してファイル読み込み v1.2.1 |
— Created 2014-12-28 by Takaaki Naganoya — Modified 2014-12-29 by Shane Stanley — Modified 2015-10-03 by Takaaki Naganoya use AppleScript version "2.5" use scripting additions use framework "Foundation" set aPath to POSIX path of (choose file) set aRes to readJapanesTextFileWithGuessingEncoding(aPath) of me set bRes to aRes as string –Read Japanese text with detecting its text encoding on readJapanesTextFileWithGuessingEncoding(aPOSIXpath as string) –ISO2022JP check set aNSData to current application’s NSData’s dataWithContentsOfFile:aPOSIXpath set aDataLength to aNSData’s |length|() if aDataLength > 1024 then set aDataLength to 1024 –0x1B check set anNSString to current application’s NSString’s stringWithString:(character id 27) — 0x1B set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set theRange to aNSData’s rangeOfData:theData options:0 range:(current application’s NSMakeRange(0, aDataLength)) –found 0x1B in aNSData if |length| of theRange = 1 and location of theRange < aDataLength then set aStr to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSISO2022JPStringEncoding)) –21 if aStr is not equal to missing value then return (aStr as text) — ISO2022JP end if –EUC set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSJapaneseEUCStringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –UTF-8 set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF8StringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –SHift JIS set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSShiftJISStringEncoding)) –log resValue if resValue is not equal to missing value then return (resValue as text) –UTF-16BE/LE/無印Unicodeは多数決を取る set resValue1 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16BigEndianStringEncoding)) as text –log resValue1 set sample1 to getTextSample(resValue1) of me set lang1 to specifyLanguageOfText(sample1) of me set para1 to length of (paragraphs of sample1) set words1 to length of (words of sample1) set resValue2 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16LittleEndianStringEncoding)) as text –log resValue2 set sample2 to getTextSample(resValue2) of me set lang2 to specifyLanguageOfText(sample2) of me set para2 to length of (paragraphs of sample2) set words2 to length of (words of sample2) set resValue3 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUnicodeStringEncoding)) as text –log resValue3 set sample3 to getTextSample(resValue3) of me set lang3 to specifyLanguageOfText(sample3) of me set para3 to length of (paragraphs of sample3) set words3 to length of (words of sample3) –文字および文法的に見て「日本語」ならそれを返す if lang1 = "ja" then return resValue1 if lang2 = "ja" then return resValue2 if lang3 = "ja" then return resValue2 –文字化けしたときには、日本語の「Word」として認識されづらく、Paragraphも少ない(1とか)なので条件で除外する if para1 is not equal to 1 then if (words1 ≤ words2) or (words1 ≤ words3) then return resValue1 end if end if if para2 is not equal to 1 then if (words2 ≤ words1) or (words2 ≤ words3) then return resValue2 end if end if if para3 is not equal to 1 then if (words3 ≤ words1) or (words3 ≤ words2) then return resValue3 end if end if return false (* –おまけ(未確認) set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1251StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1252StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1253StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1254StringEncoding)) if resValue is not equal to missing value then return resValue set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1250StringEncoding)) if resValue is not equal to missing value then return resValue return false *) end readJapanesTextFileWithGuessingEncoding on specifyLanguageOfText(aStr) set aNSstring to current application’s NSString’s stringWithString:aStr set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage) set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0 tagger’s setString:aNSstring set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value) return aLanguage as text end specifyLanguageOfText on getTextSample(aText) set aLen to length of aText if aLen < 1024 then set bLen to aLen else set bLen to 1024 end if return (text 1 thru bLen of aText) end getTextSample |
UniversalDetectorで文字コード判定
UniversalDetector.frameworkを呼び出して指定のテキストファイルの文字コードを判定するAppleScriptです。
日本語のテキストで実験してみたところ、UTF-16系以外は正常に判定できています。日本語以外の言語を対象にした場合には使い手がありそうですが、日本語を対象にした場合には、「文字エンコーディングを自動判別してファイル読み込み v1.2.1」のほうが便利です。
–> UniversalDetector.framework
AppleScript名:UniversalDetectorで文字コード判定 |
— Created 2015-10-03 by Takaaki Naganoya — 2015 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "UniversalDetector" –https://github.com/JanX2/UniversalDetector set aPath to (POSIX path of (choose file)) set aStr to current application’s NSString’s stringWithString:aPath set aDetector to current application’s UniversalDetector’s new() aDetector’s analyzeContentsOfFile:aStr set aStr to current application’s NSString’s localizedNameOfStringEncoding:(aDetector’s encoding()) –> (NSString) "日本語(EUC)" –> (NSString) "日本語(ISO 2022-JP)" –> (NSString) "日本語(Shift JIS)" –> (NSString) "Unicode(UTF-8)" –> (NSString) "キリル文字(Windows)" –NG。本当はUTF-16 no BOM –> (NSString) "中国語(GB 18030)"–NG。本当はUTF-16BE –> (NSString) "Unicode(UTF-16)" set bStr to aDetector’s MIMECharset() –> (NSString) "EUC-JP" –> (NSString) "ISO-2022-JP" –> (NSString) "Shift_JIS" –> (NSString) "UTF-8" –> (NSString) "windows-1251"–NG –> (NSString) "gb18030"–NG –> (NSString) "UTF-16" set aNum to (aDetector’s confidence()) * 100 –> 100.0–"EUC-JP" –> 100.0–"ISO-2022-JP" –> 100.0–"Shift_JIS" –> 100.0–"UTF-8" –> 5.271286144853–UTF-16 no BOM –> 100.0–NGだが100%といっている –> 100.0– "UTF-16" return {aStr as string, bStr as string, aNum} |
base64エンコード、デコード v3
テキストのBase64エンコード/デコードを行うAppleScriptです。
このような基本的なデータ変換機能についてはAppleScript標準で持っていないため、Classic MacOS時代にはOSAX(Scripting Additions)で、Mac OS X時代になってからは他の言語処理系の機能を借りたり、Mac OS X用のOSAXを利用していたりしましたが、現在のmacOSではCocoaの機能を呼び出すのが一番手頃になってきました。
# サードパーティ製のOSAX(Scripting Additions)サポートはmacOS 10.14で廃止になりました。macOS標準搭載のStandard Additionsのみ利用可能です
AppleScript名:base64エンコード、デコード v3 |
— Created 2015-07-27 by Takaaki Naganoya — Updated 2015-07-28 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "ぴよまるソフトウェアPiyomaru Software" set theNSString to current application’s NSString’s stringWithString:aStr set theNSData to theNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set bStr to base64StringFromFileString(aStr) of me return bStr –> "44G044KI44G+44KL44K944OV44OI44Km44Kn44KiUGl5b21hcnUgU29mdHdhcmU=" –set aFilePath to POSIX path of (choose file) –base64StringFromFileAtPath(aFilePath) of me –Base 64 Decode on detaFromBase64String(aStr) set dataFrom64 to current application’s NSData’s alloc()’s initWithBase64EncodedString:aStr options:(current application’s NSDataBase64DecodingIgnoreUnknownCharacters) set aStr to current application’s NSString’s alloc()’s initWithData:dataFrom64 encoding:(current application’s NSUTF8StringEncoding) return aStr as text –stringではなくtext end detaFromBase64String –Base64 Encode on base64StringFromFileAtPath(aFilePath) set aDataFromFile to current application’s NSData’s dataWithContentsOfFile:aFilePath set aBase64EncStr to aDataFromFile’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileAtPath –Base64 Encode on base64StringFromFileString(aString) set bString to current application’s NSString’s stringWithString:aString set aData to bString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding) set aBase64EncStr to aData’s base64EncodedStringWithOptions:(current application’s NSDataBase64Encoding64CharacterLineLength) return aBase64EncStr as text end base64StringFromFileString |
デコードしたQRコードのメールデータの各フィールドを取り出す v2.2
AppleScript名:デコードしたQRコードのメールデータの各フィールドを取り出す v2.2 |
— Created 2016-12-12 by Shane Stanley — Modified 2016-12-14 by edama2 — Modified 2017-01-12 by Takaaki Naganoya use AppleScript version "2.4" use scripting additions use framework "Foundation" set aStr to "こんにちは、ぴよまるです MATMSG:TO:hiyoko@piyocast.com;SUB:たいとる;BODY:ほんぶん;; Takaaki Naganoya iPhoneから送信" set aDict to (parseStrByParamlabelAndTail(aStr, "MATMSG:", ":", ";") of me) set eMailAddrs to (aDict’s valueForKey:"TO") as string–> "hiyoko@piyocast.com" set aSubject to (aDict’s valueForKey:"SUB") as string –> "たいとる" set aBody to (aDict’s valueForKey:"BODY") as string –> "ほんぶん" on parseStrByParamlabelAndTail(aParamStr, aDataHeader, aParamLabel, aParamTail) set theScanner to current application’s NSScanner’s scannerWithString:aParamStr set aDict to current application’s NSMutableDictionary’s |dictionary|() —Skip over the data header set {theResult, theKey} to theScanner’s scanUpToString:aDataHeader intoString:(reference) if theResult as boolean = false then return false –Error: Data header is not present theScanner’s scanString:aDataHeader intoString:(missing value) repeat until (theScanner’s isAtEnd as boolean) — terminate check, return the result (aDict) to caller set {theResult, theKey} to theScanner’s scanUpToString:aParamLabel intoString:(reference) — skip over separator theScanner’s scanString:aParamLabel intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:aParamTail intoString:(reference) if theValue is missing value then set theValue to "" — skip over separator theScanner’s scanString:aParamTail intoString:(missing value) aDict’s setObject:theValue forKey:theKey end repeat return aDict end parseStrByParamlabelAndTail |
date pickerによる日付選択
AppleScript名:date pickerによる日付選択 |
— Created 2015-08-20 by Shane Stanley use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use script "BridgePlus" — https://www.macosxautomation.com/applescript/apps/BridgePlus.html if not (current application’s NSThread’s isMainThread()) as boolean then display alert "This script must be run from the main thread." buttons {"Cancel"} as critical error number -128 end if — create a view set theView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 100, 200)) — create date picker set datePicker to current application’s NSDatePicker’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 100, 100)) — set style: choices are NSTextFieldAndStepperDatePickerStyle, NSClockAndCalendarDatePickerStyle, or NSTextFieldDatePickerStyle datePicker’s setDatePickerStyle:(current application’s NSClockAndCalendarDatePickerStyle) — set elements: choices include NSHourMinuteDatePickerElementFlag, NSHourMinuteSecondDatePickerElementFlag, NSTimeZoneDatePickerElementFlag, NSYearMonthDatePickerElementFlag, and NSEraDatePickerElementFlag datePicker’s setDatePickerElements:((current application’s NSYearMonthDayDatePickerElementFlag) + (current application’s NSHourMinuteSecondDatePickerElementFlag as integer)) — set initial date datePicker’s setDateValue:(current application’s NSDate’s |date|()) — get the size it needs set theSize to datePicker’s fittingSize() –resize the picker and view accordingly theView’s setFrameSize:theSize datePicker’s setFrameSize:theSize — add the picker to the view theView’s setSubviews:{datePicker} — create an alert set theAlert to current application’s NSAlert’s alloc()’s init() — set up alert tell theAlert its setMessageText:"Pick a date" its setInformativeText:"Any date" its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:theView end tell — show alert in modal loop set returnCode to theAlert’s runModal() if returnCode = (current application’s NSAlertSecondButtonReturn) then error number -128 — retrieve date set theDate to ASify from (datePicker’s dateValue()) — or simply coerce to date in 10.11 –> date "2015年8月20日木曜日 19:43:58" |
リストから選択してアイテム番号を返す
AppleScriptの配列変数であるリスト型の変数(ただし、1次元)から選択し、選択した要素のアイテム番号(1はじまり)を数値で返すAppleScriptです。
AppleScriptに標準で用意されている「choose from list」コマンドは、選択した項目の文字列を返してきますが、その仕様だと困るケースがけっこうあります。
選択された要素の内容(文字列)ではなく、何項目(インデックス、アイテム番号)が選択されたかという情報を返してきてほしいところです。
そこで、ないなら作ってしまえばよいわけで、そういう仕様のルーチンを自分で作っておいたわけです。
AppleScript名:リストから選択してアイテム番号を返す |
set aList to {"red", "blue", "green", "white"} set aMes to "項目を選択してください" set aRes to retItemFromListByItemNo(aList, aMes) of me –> 3 (選択したアイテムの番号(1はじまり)が返る –リストから選択してアイテム番号を返す on retItemFromListByItemNo(aList, aMes) set aRes to choose from list aList with prompt aMes if aRes = false then return 0 set aRes to contents of item 1 of aRes set hitNum to 1 repeat with i in aList set j to contents of i if j is equal to aRes then exit repeat end if set hitNum to hitNum + 1 end repeat return hitNum end retItemFromListByItemNo |
ステータスバーのじっけん2
AppleScript名:ステータスバーのじっけん2 |
— Created 2017-03-03 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property aStatusItem : missing value on run init() of me end run on init() set aList to {"Piyomaru", "Software", "", "Takaaki", "Naganoya", "", "Quit"} set aStatusItem to current application’s NSStatusBar’s systemStatusBar()’s statusItemWithLength:(current application’s NSVariableStatusItemLength) aStatusItem’s setTitle:"🚗" aStatusItem’s setHighlightMode:true aStatusItem’s setMenu:(createMenu(aList) of me) end init on createMenu(aList) set aMenu to current application’s NSMenu’s alloc()’s init() set aCount to 1 repeat with i in aList set j to contents of i if j is not equal to "" then if j = "Quit" then set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:j action:"actionHandler:" keyEquivalent:"") –(aMenuItem’s setKeyEquivalentModifierMask:(current application’s NSControlKeyMask)) else set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:j action:"actionHandler:" keyEquivalent:"") end if else set aMenuItem to (current application’s NSMenuItem’s separatorItem()) end if (aMenuItem’s setTarget:me) (aMenuItem’s setTag:aCount) (aMenu’s addItem:aMenuItem) if j is not equal to "" then set aCount to aCount + 1 end if end repeat return aMenu end createMenu on actionHandler:sender set aTag to tag of sender as integer set aTitle to title of sender as string if aTitle is not equal to "Quit" then display dialog aTag as string else current application’s NSStatusBar’s systemStatusBar()’s removeStatusItem:aStatusItem end if end actionHandler: |
なろう系ルビタグを置換
AppleScript名:なろう系ルビタグを置換 |
— Created 2018-01-14 by Takaaki Naganoya — 2018 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" property NSString : a reference to current application’s NSString property NSScanner : a reference to current application’s NSScanner property NSMutableArray : a reference to current application’s NSMutableArray property NSRegularExpressionSearch : a reference to current application’s NSRegularExpressionSearch property NSNumberFormatterRoundUp : a reference to current application’s NSNumberFormatterRoundUp set aStr to " 数多国ある西方諸国だが、元を辿ればとある一つの国へとつながっていた。それは幻晶騎士(シルエットナイト)の力により西方の地に覇をとなえた人類が作り上げた超巨大国家、その名を“ファダーアバーデン”という。 西方暦一二八九年の現在において西方諸国を構成する主要国家、“ジャロウデク王国”、“クシェペルカ王国”、“ロカール諸国連合”、“|孤独なる十一《イレブンフラッグス》”などの国々は、全てかの巨大国家が分裂してできた残滓なのである。" –set aStr to getEditorText() –"|○o○o○《XXXXX》" –> "XXXXX" set bRes to trimStrHeaderFromTo(aStr, "|", "《", "》") of me –"aaaaa○○○(XXXXX)" –> "XXXXX" set cStr to trimStrHeaderFromToForward(bRes, "(", ")") of me (* " 数多国ある西方諸国だが、元を辿ればとある一つの国へとつながっていた。それはシルエットナイトの力により西方の地に覇をとなえた人類が作り上げた超巨大国家、その名を“ファダーアバーデン”という。 西方暦一二八九年の現在において西方諸国を構成する主要国家、“ジャロウデク王国”、“クシェペルカ王国”、“ロカール諸国連合”、“イレブンフラッグス”などの国々は、全てかの巨大国家が分裂してできた残滓なのである。" *) –"|○o○o○《XXXXX》" –> "XXXXX" on trimStrHeaderFromTo(aParamStr, headerStr, fromStr, toStr) set theScanner to NSScanner’s scannerWithString:aParamStr set anArray to NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) set {theResult, theKey} to theScanner’s scanUpToString:headerStr intoString:(reference) theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:fromStr intoString:(reference) if theValue is missing value then set theValue to "" theScanner’s scanString:fromStr intoString:(missing value) anArray’s addObject:theValue end repeat if anArray’s |count|() = 0 then return aParamStr copy aParamStr to curStr repeat with i in (anArray as list) set curStr to repChar(curStr, i & fromStr, "") of me end repeat set curStr to repChar(curStr, toStr, "") of me return curStr end trimStrHeaderFromTo –"aaaaa○○○(XXXXX)" –> "XXXXX" on trimStrHeaderFromToForward(aParamStr, fromStr, toStr) set theScanner to NSScanner’s scannerWithString:aParamStr set anArray to NSMutableArray’s array() repeat until (theScanner’s isAtEnd as boolean) set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference) set curLoc to (theScanner’s scanLocation()) + 1 –scan back to different kind of character set prevKind to detectCharKindMain(text (curLoc – 1) of aParamStr) of me repeat with i from curLoc – 2 to 1 by -1 set aStr to text i of aParamStr set curKind to detectCharKindMain(aStr) of me if prevKind is not equal to curKind then exit repeat end if end repeat try set tmpStr to text (i + 1) thru curLoc of aParamStr theScanner’s scanString:fromStr intoString:(missing value) set {theResult, theValue} to theScanner’s scanUpToString:fromStr intoString:(reference) if theValue is missing value then set theValue to "" theScanner’s scanString:fromStr intoString:(missing value) anArray’s addObject:tmpStr end try end repeat if anArray’s |count|() = 0 then return aParamStr copy aParamStr to curStr repeat with i in (anArray as list) set curStr to repChar(curStr, i, "") of me end repeat set curStr to repChar(curStr, toStr, "") of me return curStr end trimStrHeaderFromToForward on repChar(aStr, targStr, repStr) set aString to current application’s NSString’s stringWithString:aStr set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr set cString to bString as string return cString end repChar –文字種別判定 on detectCharKindMain(aStr) set s1Res to chkKanji(aStr) of me set s2Res to chkKatakana(aStr) of me set s3Res to chkHiragana(aStr) of me set s4Res to chkLineFeed(aStr) of me set s5Res to chkSpecialSign(aStr) of me set s6Res to chkAlphaNumeric(aStr) if s1Res = true then set curKind to "Kanji" else if s2Res = true then set curKind to "Katakana" else if s3Res = true then set curKind to "Hiragana" else if s4Res = true then set curKind to "Line Feed" else if s5Res = true then set curKind to "Sign" else if s6Res = true then set curKind to "Alpha Numeric" end if return curKind end detectCharKindMain on chkKanji(aChar) return detectCharKind(aChar, "[一-龠]") of me end chkKanji on chkHiragana(aChar) return detectCharKind(aChar, "[ぁ-ん]") of me end chkHiragana on chkKatakana(aChar) return detectCharKind(aChar, "[ァ-ヶ]") of me end chkKatakana on chkLineFeed(aChar) return aChar is in {string id 10, string id 13, string id 13 & string id 10} end chkLineFeed on chkSpecialSign(aChar) return aChar is in {"「", "」", "『", "』", "ー", "―", "〜", "~", "!", "?", "&", "/", "《", "》", "#", "…", "・", "♪", "。", "、", ".", "々", "“", "”", "*", "(", ")", "(", ")", " ", " ", "§", "【", "】", "■", "%", "≒"} end chkSpecialSign on chkAlphaNumeric(aChar) return detectCharKind(aChar, "[a-zA-Z0-9a-zA-Z0-9]") of me –半角全角英数字 end chkAlphaNumeric on detectCharKind(aChar, aPattern) set aChar to NSString’s stringWithString:aChar set searchStr to NSString’s stringWithString:aPattern set matchRes to aChar’s rangeOfString:searchStr options:(NSRegularExpressionSearch) if matchRes’s location() = (current application’s NSNotFound) or (matchRes’s location() as number) > 9.99999999E+8 then return false else return true end if end detectCharKind on getEditorText() tell application "CotEditor" if (count every document) = 0 then return false tell front document return contents end tell end tell end getEditorText |
指定写真をQRコード認識してエンコードされたデータをデコード
–> {“MEMORY:(メモ文字列)
NAME1:(姓名)
NAME2:(姓名読み)
TEL1:(電話番号1)
MAIL1:(メールアドレス1)
TEL2:(電話番号2)
MAIL2:(メールアドレス2)
MECARD:N:(姓),(名);SOUND:(姓読み),(名読み);TEL:(電話番号1);TEL:(電話番号2);EMAIL:(メールアドレス1);EMAIL:(メールアドレス2);NOTE:(メモ文字列) ;;”}
AppleScript名:指定写真をQRコード認識してエンコードされたデータをデコード |
use AppleScript version "2.4" use framework "Foundation" use framework "QuartzCore" use scripting additions –画像選択 set inputFile to choose file of type {"public.image"} –QRコード検出 set recogRes to qrcodeDetect(inputFile) of me –> (* {"http://www.su-gomori.com \nMEBKM:TITLE:スゴモリ;URL:http¥://www.su-gomori.com;;"} *) on qrcodeDetect(inputFile) –画像オープン set imageRef to openImageFile(inputFile) — 検出器のオプションを NSDictonary で作成 set optDic1 to current application’s NSDictionary’s dictionaryWithObject:(current application’s CIDetectorAccuracyHigh) forKey:(current application’s CIDetectorAccuracy) set faceDetector to current application’s CIDetector’s detectorOfType:(current application’s CIDetectorTypeQRCode) context:(missing value) options:optDic1 — QRコードの検出を行う際のオプションを NSDictonary で作成 set optDic2 to current application’s NSDictionary’s dictionaryWithObject:(current application’s CIDetectorImageOrientation) forKey:"Orientation" — QRコード検出を実行 set faceArray to faceDetector’s featuresInImage:imageRef options:optDic2 set fList to {} — 検出されたQRコードの位置とサイズをログに出力 repeat with i from 1 to (count of faceArray) set face to item i of faceArray set bRec to (face’s messageString()) as string –set cRec to retURLdecodedStrings(bRec) of me –URLエンコード対策 set the end of fList to bRec end repeat return fList end qrcodeDetect on openImageFile(imageFile) — imageFile: POSIX path 形式のファイルパス — aliasをURLに変換 set fileURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of imageFile) — CIImage を生成 return current application’s CIImage’s alloc()’s initWithContentsOfURL:fileURL end openImageFile on retURLencodedStrings(aText) set aStr to current application’s NSString’s stringWithString:aText set encodedStr to aStr’s stringByAddingPercentEncodingWithAllowedCharacters:(current application’s NSCharacterSet’s alphanumericCharacterSet()) return encodedStr as text end retURLencodedStrings on retURLdecodedStrings(aURLencodedStr) set aStr to current application’s NSString’s stringWithString:aURLencodedStr set aDecoded to aStr’s stringByRemovingPercentEncoding() return aDecoded as text end retURLdecodedStrings |
指定文字列からQRコード画像(PNG)をデスクトップに作成する(日本語を含むデータ)v2_画像拡大倍率指定
AppleScript名:指定文字列からQRコード画像(PNG)をデスクトップに作成する(日本語を含むデータ)v2_画像拡大倍率指定 |
— Created 2016-03-16 by Takaaki Naganoya — Modified 2017-01-15 by Takaaki Naganoya — 2016 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" use framework "QuartzCore" –QRCodeを作成 set a to "MEMORY:(メモ文字列) NAME1:(姓名) NAME2:(姓名読み) TEL1:(電話番号1) MAIL1:(メールアドレス1) TEL2:(電話番号2) MAIL2:(メールアドレス2) MECARD:N:(姓),(名);SOUND:(姓読み),(名読み);TEL:(電話番号1);TEL:(電話番号2);EMAIL:(メールアドレス1);EMAIL:(メールアドレス2);NOTE:(メモ文字列) ;;" set aStr to current application’s NSString’s stringWithString:a set strData to aStr’s dataUsingEncoding:(current application’s NSShiftJISStringEncoding) –シフトJISにエンコード set qrFilter to current application’s CIFilter’s filterWithName:"CIQRCodeGenerator" qrFilter’s setValue:strData forKey:"inputMessage" qrFilter’s setValue:"H" forKey:"inputCorrectionLevel" set anImage to qrFilter’s outputImage() set convImg to convCIimageToNSImage(anImage) of me –NSImageを拡大(アンチエイリアス解除で) set resizedImg to my resizeNSImageWithoutAntlialias:convImg toScale:16.0 –デスクトップに保存 set aDesktopPath to (current application’s NSProcessInfo’s processInfo()’s environment()’s objectForKey:("HOME"))’s stringByAppendingString:"/Desktop/" set savePath to aDesktopPath’s stringByAppendingString:((current application’s NSUUID’s UUID()’s UUIDString())’s stringByAppendingString:".png") saveNSImageAtPathAsPNG(resizedImg, savePath) of me on convCIimageToNSImage(aCIImage) set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithCIImage:aCIImage set tmpSize to aRep’s |size|() set newImg to current application’s NSImage’s alloc()’s initWithSize:tmpSize newImg’s addRepresentation:aRep return newImg end convCIimageToNSImage on convNSImageToCIimage(aNSImage) set tiffDat to aNSImage’s TIFFRepresentation() set aRep to current application’s NSBitmapImageRep’s imageRepWithData:tiffDat set newImg to current application’s CIImage’s alloc()’s initWithBitmapImageRep:aRep return newImg end convNSImageToCIimage –NSImageを指定パスにPNG形式で保存 on saveNSImageAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:imageRep set pathString to current application’s NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value)) set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean return aRes –成功ならtrue、失敗ならfalseが返る end saveNSImageAtPathAsPNG –NSImageを指定倍率で拡大(アンチエイリアス解除状態で)–By Shane Stanley on resizeNSImageWithoutAntlialias:aSourceImg toScale:imgScale set aSize to aSourceImg’s |size|() set aWidth to (aSize’s width) * imgScale set aHeight to (aSize’s height) * imgScale set aRep to current application’s NSBitmapImageRep’s alloc()’s initWithBitmapDataPlanes:(missing value) pixelsWide:aWidth pixelsHigh:aHeight bitsPerSample:8 samplesPerPixel:4 hasAlpha:true isPlanar:false colorSpaceName:(current application’s NSCalibratedRGBColorSpace) bytesPerRow:0 bitsPerPixel:0 set newSize to {width:aWidth, height:aHeight} aRep’s setSize:newSize current application’s NSGraphicsContext’s saveGraphicsState() set theContext to current application’s NSGraphicsContext’s graphicsContextWithBitmapImageRep:aRep current application’s NSGraphicsContext’s setCurrentContext:theContext theContext’s setShouldAntialias:false theContext’s setImageInterpolation:(current application’s NSImageInterpolationNone) aSourceImg’s drawInRect:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) fromRect:(current application’s NSZeroRect) operation:(current application’s NSCompositeCopy) fraction:(1.0) current application’s NSGraphicsContext’s restoreGraphicsState() set newImg to current application’s NSImage’s alloc()’s initWithSize:newSize newImg’s addRepresentation:aRep return newImg end resizeNSImageWithoutAntlialias:toScale: |
Finder上で選択中の画像を横方向に連結
AppleScript名:Finder上で選択中の画像を横方向に連結 |
— Created 2017-11-21 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "QuartzCore" use framework "AppKit" use framework "MagicKit" –https://github.com/aidansteele/magickit property |NSURL| : a reference to current application’s |NSURL| property NSUUID : a reference to current application’s NSUUID property NSArray : a reference to current application’s NSArray property NSString : a reference to current application’s NSString property NSImage : a reference to current application’s NSImage property GEMagicKit : a reference to current application’s GEMagicKit property NSPNGFileType : a reference to current application’s NSPNGFileType property NSMutableArray : a reference to current application’s NSMutableArray property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep property xGap : 10 –連結時の画像間のアキ(横方向) tell application "Finder" set aSel to selection as alias list if aSel = {} or aSel = "" then return end tell –選択した画像をArrayに入れる set imgList to NSMutableArray’s new() repeat with i in aSel set aPath to POSIX path of i –指定ファイルのUTIを取得して、画像(public.image)があれば処理を行う set aRes to (GEMagicKit’s magicForFileAtPath:aPath) set utiList to (aRes’s uniformTypeHierarchy()) as list if "public.image" is in utiList then set aNSImage to (NSImage’s alloc()’s initWithContentsOfFile:aPath) (imgList’s addObject:aNSImage) end if end repeat –KVCで画像の各種情報をまとめて取得 set sizeList to (imgList’s valueForKeyPath:"size") as list –NSSize to list of record conversion set maxHeight to ((NSArray’s arrayWithArray:sizeList)’s valueForKeyPath:"@max.height") as real set totalWidth to ((NSArray’s arrayWithArray:sizeList)’s valueForKeyPath:"@sum.width") as real set totalCount to ((NSArray’s arrayWithArray:sizeList)’s valueForKeyPath:"@count") as integer –出力画像作成 set tSize to current application’s NSMakeSize((totalWidth + (xGap * totalCount)), maxHeight) set newImage to NSImage’s alloc()’s initWithSize:tSize –順次画像を新規画像に上書き set xOrig to 0 repeat with i in (imgList as list) set j to contents of i set curSize to j’s |size|() set aRect to {xOrig, (maxHeight – (curSize’s height())), (curSize’s width()), (curSize’s height())} set newImage to composeImage(newImage, j, aRect) of me set xOrig to (curSize’s width()) + xGap end repeat –デスクトップにPNG形式でNSImageをファイル保存 set aDesktopPath to current application’s NSHomeDirectory()’s stringByAppendingString:"/Desktop/" set savePath to aDesktopPath’s stringByAppendingString:((NSUUID’s UUID()’s UUIDString())’s stringByAppendingString:".png") set fRes to saveNSImageAtPathAsPNG(newImage, savePath) of me –2つのNSImageを重ね合わせ合成してNSImageで返す on composeImage(backImage, composeImage, aTargerRect) set newImage to NSImage’s alloc()’s initWithSize:(backImage’s |size|()) copy aTargerRect to {x1, y1, x2, y2} set bRect to current application’s NSMakeRect(x1, y1, x2, y2) newImage’s lockFocus() set newImageRect to current application’s CGRectZero set newImageRect’s |size| to (newImage’s |size|) backImage’s drawInRect:newImageRect composeImage’s drawInRect:bRect newImage’s unlockFocus() return newImage end composeImage –NSImageを指定パスにPNG形式で保存 on saveNSImageAtPathAsPNG(anImage, outPath) set imageRep to anImage’s TIFFRepresentation() set aRawimg to NSBitmapImageRep’s imageRepWithData:imageRep set pathString to NSString’s stringWithString:outPath set newPath to pathString’s stringByExpandingTildeInPath() set myNewImageData to (aRawimg’s representationUsingType:(NSPNGFileType) |properties|:(missing value)) set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean return aRes –成功ならtrue、失敗ならfalseが返る end saveNSImageAtPathAsPNG |