Archive for the 'AppleScriptObjC' Category

2017/05/20 最大公約数を求めるv2

2つの数の最大公約数を求めるAppleScriptです。

素数チェックや素因数分解を作ったので、この手の計算を行ってみました。

AppleScript名:最大公約数を求めるv2
– Created 2017-05-20 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4653

set aRes to getGCDbetweenTwoNums(12, 18) of me
–> 6

–2つの数の最大公約数を求める
on getGCDbetweenTwoNums(aNum, bNum)
  set aRes to getPrimeFactor(aNum) of me
  
set bRes to getPrimeFactor(bNum) of me
  
  
–2つのリストを集合として扱い、積集合を求める
  
set aSet to current application’s NSMutableSet’s setWithArray:aRes
  
set bSet to current application’s NSMutableSet’s setWithArray:bRes
  
aSet’s intersectSet:bSet
  
set cRes to aSet’s allObjects() as list
  
  
set dRes to multipleListElements(cRes) of me
  
return dRes
end getGCDbetweenTwoNums

–与えられた数を素因数分解する
on getPrimeFactor(aTargNum)
  copy aTargNum to a
  
set pFactList to {}
  
  
repeat
    set pRes to checkPrimeNumber(a) of me
    
if pRes = true then
      set the end of pFactList to a
      
return pFactList
    end if
    
    
set aFactor to checkFactor(a) of me
    
set the end of pFactList to aFactor
    
set a to a div aFactor
  end repeat
end getPrimeFactor

–素数チェック
on checkPrimeNumber(aNum)
  repeat with i from 2 to aNum - 1
    if aNum mod i is equal to 0 then
      return false
    end if
  end repeat
  
return true
end checkPrimeNumber

–素因数チェック
on checkFactor(aNum)
  repeat with i from 2 to aNum - 1
    if aNum mod i is equal to 0 then
      return i
    end if
  end repeat
end checkFactor

–リスト内の要素をすべて乗算する
on multipleListElements(aList)
  set aNum to 1
  
set aRes to 1
  
repeat with i in aList
    set aRes to aRes * (aNum * i)
  end repeat
  
return aRes
end multipleListElements

★Click Here to Open This Script 

2017/05/18 16進数文字列を10進数数値に変換するv2

16進数文字列をCocoaの機能を利用して10進数数値に変換するAppleScriptです。

以前、Pure AppleScriptで組んだものがありましたが、ためしにCocoaの機能を利用して実行速度を比較してみました。

 Pure AppleScript版:0.03秒ぐらい
 本AppleScript:0.02秒ぐらい

Cocoaの機能を呼び出すAppleScriptObjCのScriptは、Pure AppleScriptにくらべて1回目の実行がやや遅くなるものの、同じ処理を複数回呼び出すと2回目以降の速度が大幅に上がる傾向があります。繰り返し実行する場合にはAppleScriptObjC版のほうがおすすめです。

AppleScript名:16進数文字列を10進数数値に変換するv2
– Created 2017-05-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4645

set aHex to “0×9AC”
set hNum to retIntFromHexString(aHex) of me

on retIntFromHexString(aHex as string)
  set {aRes, hexRes} to (current application’s NSScanner’s scannerWithString:aHex)’s scanHexInt:(reference)
  
if aRes = false then
    return “” –エラーの場合
  else
    return hexRes
  end if
end retIntFromHexString

★Click Here to Open This Script 

2017/05/15 感情推定(極性判定) v2

apitoreのREST API「感情推定(極性判定) v2」を呼び出すAppleScriptです。

400文字以下のテキストを解析して、極性(感情)を判定します。ただし、文章が短すぎると判定しづらくなる傾向があるようです。これまでの感情推定APIではpositive/negativeとして判定する傾向があったため、このv2 APIではneutralとして判定する幅を広めにとってもらいました。

本Scriptをテストするためには、apitoreにサインアップしてAccess Tokenを取得し、Script末尾の伏字部分にコピー&ペーストしてください(掲載リストをそのまま実行してもエラーになります)。

AppleScript名:感情推定(極性判定) v2
– Created 2017-05-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4639

set aString to "このePubの考え方にそぐわない文章要素がいろいろある。代表的なものは「表」だ。データを掲載しておくのに、「表」は便利な存在だ。書く方からしても、いちいち長々とした文章で説明しなくていいし、読む方からしても整理された情報を読めるわけで、とくにお年寄りに好まれる。ところが、この「表」がePubの出版物にそぐわない。表の幅は変わってほしくないし、文字サイズが大きくなって数ページにわたって表示されるといったことは好ましくない。"
set a1Res to getSentimentFromString(aString) of me
–>  "positive"(なのか?)

on getSentimentFromString(aString)
  set reqURLStr to "https://api.apitore.com/api/39/sentiment-v2/predict"
  
set accessToken to retAccessToken() of me
  
set aRec to {access_token:accessToken, |text|:aString}
  
set aURL to retURLwithParams(reqURLStr, aRec) of me
  
  
set aRes to callRestGETAPIAndParseResults(aURL) of me
  
  
set aRESCode to (responseCode of aRes) as integer
  
if aRESCode is not equal to 200 then return false
  
  
set aRESTres to ((json of aRes)’s valueForKeyPath:"predict.sentiment") as string
  
return aRESTres
end getSentimentFromString

–GET methodのREST APIを呼ぶ
on callRestGETAPIAndParseResults(aURL)
  set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
aRequest’s setHTTPMethod:"GET"
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:"application/json" forHTTPHeaderField:"Accept"
  
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code & Header
  
set dRes to contents of second item of resList
  
if dRes is not equal to missing value then
    set resCode to (dRes’s statusCode()) as number
    
set resHeaders to (dRes’s allHeaderFields()) as record
  else
    set resCode to 0
    
set resHeaders to {}
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
end callRestGETAPIAndParseResults

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

on retAccessToken()
  return "xxXXXxxX-XxXx-XXXX-xXXX-XXxXXxxXxxXx" –API Tore Access Token
end retAccessToken

★Click Here to Open This Script 

2017/05/12 システムスペルチェック辞書への学習と削除

システムのスペルチェック辞書への学習と削除を行うAppleScriptです。

Shane StanleyがMLに投稿したScriptと、それを元に辞書の言語指定をしてみたものです。

AppleScript名:システムスペルチェック辞書への学習と削除
– Created 2017-01-22 by Shane Stanley
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
–http://piyocast.com/as/archives/4635

–スペルチェック辞書への学習
set theWord to "piyomaru"
set theChecker to current application’s NSSpellChecker’s sharedSpellChecker()
theChecker’s learnWord:theWord
set knewIt to theChecker’s hasLearnedWord:theWord
–>  true

–スペルチェック辞書からの削除
theChecker’s unlearnWord:theWord
set knowsItNow to theChecker’s hasLearnedWord:theWord
return {knewIt, knowsItNow}
–>  {true, false}

★Click Here to Open This Script 

システムスペルチェック辞書で、辞書の言語を指定して学習させてみました。

AppleScript名:ロシア語(ru)のシステムスペルチェック辞書を指定して学習
– Created 2017-05-12 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use scripting additions
–http://piyocast.com/as/archives/4635

set theChecker to current application’s NSSpellChecker’s sharedSpellChecker()

set langList to (theChecker’s availableLanguages()) as list
–>  {"en", "en_GB", "en_CA", "en_IN", "en_SG", "en_AU", "en_JP", "fr", "da", "de", "es", "it", "nl", "nb", "pl", "pt_BR", "pt_PT", "fi", "sv", "tr", "ru", "ko"}

set curCheckerLang to (theChecker’s |language|()) as string
–> "en_GB"

set aWord to "Su-35"
theChecker’s setLanguage:"ru"
theChecker’s learnWord:aWord
set knewIt to theChecker’s hasLearnedWord:aWord
–>  true

set curCheckerLang to (theChecker’s |language|()) as string
–>  "ru"

★Click Here to Open This Script 

2017/05/06 Bing Web Search APIでWebキーワード検索

MicrosoftのBing Web Search APIを呼び出してWebのキーワード検索を行うAppleScriptです。

Microsoft Cognitive Servicesのサイトで、開発者アカウント登録を行えば、本APIについては1か月に1,000回まで無料で使用できます(1秒間に7回までという制限もあります)。

アカウント登録を行い、Bing Web SearchをEnableに設定して、本AppleScriptの末尾のretAPIKey()ハンドラ内にAPI Key 1を入力してください(API Keyを記入したScriptを決してそのまま第三者に配布しないでください。あくまでテストと確認用です)。

個人的にBingは検索エンジンとして常用していません。Google検索にくらべて見つかる情報量が少ないと実感していることがその理由です。そのため、Bingの検索エンジンを呼び出せてもあまりメリットを見出せないところ。あくまで実験の一環です。

AppleScript名:Bing Web Search APIでWebキーワード検索
– Created 2017-05-03 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4634

set aStr to “戦場の絆”

set reqURLStr to “https://api.cognitive.microsoft.com/bing/v5.0/search” –Microsoft Project Oxford
set myAPIkey to retAPIkey() of me –API Primary Key

set aRec to {q:aStr, |count|:“5″, |offset|:“0″, mkt:“ja-JP”}
set bURL to retURLwithParams(reqURLStr, aRec) of me
set aRes to callRestGETAPI(bURL, myAPIkey) of me
set aRESTres to json of aRes
set aRESCode to responseCode of aRes
set aRESHeader to responseHeader of aRes

return (webPages of aRESTres)

–POST methodのREST APIを画像をアップロードしつつ呼ぶ
on callRestGETAPI(aURL, anAPIkey)
  –Request
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
aRequest’s setHTTPMethod:“GET”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:anAPIkey forHTTPHeaderField:“Ocp-Apim-Subscription-Key”
  
  
–CALL REST API
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
  
–Parse Results
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code
  
set dRes to contents of second item of resList
  
if dRes = missing value then
    set resCode to -1
    
set resHeaders to {}
  else
    set resCode to (dRes’s statusCode()) as integer
    
–Get Response Header
    
set resHeaders to (dRes’s allHeaderFields()) as record
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestGETAPI

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

on retAPIkey()
  return “XxXxXXxXxXxXXxXXxXXXxXXXxxxxXxxX” –API Key 1
end retAPIkey

★Click Here to Open This Script 

2017/05/04 Analyze Imageで画像認識

MicrosoftのCognitive ServicesのREST APIのひとつ、Computer Vision APIの「Analyze Image」を呼び出して画像認識するAppleScriptです。

Microsoft Cognitive Servicesのサイトで、開発者アカウント登録を行えば、本APIについては1か月に5,000回まで無料で使用できます(1分間に20回までという制限もあります)。

アカウント登録を行い、Analyze ImageをEnableに設定して、本AppleScriptの末尾のretAPIKey()ハンドラ内にAPI Key 1を入力してください(API Keyを記入したScriptを決してそのまま第三者に配布しないでください。あくまでテストと確認用です)。

指定した画像のカテゴリ(Categories)、タグ情報(Tags)、詳細内容(Description)の情報を取得しています。

精度については、実際にテスト画像と得られた認識データを見比べていただくしかありません。カタツムリとか誕生日ケーキとか夕日や花火、ワインボトルなど(!)、驚くほど正確に認識されています。夕日の手前にあるのは飛行機ではないのですが、そのぐらいの誤差はあります(イルカを「犬」と判定されたりもしました)。

ためしに、この結果(Description)をそのままGoogle Tlanstlate APIに渡して日本語訳させ画像のFinderコメント欄に入れる実験などもやってみたところ、面白い結果が得られました(実用性はまだまだですが、言いたいことはわかる、というレベル。個人的には英語のままのほうがわかりやすいかも)。

こうしたサービスを利用して、写真.app(Photos.app)内の写真にすべてタグ付けして、タグをもとに風景の写真だけを新規アルバムに入れて分類するといった使い方はできそうです(すでにやってるし)。そして、AppleのアプリケーションとMicrosoftやGoogleのWebサービスを連携させるといった使い方はAppleが提供するわけがないので、こういう用途こそAppleScriptで勝手に連携させるべきだと思います。

r0010704_resized.png
{{metadata:{width:2592, |format|:”Jpeg”, height:1944}, tags:{{|name|:”fireworks”, confidence:0.998994648457}, {|name|:”outdoor object”, confidence:0.998748064041}}, categories:{{|name|:”dark_fireworks”, score:0.99609375}}, |description|:{tags:{”fireworks”, “object”}, captions:{{|text|:“a close up of fireworks”, confidence:0.233880494749}}}, requestId:”ce5e5c15-f68f-4647-9694-5fb8ede9cd31″}}

r0015213_resized.png
{{metadata:{width:2592, |format|:”Jpeg”, height:1944}, tags:{{|name|:”ground”, confidence:0.999917149544}, {|name|:”animal”, confidence:0.993541717529}, {|name|:”invertebrate”, hint:”animal”, confidence:0.952201843262}, {|name|:”outdoor”, confidence:0.887740492821}, {|name|:”mollusk”, hint:”animal”, confidence:0.814713895321}, {|name|:”snail”, hint:”animal”, confidence:0.649717211723}}, categories:{{|name|:”abstract_texture”, score:0.6015625}}, |description|:{tags:{”animal”, “outdoor”, “shellfish”, “snail”, “piece”, “laying”, “food”, “sitting”, “top”, “surface”, “lying”, “banana”, “close”, “fruit”, “bird”, “beach”, “plate”, “board”, “street”}, captions:{{|text|:“a snail on the ground”, confidence:0.480042590526}}}, requestId:”b290dc83-0e33-41b0-8a39-76c067bcffb8″}}

r0015918_resized.png
{{metadata:{width:2048, |format|:”Jpeg”, height:1536}, tags:{{|name|:”grass”, confidence:0.99923813343}, {|name|:”outdoor”, confidence:0.997150361538}, {|name|:”ground”, confidence:0.972813665867}, {|name|:”standing”, confidence:0.93672734499}, {|name|:”animal”, confidence:0.917161226273}, {|name|:”bird”, confidence:0.824012756348}}, categories:{{|name|:”animal_horse”, score:0.98046875}}, |description|:{tags:{”grass”, “outdoor”, “standing”, “bird”, “animal”, “water”, “field”, “white”, “small”, “walking”, “front”, “sitting”, “parrot”, “brown”, “large”, “grassy”, “green”, “body”, “dirt”, “red”, “river”}, captions:{{|text|:“a bird that is standing in the grass”, confidence:0.859258793309}}}, requestId:”bc5b8778-cf96-4d3c-8ba9-be22b38c36dd”}}

img_2502_resized.png
{{metadata:{width:3264, |format|:”Jpeg”, height:2448}, tags:{{|name|:”sky”, confidence:0.999066531658}, {|name|:”outdoor”, confidence:0.99786490202}, {|name|:”sunset”, confidence:0.880310297012}, {|name|:”distance”, confidence:0.229086950421}}, categories:{{|name|:”outdoor_”, score:0.0078125}, {|name|:”outdoor_waterside”, score:0.5234375}}, |description|:{tags:{”outdoor”, “sunset”, “airplane”, “plane”, “sitting”, “building”, “runway”, “large”, “front”, “water”, “pier”, “top”, “sun”, “track”, “orange”, “light”, “road”, “bridge”, “standing”, “train”, “man”, “jet”, “white”, “city”, “riding”, “red”, “flying”, “bird”, “blue”, “night”, “river”, “tower”, “tarmac”}, captions:{{|text|:“a plane that is in front of a sunset”, confidence:0.493561860724}}}, requestId:”49705b7d-99cb-4234-9af6-b30a32f02ad5″}}

img_0313_resized.png
{{metadata:{width:4032, |format|:”Jpeg”, height:3024}, tags:{{|name|:”indoor”, confidence:0.929384291172}, {|name|:”candle”, confidence:0.877458691597}, {|name|:”birthday”, confidence:0.817751348019}, {|name|:”lit”, confidence:0.53784763813}}, categories:{{|name|:”others_”, score:0.01171875}}, |description|:{tags:{”table”, “indoor”, “cake”, “birthday”, “food”, “sitting”, “lit”, “plate”, “front”, “small”, “top”, “bowl”, “fruit”, “filled”, “chocolate”, “holding”, “man”, “woman”}, captions:{{|text|:“a birthday cake with lit candles”, confidence:0.8700279282}}}, requestId:”62b58a19-2d3a-4f9a-bd54-5aa4460d8385″}}

img_2187_resized.png
{{metadata:{width:3264, format:”Jpeg”, height:2448}, tags:{{name:”bottle”, confidence:0.999316096306}, {name:”table”, confidence:0.987863183022}, {name:”indoor”, confidence:0.968602716923}, {name:”wine”, confidence:0.928377449512}, {name:”alcohol”, confidence:0.846504926682}, {name:”food”, confidence:0.785823404789}, {name:”glass”, confidence:0.782037138939}, {name:”beverage”, confidence:0.776733756065}}, categories:{{name:”drink_”, score:0.90234375}}, description:{tags:{”bottle”, “table”, “indoor”, “wine”, “sitting”, “alcohol”, “food”, “glass”, “beverage”, “cup”, “banana”, “empty”, “top”, “sandwich”, “counter”, “beer”, “phone”, “orange”, “wooden”, “computer”, “laying”}, captions:{{text:“a bottle of wine”, confidence:0.858091829408}}}, requestId:”d2db3a05-fcb0-43bb-8191-89707904918a”}}

r0020016_resized.png
{{metadata:{width:1280, format:”Jpeg”, height:960}, tags:{{name:”sky”, confidence:0.999883055687}, {name:”outdoor”, confidence:0.997511506081}, {name:”person”, confidence:0.910886585712}, {name:”toy”, confidence:0.878364562988}}, categories:{{name:”others_”, score:0.00390625}, {name:”outdoor_”, score:0.01171875}}, description:{tags:{”outdoor”, “person”, “toy”, “thing”, “man”, “white”, “grass”, “standing”, “people”, “field”, “riding”, “jumping”, “doing”, “air”, “holding”, “group”, “trick”, “board”, “statue”, “dog”, “player”, “ramp”}, captions:{{text:“a statue of a man jumping in the air”, confidence:0.153422169506}}}, requestId:”ec5dc466-76c5-47df-b858-2e418ce891a8″}}

r0016164_resized.png
{{metadata:{width:2048, format:”Jpeg”, height:1536}, tags:{{name:”water”, confidence:0.999519586563}, {name:”animal”, confidence:0.993490874767}, {name:”outdoor”, confidence:0.992024421692}, {name:”aquatic mammal”, hint:”animal”, confidence:0.978799343109}, {name:”mammal”, hint:”animal”, confidence:0.914148926735}, {name:”ocean”, confidence:0.804374277592}, {name:”whale”, hint:”animal”, confidence:0.533892810345}, {name:”wave”, confidence:0.527211129665}, {name:”dolphin”, hint:”animal”, confidence:0.340564578772}}, categories:{{name:”outdoor_”, score:0.00390625}}, description:{tags:{”water”, “animal”, “outdoor”, “mammal”, “ocean”, “wave”, “laying”, “brown”, “riding”, “surfing”, “top”, “body”, “lying”, “board”, “large”, “beach”, “floating”, “swimming”, “standing”, “dog”, “young”, “white”, “man”}, captions:{{text:“a dog swimming in the ocean”, confidence:0.604725984086}}}, requestId:”161b6c0f-f3fd-4e06-b4be-d5baa9516e53″}}

AppleScript名:Analyze Image APIで画像認識
– Created 2017-05-03 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4625

set imgFilePath to POSIX path of (choose file of type {“public.jpeg”} with prompt “Select an Image to Analyze”)
set aRes to recogImage(imgFilePath) of me

on recogImage(imgFilePath)
  set reqURLStr to “https://api.projectoxford.ai/vision/v1.0/analyze”
  
set myAPIkey to retAPIkey() of me –API Key 1
  
  
set aRec to {visualFeatures:“Categories,Tags,Description”, details:“Celebrities”, language:“en”}
  
set bURL to retURLwithParams(reqURLStr, aRec) of me
  
  
set aRes to callRestPOSTAPIAndParseResultsWithImage(bURL, imgFilePath, myAPIkey) of me
  
set aRESTres to json of aRes
  
set aRESCode to responseCode of aRes
  
set aRESHeader to responseHeader of aRes
  
  
return (aRESTres as list)
end recogImage

–POST methodのREST APIを画像をアップロードしつつ呼ぶ
on callRestPOSTAPIAndParseResultsWithImage(aURL, imgFilePath, myAPIkey)
  –Get Image Contents from file
  
set imgPathStr to current application’s NSString’s stringWithString:imgFilePath
  
set imgData to current application’s NSData’s dataWithContentsOfFile:imgPathStr
  
set postBody to current application’s NSMutableData’s |data|()
  
postBody’s appendData:imgData
  
  
–Request
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
aRequest’s setHTTPMethod:“POST”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setHTTPBody:postBody
  
aRequest’s setValue:“application/octet-stream” forHTTPHeaderField:“Content-Type”
  
aRequest’s setValue:myAPIkey forHTTPHeaderField:“Ocp-Apim-Subscription-Key”
  
  
–CALL REST API
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
  
–Parse Results
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code
  
set dRes to contents of second item of resList
  
if dRes = missing value then
    set resCode to -1
    
set resHeaders to {}
  else
    set resCode to (dRes’s statusCode()) as integer
    
–Get Response Header
    
set resHeaders to (dRes’s allHeaderFields()) as record
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestPOSTAPIAndParseResultsWithImage

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString())
  
  
return aURL
end retURLwithParams

on retAPIkey()
  return “xXXxXXXXxXXxXXXxXXXXXXXXxXXXXXXx” –API Key 1
end retAPIkey

★Click Here to Open This Script 

2017/04/30 Computer Vision APIで文字認識(OCR)

MicrosoftのCognitive ServicesのREST APIのひとつ、Computer Vision APIを呼び出すAppleScriptです。

MicrosoftのAPIは割とシンプルでオンラインドキュメントも読みやすいため、書くのに3分ぐらいしかかかっていません(既存の別のAPI用のものをend pointとAPI keyとパラメータを書き換えただけ)。

Microsoft Cognitive Servicesのサイトで、開発者アカウント登録を行えば、本APIについては1か月に5,000回まで無料で使用できます(1分間に20回までという制限もあります)。アカウント登録を行い、OCR ServiceをEnableに設定して、本AppleScriptの末尾のretAPIKey()ハンドラ内にAPI Key 1を入力してください(API Keyを記入したScriptを決してそのまま第三者に配布しないでください。あくまでテストと確認用です)。

cognitive_key.png
▲ここの「Key 1」

Vision APIでは、対応画像ファイル形式はJPEG、PNG、GIF、BMP(!)。ファイル容量は4MB以下、50×50ピクセル以上の大きさである必要があります。

img_0320_resized.png

こんな「戦場の絆」のリプレイIDをゲームセンターで撮影して、このIDをもとにYouTubeのリプレイムービーのURLを検索することになるわけですが、このリプレイIDのOCRにComputer Vision APIを使ってみました。

この用途(ランダムに近い英数字の固定桁の組み合わせ、画面上のイメージの認識)については、かなり使える印象です。認識用に使用した画像は、iPhone 7で撮影して写真.appにiCloud経由で転送された写真をそのまま利用しており、ファイルサイズは2.6MB、画像の大きさは4032×3024ピクセルありました。このぐらいだと、認識のためにMicrosoftのクラウドにアップロードするのに少々待たされます。

{boundingBox:”929,1171,746,134″, text:”fy57nt2f“}
{boundingBox:”920,1438,770,135″, text:”3kt5y72v“}

この用途においては、とても誤認識が少ないと感じています。本来取り出したい目的のデータが日本語(ja)ではないので、言語を英数字(en)に指定して呼び出しています。

縦書きの日本語の印刷物の認識だと、もう少し結果が異なってくると思います。一応、この画面についても当初は日本語(ja)で認識していましたが、書体の問題もあり(ちょっと太すぎ?)日本語の文字については誤認識されまくっていました。

AppleScript名:Computer Vision APIで文字認識(OCR)
– Created 2017-04-30 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4622

set imgFilePath to POSIX path of (choose file of type {“public.image”} with prompt “Select an Image to OCR”)

set reqURLStr to “https://api.projectoxford.ai/vision/v1.0/ocr” –Microsoft Cognitive Services OCR endpoint
set myAPIkey to retAPIkey() of me –API Primary Key

–Request parameters
set aRec to {|language|:“en”, detectOrientation:“true”}
set bURL to retURLwithParams(reqURLStr, aRec) of me

set aRes to callRestPOSTAPIAndParseResultsWithImage(bURL, myAPIkey, imgFilePath) of me
set aRESTres to json of aRes

set aRESCode to responseCode of aRes
if aRESCode is not equal to 200 then return false
set aRESHeader to responseHeader of aRes

return ((regions of aRESTres) as list)
–>  {{language:”en”, regions:{{boundingBox:”728,366,1497,2042″, lines:{{boundingBox:”1655,366,186,28″, words:{{boundingBox:”1655,366,186,28″, text:”pea-a-r”}}}, {boundingBox:”1223,962,467,89″, words:{{boundingBox:”1223,962,467,89″, text:”UäLCOD”}}}, {boundingBox:”753,1134,922,171″, words:{{boundingBox:”753,1134,64,156″, text:”1″}, {boundingBox:”929,1171,746,134″, text:”fy57nt2f”}}}, {boundingBox:”1761,1167,458,64″, words:{{boundingBox:”1761,1175,80,53″, text:”20″}, {boundingBox:”1862,1169,169,62″, text:”17/0″}, {boundingBox:”2045,1167,174,60″, text:”4/26″}}}, {boundingBox:”2005,1231,215,52″, words:{{boundingBox:”2005,1231,215,52″, text:”17:55″}}}, {boundingBox:”742,1403,948,170″, words:{{boundingBox:”742,1403,86,160″, text:”2″}, {boundingBox:”920,1438,770,135″, text:”3kt5y72v”}}}, {boundingBox:”1765,1432,459,65″, words:{{boundingBox:”1765,1441,81,53″, text:”20″}, {boundingBox:”1866,1434,170,63″, text:”17/0″}, {boundingBox:”2050,1432,174,61″, text:”4/26″}}}, {boundingBox:”2010,1495,215,54″, words:{{boundingBox:”2010,1495,215,54″, text:”17:47″}}}, {boundingBox:”736,1672,88,176″, words:{{boundingBox:”736,1672,88,176″, text:”3″}}}, {boundingBox:”728,2240,96,168″, words:{{boundingBox:”728,2240,96,168″, text:”5″}}}}}, {boundingBox:”2817,1217,186,320″, lines:{{boundingBox:”2817,1217,175,53″, words:{{boundingBox:”2817,1217,175,53″, text:”6vs6″}}}, {boundingBox:”2826,1483,177,54″, words:{{boundingBox:”2826,1483,177,54″, text:”6vs6″}}}}}}, textAngle:0.0, orientation:”Up”}}

–POST methodのREST APIを画像をアップロードしつつ呼ぶ
on callRestPOSTAPIAndParseResultsWithImage(aURL, anAPIkey, imgFilePath)
  
  
–Get Image Contents from file
  
set imgPathStr to current application’s NSString’s stringWithString:imgFilePath
  
set imgData to current application’s NSData’s dataWithContentsOfFile:imgPathStr
  
set postBody to current application’s NSMutableData’s |data|()
  
postBody’s appendData:imgData
  
  
–Request
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
aRequest’s setHTTPMethod:“POST”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setHTTPBody:postBody
  
aRequest’s setValue:“application/octet-stream” forHTTPHeaderField:“Content-Type”
  
aRequest’s setValue:anAPIkey forHTTPHeaderField:“Ocp-Apim-Subscription-Key”
  
  
–CALL REST API
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
  
–Parse Results
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code
  
set dRes to contents of second item of resList
  
set resCode to (dRes’s statusCode()) as integer
  
  
–Get Response Header
  
set resHeaders to (dRes’s allHeaderFields()) as record
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestPOSTAPIAndParseResultsWithImage

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) –as text
  
  
return aURL
end retURLwithParams

on retAPIkey()
  return “xXXXXxXxXxXXXXxxxXXxXXXxxXxxXxxx” –API Primary Key
end retAPIkey

★Click Here to Open This Script 

2017/04/27 テックサイト ごちゃまぜフィードを呼び出す

apitoreREST API「テックサイト ごちゃまぜフィード」を呼び出すAppleScriptです。

apitore側で、以下のテック系Blogを自動巡回して(30分に一度)更新情報を蓄積、新しい順番にソートしたものがREST API経由で提供されています。

巡回サイトは、ライフハッカー、メディア・パブ、スラッシュドット、ギズモード、ゆかしメディア、TechWave、TechDoll.jp、TechCrunch、Reuters、Google Japan Blog、GIGAZINE、Engadget、CNET、All About(オールアバウト) [新着記事]、男子ハック、Techable、ReadWrite Japan、MdN Design Interactive、WIRED.jp、アンドロイドアプリが見つかる!スマホ情報ならオクトバ、ITmedia 総合、ITmedia トップストーリー

となっています(記事執筆時)。

apitoreでは、この「テックサイト ごちゃまぜフィード」のほか、「旅行系」「ニュース」「ブログ 」「デザイン系」などの情報源のフィード系REST APIを提供しています。

本Scriptをテストするためには、apitoreにサインアップしてAccess Tokenを取得して、Script末尾の伏字部分にコピー&ペーストしてください(掲載リストをそのまま実行してもエラーになります)。

Webクローラーを自前で作って定期実行しなくても、Web API経由でクローリングした結果がもらえるというのは、とてもメリットが大きいと思います。AppleScriptではGUIアプリケーションの内部機能からOS内部のCocoa API、shell script、そしてWeb上のREST APIまで直接呼べるので、こんな「なんでもアリ」な環境はなかなかないでしょう。

AppleScript名:テックサイト ごちゃまぜフィード
– Created 2016-10-27 by Takaaki Naganoya
– 2016 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4616

set allFeeds to {}

repeat with i from 1 to 100
  set {aRes, maxNum} to getAFeeds(i) of me
  
  
if aRes = false then exit repeat
  
set maxNum to maxNum as number
  
set allFeeds to allFeeds & aRes
  
if (maxNum div 10) i then
    exit repeat
  end if
end repeat

return allFeeds
–>  
(*
{{author:”Ittousai”, sourceTitle:”Engadget Japanese RSS Feed”, title:” 速報:サムスンGalaxy S8発表イベント UNPACKED 2017 (ライブ更新ページ)
“, link:”http://japanese.engadget.com/2017/03/29/galaxy-s8-unpacked-2017/”, pubDate:1.49079606E+12, description:”

“, sourceLink:”http://japanese.engadget.com/rss.xml”},
*)

on getAFeeds(aNum)
  set reqURLStr to “https://api.apitore.com/api/35/feeds/tech”
  
set accessToken to retAccessToken() —Access Token
  
set aRec to {access_token:accessToken, page:(aNum as string)}
  
set aURL to retURLwithParams(reqURLStr, aRec) of me
  
  
set aRes to callRestGETAPIAndParseResults(aURL) of me
  
  
set aRESCode to (responseCode of aRes) as integer
  
if aRESCode is not equal to 200 then return {false, false}
  
  
set aRESTres to (json of aRes) as record
  
  
set sentiRes to entries of aRESTres
  
set allNum to num of aRESTres
  
log allNum
  
  
return {sentiRes, allNum}
end getAFeeds

–GET methodのREST APIを呼ぶ
on callRestGETAPIAndParseResults(aURL)
  
  
set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
  
aRequest’s setHTTPMethod:“GET”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:“application/json” forHTTPHeaderField:“Accept”
  
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code & Header
  
set dRes to contents of second item of resList
  
if dRes is not equal to missing value then
    set resCode to (dRes’s statusCode()) as number
    
set resHeaders to (dRes’s allHeaderFields()) as record
  else
    set resCode to 0
    
set resHeaders to {}
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestGETAPIAndParseResults

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

on retAccessToken()
  return “XXXXxxxX-xxxx-XXXx-xxxX-XxxxXxXxxXXx” –API Tore Access Token
end retAccessToken

★Click Here to Open This Script 

2017/04/27 単色画像(アルファ値必要)に色を指定して塗りつぶし

背景を透明(アルファ値指定)にした単色の画像に、指定の色を指定して塗りつぶしを行うAppleScriptです。

input_and_output.png

単色の画像を作成して、指定画像との合成を行い「塗りつぶし」の状態を作り出すものです。Photoshopを使えば、あっという間にできてしまう処理ですが、Photoshopは並列処理に使えないのでこうした部品を作っておいたものです。

AppleScript名:単色画像(アルファ値必要)に色を指定して塗りつぶし
– Created 2017-04-24 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “QuartzCore”
–http://piyocast.com/as/archives/4615

set aFile to POSIX path of (choose file of type “public.image”)
set aColor to makeNSColorFromRGBA255val(0, 0, 255, 255) of me
set aColoredImage to fillColorWithImage(aFile, aColor) of me

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 NSString’s stringWithString:“testOverlay”)’s stringByAppendingString:“.png”))
set fRes to saveNSImageAtPathAsPNG(aColoredImage, savePath) of me

on fillColorWithImage(aFile, aColor)
  set anImage to (current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile)
  
set aSize to anImage’s |size|()
  
set aWidth to (aSize’s width)
  
set aHeight to (aSize’s height)
  
set colordImage to makeNSImageWithFilledWithColor(aWidth, aHeight, aColor) of me
  
colordImage’s lockFocus()
  
anImage’s drawAtPoint:{0, 0} fromRect:(current application’s NSZeroRect) operation:(current application’s NSCompositeDestinationIn) fraction:1.0
  
colordImage’s unlockFocus()
  
return colordImage
end fillColorWithImage

–指定サイズの画像を作成し、指定色で塗ってファイル書き出し
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  set anImage to current application’s NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  

  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to current application’s NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  

  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  

  
anImage’s unlockFocus()
  

  
return anImage
end makeNSImageWithFilledWithColor

on makeNSColorFromRGBA255val(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer)
  set aRedCocoa to (redValue / 255) as real
  
set aGreenCocoa to (greenValue / 255) as real
  
set aBlueCocoa to (blueValue / 255) as real
  
set aAlphaCocoa to (alphaValue / 255) as real
  
set aColor to current application’s NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa
  
return aColor
end makeNSColorFromRGBA255val

–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

★Click Here to Open This Script 

2017/04/26 指定画像の余白の自動トリミング

オープンソースのKGPixelBoundsClip(By David Keegan)をフレームワーク化した「KGPixelBoundsClipKit」を呼び出して指定画像を自動でトリミングするAppleScriptです。

OS X 10.10以降用にビルドしたフレームワークのバイナリを用意しておきました。興味のある方は自己責任で~/Library/Frameworksフォルダに入れてお試しください。

–> Download Framework Binary

指定画像(背景を透明に指定したPNGで実行)を自動トリミングして、デスクトップに結果を書き出します。

Photoshopにも同様の機能があったような記憶がありますが、フレームワーク経由で実行することで並列処理を行いやすい部品を作っておくことが目的です。

original_and_trimed.png

AppleScript名:指定画像の余白の自動トリミング
– Created 2017-04-26 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “KGPixelBoundsClipKit” –https://github.com/kgn/KGPixelBoundsClip
–http://piyocast.com/as/archives/4611

set aFile to POSIX path of (choose file of type {“public.image”})
set anImage to (current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile)

set bImage to anImage’s imageClippedToPixelBounds()

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”)
set fRes to saveNSImageAtPathAsPNG(bImage, savePath) of me

–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
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

2017/04/24 画像中の色の置き換え

オープンソースのNSImage-replace-color(By braginets)をフレームワーク化した「replaceColorKit」を呼び出して指定画像中の指定色を置き換えるAppleScriptです。

OS X 10.10以降用にビルドしたフレームワークのバイナリを用意しておきました。興味のある方は自己責任で~/Library/Frameworksフォルダに入れてお試しください。

–> Download Framework Binary

piyo_wolf.png
▲Original

piyo_gray_02.png
▲Color Replaced Image (Yellow->Gray)

rep_doc.png

R, G, Bのグラデーション画像を作成して、色の置き換えをテストしてみたところ、置き換え色がR:255やB:255の色の場合に置き換え色がやや変わってしまうという傾向があるようです。

specificated_sampledata.png

rep_color_diff.png

AppleScript名:画像中の色の置き換え
– Created 2017-04-23 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "replaceColorKit" –https://github.com/braginets/NSImage-replace-color
use framework "AppKit"
–http://piyocast.com/as/archives/4604

set aThreshold to 0.2

set aFile to POSIX path of (choose file of type {"public.image"})
set anImage to (current application’s NSImage’s alloc()’s initWithContentsOfFile:aFile)

set aColor to makeNSColorFromRGBA255val(246, 253, 0, 255) of me
set bColor to makeNSColorFromRGBA255val(154, 154, 154, 255) of me

set bImage to (anImage’s replaceColor:aColor withColor:bColor withThreshold:aThreshold)

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 NSString’s stringWithString:(aThreshold as string))’s stringByAppendingString:".png"))
set fRes to saveNSImageAtPathAsPNG(bImage, savePath) of me

–0〜255の数値でNSColorを作成する
on makeNSColorFromRGBA255val(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer)
  set aRedCocoa to (redValue / 255) as real
  
set aGreenCocoa to (greenValue / 255) as real
  
set aBlueCocoa to (blueValue / 255) as real
  
set aAlphaCocoa to (alphaValue / 255) as real
  
set aColor to current application’s NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa
  
return aColor
end makeNSColorFromRGBA255val

–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
end saveNSImageAtPathAsPNG

★Click Here to Open This Script 

2017/04/20 日本語音声認識テスト

日本語音声認識コマンドを待機、認識するAppleScriptです。

とくに日本語であることは指定していませんが、実行ユーザー環境が日本語環境で、Macに日本語音声認識エンジンがインストールされていて、サウンド入力デバイスが存在している場合には音声認識を行います(対象言語を指定して音声認識エンジンを起動できるといいのに。あるいは、与えるコマンド文字列から対応するエンジンが起動されるのか、、、、)。

OS側で用意している日本語音声認識によるAppleScript呼び出し機能よりも、素朴な機能ではありますが、音声認識文字列をリストで動的にAppleScript側から指定できる点や、他の音声認識機能の抑止指定が便利なこともあることでしょう。

recog1.png

普通に認識してくれます。認識フローティングウィンドウの「表示」をクリックすると、

recog2.png

指定したコマンド文字列一覧を表示します。

問題は音声認識の停止です。stopListening()を実行するとコマンド認識は停止するようですが、この認識フローティングウィンドウが消えないので、ちょっと困ります。

AppleScript名:日本語音声認識テスト
– Created 2017-04-20 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4595

set aCmdList to {“こんにちは”, “こんばんは”, “おはよう”}
–set aCmdList to {”Hello”, “goodnight”, “goodevening”}

set aRecognizer to current application’s NSSpeechRecognizer’s alloc()’s init()
aRecognizer’s setCommands:aCmdList
aRecognizer’s setDelegate:me
aRecognizer’s setListensInForegroundOnly:true
aRecognizer’s startListening()
aRecognizer’s setBlocksOtherRecognizers:true

on speechRecognizer:aSender didRecognizeCommand:aCmd
  set recogCmd to aCmd as string
  
say recogCmd using “Otoya” –Japanese Male Voice
  
–aSender’s stopListening()
end speechRecognizer:didRecognizeCommand:

★Click Here to Open This Script 

2017/04/19 NSColorからCIColorを作成

NSColorからCIColorを作成するAppleScriptです。

CoreImageの各種フィルタを利用して画像加工するさいに、色オブジェクトを指定するフィルタがいくつかあります。その際に指定するのがCIColor。そのため、NSColorからCIColorを求めるサンプルを書いてみました。

ただ、パラメータを指定してCIColorを作ってみても、たいして難しくもなんともないんですね(汗)

AppleScript名:NSColorからCIColorを作成
– Created 2017-04-19 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “QuartzCore”
use framework “AppKit”
–http://piyocast.com/as/archives/4591

set redValue to 0
set greenValue to 0
set blueValue to 1
set alphaVlaue to 1.0

set aNSColor to current application’s NSColor’s colorWithCalibratedRed:redValue green:greenValue blue:blueValue alpha:alphaVlaue
set aCIColor to current application’s CIColor’s alloc()’s initWithColor:aNSColor
–>  (CIColor) (0 0 1 1)

★Click Here to Open This Script 

AppleScript名:値を指定してCIColorを作成
– Created 2017-04-19 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “QuartzCore”
–http://piyocast.com/as/archives/4591

set redValue to 0
set greenValue to 0
set blueValue to 1
set alphaVlaue to 1.0

set aCIColor to current application’s CIColor’s alloc()’s initWithRed:redValue green:greenValue blue:blueValue alpha:alphaVlaue
–>  (CIColor) (0 0 1 1)

★Click Here to Open This Script 

2017/04/18 HelpBookの項目表示、キーワード検索

macOS上でヘルプを表示するHelpViewerはAppleScriptに対応しており、任意の項目の表示、キーワード検索、指定URLのオープンなどを行えるようになっています。

ただし、HelpViewerをAppleScriptから普通に操作したときの動作が怪しいので、Cocoa経由でも操作する方法を調べておきました。

HelpViewerで指定HelpBook中の指定のアンカーを表示させるだけであれば、

AppleScript名:help_sample
tell application “HelpViewer”
  activate
  
try
    lookup anchor “scpedt1126″ in book “com.apple.ScriptEditor.help”
  end try
end tell

★Click Here to Open This Script 

このぐらいの簡素な記述でOKです。これをCocoa経由で操作すると、

AppleScript名:指定アプリケーションのヘルプブック内の指定アンカーを表示する
– Created 2017-04-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4590

set anAppName to “Script Editor”
set aTargAnchor to “scpedt1126″ —-https://help.apple.com/scripteditor/mac/10.12/index.html?localePath=ja.lproj#/scpedt1126
set hRes to openHelpBook(anAppName, aTargAnchor) of me

–指定アプリケーションのヘルプブックで、指定アンカーを表示する
on openHelpBook(anAppName, aTargAnchor)
  set locBookName to getHelpBook(anAppName) of me
  
if locBookName = false then return false
  
current application’s NSHelpManager’s sharedHelpManager()’s openHelpAnchor:aTargAnchor inBook:locBookName
end openHelpBook

–指定アプリケーションのヘルプブック名称を取得する
on getHelpBook(anAppName)
  set aWorkspace to current application’s NSWorkspace’s sharedWorkspace()
  
set appPath to aWorkspace’s fullPathForApplication:anAppName
  
if appPath is equal to missing value then return false
  
  
set locBookName to (current application’s NSBundle’s bundleWithPath:appPath)’s objectForInfoDictionaryKey:“CFBundleHelpBookName”
  
if locBookName is equal to missing value then return false
  
–> “com.apple.ScriptEditor.help”
  
return locBookName
end getHelpBook

★Click Here to Open This Script 

このぐらいになります。ただし、前者の記述ではHelpBook名称があらかじめわかっていることが前提、後者ではアプリケーション名からHelpBook名を取得して項目表示するという違いがあります。

問題はキーワード検索で、HelpViewerを直接コントロールすると、

AppleScript名:HelpViewerで検索する?(未遂)
tell application “HelpViewer”
  activate
  
search looking for “用語説明”
end tell

★Click Here to Open This Script 

このぐらいの簡素な記述で済むはずですが、結果はHelpViewerに表示されません(単に記述が違っているという可能性もあります)。

これをCocoaの機能を用いて操作すると、きちんと検索結果が表示されます。Webサーバー上にあるヘルプのコンテンツを連続して同一ページを表示させると、5回に1回はエラー(未表示)になるなど、挙動がよくわかりません。

HelpViewerの中身はほぼ(遅い)Webブラウザで、有用性についても疑問が残ります。

AppleScript名:指定アプリケーションのヘルプブック内で指定キーワードを検索する
– Created 2017-04-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4590

set anAppName to “Script Editor”
set aTargString to “用語説明” –”Script Dictionary” in Japanese
set hRes to searchHelpBook(anAppName, aTargString) of me

–指定アプリケーションのヘルプブックで、指定アンカーを表示する
on searchHelpBook(anAppName, aTargString)
  set locBookName to getHelpBook(anAppName) of me
  
if locBookName = false then return false
  
current application’s NSHelpManager’s sharedHelpManager()’s findString:aTargString inBook:locBookName
end searchHelpBook

–指定アプリケーションのヘルプブック名称を取得する
on getHelpBook(anAppName)
  set aWorkspace to current application’s NSWorkspace’s sharedWorkspace()
  
set appPath to aWorkspace’s fullPathForApplication:anAppName
  
if appPath is equal to missing value then return false
  
  
set locBookName to (current application’s NSBundle’s bundleWithPath:appPath)’s objectForInfoDictionaryKey:“CFBundleHelpBookName”
  
if locBookName is equal to missing value then return false
  
–> “com.apple.ScriptEditor.help”
  
return locBookName
end getHelpBook

★Click Here to Open This Script 

2017/04/15 リストをクラス名でフィルタする v2

リストをクラス名でフィルタするAppleScriptです。指定クラスに合致するデータをリスト中から抽出します。

修正:listに対して簡単に直接フィルターする方法については別途記述しておきます。本Scriptは他の用途に転用するような場合の記述例として掲載しておきます

NSArrayに入れてNSPredicateで抽出を行う方法があります。ただし、これだとクラス名がCocoaとAppleScriptで合わないので、いまひとつ使えません。

そこで、ひたすら原始的ではありますが、リストをループで回してクラス名を照合して別リストに追加、という処理を回してみました。超高級言語のAppleScriptですが、たまーにこういう泥くさいチェック処理を書く瞬間があります。

そのままだと知性のカケラもなんにもないので、せめてクラス名の同義語辞書を定義して、クラス名の表記ゆらぎ(というよりも、クラス間の内包関係。integerとrealはnumberに含まれるなど)に対応させてみました。

AppleScript名:リストをクラス名でフィルタする v2
– Created 2017-04-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set aList to {1, “ABC”, 0.3, 5, {1, 2, 3}, {abc:“record”}, false}
set bList to filterListByClass(aList, “integer”)
–> {1, 5}
set cList to filterListByClass(aList, “number”)
–> {1, 0.3, 5}
set dList to filterListByClass(aList, “real”)
–> {0.3}
set eList to filterListByClass(aList, “string”)
–> {”ABC”}
set fList to filterListByClass(aList, “record”)
–> {{abc:”record”}}
set gList to filterListByClass(aList, “boolean”)
–> {false}

on filterListByClass(aList as list, aClass as string)
  set classNameList to getClassNameConsideringSynonyms(aClass) of me
  
  
set newList to {}
  
repeat with i in aList
    set j to contents of i
    
set myClass to (class of j) as string
    
if myClass is in classNameList then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterListByClass

on getClassNameConsideringSynonyms(aClassString)
  set smallClass to ((current application’s NSString’s stringWithString:aClassString)’s lowercaseString()) as string
  
set classRec to {|list|:{“list”}, |record|:{“record”}, |number|:{“number”, “integer”, “real”}, |integer|:{“integer”}, |real|:{“real”}, |text|:{“text”, “string”, “unicode text”}, |string|:{“text”, “string”, “unicode text”}, |unicode text|:{“text”, “string”, “unicode text”}, |boolean|:{“boolean”}}
  
set classDict to current application’s NSDictionary’s dictionaryWithDictionary:classRec
  
set aVal to (classDict’s valueForKey:smallClass) as list
  
if aVal = {missing value} then error “Unexpected class name string”
  
return aVal
end getClassNameConsideringSynonyms

★Click Here to Open This Script 

2017/04/11 指定のテキストから言語コードや言語名を取得する

Shane Stanleyによる、指定テキストを識別して言語コードや言語名を取得するAppleScriptです。

割とアラビア語のテキストを判定するのに文字数が必要だったのが意外です。

以前に掲載した「2015/09/10 テキストの言語を推測する」よりも若干(1行ぐらい)短くなっています。

AppleScript名:指定のテキストから言語コードや言語名を取得する
– Created 2017-04-10 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set str1 to “Ilmatyynyalukseni on täynnä ankeriaita.”
set str2 to “Luftputebåten min er full av ål”
set str3 to “私の名前は長野谷です。”
set str4 to أنشأ فوكوزاوا يوكيتشي (١٨٣٥-١٩٠١) في اكتوبر عام ١٨٥٨ مدرسة للدراسات الهولندية (تحولت بعد ذلك لمدرسة للغة الانكليزية) في ايدو (طوكيو حاليا). يعد فوكوزاوا يوكيتشي من أحد مؤسسي نهضة اليابان الحديثة، فونهتم بمدرستنا بنوع التعليم الذي ينمي القدرات الإبداعية والفنية التي يتطلب توافرها في طلاب الجامعة بحيث لا ينشغل الطلاب باختبار قبول الجامعات ونحترم استقلالية وتفرد كل طالب وذلك في جو دافئ في بيئة طبيعية مليئة بأشجار
set str5 to 게이오 기주쿠는 어디에나 있는 학교의 하나로 만족하지 않습니다. 게이오 기주쿠는 기주쿠(義塾, 의숙)에서 배우는 학생과 교원이 일본의기품의 원천지덕의 모범 되는 것을 목표로 하는 학숙(學塾)입니다. “
set str6 to 庆应义塾不是仅仅满足于成常常到的一般性学校。”

set a1Res to my guessLanguageCodeOf:str1 –>  ”fi”
set a2Res to my guessLanguageCodeOf:str2 –>  ”sv”
set a3Res to my guessLanguageCodeOf:str3 –>  ”ja”
set a4Res to my guessLanguageCodeOf:str4 –>  ”ar”
set a5Res to my guessLanguageCodeOf:str5 –>  ”ko”
set a6Res to my guessLanguageCodeOf:str6 –>  ”zh-Hans”

set b1Res to my guessLanguageOf:str1 –>  ”Finnish”
set b2Res to my guessLanguageOf:str2 –>  ”Swedish”
set b3Res to my guessLanguageOf:str3 –>  ”Japanese”
set b4Res to my guessLanguageOf:str4 –>  ”Arabic”
set b5Res to my guessLanguageOf:str5 –>  ”Korean”
set b6Res to my guessLanguageOf:str6 –>  ”Chinese”

on guessLanguageOf:theString
  set theTagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:{current application’s NSLinguisticTagSchemeLanguage} options:0
  
theTagger’s setString:theString
  
set languageID to theTagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return ((current application’s NSLocale’s localeWithLocaleIdentifier:“en”)’s localizedStringForLanguageCode:languageID) as text
end guessLanguageOf:

on guessLanguageCodeOf:theString
  set theTagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:{current application’s NSLinguisticTagSchemeLanguage} options:0
  
theTagger’s setString:theString
  
set languageID to theTagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return languageID as text
end guessLanguageCodeOf:

★Click Here to Open This Script 

2017/04/11 NSMutableArrayの特定要素の書き換え

NSMutableArray中の特定要素を書き換えるAppleScriptです。

NSMutableArrayの内容をpredicateで条件を指定してフィルタリングする処理はAppleScriptでも頻繁に使うようになってきました。他のSQLデータベースに依存する必要もなく、処理速度も速いため非常に有効な手段です。

ただ、抽出処理は行えるものの、当該アイテムの書き換えを行って、もとのNSMutableArrayに書き戻せないとデータベース的な運用はできません。

そこで、簡単なサンプルScriptを作ってみて、Array中の特定要素を検索して書き換える処理を書いてみました。

AppleScript名:リスト中の指定アイテムを置き換える
– Created 2017-04-11 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4579

set anArray to current application’s NSMutableArray’s arrayWithArray:{5, 2, 1, 3, 4}
anArray’s replaceObjectsAtIndexes:(current application’s NSIndexSet’s indexSetWithIndex:0) withObjects:{-1}
return anArray as list
–> {-1, 2, 1, 3, 4}

★Click Here to Open This Script 

AppleScript名:レコード入りリスト中の指定アイテムを置き換える
– Created 2017-04-11 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4579

set anArray to current application’s NSMutableArray’s arrayWithArray:{{aLabel:0, bLabel:2, cLabel:100}, {aLabel:2, bLabel:3, cLabel:1}}
anArray’s replaceObjectsAtIndexes:(current application’s NSIndexSet’s indexSetWithIndex:0) withObjects:{{aLabel:-1, bLabel:-2, cLabel:-3}}
return anArray as list
–>  {{cLabel:-3, aLabel:-1, bLabel:-2}, {cLabel:1, aLabel:2, bLabel:3}}

★Click Here to Open This Script 

AppleScript名:リスト中の指定アイテムを置き換える(登場アイテム番号自動検索)
– Created 2017-04-11 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4579

set aTargValue to 2
set aNewValue to -100
set anArray to current application’s NSMutableArray’s arrayWithArray:{5, 2, 1, 3, 4}
set aInd to anArray’s indexOfObject:aTargValue
anArray’s replaceObjectsAtIndexes:(current application’s NSIndexSet’s indexSetWithIndex:aInd) withObjects:{aNewValue}
return anArray as list
–>  {5, -100, 1, 3, 4}

★Click Here to Open This Script 

AppleScript名:レコード入りリスト中の指定アイテムを置き換える(登場アイテム番号自動検索)
– Created 2017-04-11 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4579

set aTargValue to {aLabel:2, bLabel:3, cLabel:1}
set aNewValue to {aLabel:-1, bLabel:-2, cLabel:-3}

set anArray to current application’s NSMutableArray’s arrayWithArray:{{aLabel:0, bLabel:2, cLabel:100}, {aLabel:2, bLabel:3, cLabel:1}, {aLabel:0, bLabel:0, cLabel:0}}
set aInd to anArray’s indexOfObject:aTargValue

anArray’s replaceObjectsAtIndexes:(current application’s NSIndexSet’s indexSetWithIndex:aInd) withObjects:{aNewValue}
return anArray as list
–>  {{cLabel:100, aLabel:0, bLabel:2}, {cLabel:-3, aLabel:-1, bLabel:-2}, {cLabel:0, aLabel:0, bLabel:0}}

★Click Here to Open This Script 

2017/03/31 簡単ツイート収集_search

Apitoreの「簡単ツイート収集」REST APIを呼び出して、指定キーワードによるTweet内容の検索を行うAppleScriptです。

実行前にApitoreにユーザー登録を行い(無料)、Web上でアクセストークンを取得。そのトークンをretAccessToken()内で返すように書いておく必要があります(掲載のリストのまま実行すると、エラーになります。かならずアクセストークンを取得してください)。

また、Twitterのサービスとの連携をオンにするために、Apitoreのマイページから「Twitterと連携する」をクリックし、ApitoreをTwitterとアプリ連携してください。

AppleScript名:簡単ツイート収集_search
– Created 2017-03-29 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4572

set aQuery to “#07Itakura”
set aResList to twitterSearchByQuery(aQuery) of me
–> {tweets:{{sentiment:missing value, favoritedCount:409, source:”Echofon“, retweetCount:392, userId:371790917, userName:”機動戦士ガンダム第07板倉小隊”, userScreenName:”07itakura”, text:”【お知らせ】本日放送した板倉小隊特番のアーカイブを明日26日の昼12時から板倉小隊のHPにて1ヵ月限定で配信決定!見逃してしまった方、もう一度見たいという方、ぜひお楽しみに! https://t.co/Q9q6VhiNGU #07itakura”, statusId:8.45606316664021E+17, sentimentScore:missing value, retweeted:false, favorited:false, createdAt:1.490443231E+12, userProfileImageURL:”http://pbs.twimg.com/profile_images/2578804231/hmzlhl1aaxaen8nf8i5b_normal.png”},….

on twitterSearchByQuery(aQuery)
  set reqURLStr to “https://api.apitore.com/api/23/twitter/search”
  
set accessToken to retAccessToken() —Access Token
  
set aRec to {access_token:accessToken, q:aQuery, sinceId:“-1″, maxId:“-1″, iter:“1″}
  
set aURL to retURLwithParams(reqURLStr, aRec) of me
  
  
set aRes to callRestGETAPIAndParseResults(aURL) of me
  
set aRESCode to (responseCode of aRes) as integer
  
set aRESTres to (json of aRes) as record
  
  
return aRESTres
end twitterSearchByQuery

–GET methodのREST APIを呼ぶ
on callRestGETAPIAndParseResults(aURL)
  set aRequest to current application’s NSMutableURLRequest’s requestWithURL:(current application’s |NSURL|’s URLWithString:aURL)
  
  
aRequest’s setHTTPMethod:“GET”
  
aRequest’s setCachePolicy:(current application’s NSURLRequestReloadIgnoringLocalCacheData)
  
aRequest’s setHTTPShouldHandleCookies:false
  
aRequest’s setTimeoutInterval:60
  
aRequest’s setValue:“application/json” forHTTPHeaderField:“Accept”
  
  
set aRes to current application’s NSURLConnection’s sendSynchronousRequest:aRequest returningResponse:(reference) |error|:(missing value)
  
set resList to aRes as list
  
  
set bRes to contents of (first item of resList)
  
set resStr to current application’s NSString’s alloc()’s initWithData:bRes encoding:(current application’s NSUTF8StringEncoding)
  
  
set jsonString to current application’s NSString’s stringWithString:resStr
  
set jsonData to jsonString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set aJsonDict to current application’s NSJSONSerialization’s JSONObjectWithData:jsonData options:0 |error|:(missing value)
  
  
–Get Response Code & Header
  
set dRes to contents of second item of resList
  
if dRes is not equal to missing value then
    set resCode to (dRes’s statusCode()) as number
    
set resHeaders to (dRes’s allHeaderFields()) as record
  else
    set resCode to 0
    
set resHeaders to {}
  end if
  
  
return {json:aJsonDict, responseCode:resCode, responseHeader:resHeaders}
  
end callRestGETAPIAndParseResults

on retURLwithParams(aBaseURL, aRec)
  set aDic to current application’s NSMutableDictionary’s dictionaryWithDictionary:aRec
  
  
set aKeyList to (aDic’s allKeys()) as list
  
set aValList to (aDic’s allValues()) as list
  
set aLen to length of aKeyList
  
  
set qList to {}
  
repeat with i from 1 to aLen
    set aName to contents of item i of aKeyList
    
set aVal to contents of item i of aValList
    
set the end of qList to (current application’s NSURLQueryItem’s queryItemWithName:aName value:aVal)
  end repeat
  
  
set aComp to current application’s NSURLComponents’s alloc()’s initWithString:aBaseURL
  
aComp’s setQueryItems:qList
  
set aURL to (aComp’s |URL|()’s absoluteString()) as text
  
  
return aURL
end retURLwithParams

on retAccessToken()
  return “XXXXxxxX-xxxx-XXXx-xxxX-XxxxXxXxxXXx” –API Tore Access Token
end retAccessToken

★Click Here to Open This Script 

2017/03/28 macOS 10.12のsayコマンドのバグはNSSpeechSynthesizerのレベルで発生

macOS 10.12.4アップデートがリリースされましたが、不可解なバグや理解しにくい仕様の多くはいまだ解消されていません。

# FAX modemのサポート機能を削ったのはやりすぎだろう(ーー;

そのうちの1つである、sayコマンドで日本語の特定のテキスト読み上げに失敗するというバグ。これを回避するために、NSSpeechSynthesizerを直接呼び出すテストを行ってみたところ、sayコマンドと同様のおかしな音声出力が得られました。

一応、Voice側に問題がある可能性を考慮して、OtoyaとKyokoの両方のVoiceでチェックしてみましたが、両方で同じ現象が発生します。このため、NSSpeechSynthesizerにバグがあるか、OtoyaとKyokoの両方のVoiceに問題があるかといったところなんでしょう。

このレベルで問題があるということは、iOS側でも同じ問題があるのではないかと考え、iOS 10.3上でも読み上げを確認してみたところ、「もげる」→「もげ」、「捥げる」→(読み上げすらしない) と、同様に問題があることがわかりました。

AppleScript名:NSSpeechSynthesizerのバグ
– Created 2017-03-28 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4569

set vList to {“com.apple.speech.synthesis.voice.otoya.premium”, “com.apple.speech.synthesis.voice.kyoko.premium”}

repeat with i in vList
  set aSynth to (current application’s NSSpeechSynthesizer’s alloc()’s initWithVoice:i)
  
if aSynth is not equal to missing value then
    (aSynth’s startSpeakingString:げる”) –> “げる”(Bug)
    
delay 1
    (
aSynth’s startSpeakingString:“もげる”) –> “もげ”(Bug)
    
delay 1
  end if
end repeat

★Click Here to Open This Script 

2017/03/27 実体参照している文字列をデコードする(ASOC)

HTMLの中などで実体参照(Character reference)しているエンコードされた文字列をデコードするAppleScriptのCocoa呼び出し版です(Pure AppleScript版はこちら)。

AppleScript名:実体参照している文字列をデコードする(ASOC)
– Created 2017-01-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4568

set aStr to "龍馬伝"
set aRes to decodeCharacterReference(aStr) of me
–>  "龍馬伝"

set aStr to "\"第2エア\""
set aRes to decodeCharacterReference(aStr) of me
–>  "\"第2エア\""

on decodeCharacterReference(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF16StringEncoding)
  
set styledString to current application’s NSAttributedString’s alloc()’s initWithHTML:theData documentAttributes:(missing value)
  
set plainText to (styledString’s |string|()) as string
  
return plainText
end decodeCharacterReference

★Click Here to Open This Script 

2017/03/21 CoreImage(CIFilter)で指定画像を2階調ポスタライズ v2

CoreImageのCIFilterを用いて、指定の画像を2階調でポスタライズするAppleScriptです。

CPUImageにも同様のポスタライズ用のフィルタが存在しているのですが、パラメータを指定してもうまく効かなかったので、CIFilterを使ってみました。

6ba2129c-12c5-42bf-b1a6-48dc883a97ec.png
▲実行前

81421d35-72aa-4d9d-9e6b-e2c59f9c9109.png
▲実行後

AppleScript名:CoreImageで指定画像を2階調ポスタライズ v2
– Created 2017-03-21 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “ASObjCExtras”
use framework “QuartzCore”
–http://piyocast.com/as/archives/4541

–画像を選択
set aPath to POSIX path of (choose file of type {“public.image”})
set aNSImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aPath

set imgRes to execCIFilterWithNSImage(aNSImage, “CIColorPosterize”) of me

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”)

set fRes to saveNSImageAtPathAsPNG(imgRes, 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をCIImageに変換してCIfilterを実行
on execCIFilterWithNSImage(aNSImage, aFilterName)
  set aCIImage to convNSImageToCIimage(aNSImage) of me
  
  
set aFilter to current application’s CIFilter’s filterWithName:aFilterName
  
aFilter’s setDefaults()
  
aFilter’s setValue:aCIImage forKey:“inputImage”
  
aFilter’s setValue:2 forKey:“inputLevels”
  
set aOutImage to aFilter’s valueForKey:“outputImage”
  
  
set newNSImage to convCIimageToNSImage(aOutImage) of me
  
return newNSImage
end execCIFilterWithNSImage

–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

★Click Here to Open This Script 

2017/03/21 CIImageとNSImageの相互変換

CIImageとNSImageの相互変換を行うAppleScriptです。

ファイル入出力をはじめ、さまざまな処理を行う場合にはNSImageで指定するように各種ライブラリの入出力を統一するようにしています。そのため、CIFilterを利用するような場合でもNSImageで画像データを渡すようにしています。

CIFilterを実行するサブルーチン内では、CoreImageで画像データを扱うのでCIImageで画像を渡す必要があるためCIImageに変換してFilter処理を行い、その後にNSImageに変換して結果を返すようにしています。

似たような名前のオブジェクトとして「CGImage」(CoreGraphicsの)がありますが、これはAppleScript側からは手が出ないオブジェクトに見えます。少なくとも、自分はCGImageと他フォーマットとの変換についてはやり方はわかりません。

AppleScript名:CIImageとNSImageの相互変換
– Created 2017-03-21 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use framework "QuartzCore"
–http://piyocast.com/as/archives/4540

–Get Computer Icon (NSImage)
set anImage to current application’s NSImage’s imageNamed:(current application’s NSImageNameComputer)

set aCIImage to convNSImageToCIimage(anImage) of me
–> (CIImage)

set bNSImage to convCIimageToNSImage(aCIImage) of me
–> (NSImage)

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

★Click Here to Open This Script 

2017/03/18 文字を集合(CountedSet)に変換して文字列同士の近似度を計算する v2

複数の文字列同士の近似度を擬似的に計算できないかと考えて、文字列をCountedSetに変換して、CountedSet同士でand演算(intersectSet)を実行。その計算結果が大きいほど「文字列中に含まれている文字列の傾向が似ている」と判断するテストのAppleScriptです。

countedset_intersect_resized.png

とりあえずはintersectSetで積集合を計算しています。重複している部分を求めているわけです。

 「This is an apple.」と「This is a pinapple.」–> 11
 「This is a pinapple.」と「Piyomaru San Dayo.」–> 5
 「Piyomaru San Dayo.」と「This is an apple.」–> 5

v1とv2の計算結果を合わせて、両方の傾向を反映させるようにするとよいのかもしれません。

AppleScript名:文字を集合(CountedSet)に変換して文字列同士の近似度を計算する v2
– Created 2017-03-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
–http://piyocast.com/as/archives/4532

set aStr to "This is a pinnapple."
set bStr to "This is an apple."
set cStr to "Piyomaru San Dayo."

set a1Res to getApproximationBetweenStringsIntersect(aStr, bStr) of me
–>  11

set bRes to getApproximationBetweenStringsIntersect(bStr, cStr) of me
–>  5

set cRes to getApproximationBetweenStringsIntersect(cStr, aStr) of me
–>  5

on getApproximationBetweenStringsIntersect(aStr, bStr)
  set aList to current application’s NSMutableArray’s arrayWithArray:(characters of aStr)
  
set bList to current application’s NSMutableArray’s arrayWithArray:(characters of bStr)
  
  
set aIndex to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bIndex to current application’s NSCountedSet’s alloc()’s initWithArray:bList
  
  
aIndex’s intersectSet:bIndex
  
set aRes to aIndex’s allObjects()’s |count|()
  
return aRes
end getApproximationBetweenStringsIntersect

★Click Here to Open This Script 

2017/03/18 文字を集合(CountedSet)に変換して文字列同士の近似度を計算する v1

複数の文字列同士の近似度を擬似的に計算できないかと考えて、文字列をCountedSetに変換して、CountedSet同士で減算を実行。その計算結果が少ないほど「文字列中に含まれている文字列の傾向が似ている」と判断するテストのAppleScriptです。

countedset.png

とりあえずはminusSetで減算を行なっていますが、ほかの方法も試してみたいところです。

本Scriptでは、得られた結果の数値が小さければ重複している文字が多いということで、計算結果そのものにはあまり意味はありませんが、複数の結果を大小比較して、数値が小さいもののペアが「似たような傾向を持つもの」として期待できます。

 「This is an apple.」と「This is a pinapple.」–> 3
 「This is a pinapple.」と「Piyomaru San Dayo.」–> 8
 「Piyomaru San Dayo.」と「This is an apple.」–> 9

ということで、これらの間では「This is an apple.」と「This is a pinapple.」の近似度が一番高いといえることになります。

AppleScript名:文字を集合(CountedSet)に変換して文字列同士の近似度を計算する v1
– Created 2017-03-18 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4530

set aStr to “This is a pinnapple.”
set bStr to “This is an apple.”
set cStr to “Piyomaru San Dayo.”

set a1Res to getApproximationBetweenStrings(aStr, bStr) of me
–>  3

set bRes to getApproximationBetweenStrings(bStr, cStr) of me
–>  8

set cRes to getApproximationBetweenStrings(cStr, aStr) of me
–>  9

on getApproximationBetweenStrings(aStr, bStr)
  set aList to current application’s NSMutableArray’s arrayWithArray:(characters of aStr)
  
set bList to current application’s NSMutableArray’s arrayWithArray:(characters of bStr)
  
  
set aIndex to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set bIndex to current application’s NSCountedSet’s alloc()’s initWithArray:bList
  
  
aIndex’s minusSet:bIndex
  
set aRes to aIndex’s allObjects()’s |count|()
  
  
bIndex’s minusSet:aIndex
  
set bRes to bIndex’s allObjects()’s |count|()
  
  
if aRes bRes then
    return bRes
  else
    return aRes
  end if
end getApproximationBetweenStrings

★Click Here to Open This Script 

2017/03/16 Dockとメニューバーを隠す→戻す

メニューバーとDockを隠して10秒たったら元に戻すAppleScriptです。

隠すことが目的で、元に戻すのは単なる後片付けです。

Objective-Cの「|」記号がORであることを忘れてしばらく考えてしまいましたが、ORだとわかればEnumを加算して数値で指定すればいいだけなので、パラメータを直接数値で指定しました。

AppleScript名:Dockとメニューバーを隠す→戻す
– Created 2017-03-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4529

–Main MenuとDockを隠す
current application’s NSApplication’s sharedApplication()’s setPresentationOptions:10 –NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock

delay 10

–MenuとDockを通常に戻す
current application’s NSApplication’s sharedApplication()’s setPresentationOptions:(current application’s NSApplicationPresentationDefault)

★Click Here to Open This Script 

2017/03/15 Spotlightで指定フォルダ以下の指定文字を含むファイル一覧を取得

Cocoaの機能を呼び出すAppleScriptObjCでは、さまざまなCocoaのAPIを呼び出す手法が模索されてきました。その中でもSpotlight検索は「割とまだ決定版の手法が確立していない」ものでありました。

spotlightでタグを指定して検索
http://piyocast.com/as/archives/3731

ASOCでmdfindするじっけん v4(フルパスを返す)
http://piyocast.com/as/archives/4122

などなど、徐々に進化してきて、Shane StanleyのAppleScript Libraries「BridgePlus」にSpotlightの呼び出し命令が実装されたりと、手段が洗練されてきたという経緯があります。

書籍「AppleScript 10大最新技術」にも掲載していますが、その時点のバージョンよりもはるかにこなれた書き方がML上でShane Stanleyから提示されました。いままでよりもはるかに短いので、ちょっと腰を抜かしてしまったほど。しかも、とてもさりげなく、、、

「ああ、こういう書き方でもいいんだ、、、」

と、かなりすごいことになっています。

AppleScript名:Spotlightで指定フォルダ以下の指定文字を含むファイル一覧を取得
– Created 2017-03-15 By Shane Stanley
use AppleScript version “2.4″ – Yosemite (10.10) or later
use framework “Foundation”
use scripting additions
–http://piyocast.com/as/archives/4528

set thePath to POSIX path of (path to desktop) – whatever

–ファイル名で検索
set theKeyword to “スクリーンショット”
set fResList to my searchPath:thePath searchPredicate:“(kMDItemFSName CONTAINS [c]%@)” predicateArgs:{theKeyword}
–>  {”/Users/me/Desktop/2013/03/スクリーンショット 2016-12-15 8.44.28.png”, “/Users/me/Desktop/FromDesktop/samples/list splitted or broken/スクリーンショット 2015-08-31 10.49.30.png”, …… }

–UTI(File Kind)で検索
set theKeyword to “public.png”
set fResList to my searchPath:thePath searchPredicate:“(kMDItemContentType == [c]%@)” predicateArgs:{theKeyword}
–> {”/Users/me/Desktop/2013/03/スクリーンショット 2016-12-15 8.44.28.png”, “/Users/me/Desktop/FromDesktop/IMG_3143_resized.png”, “/Users/me/Desktop/FromDesktop/asoctable.png”….}

–ファイルの内容で検索
set fResList to my searchPath:thePath searchPredicate:“(kMDItemTextContent == [c]%@)” predicateArgs:{“戦場の絆”}
–>  {”/Users/me/Desktop/2013/01/gundam_games_history.txt”, “/Users/me/Desktop/book1_2.0.pdf”}

on searchPath:thePath searchPredicate:predString predicateArgs:argList
  set thePred to current application’s NSPredicate’s predicateWithFormat:predString argumentArray:argList
  
set targetURL to current application’s |NSURL|’s fileURLWithPath:thePath
  
set theQuery to current application’s NSMetadataQuery’s new()
  
  
theQuery’s setPredicate:thePred
  
theQuery’s setSearchScopes:{targetURL}
  
theQuery’s startQuery()
  
  
repeat while theQuery’s isGathering() as boolean
    delay “0.001″ as real
  end repeat
  
theQuery’s stopQuery()
  
  
set theCount to theQuery’s resultCount()
  
set theResults to current application’s NSMutableArray’s array()
  
  
repeat with i from 1 to theCount
    set aResult to (theQuery’s resultAtIndex:(i - 1))
    
set thePath to (aResult’s valueForAttribute:(current application’s NSMetadataItemPathKey))
    (
theResults’s addObject:thePath)
  end repeat
  
  
return (theResults’s sortedArrayUsingSelector:“compare:”) as list
end searchPath:searchPredicate:predicateArgs:

★Click Here to Open This Script 

2017/03/11 256×3のグラフ画像を縦方向に拡大する v2

GPUImage.frameworkの明度ヒストグラムの出力画像を加工するために作成したAppleScriptの改良版です。

256×3ドットの画像から、

6ed48d0a-5718-4562-9ad3-b7a63269678f.png

明度ヒストグラムのデータ部分である中央の256×1ドットのパターンを切り抜いて取得。そのパターンで256×90の空白の画像を塗りつぶして保存します。

53da8086-f585-4d45-9d4b-e5b9ceee7f03.png

最初のバージョンでは、バカていねいに元の画像の色情報を読み取って、その通りに新規画像に点で描画していました。そのため、処理に数秒(4秒ぐらい?)かかっていました。

本バージョンは、MacBook Pro Retina 2012(Core i7 2.66GHz)で0.008秒ぐらいでファイル書き込みも含めて終了します。

AppleScript名:256×3のグラフ画像を縦方向に拡大する v2
– Created 2017-03-11 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
–http://piyocast.com/as/archives/4522

set aHeight to 90
set aWidth to 256

set aPath to POSIX path of (choose file of type {“public.image”})
set anImage to current application’s NSImage’s alloc()’s initWithContentsOfFile:aPath

–256×1で切り抜き
set bImage to my cropNSImageBy:{0, 1, 256, 1} fromImage:anImage
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:(anImage’s TIFFRepresentation())

–256×90の画像を作成
set cImage to current application’s NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))

–256×1のパターンでぬりつぶし
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
cImage’s lockFocus()
(
current application’s NSColor’s colorWithPatternImage:bImage)’s |set|()
current application’s NSBezierPath’s fillRect:theRect
cImage’s unlockFocus()

–PNG形式で保存
set aPath to (POSIX path of (path to desktop) & (current application’s NSUUID’s UUID())’s UUIDString() as string) & “.png”
saveNSImageAtPathAsPNG(cImage, aPath)

–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を指定の大きさでトリミング
on cropNSImageBy:{x1, y1, newWidth, newHeight} fromImage:theImage
  set theSize to (theImage’s |size|()) as record
  
set oldHeight to height of theSize
  
  
– transpose y value for Cocoa coordintates
  
set y1 to oldHeight - newHeight - y1
  
set newRect to {{x:x1, y:y1}, {width:newWidth, height:newHeight}}
  
theImage’s lockFocus()
  
set theRep to current application’s NSBitmapImageRep’s alloc()’s initWithFocusedViewRect:newRect
  
theImage’s unlockFocus()
  
  
set outImage to current application’s NSImage’s alloc()’s initWithSize:(theRep’s |size|())
  
outImage’s addRepresentation:theRep
  
  
return outImage
end cropNSImageBy:fromImage:

★Click Here to Open This Script 

2017/03/09 ASCIImageでPNG画像をデスクトップに作成する

オープンソースのプログラム「ASCIImage」(By Charles Parnot)を用いて、ASCII ARTからPNG画像を作成するAppleScriptです。AppleScriptからの呼び出しは、同プログラムをフレームワーク化した「asciiImageKit」を経由しています。

本AppleScriptのテストのためには、asciiImageKit.frameworkを~/Library/Frameworksフォルダに入れておく必要があります。バイナリを用意しておきましたので、自己責任でおためしください。

Download Binary (30KB)

ASCIImageは(どうして作者がこれを作ったのかが)とても不思議なプログラムで、画像描画を文字で(ASCII ARTっぽく)指定するとNSImageが得られます。NSImageが得られれば、あとはPNGなりJPEGなり好みの画像フォーマットで書き出しできます。

ascii1.png
▲shouldAntialias=falseでレンダリングした画像

ascii2.png
▲shouldAntialias=trueでレンダリングした画像

inv.png
▲自分でデータ作成をこころみてみたものの、思い通りに描画されなかったデータ。コツが必要なのか意外と難しい、、、、

AppleScript名:ASCIImageでPNG画像をデスクトップに作成する
– Created 2017-03-09 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “asciiImageKit” –https://github.com/cparnot/ASCIImage
use framework “AppKit”
–http://piyocast.com/as/archives/4517

set aColor to current application’s NSColor’s blackColor()

set aRep to {· · · 1 2 · · · · ·, ¬
  · · · A # # · · · ·, ¬
  
· · · · # # # · · ·, ¬
  
· · · · · # # # · ·, ¬
  
· · · · · · 9 # 3 ·, ¬
  
· · · · · · 8 # 4 ·, ¬
  
· · · · · # # # · ·, ¬
  
· · · · # # # · · ·, ¬
  
· · · 7 # # · · · ·, ¬
  
· · · 6 5 · · · · ·}

set anImage to current application’s NSImage’s imageWithASCIIRepresentation:aRep |color|:aColor shouldAntialias:false

set aPath to (POSIX path of (path to desktop) & (current application’s NSUUID’s UUID())’s UUIDString() as string) & “.png”
set fRes to saveNSImageAtPathAsPNG(anImage, aPath) of me

–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

★Click Here to Open This Script 

2017/03/07 矩形座標同士の合計

NSUnionRectによる矩形座標(NSRect)の合計をためしてみました。

unionrect.png

実際に方眼紙を塗りつぶしてみると、計算結果が不思議な感じもするのですが(空いているセルもあるので)、、、そういうものなんでしょう、、、か(^ー^;;;;;

AppleScript名:矩形座標同士の合計
– Created 2017-03-06 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4515

set a1Rect to {origin:{x:10, y:10}, |size|:{width:40, height:40}}
set b1Rect to {origin:{x:30, y:30}, |size|:{width:40, height:40}}
set a1Res to current application’s NSUnionRect(a1Rect, b1Rect)
–>  {origin:{x:10.0, y:10.0}, size:{width:60.0, height:60.0}}

★Click Here to Open This Script 

2017/03/06 矩形座標同士の衝突判定 v3

なんとなくあるとは予想していた矩形座標(NSRect)同士の衝突検出。Cocoa勉強会池袋で聞いてみたら、やっぱりありました(汗)

面倒な処理も必要なく、NSIntersectionRect(aRect, bRect) で重なり合う(and)箇所を検出できてしまいました。1対の矩形座標の衝突検出で所要時間0.001秒以下。たいへん簡単かつお手軽に検出できました。

NSIntersectionRectとNSUnionRectのことは、しばらく忘れられないことでしょう。

AppleScript名:矩形座標同士の衝突判定 v3
– Created 2017-03-06 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4514

set a1Rect to {origin:{x:10, y:10}, |size|:{width:100, height:100}}
set b1Rect to {origin:{x:30, y:30}, |size|:{width:100, height:100}}
set a1Res to detectRectanglesCollision(a1Rect, b1Rect) of me
–>  true

set a4Rect to {origin:{x:0, y:20}, |size|:{width:100, height:10}}
set b4Rect to {origin:{x:1000, y:10000}, |size|:{width:50, height:100}}
set a2Res to detectRectanglesCollision(a4Rect, b4Rect) of me
–>  false

set a3Rect to {origin:{x:30, y:30}, |size|:{width:50, height:50}}
set b3Rect to {origin:{x:10, y:10}, |size|:{width:100, height:100}}
set a3Res to detectRectanglesCollision(a3Rect, b3Rect) of me
–> true

set a4Rect to {origin:{x:0, y:20}, |size|:{width:100, height:10}}
set b4Rect to {origin:{x:10, y:10}, |size|:{width:50, height:100}}
set a4Res to detectRectanglesCollision(a4Rect, b4Rect) of me
–> true

–NSRect同士の衝突判定
on detectRectanglesCollision(aRect, bRect)
  set a1Res to current application’s NSIntersectionRect(aRect, bRect)
  
return not (a1Res = {origin:{x:0.0, y:0.0}, |size|:{width:0.0, height:0.0}})
end detectRectanglesCollision

★Click Here to Open This Script