Hatena::ブログ(Diary)

ザリガニが見ていた...。 このページをアンテナに追加 RSSフィード

2012-01-26

マウスを自在にコントロールするAppleScript

前回からの続き。

AppleScriptからマウスイベントを徹底的にコントロールする方法をある程度理解できたので、ハンドラにまとめてみた。数か月後に別人となった自分のために、自分用のAppleScriptライブラリに_mouse.scptとして追加しておいた。

AppleScriptコード

 -------- CGEventType --------
 property kCGEventNull : 0
 property kCGEventLeftMouseDown : 1
 property kCGEventLeftMouseUp : 2
 property kCGEventRightMouseDown : 3
 property kCGEventRightMouseUp : 4
 property kCGEventMouseMoved : 5
 property kCGEventLeftMouseDragged : 6
 property kCGEventRightMouseDragged : 7
 property kCGEventKeyDown : 10
 property kCGEventKeyUp : 11
 property kCGEventFlagsChanged : 12
 property kCGEventScrollWheel : 22
 property kCGEventTabletPointer : 23
 property kCGEventTabletProximity : 24
 property kCGEventOtherMouseDown : 25
 property kCGEventOtherMouseUp : 26
 property kCGEventOtherMouseDragged : 27
 property kCGEventTapDisabledByTimeout : "0xFFFFFFFE"
 property kCGEventTapDisabledByUserInput : "0xFFFFFFFF"
 -------- CGEventType --------
 
 -------- CGMouseButton --------
 property kCGMouseButtonLeft : 0
 property kCGMouseButtonRight : 1
 property kCGMouseButtonCenter : 2
 -------- CGMouseButton --------
 
 -------- CGEventFlags --------
 property kCGEventFlagMaskAlphaShift : 65536 --caps lock
 property kCGEventFlagMaskShift : 131072
 property kCGEventFlagMaskControl : 262144
 property kCGEventFlagMaskAlternate : 524288 --option
 property kCGEventFlagMaskCommand : 1048576
 property kCGEventFlagMaskHelp : 4194304
 property kCGEventFlagMaskSecondaryFn : 8388608 --fn
 property kCGEventFlagMaskNumericPad : 2097152
 property kCGEventFlagMaskNonCoalesced : 256
 -------- CGEventFlags --------
 -------- CGEventFlagsの短縮形 --------
 property command : kCGEventFlagMaskCommand
 property option : kCGEventFlagMaskAlternate
 property shift : kCGEventFlagMaskShift
 property control : kCGEventFlagMaskControl
 property fn : kCGEventFlagMaskSecondaryFn
 -------- CGEventFlagsの短縮形 --------
 
 -------- CGEventField --------
 property kCGMouseEventClickState : 1
 -------- CGEventField --------
 
 (*    サンプルコード
 CGEventPost(kCGEventLeftMouseDown, 27, 12, kCGMouseButtonLeft, option + shift, 1) --optionshiftを押しながら、アップルメニューでマウスボタンを押す
 CGEventPost(kCGEventLeftMouseUp, 27, 12, kCGMouseButtonLeft, option + shift, 1) --optionshiftを押しながら、アップルメニューでマウスボタンを放す
 *)
 --ruby_cocoaを利用して、AppleScriptから最もローレベルなマウスイベントを発行する
 --(最もローレベルなマウスイベント=マウスボタンを押す、放す、移動するなど)
 --引数:
 --●CGEventType      : kCGEventLeftMouseDown, kCGEventMouseMovedなど
 --●x,y              : マウスカーソルの座標
 --    例:27,12            数値による絶対座標指定
 --    例:"m+100","m-5"    mを含めた相対座標指定(mは現在のカーソル位置のx座標・y座標に変換される)
 --●CGMouseButton  : 押されたマウスボタンの番号
 --    下記のCGEventTypeの時だけ有効になる。下記以外の場合は無視される。
 --    kCGEventOtherMouseDown, kCGEventOtherMouseDragged, kCGEventOtherMouseUp
 --●click_count      : クリック回数(MouseDown時に指定した回数が有効になる)
 --●CGEventFlags    : 修飾キーの状態
 --    例:option + shift      optionキーとshiftキーを押しながらマウスを操作する扱いになる
 on CGEventPost(CGEventType, x, y, CGMouseButton, click_count, CGEventFlags)
   set ruby_cocoa to "require 'osx/cocoa'
   loc=OSX::CGEventGetLocation(OSX::CGEventCreate(nil))
   x=eval('" & x & "'.sub(/m/,loc.x.to_s))
   y=eval('" & y & "'.sub(/m/,loc.y.to_s))
   point=OSX::CGPointMake(x,y)
   event=OSX::CGEventCreateMouseEvent(nil, " & CGEventType & ", point, " & CGMouseButton & ")
   OSX::CGEventSetIntegerValueField(event, " & kCGMouseEventClickState & ", " & click_count & ")
   OSX::CGEventSetFlags(event, " & CGEventFlags & ")
   OSX::CGEventPost(0,event)"
   do shell script "/usr/bin/ruby -e " & quoted form of ruby_cocoa
 end CGEventPost
 
 (*    サンプルコード
 mouse_move(26, 12) --マウスカーソルをアップルメニューへ移動する
 *)
 --マウスカーソルを移動する
 on mouse_move(x, y)
   CGEventPost(kCGEventMouseMoved, x, y, kCGMouseButtonLeft, 0, 0)
 end mouse_move
 
 (*    サンプルコード
 left_click(26, 12) --アップルメニューをクリック
 left_click("m", "m") --現在のカーソル位置をクリック
 left_click("m+" & 100, "m") --現在のカーソル位置から右に100px移動した位置をクリック
 *)
 --左クリックする
 on left_click(x, y)
   modifire_left_click(x, y, 1, 0)
 end left_click
 
 --右クリックする
 on right_click(x, y)
   modifire_right_click(x, y, 1, 0)
 end right_click
 
 (*    サンプルコード
 center_click("m", "m",) --現在のカーソル位置で中央クリック
 *)
 --中央クリックする
 on center_click(x, y)
   modifire_other_click(x, y, 1, 0, kCGMouseButtonCenter)
 end center_click
 
 (*    サンプルコード
 modifire_left_click(26, 12, 1, option + shift) --optionshiftを押しながら、アップルメニューをクリック
 modifire_left_click("m", "m", 2, 0) --現在のカーソル位置で左ダブルクリック
 modifire_left_click("m", "m", 3, 0) --現在のカーソル位置で左トリプルクリック
 *)
 --修飾キーを押しながら、左ボタンをクリック・ダブルクリック等する
 on modifire_left_click(x, y, click_count, modifire_key)
   CGEventPost(kCGEventLeftMouseDown, x, y, kCGMouseButtonLeft, click_count, modifire_key)
   CGEventPost(kCGEventLeftMouseUp, "m", "m", kCGMouseButtonLeft, click_count, modifire_key)
 end modifire_left_click
 
 --修飾キーを押しながら、右ボタンをクリック・ダブルクリック等する
 on modifire_right_click(x, y, click_count, modifire_key)
   CGEventPost(kCGEventRightMouseDown, x, y, kCGMouseButtonRight, click_count, modifire_key)
   CGEventPost(kCGEventRightMouseUp, "m", "m", kCGMouseButtonRight, click_count, modifire_key)
 end modifire_right_click
 
 (*    サンプルコード
 modifire_other_click("m", "m", 1, 0, 0) --mightyマウスの左クリック
 modifire_other_click("m", "m", 1, 0, 1) --mightyマウスの右クリック
 modifire_other_click("m", "m", 1, 0, 2) --mightyマウスの中央クリック
 modifire_other_click("m", "m", 1, 0, 3) --mightyマウスのサイドクリック
 *)
 --修飾キーを押しながら、マウスのボタン番号を指定してクリック・ダブルクリック等する
 on modifire_other_click(x, y, click_count, modifire_key, CGMouseButton)
   CGEventPost(kCGEventOtherMouseDown, x, y, CGMouseButton, click_count, modifire_key)
   CGEventPost(kCGEventOtherMouseUp, "m", "m", CGMouseButton, click_count, modifire_key)
 end modifire_other_click
 
 (*    サンプルコード
 mouse_location()
 --結果:{x:28, y:14}
 *)
 --マウスカーソルの座標(左上原点)を返す
 on mouse_location()
   set ruby_cocoa to "require 'osx/cocoa'
   pt=OSX::CGEventGetLocation(OSX::CGEventCreate(nil))
   puts pt.x, pt.y"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of ruby_cocoa
   {x:pt's paragraph 1 as number, y:pt's paragraph 2 as number}
 end mouse_location

  • CGEventPostハンドラによって、RubyCocoaを利用して、AppleScriptからローレベルなマウスイベントを発行する。
    • CGEventPost(CGEventType, x, y, CGMouseButton, click_count, CGEventFlags)
  • CGEventPostハンドラを使えば、かなり詳細なローレベルイベントを発行できるが、引数が多くて扱いにくい...。
  • 引数を少なくして簡単に扱える簡易ハンドラも用意した。
    • mouse_move(x, y)
    • left_click(x, y)
    • right_click(x, y)
    • center_click(x, y)
  • さらに修飾キーやダブルクリック・トリプルクリックなども扱えるようにした簡易ハンドラ。
    • modifire_left_click(x, y, click_count, modifire_key)
    • modifire_right_click(x, y, click_count, modifire_key)
    • modifire_other_click(x, y, click_count, modifire_key, CGMouseButton)
  • マウスの座標だけ取得したこともあるかと思いマウス座標を返すハンドラ。
    • mouse_location()

参考ページ

以下のページがたいへん参考になりました。感謝です!

悩みどころ

  • ObjectiveCのCocoa環境からは、kCGEventLeftMouseDownのような定数に簡単にアクセスできるのだが、RubyCocoaからはどうやってアクセスすれば良いのだろう?
  • 結局分からなくて、以下のようなNSLog出力を実行して値を取得し、AppleScriptのプロパティとしてしまった...。
  • だから_mouse.scptにはプロパティが異常に多いのだ。RubyCocoaから定数にアクセスできればなくせるのに...。
//
//  main.m
//  kCGEventLeftMouseDown
//
//  Created by zarigani on 12/01/25.
//  Copyright 2012 __MyCompanyName__. All rights reserved.
//

#import <Cocoa/Cocoa.h>

int main(int argc, char *argv[])
{
    NSLog(@"kCGEventNull: %u", kCGEventNull);
    NSLog(@"kCGEventLeftMouseDown: %u", kCGEventLeftMouseDown);
    NSLog(@"kCGEventLeftMouseUp: %u", kCGEventLeftMouseUp);
    NSLog(@"kCGEventRightMouseDown: %u", kCGEventRightMouseDown);
    NSLog(@"kCGEventRightMouseUp: %u", kCGEventRightMouseUp);
    NSLog(@"kCGEventMouseMoved: %u", kCGEventMouseMoved);
    NSLog(@"%kCGEventLeftMouseDragged: u", kCGEventLeftMouseDragged);
    NSLog(@"kCGEventRightMouseDragged: %u", kCGEventRightMouseDragged);
    NSLog(@"kCGEventKeyDown: %u", kCGEventKeyDown);
    NSLog(@"kCGEventKeyUp: %u", kCGEventKeyUp);
    NSLog(@"kCGEventFlagsChanged: %u", kCGEventFlagsChanged);
    NSLog(@"kCGEventScrollWheel: %u", kCGEventScrollWheel);
    NSLog(@"kCGEventTabletPointer: %u", kCGEventTabletPointer);
    NSLog(@"kCGEventTabletProximity: %u", kCGEventTabletProximity);
    NSLog(@"kCGEventOtherMouseDown: %u", kCGEventOtherMouseDown);
    NSLog(@"kCGEventOtherMouseUp: %u", kCGEventOtherMouseUp);
    NSLog(@"kCGEventOtherMouseDragged: %u", kCGEventOtherMouseDragged);
    NSLog(@"kCGEventTapDisabledByTimeout: %u", kCGEventTapDisabledByTimeout);
    NSLog(@"kCGEventTapDisabledByUserInput: %u", kCGEventTapDisabledByUserInput);

    NSLog(@"kCGEventFlagMaskAlphaShift: %u", kCGEventFlagMaskAlphaShift);
    NSLog(@"kCGEventFlagMaskShift: %u", kCGEventFlagMaskShift);
    NSLog(@"kCGEventFlagMaskControl: %u", kCGEventFlagMaskControl);
    NSLog(@"kCGEventFlagMaskAlternate: %u", kCGEventFlagMaskAlternate);
    NSLog(@"kCGEventFlagMaskCommand: %u", kCGEventFlagMaskCommand);
    NSLog(@"kCGEventFlagMaskHelp: %u", kCGEventFlagMaskHelp);
    NSLog(@"kCGEventFlagMaskSecondaryFn: %u", kCGEventFlagMaskSecondaryFn);
    NSLog(@"kCGEventFlagMaskNumericPad: %u", kCGEventFlagMaskNumericPad);
    NSLog(@"kCGEventFlagMaskNonCoalesced: %u", kCGEventFlagMaskNonCoalesced);
    return NSApplicationMain(argc,  (const char **) argv);
}
  • 工夫も何もなく、ただひたすら定数の値をNSLog出力する、やっつけコードなのであった。
run
[Switching to process 19005]
実行中...
2012-01-26 0:32:52.467 kCGEventLeftMouseDown[19005:a0f] kCGEventNull: 0
2012-01-26 0:32:52.470 kCGEventLeftMouseDown[19005:a0f] kCGEventLeftMouseDown: 1
2012-01-26 0:32:52.471 kCGEventLeftMouseDown[19005:a0f] kCGEventLeftMouseUp: 2
2012-01-26 0:32:52.471 kCGEventLeftMouseDown[19005:a0f] kCGEventRightMouseDown: 3
2012-01-26 0:32:52.472 kCGEventLeftMouseDown[19005:a0f] kCGEventRightMouseUp: 4
2012-01-26 0:32:52.473 kCGEventLeftMouseDown[19005:a0f] kCGEventMouseMoved: 5
2012-01-26 0:32:52.474 kCGEventLeftMouseDown[19005:a0f] kCGEventLeftMouseDragged: u
2012-01-26 0:32:52.474 kCGEventLeftMouseDown[19005:a0f] kCGEventRightMouseDragged: 7
2012-01-26 0:32:52.485 kCGEventLeftMouseDown[19005:a0f] kCGEventKeyDown: 10
2012-01-26 0:32:52.486 kCGEventLeftMouseDown[19005:a0f] kCGEventKeyUp: 11
2012-01-26 0:32:52.486 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagsChanged: 12
2012-01-26 0:32:52.487 kCGEventLeftMouseDown[19005:a0f] kCGEventScrollWheel: 22
2012-01-26 0:32:52.488 kCGEventLeftMouseDown[19005:a0f] kCGEventTabletPointer: 23
2012-01-26 0:32:52.488 kCGEventLeftMouseDown[19005:a0f] kCGEventTabletProximity: 24
2012-01-26 0:32:52.489 kCGEventLeftMouseDown[19005:a0f] kCGEventOtherMouseDown: 25
2012-01-26 0:32:52.489 kCGEventLeftMouseDown[19005:a0f] kCGEventOtherMouseUp: 26
2012-01-26 0:32:52.490 kCGEventLeftMouseDown[19005:a0f] kCGEventOtherMouseDragged: 27
2012-01-26 0:32:52.490 kCGEventLeftMouseDown[19005:a0f] kCGEventTapDisabledByTimeout: 4294967294
2012-01-26 0:32:52.491 kCGEventLeftMouseDown[19005:a0f] kCGEventTapDisabledByUserInput: 4294967295
2012-01-26 0:32:52.492 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskAlphaShift: 65536
2012-01-26 0:32:52.492 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskShift: 131072
2012-01-26 0:32:52.493 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskControl: 262144
2012-01-26 0:32:52.494 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskAlternate: 524288
2012-01-26 0:32:52.495 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskCommand: 1048576
2012-01-26 0:32:52.495 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskHelp: 4194304
2012-01-26 0:32:52.496 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskSecondaryFn: 8388608
2012-01-26 0:32:52.497 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskNumericPad: 2097152
2012-01-26 0:32:52.497 kCGEventLeftMouseDown[19005:a0f] kCGEventFlagMaskNonCoalesced: 256

Debugger stopped.
Program exited with status value:0.

2012-01-10

あらゆる操作を実行可能マウスカーソルを動かす方法いろいろ

GUIなOS環境では、マウスを操作してカーソルを移動することで、操作対象を選択して、命令を実行する。通常マウスは人の手で操作するのだけど、もしコードで自由に制御できれば、面倒な一連のマウス操作を自動化できるのだ。

但し、人がマウスを操作する時は画面の状況を確認しながら操作できるけど、マウスカーソルを自動制御する時には、そうはいかない。今時のOSXでは、ウィンドウがしまわれていたり、アプリが隠れていたり、Spacesでスペースがいくつもあったりと、考慮しておくことが多くて大変なのだ。

一方、マウスを操作して実行する命令には、大抵ショートカットが用意されていたり、同等のコマンドがあったりする。AppleScriptでも操作可能かもしれない。可能な限りマウスカーソルの自動制御以外の方法で操作した方が、GUIの状況に左右されず、素早く、確実に、命令が完了するはずである。

そうは言っても、マウス以外の操作方法が見当たらないことも多々ある。あるいは、GUIスクリプティングがどうにも上手く動いてくれないとか、コードの書き方がよくわからないとか。そんな時、マウスカーソルを自動制御する方法を知っていれば、かなり楽して幸せになれる。マウスカーソルをコードで制御するのは、冗長で、環境にも思いきり依存し、そこでしか使えない限定的なツールになりがちだが、覚えておいて損はないと思われる。調べてみた。

AppleScriptの click atコマンド

  • 以下のように click atコマンドを使うことで、目標の座標(x=36, y=33)がクリックされる。
    • 座標(x=36, y=33)は、AppleScriptエディタのウィンドウのオレンジボタン。
    • 実行すると、Dockにウィンドウがしまわれる。(アニメーション付き)
  • 但し、目標の座標をクリックするイベントが発生するだけで、現在のマウスカーソルの位置は変化しない。
  • 目標の座標は、画面左上を原点(0, 0)とした絶対座標で指定する。
    • MacBook13インチの場合は、画面右下(1280, 800)までの範囲となる。
  • ちなみに、絶対座標は、スクリーンショットcommand-shift-4のショートカットで簡単に計測できる。

 tell application "System Events"
   tell process "AppleScript Editor"
     click at {36, 33}
   end tell
 end tell

Automatorで記録する

  • Automatorの「記録」ボタンを押すと、簡単にGUI操作がワークフローとして記録される。
  • 記録したワークフローは、「実行」ボタンを押すことで再生される。
  • 以下のワークフローは、アップルメニューのクリックを記録したもの。

f:id:zariganitosh:20120110144825p:image

  • 再生速度を×10にしておくと、ほとんど待ち時間なく、テキパキと実行してくれる。
  • マウス操作を記録したワークフローを実行すると、現在のマウスカーソルの位置がワークフローに従って動く。
  • ちなみに、記録されたイベントを、ワークフローエリアにドラッグ&ドロップすると、AppleScriptに変換される。
  • 未知のGUIスクリプティングの記述方法を知る便利な方法でもある。

cliclickコマンド

$ cliclick -h

 cliclick - Command Line Interface Click
 Version 1.3.1
 Carsten Bluem, 2010-04-13
 http://www.bluem.net/en/mac/cliclick/

 Usage: cliclick [-v] [-r] [-q] [-w n] x y [x2 y2] [x3 y3] [...]
   x and y are integer numbers which specify the screen coordinate(s)
   where the mouse click(s) should be emulated. (Upper left corner is 0 0)
   Instead of a number, you may pass "m" as x and / or value to
   use the current x and / or y position.

   If you need a doubleclick, prefix the x coordinate with "d".
   If you need a control click, use prefix "c".

 Options:
   -w <n> You can pass multiple coordinate pairs as argument. But if you do,
          it is often useful to have a small delay between events -- that is
          what the -w option is for: It will cause cliclick to wait for the
          specified number of milliseconds after each event.
   -q     Instead of clicking, print the current mouse pointer.
          location on the screen (format "x,y") and exit.
   -r     Restore initial mouse location after performing the clicks.
   -v     Makes cliclick more verbose.

 Examples:
   'cliclick 26 12' will click the apple menu
   ((x=26, y=12)の座標をクリックする。つまり、アップルメニューをクリックする。)

   'cliclick 50 60 c70 80' will click at 50/60, then Control-click at 70/80
   (cに続く座標はControl-click、つまり右クリックと同等になる。)

   'cliclick d50 60' will doubleclick at 50/60
   (dに続く座標はダブルクリックになる。)

   'cliclick dm m' will doubleclick the current mouse location
   ((m,m)は現在のマウスカーソルの座標、と読まれる。)

   'cliclick c500 m' will control-click at x position 500 and the mouse's current y position.
   (500,m)は、x=500、y=現在のy座標、と読まれる。)

   'cliclick -w 50 26 11 26 33' will open the "About this Mac" panel
   (-wに続く数値はミリ秒指定。連続クリックする時の間隔が指定される)

   'cliclick -r 26 12' will click the apple menu and, afterwards, restore the initial mouse location.
   (-rオプションは、cliclickコマンド実行後、実行前のマウスカーソル位置に戻す)

   'cliclick -q' will print the current mouse location.
   (-qオプションは、現在のマウス座標を返す)
$ cliclick -q
317,515
  • cliclickコマンドでは、クリックの連続技を簡潔なワンライナーで記述できるところが好き。

クリックせずにカーソルだけ移動する

  • 上記はすべてマウスクリックの操作だったが、クリックせずにマウスカーソルの移動のみは出来ないのだろうか?
MacRuby
  • OSX標準搭載のMacRubyを利用することで、以下のようにAppleScriptから操作できた。
    • OSX標準搭載は、MacRubyでなく、CocoaRubyだった。
    • MacRubyを利用するためには環境のインストールが必要。
  • Re: Move cursor with Applescript(サンプルコードの参考ページ。感謝です!)

 do shell script "/usr/local/bin/macruby -e \"framework 'carbon'\" -e \"framework 'ApplicationServices'\" -e \"CGWarpMouseCursorPosition(CGPointMake(" & 26 & "," & 12 & "))\""

  • 上記AppleScriptは、マウスカーソルを座標(x=26, y=12)、つまりアップルメニュー アイコンの真ん中に移動するのだ。
  • 以下のようにmove_mouseハンドラとして登録しておけば、使いやすいかもしれない。

 move_mouse(26, 12)
 
 on move_mouse(x, y)
   do shell script "/usr/local/bin/macruby -e \"framework 'carbon'\" -e \"framework 'ApplicationServices'\" -e \"CGWarpMouseCursorPosition(CGPointMake(" & x & "," & y & "))\""
 end move_mouse


CocoaRuby版(あるいはRubyCocoaと呼ばれる)

 do shell script "/usr/bin/ruby -e \"require 'osx/cocoa'\" -e \"OSX::CGWarpMouseCursorPosition(OSX::CGPointMake(" & 26 & "," & 12 & "))\""

 move_mouse(26, 12)
 
 on move_mouse(x, y)
   do shell script "/usr/bin/ruby -e \"require 'osx/cocoa'\" -e \"OSX::CGWarpMouseCursorPosition(OSX::CGPointMake(" & x & "," & y & "))\""
 end move_mouse


マウスボタンを押す・放す

  • 「クリックせずにカーソルだけ移動する」方法では、確かにマウスカーソルは移動するが、実際に手でマウスを握って動かすのと状況は異なる。
  • move_mouse()を使ってメニュー項目上に移動しても、ハイライト表示もされず、サブメニューも表示されないのだ。
  • おそらくCGWarpMouseCursorPositionは、マウスカーソルを特定の位置にセットするだけで、マウスを動かしたというイベントは発生させないのだ。
  • キー操作でメニュー選択をする方法もあるが、フルキーボードアクセスを有効にしても操作できないメニュー項目もあったりする。
    • メニューバー右側のアイコンメニューの中に、フルキーボードアクセスでは届かない項目が存在することが多い。
  • cliclickコマンドを利用しても良いのだが、クリックする一歩手前で項目をハイライトした状態で停止させておきたい需要もある。

こうなったら、マウスボタンのキーダウン・キーアップをシミュレートするしかない!

 --左のマウスボタンをダウン(押し下げ)
 left_mouse_down(26, 12)
 left_mouse_down(46, 174)
 left_mouse_down(370, 61)
 (*
 --間隔を空けてマウスボタンをアップ(放す)すればクリックになる
 delay 0.5
 left_mouse_up(370, 61)
 *)
 
 (*  
 --右クリック
 right_mouse_down(261, 527)
 delay 0.1
 right_mouse_up(261, 527)
 *)
 
 on left_mouse_down(x, y)
   set cocoa_ruby to "require 'osx/cocoa'; event=OSX::CGEventCreateMouseEvent(nil, 1, OSX::CGPointMake(" & x & "," & y & "), 0); OSX::CGEventPost(0,event);"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of cocoa_ruby
 end left_mouse_down
 
 on left_mouse_up(x, y)
   set cocoa_ruby to "require 'osx/cocoa'; event=OSX::CGEventCreateMouseEvent(nil, 2, OSX::CGPointMake(" & x & "," & y & "), 0); OSX::CGEventPost(0,event);"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of cocoa_ruby
 end left_mouse_up
 
 on right_mouse_down(x, y)
   set cocoa_ruby to "require 'osx/cocoa'; event=OSX::CGEventCreateMouseEvent(nil, 3, OSX::CGPointMake(" & x & "," & y & "), 0); OSX::CGEventPost(0,event);"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of cocoa_ruby
 end right_mouse_down
 
 on right_mouse_up(x, y)
   set cocoa_ruby to "require 'osx/cocoa'; event=OSX::CGEventCreateMouseEvent(nil, 4, OSX::CGPointMake(" & x & "," & y & "), 0); OSX::CGEventPost(0,event);"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of cocoa_ruby
 end right_mouse_up

  • AppleScriptからマウスボタンを押す・放す、という非常に低レベルなイベント操作まで出来てしまうのであった!
  • さらに、以下のページで紹介されているmouseClickハンドラは、あらゆるマウスイベントを発生させる。
  • mouseClickハンドラを活用すれば...
    • commandキーやoptionキーなども併用し、
    • ダブルクリック・ドリプルクリックも簡単に行えるのだ!
    • しかも、現在のマウスカーソル位置を活用することもできる!

素晴らし過ぎる!AppleScriptからここまで出来るとは!感動した!

  • 中身は、cocoaRubyを使ってCocoaの機能を利用しているのだけど、
  • AppleScriptとして配布すれば、OSX10.6標準の環境で実行できてしまうのである。
  • 余分なインストールなしに、そのまま実行できてしまう所が最大の魅力だと思う。

カーソルの座標を取得する

  • マウスカーソルを操作していると、現在のカーソル位置を活用したくなることがよくある。そんな時に...

 mouse_position()
 --mouse_position()'s x
 --mouse_position()'s y
 --mouse_position() as list
 
 --マウスカーソル位置{x:100, y:100}を返す
 on mouse_position()
   set cocoa_ruby to "require 'osx/cocoa'; pt=OSX::NSEvent.mouseLocation; puts pt.x, OSX::NSScreen.mainScreen.frame.size.height-pt.y;"
   set pt to do shell script "/usr/bin/ruby -e " & quoted form of cocoa_ruby
   {x:pt's paragraph 1 as number, y:pt's paragraph 2 as number}
 end mouse_position

  • もはや、NS(NextStep)系の古いオブジェクトより、最新のCG(コア・グラフィック?)系のオブジェクトを利用するべきかもしれない。

 --別解
 getMouseLocation()
 
 on getMouseLocation()
   set theRubyScript to "require 'osx/cocoa'; pt=OSX::CGEventGetLocation(OSX::CGEventCreate(nil)); puts pt.x, pt.y"
   set thePtText to do shell script "/usr/bin/ruby -e " & quoted form of theRubyScript
   {paragraph 1 of thePtText as number, paragraph 2 of thePtText as number}
 end getMouseLocation

AppleScriptであれこれする

マウスカーソルを制御して幸せな環境を作ろう!

2011-12-07

なぜ足し算より掛け算を先に計算するのか?

1+2×3
  • 突然ではあるが、上記数式の答えは、7である。(2×3=6、1+6=7)
  • 左から順に計算すると9になるのだが、9と答えてはいけない。(1+2=3、3×3=9)
  • 四則演算(しそくえんざん)には、加減算よりも乗除算を先に計算する、というルールがあるのだ。
  • ルールと言われると、決まり事だから守らなければならない、と思って今まで何の疑問も抱かず計算してきた。

ところで一体、どうしてそんなルールになったのだろう?

ルールだから?

  • 自分が少年の頃はルールだから、規則だから、と言われると渋々納得していた。
  • 周りの皆もそうするし、乗除算を先に計算しないとテストでも○が貰えないので、言われたとおりに計算してきた。
  • そんなことを繰り返すうちに、それはいつしか当然の常識となってしまい、何の疑問も感じなくなっていた。
  • では、自分が大人の今、少年から同じ質問をされたら「ルールなんだよ」と答えるべきなのか?
  • いや、その一言で済ませてしまうのは、あまりにも怠惰である。
  • ルールとしか言えないのは自分が知らないことの言い訳なのだ。
  • ルールとは、皆でそうしようと決めて守る約束事である。
  • 皆でそうしようと決めたことには、どこかに合理的な理由があってそうしたはず。
  • その合理的な理由とは何なのか、それを探って、教えてあげるべきなのだ。

掛算の定義から考える

(いずれも 0 でない)自然数 m と n に対して、m を n 個分加えた数

m × n, m · n, mn

などのように書いて m に n を掛けた数とか m と n の積、m 掛ける n などという。

乗法 - Wikipedia

つまり...

0 = 2×0
2 = 2×1
2+2 = 2×2
2+2+2 = 2×3
2+2+2+2 = 2×4
...

なのだ。

  • 掛け算とは、足し算によって定義される概念なのだ。
  • 足し算と掛け算では、概念の次元が違っている。
  • 計算する時には同じ次元の概念にしておくべき。
1+2×3 = 1+2+2+2
  • 同じ次元の概念なら、先に計算しようと、後に計算しようと、答えは常に7となる。
  • ところで毎回、掛け算を足し算の概念に展開して、計算するのは面倒である。
  • だから、掛け算九九を覚えて、足し算の概念に展開した後の計算結果のみ想像して、数式全体を計算しているのだ。
  • 掛け算を先に計算するというよりは、より基本的な概念である足し算に展開していたのだ。
  • 足し算に展開する過程で、より合理的に計算するために、掛け算九九を利用して、その計算結果のみ利用していた。

掛け算九九が存在しない世界を想像してみる

  • 大人になると、掛け算九九のような数表を無意識のうちに利用して、掛け算を計算している気になっている。
  • しかし、その計算の実体は記憶から導いているだけで、純粋な計算とは言えないのである。
  • ドラえもんの秘密道具に、かの有名な「もしもボックス」という電話ボックスがある。
  • もしも、掛け算九九が存在しない世界だったら、掛け算を計算するためには、足し算に展開して、地道に足し算するしかないのである。
  • 掛け算の混じった数式は、より基本的な概念の足し算に統一することで、はじめて計算できるようになるのだ。

日常的な合理性から考える

以上のように考えたとしても、ルールとしては、左から順番に計算するというルールにしても悪くない気がする。

1+2×3 = 9
  • 上記のようなルールとならなかったのは、なぜなのか?
  • 日常生活の中で計算する状況を考えてみる。
  • すると、圧倒的に掛け算してから足し算する状況が多いことに気付いた。
    • レジでの代金精算は、商品単価×数量を足し算していくことの繰り返し。
    • お金の計算も、100円が3枚、10円が2枚...のように確認しながら、暗黙の掛け算をしながら、足し算している。
    • 回転寿しの代金計算も、お皿の種類ごとに枚数を掛け算した結果を足し算している。
  • 掛け算した結果を合計するという手順は、日常に即したルールだったのだ。
  • もちろん、足し算した結果に掛け算するという状況もないわけではない。
    • 回転寿しに3人で行って、本日のお勧め5品を3皿ずつ握ってもらう場合など。
  • 5品の金額がそれぞれ100円、200円、300円、400円、500円だったとして...
    • 一人の代金を求めて、3人分する方法なら、簡潔に計算できる。
(100+200+300+400+500)×3 = 4500円
    • 一方、お皿ごとに掛け算すると、掛け算の回数が5回に増えてしまい、煩雑である。
100×3+200×3+300×3+400×3+500×3 = 4500円
  • しかし、寿司屋に3人で行って、まったく同じものを食べて、帰ってくるという状況は極めて稀である。
  • 一般的には、3人がそれぞれ自分の好みの物を、好きなだけ食べる、という状況がありふれているだろう。
  • つまり、1の状況よりも、2の状況の方がありふれているのだ。
    1. 100+200+300+400+500×3 = (100+200+300+400+500)×3
    2. 100×3+200×3+300×3+400×3+500×3 = (100×3)+(200×3)+(300×3)+(400×3)+(500×3)
  • ならば、よくある状況である掛け算を先に計算して、括弧を省略可能なルールとした方が、合理的なのだ。

因数分解と展開

  • 1は数式を因数分解した形、2は数式を展開した形。
    1. 100+200+300+400+500×3 = (100+200+300+400+500)×3
    2. 100×3+200×3+300×3+400×3+500×3 = (100×3)+(200×3)+(300×3)+(400×3)+(500×3)
  • 因数分解は、状況の中に共通因数を見つけられなければ数式にできないが、(特別な状況)
  • 展開は、どのような状況であっても必ず数式にできるのだ。(必ず可能)
  • 日常に、掛け算した結果を足し算する状況が多いのも頷ける。(どのような状況でも使える計算方法だから)

必ず括弧で明示するルールにならなかったのは?

暗黙の優先順位なんて作らずに、明示的に括弧で括れば良いという考え方もある。

  • ところで、数式は、可能な限りシンプルに表現できることが好まれる。
  • 小学時代は四則演算で十分だが、中学、高校と数学の奥深くに進むほどに、新たな概念が登場する。
  • ベキ乗、ルート、対数...など、様々な演算子が入り乱れて、複雑な数式に出会う機会もある。
  • その時、演算子の優先順位が左から順に計算するルールのみだと、複雑な数式の中に多数の括弧が含まれて、さらに複雑な様相となってしまう可能性がある。
  • シンプルな表現を目指して、プラス・マイナス・代数の概念を学んだ中学以降は、四則演算の記号は姿を消してしまう。
    • 加減算については、数値のプラスかマイナスかを明示して並べるだけになる。(減算はマイナスの加算という概念になる)
    • 掛け算については、代数の掛け算記号は省略される。(割り算は逆数の掛け算に変換される)
  • そのような暗黙のルールがあるからこそ、かの有名な公式も美しいと言われるのだ。
E=mc^2
      • ^は、ベキ乗の意味。
  • 仮に、左から順に計算するルールのみだと、とんでもない誤解の公式になってしまう。
    • ベキ乗は、掛け算より優先順位が高いのだ。
  • mc^2 = m(c^2)である。(くれぐれも(mc)^2ではないので誤解のないように)
  • 暗黙の優先順位は、数式をシンプルで美しくするのである。シンプルで美しい数式は、分かりやすい。
  • よって、加減算より乗除算を優先することで余分な括弧を省略するルールは、より多くの状況で数式をシンプルにする、理に適ったルールなのである。

優先順位を考慮して計算するアルゴリズム

  • 今どきのスクリプト言語は、当然のように1+2*3=7と計算してくれる。(AppleScriptでもそうなる)
  • ところが、数式をテキストとして受け取り、構文解析して、優先順位を考慮した計算を自力で処理するのは、かなり手強い。
  • そのような必要性はほとんどないのだが、手法の一つとしてちゃんと理解しておきたかったので、試しにやってみた。
  • 調べてみると、それを実現する定石のような方法があって、逆ポーランド記法というそうだ。
    • ちなみに、ポーランド人の論理学者が考案したポーランド記法というのもある。
    • 論理学者の名前ではなく、出身国のポーランドが記法名称になってしまったところが面白い。
  • ポーランド記法とは...
    • 演算子を先に書いて、それに続けて二つの数字を書く記法である。
    • 演算子を関数のように見立てた表現方法である。
  • 逆ポーランド記法は、その名のとおりポーランド記法とは逆になる。
    • 二つの数字を先に書いて、後に演算子を書く表現方法である。
    • 日本語の語順に似た表現方法である。
1+2
=+12 ...... ポーランド記法
=12+ ...... 逆ポーランド記法
  • 逆ポーランド記法の素晴らしいところは、一般的な数式を、括弧不要で優先順位を考慮した数式に変換できるところである。
1+2*3 → 123*+ → 「2と3を掛け算して、その結果と1を足し算する」
2*3+4*5 → 23*45*+ → 「2と3を掛け算して、4と5を掛け算して、その結果同士を足し算する」
1+2*3+4 → 123*+4+ → 「2と3を掛け算して、その結果と1を足し算して、その結果と4を足し算する」
  • 数字の順番は変わらず、演算子の順番だけ変化している。
  • そして、一旦逆ポーランド記法に変換してしまえば、とても簡単に目的の計算が達成できてしまうのだ。
  • その方法は、演算子を見つけたら手前の2要素を演算子に従って計算する、という非常にシンプルなもの。
  • 難関は、一般的な数式を逆ポーランド記法に変換する処理の部分。やってみた。(AppleScript)
  • 実験的なサンプルコードなので、数値は1桁、使える記号は+-*/()のみ、数式のエラーチェックもなし。

 global re_poland
 global temp
 
 --calc(revrse_polish_notation("5+8*(4+5)"))
 --calc(revrse_polish_notation("(5+8)*(4+5)"))
 --calc(revrse_polish_notation("1+2*3+4*5"))
 calc(revrse_polish_notation("1+(2*3+4)*5"))
 
 on calc(formula_elements)
   set temp to {}
   repeat with e in formula_elements
     if e is in "01234456789" then
       push_temp(e)
     else
       set num1 to pop_temp()
       set num2 to pop_temp()
       push_temp(run script (num2 & e & num1))
     end if
   end repeat
   {formula_elements, temp}
 end calc
 
 on revrse_polish_notation(formula)
   set re_poland to {}
   set temp to {""}
   repeat with e in (formula's text items)
     if e is in "01234456789" then
       push_re_poland(e)
     else if e is in "(" then
       push_temp(e)
     else if e is in ")" then
       bracket_repeat()
     else
       operator_repeat(e)
     end if
   end repeat
   operator_repeat(")")
   
   re_poland
 end revrse_polish_notation
 
 
 
 on bracket_repeat()
   repeat
     set last_op to pop_temp()
     if last_op = "(" then
       exit repeat
     else
       push_re_poland(last_op)
     end if
   end repeat
 end bracket_repeat
 
 on operator_repeat(op)
   repeat
     set last_op to pop_temp()
     if priority(last_op) < priority(op) then
       push_temp({last_op, op})
       exit repeat
     else
       push_re_poland(last_op)
     end if
   end repeat
 end operator_repeat
 
 
 
 on push_re_poland(elements)
   repeat with e in (elements as list)
     set re_poland's end to e as text
   end repeat
 end push_re_poland
 
 on push_temp(elements)
   repeat with e in (elements as list)
     set temp's end to e as text
   end repeat
 end push_temp
 
 on pop_temp()
   set i to temp's item -1
   set temp to temp's reverse's rest's reverse
   i
 end pop_temp
 
 on priority(i)
   if i is in "()" then return 0
   if i is in "+-" then return 1
   if i is in "*/" then return 2
   -1
 end priority

  • AppleScriptには、もともとpush・popの概念がないから、まずはその処理をするハンドラ(メソッド)から作らなければならなかった。
  • 逆ポーランド記法にして計算する方法は定石とされる方法だけど、アセンブラC言語のスタック処理と素晴らしく相性の良い方法だと思った。
  • 今どきのスクリプト言語なら、その高度な機能を利用して、より効率的な処理方法があるのかもしれない。

参考ページ

2011-11-29

iPhone4Sカメラの写り

iPhone3GSからiPhone4Sに変更した。3GSからすると、Retinaディスプレイ、CPUの高速化など、あらゆるものが魅力的になっていた。なかでも最も魅力を感じたのが、カメラである。

カメラ性能

  • 絞りは、F2.4固定
  • シャッタースピードは、1/15〜1/11111(今まで撮影した写真の範囲)
  • 画角は、焦点距離32mm前後(35mmフィルム換算)だと思う。
    • 上:CX4 35mm
    • 下:iPhone4S(CX4 35mmより画角が若干広い)

f:id:zariganitosh:20111129142104p:image

  • ISO感度は、64〜800(今まで撮影した写真の範囲)
  • 撮像素子は、裏面照射型CMOSセンサー
    • 裏面を受光面とすることで、CMOSに接続する配線が影にならない。(表面に配線がある)
    • レンズの光を無駄なくCMOSで受光できるので、多少也とも薄暗い被写体の写りも良くなる。

快適な操作

  • スリープ状態から、ホームボタン2度押し、カメラアイコンをタッチして、カメラ起動。(iPhone4Sの機能)
    • ちなみに、iPhone3GSの場合は、一旦スリープ解除して、ホームボタン2度押し...する必要があった。
    • iPhone4Sになって、一旦スリープ解除するひと手間を省略できるようになったのだ。(iPhone4では試してない)
  • カメラ撮影中に、右フリックでカメラロールに移動、左フリックで撮影中に戻る、ようになった。(iOS5の機能)
    • 以前は左下の写真アイコン、またはカメラアイコンをタッチして切り替えていた。
    • アイコンではタッチする位置をシビアに限定されるが、
    • フリックなら画面全体のどこをフリックして大丈夫だ。
    • フリックによる切り替えの方が直感的で好き。
  • 画面の任意の位置をタップすると、タップした位置に露出とフォーカスを合わせる。
  • 画面の任意の位置を押し続けると、タップした位置に露出とフォーカスをロックする。
    • 画面下に「AE/AFロック」と表示される。
    • 「AE/AFロック」は、画面のどこかをタップすることで解除される。

改悪な操作

  • HDRのオン・オフが、オプションにまとめられて2タッチ必要になってしまったのは残念。
    • グリッドとHDRの設定がオプションにまとめられてしまったのだ...。
    • 以前のように、1タッチでHDRのオン・オフを切り替えたい。

f:id:zariganitosh:20111129171339p:image

HDR

HDRの使いどころ
  • iPhone4Sは、絞りF2.4固定で、シャッタースピード・ISO感度・ホワイトバランスが自動設定され、撮影される。
  • ところが、自動設定に任せていると、状況によっては被写体が暗過ぎたり、明る過ぎたりすることは多々ある。
  • でも、iPhoneのカメラに手動の露出補正は存在しない...。
  • そんな時、HDRをオンにすると幸せになる。
    • HDRオンでは、1回の撮影で、露出を変化させた3枚を連続撮影し、3枚の露出の「良い部分」を合成した写真にするのだ。
HDRの設定
  • 自分の場合、設定 >> 写真 >> 通常の写真を残す=オン にしている。
    • これで、HDR合成した写真に加えて、標準露出の写真も保存される。
    • つまり、1回の撮影で2枚の写真が保存されるのだ。
HRDの限界
  • HDRと言えども、3枚の露出の「良い部分」を選択するのは自動であり、万能ではない。
    • 状況によっては、標準露出の写真よりも悪くなる可能性もあるのだ。(好みの問題もあるけど)
  • だから、上記HDRの設定で標準露出の写真も残す設定にしている。
    • 不要なら、あとで削除すればいい。
    • 残さないと、より良い標準露出の写真を見逃してしまうかもしれないので。

  • また、HDRは同時撮影ではなく、連続撮影である。
  • つまり、若干の時間差をおいて3回シャッターが切られるのだ。
  • よって、動きのあるものをHDR撮影すると、以下のようになる。

f:id:zariganitosh:20111129154945p:image

  • HDRは、動きのある被写体には向かないのだ...。

  • 一方、標準露出を見ると、以下のようになる。

f:id:zariganitosh:20111129154944p:image

好みの使い方

  • LEDフラッシュ オフ
  • グリッド オフ
  • HDR オフ
    • HDR オンだと、1撮影ごとに3枚合成する時間が数秒かかる。
    • HDR オフなら、1秒に1回くらいのペースで撮影できる。
  • シャッターボタンに音量の+ボタンは使わない。(手ブレしそうなので)
    • 今までどおり、GUIのシャッターボタンをタッチしている。
    • その方が、HRDの切り替え、AE/AFロック等の操作もし易い気がする。

苦手な薄暗い状況

  • F2.4の明るいレンズに裏面照射型CMOSセンサーの組み合わせと言えども、センサーサイズは小さいので、やはり暗闇は苦手。
  • 以下の写真は、シャッタースピード1/15、ISO感度800、で撮影した写真。
    • ISO感度800では、やはり相当ノイズが目立つようだ。
    • いくら暗くなっても、シャッタースピード1/15よりスローなシャッターにはならなかった。

IMG_1430

IMG_1431

IMG_1432

得意な明るい状況

  • 明るい状況では、iPhone4Sは素晴らしい写りだ。

IMG_1593

IMG_1599

IMG_1605

IMG_1616

IMG_1619


  • 朝焼けもきれいに写った。(ISO感度64〜80)

IMG_1667

IMG_1675

GXR A12 28mm

  • 参考までに、薄明かりの室内で撮ったGXR A12 28mmの写真。(ISO感度400、シャッタースピード1/13)

R0011058

    • どうでもいい話しだが、この切り身は鰹である。
    • 鰹なのに、鮪中トロのような脂ののりだ。絶品。

  • 薄明かりの早朝に撮影したGXR A12 28mmの写真(ISO感度400、シャッタースピード1/7)

R0011266

2011-11-28

伝記スティーブ・ジョブズをとっても興味深く読む方法

伝記スティーブ・ジョブズには、いろいろなエピソードが出てくる。しかし、すべてのことが詳細に書かれている訳ではない。書籍には限りがある。だから、関連したキーワードを調べてみると、また世界が広がるかもしれない。

日本語訳の奮闘記

  • 今回の伝記スティーブ・ジョブズは、各国語翻訳版の世界同時発売ということになっている。
  • 原著の原稿は3部に分かれて、7月頭・8月頭・9月半ばに訳者の元に届いたそうである。
  • 当初の11/21発売予定も、諸事情によって10/24に繰り上げられ、限界を超えた翻訳作業が続いたそうである。
  • その辺の話しは以下のページに綴られている。

訳者の井口さん曰く...

■品質への影響

その無理は翻訳の品質に影響を与えないのか?

影響、あります。あるはずです。プロの翻訳者として、「影響ありません」なんてウソは言えません。正直な話、影響はあると思っています。

...(中略)...

●疲れによる品質低下

心配もしており、かつ、正直なところ、絶対に影響が出ているはずだと思うのが、「疲れによる品質低下」です。翻訳の場合、まず、原文の意味やイメージを把握します。そのあと、それをぴったりな日本語で表現するわけですが、その際、(同意語辞典などの助けも借りながら)連想ゲームのようなことを頭のなかでやり、いろいろなバリエーションの中からこれがいいと思うものを選びます。疲れがたまれば頭の働きは落ちるはずで(落ちたかどうかを判断する能力も落ちるので、本人は頭の働きが落ちた感覚がなかったりしますが)、頭の働きが落ちれば連想ゲームで思いつく範囲が狭くなったりします。あと一歩広がればいい表現に思いついたかもしれないのに、そこに到達できずに終わってしまうわけです。この影響は、あったはずです。意識はしていませんが(というか、意識しようにもできないことなわけですが)。

...(中略)...

http://buckeye.way-nifty.com/translator/2011/11/4-e807.html
  • 但し、できる限りの努力をして、その影響を小さいレベルに押さえ込む努力をされているとのこと。

世界同時発売の影響

  • それにしても、何故に各国語翻訳版の世界同時発売、という出版方法にしたのだろう?
  • 翻訳は原著が完成してから行われるものだから、同時発売を目指すなら、翻訳語版の作業を考慮した発売日にする必要があるはず。
  • にもかかわらず、最終的には当初の発売日から4週間繰り上げて発売に踏み切ってしまっている。
  • 原著では各章に挿入されている写真も、日本語版ではその一部が巻頭に集められた状態になっている。(日本語版の各章に写真はない)
  • 原著にある写真が見られないのは非常に残念である。
  • 仕方なく、Amazon Kindleで原著の英語版を購入してしまった。
    • $11.99(≒929円)だった。(衝動的にポチリ易い価格だ)
    • 原文の英語を通して読むほどの英語力は自分にはない...。

"Regions" = 「領域」?

  • "Regions"が「領域」と訳されてしまっている部分(第8章 偉大な芸術家は盗む iPadでP209/564)は、残念な気がした。
  • 自分の中では、"Regions" = 「リージョン」である。訳さずに英語の響きそのままのカタカナ表記として欲しい。
  • 2つのウィンドウ同士が重なったとき、下のウィンドウは上のウィンドウに隠され、画面に見えている部分はL字型の領域となる。
  • もし、下のウィンドウの内容が変化したとき、下のウィンドウ全体を描いてしまうと、重なっている上のウィンドウの内容まで侵してしまう*1ことになる。
  • ウィンドウの重なりを考慮すれば、L字型の領域のみ描画すべきなのだ。
  • QuickDraw(Macintoshの描画ルーチン)なら、ウィンドウの重なりを考慮して、L字型の部分のみを描画してくれる。
  • ウィンドウの重なりは2つとは限らない。3つ、4つ、あるいはそれ以上のウィンドウが重なって、複雑な領域形状となっている可能性がある。
  • しかも、ウィンドウの角は丸みを帯びているかもしれない。曲線を含む複雑な形状となるかもしれないのだ。
  • そのような場合でも、QuickDrawは素早く、必要な部分のみ描画する仕組みを備えている。

その仕組みこそが「リージョン」と呼ばれるもの。

  • 「リージョン」とは、QuickDraw、さらにはMacintoshでGUIを可能にした最も重要な機能の一つなのだ。
  • そんな訳で、"Regions"が「領域」と訳されている部分を読むと、自分の中ではガックリしてしまうのであった。
  • これはスティーブ・ジョブズの伝記であり、技術書ではないのだから、しょうがないとも言える。
  • でも、仮にもっと十分な翻訳・校正の時間があったら、「リージョン」と表記された可能性もある。
  • いや、訳者の井口さんなら最終的に「リージョン」とするはずだと想像する。
  • Appleの文献、ひいてはWeb検索において、QuickDrawに関連する技術として「リージョン」という表記が多数出てくるのだから。

例:

スティーブジョブズの電卓自作セット

ジョブズから指摘があるたび、毎日のようにエスピノザは改良を重ねる。しかし、どこをどう直しても必ずなにかを指摘される。それならばとエスピノザが開発したのが、「スティーブ・ジョブズの電卓自作セット」だ。

...(中略)...

ジョブズは真剣にいじりはじめ、10分ほどで自分好みの電卓を完成。当然かもしれないが、この電卓はマックとともに出荷され、その後15年ほどもスタンダードとして使われた。

伝記スティーブ・ジョブズ 第12章 書体へのこだわり(iPadでP266/564)
  • なんと!OS9までのアップルメニューに含まれる計算機は、ジョブズのデザインだったのか!

f:id:zariganitosh:20111128134711p:image

角の丸い四角形

ある日、ビル・アトキンソンがテキサコタワーにわっと駆け込んできた。円や楕円を素早く描けるアルゴリズムを思いついたのだ。...

伝記スティーブ・ジョブズ 第12章 ポルシェのように(iPadでP261/564)

1984CM

Think different

スタンフォード大学2005年卒業式で行われた伝説のスピーチ

ひまわりiMac

ローリーンがたくさんのヒマワリを植えた庭を二人で歩く。

...(中略)...

そのときジョニーが『ヒマワリのような感じにスクリーンをベースから分かれさせたらどうだろう?』と言い、うん、そうだ、それがいいとスケッチをはじめたのです」

伝記スティーブ・ジョブズ 第33章 貝殻、角氷、ヒマワリ(iPadでP312/547)

アップルストア開店準備

フラッシュについての見解

iPadのCM

必ず掛かってくる電話

ロンドン出張のホテル選びも苦労したらしい。アイブが選んだのは、サービスに定評のあるザ・ヘンペルという5つ星のこぢんまりとしたホテル。ここならジョブズも気に入るだろうと思ったのだが、チェックイン直後、これはまずかったかもと身構えた。案の定、1分もすると電話が鳴る。

「なんだこの部屋は。ひどすぎる。でるぞ」

伝記スティーブ・ジョブズ 第34章 50歳の獅子(iPadでP339/547)

ゴリラガラス

化学交換法という製法を開発し、「ゴリラガラス」と呼ばれるガラスを作ったこと、信じられないほど強いが市場がなく、作るのをやめたことを話す。

伝記スティーブ・ジョブズ 第35章 ゴリラガラス(iPadでP357/547)

自分の経験

  • 以前、iPhone3GSに保護フィルムを貼って、1年半使用していた。
  • ある時、iPhone4のRetineディスプレイを見て、その画面品質に嫉妬した。
  • 3GSとの差は何だろうと。思い付いて3GSの保護フィルムを剥がしてみた。
  • すると、予想外に3GSの画面もクリアなことに気付いた。
  • 今までの1年半、くすんだ画面を見ていて損した気がした。
  • ゴリラガラス採用のiPhone4以降は、保護フィルム無しで使うべき?
  • 試しに現在iPhone4Sを保護フィルムなしで使用中なのだ。
  • 腕時計のガラスにも保護フィルムなんて貼らない。(だから、iPhoneでも試してみる)
  • さらに、最近はゴリラならぬ、ゴジラガラスなんて代物も開発されているらしい。
  • ゴジラにもびくともしないガラス。それが実現された暁には、保護フィルムも、保護ケースも不要になってしまう日が来るのかもしれない。

アンテナ問題

リードもハワイから連れて戻ることにする(リードは高校の最上級生だった)。

「お父さんはこれからたぶん2日ほど、会議漬けになる。そのすべてにお前も出ろ。この2日で、ビジネススクールに2年間通うよりもたくさんのことが学べるはずだ。世界でもトップクラスの人間がとても難しいことを検討し、決めていく瞬間に同席し、...」

伝記スティーブ・ジョブズ 第38章 アンテナゲート――デザイン対エンジニアリング(iPadでP453/547)
  • 驚いたことに、その記者会見のあと、ジョブズはハワイに戻り、そして京都に来日していたのだ。

ジョブズは、子どもたちに約束したことがある。13歳の誕生日を迎え、ティーンエイジャーになるときには、それぞれ、どこでも好きなところに連れて行ってやる――だ。...

伝記スティーブ・ジョブズ 第40章 家族の絆(iPadでP490/547)

愛妻家

20周年にはちょっとしたサプライズとして、結婚式をあげたヨセミテのアワニーロッジにパウエルを連れていこうと考えた。しかし予約がいっぱいだと断られてしまう。あきらめきれないジョブズは、自分たちが泊まったスイートを譲ってくれないかと、予約した人にホテル経由でたずねた。...

伝記スティーブ・ジョブズ 第39章 iPad2(iPadでP468/547)

その他関連リンク

宿・寺

休暇で度々訪れるハワイや日本の宿が気になった。

テクノロジーとリベラルアーツの交差点

  • 何度も記述されている「テクノロジーとリベラルアーツの交差点」とは、このイメージだった。

f:id:zariganitosh:20111128140338p:image

所感

  • ジョブズ本人への取材を元に、公式伝記として、いろいろなことの真実が確認できるところは素晴らしい。
  • 英語版と日本語版がリンクして原文と訳文が比較できると、いいなあ。
  • 重要なことは散歩しながら話す、のがジョブズ流。(なるほど)
    • 「散歩」をキーに検索してみると、重要な決定に散歩が絡んでいて面白い。

  • 日本国内の伝記スティーブ・ジョブズは、(1・2合わせて)紙本の発行部数は百万部を超えたそうである。
  • 電子書籍も、おそらく相当な販売部数となっていると思われる。(発売後2日間の販売部数が電子書籍は紙本の5割と発表されていたので)
  • 今回、iPadで長編の電子書籍を読んでみて、紙本と遜色なく読めることが体感できた。
  • さらに電子書籍なら、本文検索、辞書・webなどとの連携もできる。
  • もっと進化すれば、webベージをソーシャルブックマークするように、電子書籍の本文を自由にブックマークして、感動を共有できるようになるかもしれない。
    • 実際、KindleにはPopular Highlightsという機能があり、多くの人がマーカーを引いた部分を共有できる仕組みが用意されていた。
  • 本当は、このブログに書いたような関連情報は、電子書籍の本文にマーカーを引いた部分からリンクできる情報として共有できると良いのだと思う。
    • そうすれば、自分の知らいない新たな関連情報を手軽に得られる強力な手段となる。
  • もし、教科書が電子書籍に置き換わった時、このような情報共有の仕組みは、電子書籍の相当な魅力となりそう。
    • 多くの学生がどこに興味を持っているとか、どこが理解できていないとか、判断し易くなるのだ。
    • それらの情報は、教える先生にも、教わる生徒にも、とっても重要な情報なのである。

  • また、電子書籍はアップデートが可能なはずである。
    • 実際、アプリ版のスティーブ・ジョブズは、バージョン1.2にアップデートされている。
      • > 本文中の誤字を修正しました。
      • > 奥付に情報を追加しました。
  • 今回、時間的要因で日本語版に含まれなかった内容は、講談社のWEB上にPDFとして公開されているが、
  • 電子書籍版には、それらの情報を付加した修正版を配信してくれれば良いのにと思った。
    • そのようなことができるのが、電子書籍の良いところ。
  • 原著の英語版の各章ごとに付加されている写真も、追加して欲しい気持ちでいっぱいだ。

  • 伝記スティーブ・ジョブズは、自分が電子書籍のあり方を真剣に考える機会になった。
  • 世界中でミリオンセラーとなっているので、自分以外の多くの人も、電子書籍に不満や期待を抱く、きっかけとなっているはず。

もしかしたら...(勝手な想像)

  • ジョブズは、iTunesのような標準のない電子書籍の世界に、自身の伝記をとおして一石を投じたかったのかもしれない。
  • それがジョブズ最期の仕事であり、伝記の執筆を依頼した、もう一つの理由なのかもしれない。

*1:そう、幾重にも重なっているように見えるウィンドウだが、実は物理的なディスプレイは1枚しかなく、ウィンドウを動かす度に、あるいはウィンドウの内容が変化する度に、1枚のディスプレイに必要な部分を高速に描画しているに過ぎないのだ。

2011-11-17

最高の電子書籍はどこにあるのか?

伝記スティーブ・ジョブズ1・2、ようやく読み終わった。今回は電子書籍で購入した。かつて、アラン・ケイが夢見たDynabook、それを実現してしまったジョブズ渾身の傑作iPadで、長編書籍(しかもジョブズ自身の伝記という内容)を果たしてどこまで快適に読めるのか、身を持って体感するため。

iPadで、伝記スティーブ・ジョブズが読める電子書籍リーダーにもいろいろある。このブログを書いている時点で7つの電子書籍リーダーを選択できた。果たして自分はどの電子書籍リーダーで読めば良いのだろう?探ってみた。

一覧比較

  • 最初だらだらと調べていたのだけど、いろいろな要素があって非常に分かりにくい...。
  • とりあえず、iPadで伝記スティーブ・ジョブズを読む状況に限定して調べてみた。
ebiReaderKinoppyhontoパブリBookLiveVoyagerアプリ
価格1995円2000円1995円1995円1995円1995円1900円
ストア機能SafariありSafariSafariSafariあり*1あり
フォーマットebi.j.book.book.bookMCBook
フォント画像扱い秀英明朝秀英横太明朝秀英横太明朝凸版明朝秀英横太明朝リュウミンL
ページの記録前回ページと栞1つ前回ページ前回ページ前回ページ前回ページ前回ページ前回ページと栞複数
文章のマーキングなしあり(メモ書き可)なしなしなしなしあり(6色・メモ書き可)
検索本文本文・GoogleWikipedia・辞書本文本文なし本文本文・Google・Wikipedia・Yahoo!・辞書など
複数端末対応3台まで3台まで3台まで
再ダウンロード期限無期限無期限1年1年無期限無期限無期限
      • ○=iPad・iPhoneどちらも同時に閲覧できた。
      • 但し、無期限であっても、販売中止になってしまうと再ダウンロードできない。

フォント比較

  • フォントはiPadで読むか、iPhoneで読むかによって印象も変わってくると思う。
    • iPhone3GSや、さらにはRetinaディスプレイ化されたiPhone4以降なら、また違った印象になるはず。
  • 個人的には、iPadで読むなら秀英横太明朝が横のラインも鮮明で読みやすいと思った。
秀英横太明朝

f:id:zariganitosh:20111117110737p:image

秀英明朝

f:id:zariganitosh:20111117110738p:image

凸版明朝

f:id:zariganitosh:20111117110739p:image

リュウミンL

f:id:zariganitosh:20111117110740p:image

現状の選択

  • 実は、このように詳細に比較することもなく、フォントの読みやすさの印象だけで「パブリ」で購入してしまったのだった。(早く読みたかったので)
    • iPadで読む場合、秀英横太明朝は自分好みのフォントである。
    • 紙の本と同じ感覚で読み進めることができた。
  • 実際に電子書籍で読み始めると、当初は考えていなかった、いろいろな欲求が湧いてくる。
    • 当初は、快適に読む以上のことは考えていなかったが、伝記スティーブ・ジョブズは、単なる本以上にAppleを知る資料となる。
    • そうなってくると、マーカーを引きたいとか、付箋を貼ってメモ書きしたいとか、思うようになる。
    • また、知らない単語は今までと同じように辞書を引けば良いのだけど、書籍リーダーが辞書と連携していると快適である。
    • Google検索等のWeb検索とも連携していれば、なお嬉しい。
  • 電子書籍には、紙の本にはない素晴らしい機能もある。本文検索である。
    • 紙の本は検索できないので、索引を設けて参照ページを記載している。
    • 電子書籍の良いところは、自分の興味のある単語をキーに、自由に検索できることである。
    • 特にこの本を資料と考えれば、この検索機能は絶大なメリットになる。
  • 電子書籍は著作権保護のためか、コピー機能が無効にされている。
    • コピー機能がない環境では、検索や辞書機能と連携するこの仕組みがとっても有り難いのだ。
  • 以上のことを考えると、「Kinoppy」で購入しておくのがベストだったのではないかと、後悔している...。
    • 読み易さを優先すると、秀英横太明朝の「パブリ」が良さそう。
    • しかし、資料となる書籍ならマーキングやメモ書き機能も欲しい。
    • となると、Kinoppyかアプリ版なのだが...
      • フォントはKinoppyの秀英明朝の方が好み。
      • Kinoppyには、アプリ内にショップ機能(立ち読み・購入する機能)がある。
      • Kinoppyでは、購入した書籍以外にも、自炊したPDF・テキストなども本棚で管理し、閲覧もできる。

近い将来

  • ところで、上記の電子書籍には大御所が二つ抜けている。
  • AppleのiBooksと、AmazonのKindleである。
  • iBooksとKindleは、現状では日本語・縦書きフォーマットに対応していないのだ...。
  • あるいは対応しているかもしれないが、何らかの事情で日本語の書籍を取り扱っていない。
  • 実は、英語版のSteve JobsもKindleで購入している。
  • amazon.comで$11.99(≒924円)と非常に安価だ。
  • Amazonで購入すると即、iPadとiPhoneのKindleに反映され、読めるようになった。(どうゆう仕組みなんだ?)
  • iPadのKindleで読んでいるページをiPhoneのKindleに同期して続きを読むなんてことも当然のようにできた。
  • もちろん、本文検索・Google検索・Wikipedia検索・辞書・マーキング・メモ書き・Tweetなどの機能もある。
  • iOSに準拠したUIであり、その操作感は期待を裏切らず、迷わない。
  • Kindleの日本語書籍ストアができたら、間違いなく繁盛しそうな気がする。
  • iBooksの日本語書籍ストアもしかり。

その他雑感

  • 1000ページ以上めくっていると、紙の本を模したページめくりアニメーションより、シンプルなスライドアニメーションの方が好きになった。
  • ページを移動する時のアニメーションは重要。
    • 瞬時にページが切り替わってしまうと、ページをめくった気がせず、不満が残る。
    • 誤操作によるページめくりにも気付きにくく、次に進んだか、前に戻ったのかも分からない。
  • 読書に集中していても、ふとした時に時間を知りたくなる。
    • 全画面表示の電子書籍リーダーでは、一旦終了しないと時間が確認できなくてイライラする。
    • iBooks・Kindle・Kinoppyは常にステータスバーに時刻が表示されていて、安心できる。
  • 今、全体のどこまで読んでいるのか?という情報も気になる。
    • 紙の本であれば、見開きした左右の紙の厚みで、暗黙に確認できていた情報である。
    • 電子書籍でも、常に、あるいはページをめくる時には、表示して欲しい情報である。
  • パブリで購入したのは.bookフォーマットのスティーブ・ジョブズ。
  • .bookはKinoppyでも閲覧可能なフォーマットだ。
  • しかし、現状はパブリで購入したものは、パブリでしか読む術がない。
  • Kinoppyでも読めれば良いのに。
    • 例えKinoppyで読めたとしても、T-TimeのUIを超える操作性は期待できないのだろうか?
    • マーキングやメモ書き機能に憧れる。


以下、一覧比較の元となる調査データ

電子書籍・コミックリーダー ebiReader

立ち読み・購入(1・2 各1995円)
ファイルフォーマット
  • ebi.j(.ebija)
    • イーブック・イニシアティブ・ジャパンが開発したフォーマット。
  • 文字データも画像として扱っている。
  • 漫画の品揃えが豊富。
フォント
  • 画像なので紙の書籍のフォントに準ずるのか?
機能
  • 栞(記録されるページ)
    • 前回開いていたページ
    • 栞を挟んだページ(栞は1つしかない)

以下の機能はすべて不可能(文字は画像扱いなので)

  • 本文検索 なし
  • 辞書 なし
  • メモ書き なし
  • マーキング なし
複数デバイス対応
  • トランクルーム本棚からダウンロードすることで、一つの電子書籍を複数デバイスで読めるようだ。

紀伊國屋書店Kinoppy

立ち読み・購入(1・2 各2000円)
  • 電子書籍リーダー内ですべて完結する。
ファイルフォーマット
  • .book、XMDF、EPUB3.0の縦書きに対応
フォント
  • 秀英明朝
機能
  • 栞(記録されるページ)
    • 前回開いていたページ
  • 本文検索
  • Google検索
  • Wikipedia検索
  • 辞書
  • マーキング
  • メモ書き
複数デバイス対応
  • 電子書籍を一度購入すれば、複数の端末で再購入なしに再ダウンロードできる。

honto BOOK

立ち読み・購入(1・2 各1995円)
対応フォーマット
  • .book、XMDF、MCBook、イメージビューア形式
フォント
  • 秀英横太明朝
機能
  • 栞(記録されるページ)
    • 前回開いていたページ
  • 本文検索
    • 単語を選択して検索できない。
    • キー入力する必要があり面倒。

以下の機能はすべて不可能

  • 辞書 なし
  • マーキング なし
  • メモ書き なし
複数デバイス対応
  • アプリの会員IDを登録した一つの端末でのみ閲覧できる。
    • 同時に複数端末では閲覧できないらしい。(試してないが、説明を読んで理解したこと)
ダウンロード期限
  • 伝記スティーブ・ジョブズには、365日のダウンロード期限が設定されている。
  • ダウンロード期限内であれば、何度でもダウンロードできる。
  • ダウンロード期限を過ぎると、ダウンロードできなくなる。
  • ダウンロード期限を過ぎても、ダウンロード済の書籍については継続して閲覧できる。

電子文庫パブリ

立ち読み・購入(1・2 各1995円)
対応フォーマット
  • .book、XMDF
フォント
  • 秀英横太明朝
機能
  • 栞(記録されるページ)
    • 前回開いていたページ
  • 本文検索
    • 単語を選択して検索できない。
    • キー入力する必要があり面倒。

以下の機能は.bookフォーマットではすべて不可能(但し、XMDFフォーマットならすべて可能になる)

  • 辞書 なし
  • マーキング なし
  • メモ書き なし
  • Google検索
  • Wikipedia検索
  • Yahoo!検索
複数デバイス対応
  • アプリの会員IDを登録した複数端末(iPad・iPhone)で閲覧できた。
ダウンロード期限
  • 伝記スティーブ・ジョブズには、2012/11/08のダウンロード期限が設定されている。

BookLive! Reader

立ち読み・購入(1・2 各1995円)
対応フォーマット
  • .book、XMDF
フォント
  • 凸版明朝
機能
  • 栞(記録されるページ)
    • 前回開いていたページ

以下の機能はすべて不可能

  • 本文検索 なし
  • 辞書 なし
  • マーキング なし
  • メモ書き なし
複数デバイス対応
  • 端末登録して、最大3台の端末で閲覧できる。

Voyager Books

立ち読み・購入(1・2 各1995円)
対応フォーマット
  • .book
フォント
  • 秀英横太明朝
機能
  • 目次は本文へのリンク
  • 栞(記録されるページ)
    • 前回開いていたページ
  • 本文検索
    • 単語を選択して検索できない。
    • キー入力する必要があり面倒。

以下の機能はすべて不可能

  • 辞書 なし
  • マーキング なし
  • メモ書き なし
複数デバイス対応
  • ログインした複数端末で閲覧できる。

スティーブ・ジョブズ(アプリ)

立ち読み・購入(1・2 各1900円)
  • アプリ内ですべて完結する。
    • 無料アプリをダウンロードして、アプリ内決済によって行う。
    • このアプリが、スティーブ・ジョブズ専用の電子書籍リーダーなのだ。
対応フォーマット
  • MCBook
フォント
  • リュウミンL
機能
  • 栞(記録されるページ)
    • 前回開いていたページ
    • 栞を挟んだページ(栞は複数挟める)
  • 本文検索
  • Google検索
  • 辞書
  • マーキング(6色)

以下の機能は不可能

  • メモ書き なし
複数デバイス対応
  • アプリをインストールした複数端末で閲覧できる。

参考ページ

以下のページがたいへん参考になりました。感謝です!

*1:立ち読みはMacBookSafariでしかできなかった。

2011-11-08

ボケる広角が欲しかった

カメラを初めて手にした時、俄然、望遠レンズに憧れた。遠くのものが大きく、詳細に写る、裸眼では確認できなかったものが見えるようになることに純粋に感動した。だから、自分の初期のカメラ選びは、光学何倍ズームが付いているかが重要だった。5倍よりは10倍を魅力的に思っていた。デジタル一眼を手にしても、その考えは暫く変わらなかった。標準キットレンズで満足していたのだ。まだ見ぬ素晴らしいレンズの世界があることに、気付く余地もなかった。

ところが、D40に明るい単焦点レンズを付けてみて、全く別の世界があることに初めて気付いた。(付けたレンズは以下)

撮りたいモノ以外がボケる世界の魅力を知ってしまったのだ。すると、標準キットレンズの明るさでは物足りなくなる。自分が撮りたいものの多くは、身近な人・モノ・植物・風景である。考えてみれば、遠くのものを望遠レンズで大きく写す必要性なんて、自分にはほとんどなかったのだ。大きく写したいのなら、被写体に近付けば良いのだ。それに気付いた時に、今度は広角レンズが気になり始める。

最初はCX4の28mmで撮っていた。光の明るさが十分なら、結構綺麗に撮れた。しかし、一度でもボケる世界を知ってしまうと、やはり広角の28mmでも綺麗にボケてもらいたい。CX4でボケを活かすには、被写体にかなり近寄る必要があった。物足りない。多少離れても、背景が若干ボケて欲しいと感じていた。

目指すは明るい広角レンズだ。同じ焦点距離なら、F値が小さいほど、撮像素子(感光する部分)が大きいほど、被写界深度は浅くなりボケやすくなるだ。

D40の交換レンズ

  • 一眼レフ用に様々なレンズがあって、もちろん明るい広角レンズ28mmもある。
  • しかし、D40に28mmのレンズを取り付けても、撮像素子がAPS-Cサイズなので周辺部はトリミングされ、1.5倍の約42mm相当の画角になってしまう。
  • D40で28mmの画角を得るには、18mmのレンズが必要なのだ。
  • 残念ながら、単焦点レンズには18mmという選択肢はなかった。
  • 単焦点の明るさにこだわらず、ズームで、F2.8以上の明るさを目指してみると、一気に選択肢は増える。
  • 以上のレンズは、かなり魅力を感じたが、ただ一つ、気になる点があった。

それは、デカくて、重いこと。

  • どちらも90mmの長さ、400〜500gの重さ、である。
  • 手軽に持ち歩くには、ちょっと大きさと重さを感じる。

手軽に持ち歩ける広角を求めて

  • 一眼レフのファインダーを覗いて、カシャカシャ撮るのは好きだ。本物のシャッター音も心地良い。
  • しかし、スナップの魅力は日常の中にあり、常に大きな一眼レフを携帯する気にはとてもなれない。
    • 本体とレンズの形状からどうしてもかさばる構造である。
  • 欲を言えば、コンパクトなデジカメ形状なのだけど、ボケる広角が欲しいのだ。(ファインダーを覗けないのは寂しいけど)

選択要素

いろいろな選択肢があった。

  • 上記のミラーレス一眼も有力な選択肢の一つだが、
  • 広角でボケを活かした撮影が出来れば、特にレンズ交換できなくてもよいと思っていた。
  • よって、シグマ DP1系も良さそうな気がしてくる。
  • ライカ系という選択肢もあるが、ちょっと高価過ぎて手が出ない。
  • FinePix X100も魅力ある。
  • 散々悩んだのだが、基本に戻って綺麗にボケることに重点をいて考えれば、以下の要素が重要になるはず。
    • より明るいレンズ(F値が小さい)
    • より大きな撮像素子
    • なるべく被写体に近付けること
  • さらに、コンパクトなサイズで持ち運びが楽ならば、言うことなしなのだ。

GXR

  • いろいろ考えた末に手に入れたのがこれ。

f:id:zariganitosh:20111108061842p:imagef:id:zariganitosh:20111108061843p:image

f:id:zariganitosh:20111108061846p:imagef:id:zariganitosh:20111108061845p:image

f:id:zariganitosh:20111108061844p:image

撮影

  • 早速、撮影してみた。

f:id:zariganitosh:20111107175452p:imagef:id:zariganitosh:20111107175453p:image

f:id:zariganitosh:20111107175451p:imagef:id:zariganitosh:20111107175450p:image

f:id:zariganitosh:20111107175456p:imagef:id:zariganitosh:20111107175454p:image

f:id:zariganitosh:20111107175448p:imagef:id:zariganitosh:20111107175457p:image

f:id:zariganitosh:20111107175449p:imagef:id:zariganitosh:20111107175447p:image

f:id:zariganitosh:20111107175446p:imagef:id:zariganitosh:20111107175444p:image

f:id:zariganitosh:20111107175445p:imagef:id:zariganitosh:20111107175455p:image

  • ボケる!ついついF2.5解放にして撮ってしまう。楽しい!

レンズ交換

  • 最近はライカM互換マウントユニットまで出てしまったらしい。(マニュアルフォーカスのみ)
  • レンズと撮像素子をユニット化したGXRの拡張性には驚く。
  • 今後、どのような面白いユニットが出てくるのか、楽しみ。
  • いつか、ライカのレンズを付けて、撮影してみたい。

2011-10-25

今でも便利に使っているAppleScript集

ブログを始めた当初、カテゴリーのタグ付けがよく分かっていなかった。また、この後どんな話題について書いていくか、という想像力もなかった。だからこのブログのカテゴリー分けは、いい加減なのである。ところで、最近はAppleScriptの話題が多いのに、AppleScriptカテゴリーがないことに気付いた。そこで意を決して、過去の記事まで遡ってAppleScriptカテゴリーをタグ付けしてみた。(結構面倒だった)何とか終わって、AppleScriptタグをクリックしてみると、気持ち良く一覧表示された。

現在まで、全部で74記事ある。予想外に多い。記事の人気としてはどんな傾向があるのか、少し調べてみた。

ブックマーク数ランキング(ベスト10)

こんな感じであった。

      • ブックマークは変動するので、順位は若干変化しているかもしれない。

なるほど、なるほど。

  • それにしても、トップの458ブクマは異常。
  • なにゆえにこれ程の支持を受けたのか、謎。
  • 普通は支持されても、せいぜい数十ブクマだと思っているので、もはや祭りである。
  • タイトルが良かったのか、本当に需要があったのか、はてブの付き方は何年書いていても予測がつかない。

もはや手離せないスクリプト

ブログの中で紹介しているAppleScriptは、実際に自分が不便を感じて、その改善を目指して作ったものである。出来上がったら実際に自分のMacBookで使ってみる。実益を兼ねたAppleScriptなのである。

で、その後状況が変わって不要になったり、あまり役立たなかったものもあるが、今でも便利に使っている、もはや手離せないスクリプトも結構ある。ブクマ数とは関係なく、作者自身の満足度が高い一押しのAppleScriptをリストアップしてみた。

安全確実に自動ログイン

1Passwordにも負けない(実際には負けるのかもしれませんが)使い易さを目指して作った、あらゆるページでログイン情報の自動入力を可能にするAppleScript。

  • そもそもは、金融機関のログインの煩雑さ(Safari標準の機能では自動ログインできない)に辟易して作り始めたスクリプト。
  • テキストフィールドのみならず、ラジオボタンチェックボックス・ポップアップリスト(セレクトタグ)に対応して、広範な情報入力ページを一括入力できる。
  • このログイン情報はブックマークレットとして書き出すことも可能で、iPhoneiPadでもあらゆるページでログイン情報の自動入力の恩恵を受けられる。
  • セキュリティを考えて、aes-128-cbc形式で暗号化もしている。(ログイン情報を自動入力する時には、マスターパスワードの入力を求める)
あらゆるウィンドウのキー操作

あらゆるウィンドウの拡大・縮小・ハーフサイズ・最大化・移動・上下左右寄せ、等をキー操作で可能にするAppleScript。

  • そもそもは、OSXになって、ウィンドウの最大化ができない状況が多々あることに嘆いて作り始めた。
  • Quicksilverでショートカットを割り当てることで、キー操作可能にしている。
良きに計らうクリップボード拡張

クリップボードを拡張して、複数のクリップボードを使い分けてコピー&ペースト可能にするAppleScript。

  • そもそもは、クリップボード履歴管理ソフトでは、コピーする度にショートカットが変化してしまうことに不便を感じて作り始めたスクリプト。
  • 例えば、control-1でコピーして、control-option-1でペーストする、ショートカットが変化しない普遍的なコピー履歴が欲しかった。
  • その後、特定の条件でコピーした場合には、特殊な形式でコピーするように改良した。
    • AppleScriptエディタで何も選択せずにコピーすると、シンタックスハイライトなHTMLがコピーされる。
    • Finderでファイルを選択してコピーした時には、UNIX形式のファイルパスとしてコピーされる。
    • Webブラウザで何も選択せずにコピーすると、そのページへのaタグのリンクとしてコピーされる。

この自分好みの状況に応じたコピーが、かなり便利だ!

  • 必要に応じて、自分でショートカットを選択する手間がなくなり、
  • 同時に増え過ぎたショートカットを一つにまとめることもできた。
スリープコントロール

自動スリープしてくれない状況と、モニタを閉じてしまうとスリープを解除できないという、相反する二つの状況を解消したかった。

最高のゴミ箱環境

OSXのゴミ箱に不足していると思われる、一部だけ削除する機能と、削除日順に管理する機能を追加するAppleScript。

  • ゴミ箱はすぐに空にするのではなく、不要ファイルの長期的なストック場所と考え運用する。そのため、以下の機能を追加した。
    • 選択アイテムのみ一部だけ削除する(空にする)機能。
    • ゴミ箱に捨ててから一定時間以上経過したファイルを削除する機能。
便利過ぎるテキスト操作

テキストの選択範囲広げたり、狭めたり、括弧で囲ったりと、テキスト編集時の小技を素早く完了させるAppleScript。Automatorも活用することで、サービスメニューとして登録することで、右クリック(二本指クリック・control-クリック)で素早く指定できる。


OSXでは、OSが標準で備えるキー操作に連動したテキスト編集アクションを、キーバインドの設定として自分好みに再設定できる。

  • AppleScriptやAutomatorでは、それが実行されるまでに若干のタイムラグが発生する。(テキスト編集中には、その時間差にイライラすることもある)
  • キーバインドの設定であれば、全くタイムラグを感じない軽快なテキスト編集操作が可能になる。
スクロールバー付きSpotlight対応なスティッキーズ

日本語MacOS漢字Talkと呼ばれていた頃から標準添付されてきたスティッキーズに、スクロールバーを付け、Spotlightにも対応させる。

  • 自分が知る限り、オートセーブ機能を搭載した最古のソフトウェア。
  • 最新のOSX 10.7 Lionのオートセーブの原点はここなのではないか?
  • 手軽に確実にメモを残すという目的に特化したシンプルさが、息の長いソフトウェアとなった要因かもしれない。
メモリ解放

4GBでも不足しつつあるMacBookのメモリ。その未使用領域をなるべく解放するAppleScript。

  • OSXよ、お前はどれだけメモリを浪費するのか?
  • OSX曰く、浪費ではない、次回アクセスに備えているだけだ。

いろいろ試してみたが、最近のメモリ価格の低下を見ると、増設する方が良さそう。(当然だが、一番効果がある)

  • 但し、たとえ8GBに増設したとしても、メモリが上手く解放されずスワップが発生することはあるようだ。
  • そんな場合に備えて、メモリ解放の手段を覚えておくと、後々役立つかもしれない。
コメント付きTimeMachine

TimeMachineでバックアップ前にインストールログを書き出し、バックアップのコメントの代わりにするAppleScript。

  • TimeMachineは便利なのだが、日時でしか復元時点を検索できない。
  • しかしそれでは、いつの時点の過去に戻るべきかさえ、分からないこともある。(いつでも過去にでも戻れます、と謳うのは良いが)
  • そこで、インストールログをコメントファイルとすることで、戻るべき過去を特定し易くするのだ。
ルールで賢くする

Mail.appのルール駆動でAppleScriptを起動して作業をするサンプル。

  • 宅配便の照会ページを開くルールは今でも使っている。
    • 配送伝票番号の書式を認識して、メールが着信すると照会ページを自動で開くのだ!
  • saykanjiがメールを読み上げるルールは、夜中に呪文のような独り言が聞こえてきて、不気味なのでやめた。
StationTVと画面共有

StationTVの起動を邪魔をすることがないように画面共有サービスを終了し、StationTVを終了したら画面共有サービスを復元するAppleScript。

  • 著作権がらみの仕様なのか、画面共有サービス、スクリーンショット系アプリ(EvernoteもNG)が起動していると、StationTVを起動できないという、制限がある。
  • 地デジの映像に一体どれほどの権限があるというのだ?EvernoteさえNGとするこの制限は、いつ、どこで、誰が決めたものなのか?
  • もっと自由に映像を見たい!5年後、10年後、スカイツリーは完成したが、視聴率数パーセントしかない電波とならないことを祈る!
ヘッドフォンの音量

MacBookを再起動した時、ヘッドフォンが最大音量にリセットされ、痛い目に遭うのを防止する。

壁紙カレンダー

三階ラボさんの壁紙カレンダーを便利に使うためのAppleScript。

  • 壁紙カレンダーを自動的に切り替える、今日の日付のマス目にアイコンを移動する、等々。
購読者チェック

googleリーダーlivedoorリーダー・Fastladderの購読者数をログに記録するAppleScript。

たまに使うと便利を感じるスクリプト

テキストエディットの余白

印刷すると常に余白あり過ぎなテキストエディットの余白を自在にコントロールするAppleScript。

PDF圧縮

古いスキャナで取り込んだPDFを、iPhone・iPadでも軽快に閲覧できるサイズに圧縮する。

Exif情報削除

JPEGファイルに付加される様々な撮影情報を削除するAppleScript。

  • GPSの位置情報など、不要な個人情報が公開されないようにする目的で作った。
読み合わせ

saykanjiを活用して、銀行振込データの読み合わせに挑戦してみた。(saykanjiが読み上げ、自分が聞いてチェック)

ファストユーザスイッチ

ショートカットでファストユーザースイッチするAppleScript。

利用環境

  • MacBook OSX 10.6.8
  • AppleScript エディタ バージョン2.3(118)
  • AppleScript 2.1.2
  • Quicksilver β60(3850)
    • スクリプトへのショートカットの割り当てに利用

所感

  • AppleScriptは、アプリケーションやOS・スクリプト言語を連携させる能力に長けている。
    • 連携させることで、面倒な操作を一瞬で完了できたり、
    • 普段、GUIからは操作できない機能を呼び出せたり、
    • イベントを監視して作業を完全に自動化したり、
  • ...等々、ユーザーの操作をコーディングすることで、便利な作業環境を構築できるのだ。
  • 自ら作って、使って、さらに使い易さを求めて修正したスクリプトは、そのユーザーにとっては最高のツールとなる。
  • そして、最高のツールがいくつか集まって、次第に最高の作業環境となるのだ。

2011-10-18

iMacが始まりだった

何でもいいから、何か書いて、残しておくべきだと思った。まとまりがないけど。

  • そもそも、Macが存在しなかったら、今このブログを書いていたかどうかも分からない。
  • 人生においては常にそうなのかもしれないが、あの時、あの瞬間に、何かに出会っていなかったら、きっと今の状況はなかったのではないかと、そう思うことがよくある。
  • あの時、偶然にもiMacを買っていなかったら、VAIOがすんなり購入できていたら、今頃はどうしていたのか?
  • 現在も続く貴重な友人関係も、あの時iMacを購入したからこそ続いている、そんな状況もある。
  • 仕事をしていく上でも、本質を追究したソフトウェア作りの知識が広い意味で役立っていた。
  • 本質を追究する心は、このブログのポリシーにもなっている。

思い出

初めて購入したパソコンがブルーベリーのiMacだった。なぜiMacだったかというと、お金の問題だった。当初、生存給付金の25万を元手にVAIO(ソニー)を買おうとしていたが、欲しいモデルはことごとく売り切れ。(その当時、VAIOは相当人気があったのだ)仕方なく、パソコンなしの生活を続けていた。ところが、お金というものは水物である。VAIOの次期モデルが出た頃に、いざ購入しようと再び手元を確認してみると、無情にも15万しか残っていなかった...。10万はどこへ消えたのだろう?謎である。

ただ、現実は直視しなければならない。15万しかないのだ。選択肢は15万で買えるパソコンにするか、このままパソコンなしの生活を続けるか、である。そんな時、同僚に勧められたのがiMacだった。売場に行くと、カラフルな5色の色で展示されていた。マウスはまん丸だった。FD(フロッピー)ドライブもなかった。以前からiMacのことは知っていたが、こんなお子ちゃまパソコン誰が買うか、と思っていた。

しかし、その同僚曰く、マックを絶賛する。そして、手元には15万しかない。もはやパソコン買うならiMacしかないという状況。このままパソコンなしの生活は、時代に取り残されそうで嫌だった。買うと決めた。

自分:「iMacください。」

店員:「何色にしますか?」

何だかパソコン買っているはずなのに、これじゃ服を買うときの会話だなと思いつつ、

自分:「青にします。」

こうして、パソコンのある生活が始まったのである。

さっそく、iMacを起動してみた。電源を入れると「ジャーン」と音がして、起動が始まる。暫くして、次々とアイコンが表示される。そうして起動が完了するも、デスクトップは異常にシンプル。ハードディスクとゴミ箱他、数個のアイコンしか表示されていない...。これから自分は一体どうすれば良いのだろう?そんな途方もない不安を感じた。お店で見たVAIOをはじめとした他のWindowsパソコン(デスクトップにはたくさんのアプリのアイコンがあって華やか)とは対照的である。こ、これは、失敗してしまったかな?とその時は正直思った。(今思えば、デスクトップはシンプルな方が良いのに)

しかし、それから3日間、寝る間を惜しんでiMacの前に座る自分がいた。デスクトップがシンプルということは、逆に最初にできることは限られてくる。

  • デスクトップにはMacintosh HDとゴミ箱、メール、ブラウザ、ユーザー登録。
  • メニューには七色のリンゴとファイル、編集、表示、特別、ヘルプ。

最初にクリックできる場所は、10箇所程しかないのだ。だから次々と、クリックできるとところから操作していくしかない。そうやって、どんどん開いていく。iMacのデスクトップ探検が始まった。

デスクトップのシンプルさとは裏腹に、そこから辿れる世界は、とても深く、興味深いものだった。マウス操作に伴う操作音にも心地良さを感じて、操作するほどにその先には何があるのか、知りたくなって、どんどん深みにハマっていった。

当初*1、DOSシェルとか、Windowsのファイルマネージャーに相当するものはないのかとか、レジストリーの設定はどうするのか、バックアップソフトは何を使えば良いのかなど、次々と疑問が浮かんできた。それをiMacをお勧めした同僚に聞くと、笑いながら教えてくれる。「全部アップルメニューやFinderからマウス操作で出来るよ。」

全くそのとおりだった。iMacに関するすべての設定はGUIから操作して設定可能だった。コマンドを操作する必要性は全くなかった。Finderをリスト表示にすれば、ファイルマネージャーに似た表示にもなる。そもそも、アイコン表示であろうが、リスト表示であろうが、ファイルにアクセスできれば問題ないのだ。*2普段は見えないリソースファイルさえも、ResEditを使えばアイコン表示で中身を編集できた。バックアップは、デスクトップのMacintosh HDを外付けのメディアにドラッグ&ドロップするだけだった。

すべてが、グラフィカルなインターフェースの世界だった。何もかも。その徹底ぶりが素晴らしいと思った。また、その操作感には画面の中のものを触っている感触が、確かにある。マウスの動き一つとっても、iMacには加速性能が加味されていた。マウスを手元で一定距離動かしたとしても、素早く動かした時と、ゆっくり動かした時では、ポインタの移動量が違うのである。今では一般的になったマウスの加速性能も当時はまだApple系のマシンでしか実現されていなかったのだ。ウィンドウやボタンの角が丸いのもiMacだけだった。*3些細なことかもしれないが、たぶん誰かのこだわりだと思う。そのような微妙な蓄積が、全体としてのiMacの操作感を演出していた。

そのようなことを知れば知るほどに、iMacについての興味が深まっていった。一体これは、どんな人が設計して、作ったものなのだろうと。iMac以前のマシンはどのようなものだったのだろうと。Macに関する書籍をむさぼり読んだ。奇遇にも転職した会社の向かいはMacの中古ショップだった。昼休みは中古ショップに入り浸って、極上の出物を見つけると購入してワクワクした。

古いMacのことを調べると、さらにマックへの興味は深まった。面白いことに、古いMacを触ったり、付属のソフトを操作することは、iMac以上にドキドキ、ワクワクした。処理スピードは確かに遅い。しかし、操作感はそれほど悪くない。もう少しキビキビ動けば、iMacと変わらないじゃないか、というレベル。

付属しているソフトウェアも高品質だった。表示が白黒であっても、ディザリングによる中間色表示であっても、できる限りの技術を使って、その性能を最大限に引き出している気がした。古いんだけど、古くさくない。むしろ、最新のiMacのルーツを辿って行くようだった。

一貫性

初代Macintosh開発チームのリーダである彼は、1984年にMacintoshを世に送り出してから、1985年には自ら設立したAppleを辞めてしまう。「このまま一生砂糖水を売りつづけたいか? それとも世界を変えたいか?」と口説いて自ら招き入れた社長に、職を追われ、会長以外の職を剥奪されてしまった経緯から。

同年、直ぐにNeXTという会社を立ち上げる。その後の彼の意志は、NeXTでの製品開発として継続されることとなった。その数年後のインタビュー記事が以下で読める。

そのインタビューの中で、彼は分からないことは分からないと真摯に答えながらも、頭の中に将来のビジョンを思い描いていたことを感じ取れる。2011年の今読むと、そのビジョンが全くブレることなく、今日まで続いていることが感じられる。

では、そのビジョンはいつ生まれたのだろうか?おそらくそれは、1979年にゼロックス社パロアルト研究所を訪問して、Altoのデモを見た時からだと思われる。

彼はAppleを辞めて以降も、当初のビジョンを持ち続け、理想に向かってNeXTで開発を続けた。1996年AppleはNeXTを買収し、彼は暫定CEOとして再び戻ってきた。時代遅れとなったOS9は、NeXTベースのOSXに置き換えられることになった。その後、OSXをベースにタッチインターフェースを組み込んだiOSも生まれた。現在のApple製品のすべてのベースとなる技術は、なんと25年以上前に開発が始まったNeXTの技術だったのである。

その面影は現在のコードの中にもある。NSが頭に付くクラス名は、NeXT時代に開発されたオブジェクトを引き継いでいるのだ。NSはNEXT STEP(NeXT社が開発したOS)の頭文字をとった略。最新のiOSの開発でさえ、NS****という表記がたくさん出てくる。圧巻である。高い理想を持って開発された技術は、25年経った現在でも色褪せることはないのだ。最新のiPhoneiPadにも活用され、この先もまだまだ生き続ける技術となっている。

彼が生涯をかけてやって来たことは、すべてiPhone・iPadの開発まで一筆書きで繋がるのだ。過去の経験が、すべて将来の開発に役立っているように見える。大学は中退したが、そこで学んだカリグラフィーの講義を受けたことさえも。

ポリシーを持って続けることが、このような一貫性を生むのだろうか?

QuickDraw開発秘話

かつてのMac OS9までの描画エンジンの主役はQuickDrawが担っていた。GUIなOSでは、文字も含めてすべてをグラフィックとして扱うので、画面に見えているすべてのもの*1はQuickDrawによって描かれていたことになる。描画エンジンは、GUIなOS開発の要となる技術である。その出来が、GUIなOS開発の成否を分けるとも言える。

そして、最初期のQuickDrawは、ビル・アトキンソンがたった一人で開発したそうである。

当時(25年以上前)のCPUは、動作クロックが8MHzという性能だった。(現在は2GHz=2000MHzかつ、複数コアが当たり前)そのような性能であっても、違和感なくマウスで操作できるOS環境にするために、斬新な発想や試行錯誤を重ね、相当な努力の末に開発されたのがLisaやMacintoshであった。

Amazon.co.jp: レボリューション・イン・ザ・バレーの中で、QuickDrawを開発する逸話が少し紹介されている。

当時、研究所の中で開発されていたGUIなOS「Alto」のデモを見たスティーブ・ジョブズとビル・アトキンソンは、その斬新さに感銘を受け、自身でも開発を始めた。

Altoは、実際には専用に開発されたハードウェアの性能に助けられて実現していた環境だった。

にもかかわらず、ビル・アトキンソンは、Altoのすべてはソフトウェアで実現されていると勝手に思い込んで、そのまま開発を続けて、最終的にはQuickDrawを完成させてしまった。

とにかく、素早く描画するために、斬新な発想で様々な工夫がされた。

例えば、円(本当は楕円ルーチンだけどシンプルに円で考える)を描くには普通に考えれば、sin・cosあるいは平方根の計算が必要になる。

しかし、小数を扱うと、浮動小数点計算ユニットを持たない当時のCPUではスピードが問題になった。

そこで、奇数の数列の和が、二乗の数列になる(1 + 3 = 2^2、1 + 3 + 5 = 3^2、1 + 3 + 5 + 7 = 4^2、... )ことを利用して、座標までの距離を整数値を概算しながら描画することを思い付いたそうである。

QuickDrawの開発逸話には続きがあって、

  • 奇数の数列を利用して高速に円を描く発想を得たビル・アトキンソンは、高速に丸や四角を描くデモを見せびらかして喜んでいた。
  • しかし、そのデモを見たスティーブ・ジョブズは、全く誉めもせずに「角が丸い四角は描けないのか?」と聞いてきた。
  • それを聞いたビル・アトキンソンは、不機嫌そうに「そんなことするのは面倒だし、必要だとも思わない」と答えた。
  • その答えにスティーブジョブズは、部屋中のものを指差し角が丸いことを指摘した。
  • さらには、ビルを外に連れ出し、街中に角が丸い四角が溢れていることを指摘した。
  • スティーブ・ジョブズの説得にギブアップしたビル・アトキンソンは、角が丸い四角を描画するルーチンの開発を約束した。
  • 次の日、またしてもビルはデモを見せびらかしていた。
  • そのデモは、ほとんど普通の四角と変わらない、猛烈な速さで角が丸い四角を描いていた。
  • ビル・アトキンソンはそれをRoudRectと名付けて、QuickDrawに追加した。
  • その後、RoundRectはGUIの様々な部分で利用され、必要不可欠な存在になったということだ。

たぶん、ビルはブレゼンハムのアルゴリズムにも気付いたのかもしれない。スティーブ・ジョブズのこだわりが、QuickDrawをより高いレベルに引き上げてしまった。今でこそ角の丸い四角はGUIとして一般的になったが、25年以上も前からRoundRect一発で描けるQuickDrawって素晴らしい!


ドナルド・クヌース(Donald.E.Knuth)博士の質問で始まったQuickDraw・MacPaintのソースコードの公開までの話し。

2004年末に始まった出来事であったが、AppleからComputer History Museumに寄贈されてから、一般公開されるまで、長い時間がかかっていた。

Museumがコードを一般公開することについて、Appleとの合意(a handshake deal)は取れているのだが、実はSteve Jobsからの「魔法の一言(the magical words)」を、いまだに我々は待っているというのが現在の状況だ。

MacPaintのソースコード、続報

Computer History Museumには速やかに寄贈され、Appleは合意(握手の取り交わし)していたにもかかわらず、結局、一般公開されたのは、2010年になってから。実に5年近くの歳月が流れていた。

ヒューマン・インターフェース・ガイドライン

Macintoshには初期の頃から、ヒューマン・インターフェース・ガイドラインというものがあって、様々なGUI部品の使い方、意義、世界観みたいなことを詳細に解説していた。GUI部品のピクセル数レベルのサイズ、余白のピクセル数、OK・キャンセルボタンなどの並び順まで、事細かに規定されている*4。それは、最新のiOSヒューマン・インターフェース・ガイドラインにも引き継がれている。

以上のガイドラインをMacintosh、あるいはiPhone・iPadで開発する時に、尊守するよう求めているのだ。そのようにして、ガイドラインに乗っ取ったアプリケーションが提供されるからこそ、あの統一された外観と操作感が得られていたのだ。そのようにすることで、誰がデザインしてもある一定のMacintoshらしいデザインになる。ボタンは単なる画像のボタンではなく、操作した時により現実に近いリアルな感触を感じられるボタンになる。本質を理解して実装するからこそ、上辺だけ着飾った見た目だけのGUIにならず、ユーザーを自然と納得させる操作感が生まれる。

これはもう、職人の世界観を詳細なマニュアルにして、それを守ってもらうようなものだ。職人の親方は、些細なことでも とことんこだわって、厳しく注意する。利益を度外視しても、仕事の出来を厳しく追及する。そんなイメージがある。きっとAppleには職人の親方がいて、その規律をマニュアル化しているのである。それは彼が直接指示したものではないかもしれないが、彼の求める高いレベルの品質を維持するためには、どうしても必要となるガイドラインだったのかもしれない。

興味深いリンク

  • 気に入らない家具なら、ない方がマシと。


彼には会ったことも、話したこともないけれど、MacintoshやOSX、iPhone・iPadといった製品を通して、そのポリシーだけは常に感じ取っていた。そのポリシーの10000分の1くらいは、このブログにも引き継がれていると思われるように、精進しようと思う。

追悼。

*1:会社で使っていたWindowsパソコンについては、多少の知識があった。

*2:desktop.dbなどアクセスできない不可視ファイルもあったが、OS側が利用する設定ファイルなので、アクセスの必要性は全くなかった。アクセスは出来ないが、デスクトップの再構築で作り直すことはできた。

*3:iMacデスクトップの角が丸いのも実はディスプレイの性能ではなく、デスクトップを角丸で描画していたからなのだ。それが操作性やデザインの向上に寄与したかどうかは疑問だが。

*4:Webの世界で言えば、ユーザビリティーの高いページデザインとは何かを詳細に規定して、ボックスサイズやマージン・パッディングをピクセル単位で規定している感じ。

2011-10-14

coding()ハンドラをより高速にする

今回の一連のAppleScriptの話題は、coding()ハンドラの発見がすべての始まり。ところが、そのcoding()ハンドラ自体は、最初にダメ出しを修正した以降は、ほとんど見直していなかった。json_from()、for_key()、set_key_value()はより効率的な処理を目指して修正したのに、そのベースとなるcoding()ハンドラの効率が悪いと、すべてのハンドラに悪い影響が及んでしまう。

  • for_key()、set_key_value()は、見直しによってもはやcoding()ハンドラに依存しなくなってしまったが...。

今一度、coding()ハンドラを徹底的に見直してみた。

現状のコード

 on coding1(obj)
   try
     if obj's class = text then
       "\"" & obj & "\""
     else if obj's class = list or obj's class = record then
       obj as number
     else
       obj as text
     end if
   on error msg
     try
       --match_str("/\\{.*\\}/=~" & quoted form of msg) --依存するので以下のコードに回避した
       "require \"jcode\";$KCODE=\"u\";/\\{.*\\}/=~" & quoted form of msg & ";puts($&);"
       do shell script "ruby -e " & quoted form of result
       --do shell script "echo " & quoted form of msg & "|sed -e \"s/^[^{]*//g\"|sed -e \"s/[^}]*$//g\""--シェルコマンドのみ
     on error
       --do shell script262,144バイト制限エラーでも、日本語環境なら救われる(それ以外はNG
       --http://developer.apple.com/jp/technotes/tn2002/tn2065.html
       msg's items 1 thru -24 as text --3
     end try
   end try
 end coding1

現状の問題点

  • do shell scriptによって、シェルスクリプトとRubyに依存している。
  • そのため、シェルの制限である262144バイトを超える情報を渡そうとすると、エラーになってしまう。
error "0 以外の状況でコマンドが終了しました。" number 255
  • そのエラーが発生しても日本語環境なら救われるようになっているが、それ以外の言語環境ではどうしようもない。

パフォーマンス計測

  • 実際に利用しているauto_loginのログイン情報のレコードを引数に、coding()ハンドラを1000回繰り返す時間を計測してみた。
    • 3回計測して、31秒、32秒、33秒だった。

 set obj to result
 
 display dialog "計測開始"
 set t to current date
 repeat 1000 times
   set res to coding1(obj)
 end repeat
 (current date) - t
 display dialog result
 res

AppleScriptのみで文字列処理

  • 現状では、エラーメッセージに含まれる、余分な文字列を取り除くために、Rubyの正規表現を利用している。
    • 余分な文字列 = 日本語環境では" のタイプを number に変換できません。"
  • これをAppleScriptだけで何とかしてみる。

 on coding2(obj)
   try
     if obj's class = text then
       "\"" & obj & "\""
     else if obj's class = list or obj's class = record then
       obj as number
     else
       obj as text
     end if
   on error msg
     set head to offset of "{" in msg
     set tail to -(offset of "}" in (msg's items's reverse as text))
     msg's items head thru tail as text
   end try
 end coding2

  • 変更したのはon error以下のブロック内。動作は正常。

しかし、遅い...

  • 1000回ループさせて62〜64秒だった。
  • coding1()では31秒前後だったので、do shell script方式よりも2倍も時間がかかってしまった。
  • 何がそんなに遅いのか?試しに、同じ仕組みだけど、自前でループ作ってやってみた。

 on coding2(obj)
   try
     if obj's class = text then
       "\"" & obj & "\""
     else if obj's class = list or obj's class = record then
       obj as number
     else
       obj as text
     end if
   on error msg
     repeat with i from 1 to msg's number
       if msg's item i = "{" then exit repeat
     end repeat
     set head to i
     
     repeat with i from 1 to msg's number
       if msg's item -i = "}" then exit repeat
     end repeat
     set tail to -i
     
     msg's items head thru tail as text
   end try
 end coding2

  • すると、予想外の好成績。
  • 1000回ループさせて、37秒だった。
  • なんと、offset inとreverse使うよりは、自前のループで検索した方が速いのである。

文字列置き換えを駆使する

  • AppleScriptの文字列操作はイケてない。このスピードにはガックリである。
  • 但し、区切り文字を活用した文字列置き換えだけは、超高速なのだけど...。
  • 試しに、文字列置き換え方式で計測してみることにする。

 on coding3(obj)
   try
     if obj's class = text then
       "\"" & obj & "\""
     else if obj's class = list or obj's class = record then
       obj as number
     else
       obj as text
     end if
   on error msg
     replace(msg, " のタイプを number に変換できません。", "")
   end try
 end coding3
 
 on replace(src_text, text1, text2)
   join(split(src_text, text1), text2)
 end replace
 
 on split(src_text, delimiter)
   set last_delimiter to AppleScript's text item delimiters
   set AppleScript's text item delimiters to delimiter
   set res to src_text's text items
   set AppleScript's text item delimiters to last_delimiter
   res
 end split
 
 on join(src_list, delimiter)
   set last_delimiter to AppleScript's text item delimiters
   set AppleScript's text item delimiters to delimiter
   set res to src_list as text
   set AppleScript's text item delimiters to last_delimiter
   res
 end join

  • すると、激速である!
  • 1000回ループさせて、たったの9秒。
  • 今までと次元の違う速さである。
  • しかし、この方法では日本語環境しか対応できない。
  • この超高速を活かして、文字列置き換えだけで、言語環境に依存せず、{ }内だけを取得する方法はないものか...。
  • そう考えてやってみたのが以下のコード。

 on coding(obj)
   try
     if obj's class = text then
       "\"" & obj & "\""
     else if obj's class = list or obj's class = record then
       obj as number
     else
       obj as text
     end if
   on error msg
     set a_list to split(msg, "{")
     set a_list's item 1 to ""
     set a_list to split(join(a_list, "{"), "}")
     set a_list's item -1 to ""
     join(a_list, "}")
   end try
 end coding
 
 on split(src_text, delimiter)
   set last_delimiter to AppleScript's text item delimiters
   set AppleScript's text item delimiters to delimiter
   set res to src_text's text items
   set AppleScript's text item delimiters to last_delimiter
   res
 end split
 
 on join(src_list, delimiter)
   set last_delimiter to AppleScript's text item delimiters
   set AppleScript's text item delimiters to delimiter
   set res to src_list as text
   set AppleScript's text item delimiters to last_delimiter
   res
 end join

  • 計測もしてみた。

すると...

  • 1000回ループさせて10秒!
  • 当初30秒だったので、3倍速くなった。
  • 素晴らしい速さ。

AppleScriptの置き換え処理だけは超高速なのであった。

  • そして、do shell scriptに依存しないので、もはや262144バイトの制限も受けない。
  • コード自体は何をやっているか分かりにくくなったが、二重のtryブロックが不要になって構造はシンプルになった。
  • split()、join()ハンドラに依存してしまうが、このハンドラは何をやるにも外せないほど必須となる基本ハンドラだ。
    • スピードの改善、
    • 262144バイトの制限も受けない、
  • この二つの恩恵を受けられるのなら、split()、join()ハンドラへの依存くらいなら許せる。

以上で、より高速かつ、バイト制限のないcoding()ハンドラが完成した!