FileMaker でカラーピッカー作ってみた

色をチョイスして数値を得たり、数値から色を確認したり、そういう作業を頻繁に行っていて、ちょっとしたことだけど面倒です。面倒だけどちょっとしたことです。こういう微妙なことは長年放置されますが・・・そうだ自動化して簡単アプリを作ろうか、と思ったけどアプリ作る技能ないし。というわけでFileMakerで簡単カラーピッカー作った。

頻繁にやる作業なわけですよ、Hex から色を確認したり、HSBで作った色をRGBやHexに変換したり、そういうの。Apple の Digital Color Meter が非常によろしいんですが足りないこともあります。

画面上で測定するアプリ

こういうとき今どきなら AI にブラウザアプリを作ってもらったりできるんでしょうか。いらんけど。FileMakerなら自分にも作れそうだから作ってみました。

FileMaker Color Picker

カラーピッカーじゃなくて、色の値を変換する小さなFMファイルです。小気味よい小さなアプリのような挙動ですがアプリケーションではなくFileMaker書類です。FileMakerがないと開けません。あとMac専用です

FM Color Picker

まだ改良したりもっとウインドウを小さくしたいところですがとりあえずダウンロードできるようにしておきます。

カラーピッカー.fmp12.zip

以下、何ができるかご紹介。

カラーピッカーで色をチョイス

ボタンでAppleのカラーピッカーが開きます。色を作るなり選ぶなりスポイトで拾うなりして OK したら、フィールドにRGBの値が入り色も確認できます。同時に、Hex(16進数)と HSB に変換され、表示されます。

Apple のカラーピッカー FM Color Picker

数値を入れて変換

ウインドウに数値を直接入れてもOK。Hex、RGB、HSB、どれを入れてもそれぞれ変換された値が示されます。RGBとHSBはスペースまたはカンマで区切ります。

RGB と HSB は自動で判別できない場合があるので、そういうときは RGB か HSB かを手動で指定します。

RGBかHSBか自動で判断できない場合は指定する

という、それだけのことですが、これがなかなか便利で我ながら作業中画面の端に常駐させているほどです。

カラーの値を変換する関数

さて、カラーの値を変換する計算ですが、Hex を RGB と HSB に、RGB を Hex と HSB に、HSB を RGB に変換するのまでは自力で作れましたが、HSB を Hex に変換する計算式が難しくて頓挫、長く放置していました。今どきならAIが教えてくれる筈だと思って訊いてみたらサクッと教えていただきまして、それでようやく実現したというのが秘密の答えです。秘密じゃないですけど。

以下は計算式です。カスタム関数化していますので、引数として入力された値のテキストを使用します。そこんところお気を付けを。

計算式は内容がダブっている記述もあり無駄にも満ちています。ベテランの先生方には、不細工な部分や「”~”を付けろやド素人が」な部分ががあっても優しく微笑んどいてくださいと申し添えておきます。

RGB を Hex に

/*
 引数: txtRGB (例: "43, 98, 110" や "43 98 110")
 戻り値: 6桁のHEX値 (例: "56626E")
*/
Let ( [
    // 区切り文字を改行に
    ~rgb_list = Substitute ( RGBtext ; [ ", " ; ¶ ] ; [ "," ; ¶ ] ; [ " " ; ¶ ] ) ;
    
    // 値を取得
    ~r = GetValue ( ~rgb_list ; 1 ) ;
    ~g = GetValue ( ~rgb_list ; 2 ) ;
    ~b = GetValue ( ~rgb_list ; 3 ) ;

    // 16進変換用の参照文字列
    ~hex_chars = "0123456789ABCDEF"
] ;

    "#" &
    // Rの変換 (上位桁 & 下位桁)
    Middle ( ~hex_chars ; Div ( ~r ; 16 ) + 1 ; 1 ) & 
    Middle ( ~hex_chars ; Mod ( ~r ; 16 ) + 1 ; 1 ) &

    // Gの変換
    Middle ( ~hex_chars ; Div ( ~g ; 16 ) + 1 ; 1 ) & 
    Middle ( ~hex_chars ; Mod ( ~g ; 16 ) + 1 ; 1 ) &

    // Bの変換
    Middle ( ~hex_chars ; Div ( ~b ; 16 ) + 1 ; 1 ) & 
    Middle ( ~hex_chars ; Mod ( ~b ; 16 ) + 1 ; 1 )

)

RGB を HSB に

/*
関数名: Color_RGBtoHSB
引数: RGB テキスト(カンマまたはスペース区切り)
戻り値: H S B スペース区切り
*/

Let ( [

~list = Substitute ( RGBtext ; [ ", " ; ¶ ] ; [ " " ; ¶ ] ; [ "," ; ¶ ] );

R = GetValue ( ~list ; 1 ) ;
R = R / 256;
G = GetValue ( ~list ; 2 ) ;
G = G / 256;
B = GetValue ( ~list ; 3 ) ;
B = B / 256;

max = If ( R < G ; G ; R );
max = If ( max < B ; B ; max );

min = If ( R < G ; R ; G );
min = If ( min < B ; min ; B );

H =
 If ( max = min ; 0 ;
	Case ( 
		 G = max ; 60 * ( ( B - R) / (max - min ) ) + 120  ;
		 B = max ; 60 * ( ( R - G) / (max - min ) ) + 240 ;
		 R = max ; 60 * ( ( G - B) / (max - min ) )
 	)
 ) ;
H = If( H ≠ 0 ; Round ( H ; 0 ) ; H );
H = If ( H < 0 ; 360 + H ; H );

S = If ( max = 0 ; 0 ; ( max - min ) / max ) ;
S = Round ( S * 100 ; 0 );

B = max ;
B = Round ( B * 100 ; 0 )

]; 

If( IsEmpty(RGBtext) ; ""  ;
H & " " & S & " " & B 
)

 )

Hex を RGB に

/*
 関数名: Color_HextoRGB
 引数: Hex テキスト #FFFFFF または FFFFFF
 戻り値: RGB(スペース区切り)
*/

Let(
	[
		~t = Hex;
		~t = Substitute( ~t; "#"; "" );
		~R = Left( ~t; 2 );
		~R1 = Left( ~R; 1 );
		~R2 = Right( ~R; 1 );
		~G = Middle( ~t; 3; 2 );
		~G1 = Left( ~G; 1 );
		~G2 = Right( ~G; 1 );
		~B = Middle( ~t; 5; 2 );
		~B1 = Left( ~B; 1 );
		~B2 = Right( ~B; 1 );
		~RGB = ~R1 & ¶ & ~R2 & ¶ & ~G1 & ¶ & ~G2 & ¶ & ~B1 & ¶ & ~B2;
		~RGB = Substitute(
			~RGB;
			[ "A"; 10 ];
			[ "B"; 11 ];
			[ "C"; 12 ];
			[ "D"; 13 ];
			[ "E"; 14 ];
			[ "F"; 15 ]
		);
		~RR =( GetValue( ~RGB; 1 ) * 16 ) +( GetValue( ~RGB; 2 ) );
		~GG =( GetValue( ~RGB; 3 ) * 16 ) +( GetValue( ~RGB; 4 ) );
		~BB =( GetValue( ~RGB; 5 ) * 16 ) +( GetValue( ~RGB; 6 ) )
	];

	~RR & " " & ~GG & " " & ~BB

)

Hex を HSB に

前提として、HexをRGBにする関数と、RGBをHSBに変換する関数を使っております。

/*	
引数: Hex テキスト #FFFFFF または FFFFFF
戻り値: HSB スペース区切り
使用する他のカスタム関数:
	Color_HextoRGB
	Color_RGBtoHSB
*/
Let(
	[
		Hex = Substitute( Hex ; "#" ; "" ) ;
		~RGB = Color_HextoRGB( Hex ) ;
		~tL = Substitute( ~RGB ; [ ", " ; ¶ ] ; [ " " ; ¶ ] ; [ "," ; ¶ ]);
		~R = GetValue( ~tL ; 1 ) ; 
		~G = GetValue( ~tL ; 2 ) ;
		~B = GetValue( ~tL ; 3 ) ;

//		~hsb = Color_R_G_BtoHSB( ~R ; ~G ; ~B ) ;
		~hsb = Color_RGBtoHSB( ~RGB )
	];

	~hsb

)

HSB を RGB に

/*
  関数名: Color_HSBtoRGB ( HSB )
  引数: HSB (カンマまたはスペース区切り)
  概要: HSB (0-360, 0-100, 0-100) の文字列を RGBに変換する
*/

Let ( [
    // --------------------------
    // 1. 入力値のクリーニングと解析
    // --------------------------
    
    ~cleanText = Substitute ( HSB ; [ "," ; " " ] ) ;
    
    ~h = GetAsNumber ( MiddleWords ( ~cleanText ; 1 ; 1 ) ) ;
    ~s = GetAsNumber ( MiddleWords ( ~cleanText ; 2 ; 1 ) ) / 100 ; 
    ~b = GetAsNumber ( MiddleWords ( ~cleanText ; 3 ; 1 ) ) / 100 ; 

    // --------------------------
    // 2. HSB から RGB への変換計算
    // --------------------------
    ~c = ~b * ~s ;
    ~x = ~c * ( 1 - Abs ( Mod ( ~h / 60 ; 2 ) - 1 ) ) ;
    ~m = ~b - ~c ;

    ~sector = Mod ( Floor ( ~h / 60 ) ; 6 ) ;

    ~r_temp = Choose ( ~sector ; ~c ; ~x ; 0  ; 0  ; ~x ; ~c ) ;
    ~g_temp = Choose ( ~sector ; ~x ; ~c ; ~c ; ~x ; 0  ; 0  ) ;
    ~b_temp = Choose ( ~sector ; 0  ; 0  ; ~x ; ~c ; ~c ; ~x ) ;

    // 数値計算の確定 (0-255)
    ~R = Round ( ( ~r_temp + ~m ) * 255 ; 0 ) ;
    ~G = Round ( ( ~g_temp + ~m ) * 255 ; 0 ) ;
    ~B = Round ( ( ~b_temp + ~m ) * 255 ; 0 ) 

] ;

	~R & " " & ~G & " " & ~B    

)

HSB を Hex に

/*
  関数名: HSBtoHex ( text )
  引数: text (カンマまたはスペース区切り)
  概要: HSB (0-360, 0-100, 0-100) の文字列を 16進数カラーコードに変換する
*/

Let ( [
    // --------------------------
    // 1. 入力値のクリーニングと解析
    // --------------------------
    
    ~cleanText = Substitute ( HSB ; [ "," ; " " ] ) ;
    
    ~h = GetAsNumber ( MiddleWords ( ~cleanText ; 1 ; 1 ) ) ;
    ~s = GetAsNumber ( MiddleWords ( ~cleanText ; 2 ; 1 ) ) / 100 ; 
    ~b = GetAsNumber ( MiddleWords ( ~cleanText ; 3 ; 1 ) ) / 100 ; 

    // --------------------------
    // 2. HSB から RGB への変換計算
    // --------------------------
    ~c = ~b * ~s ;
    ~x = ~c * ( 1 - Abs ( Mod ( ~h / 60 ; 2 ) - 1 ) ) ;
    ~m = ~b - ~c ;

    ~sector = Mod ( Floor ( ~h / 60 ) ; 6 ) ;

    ~r_temp = Choose ( ~sector ; ~c ; ~x ; 0  ; 0  ; ~x ; ~c ) ;
    ~g_temp = Choose ( ~sector ; ~x ; ~c ; ~c ; ~x ; 0  ; 0  ) ;
    ~b_temp = Choose ( ~sector ; 0  ; 0  ; ~x ; ~c ; ~c ; ~x ) ;

    // 数値計算の確定 (0-255)
    ~R = Round ( ( ~r_temp + ~m ) * 255 ; 0 ) ;
    ~G = Round ( ( ~g_temp + ~m ) * 255 ; 0 ) ;
    ~B = Round ( ( ~b_temp + ~m ) * 255 ; 0 ) ;

    // --------------------------
    // 3. 10進数(RGB) から 16進数(Hex) への変換
    // --------------------------
    ~hexChars = "0123456789ABCDEF"

] ;
    "#" & 
    // Red
    Middle ( ~hexChars ; Int ( ~R / 16 ) + 1 ; 1 ) & 
    Middle ( ~hexChars ; Mod ( ~R ; 16 ) + 1 ; 1 ) & 
    
    // Green
    Middle ( ~hexChars ; Int ( ~G / 16 ) + 1 ; 1 ) & 
    Middle ( ~hexChars ; Mod ( ~G ; 16 ) + 1 ; 1 ) & 
    
    // Blue
    Middle ( ~hexChars ; Int ( ~B / 16 ) + 1 ; 1 ) & 
    Middle ( ~hexChars ; Mod ( ~B ; 16 ) + 1 ; 1 )
)

既存関数を使うならこんなに必要ないんですけどね。一応。

スクリプト

FM Color Pickerでは次の挙動をスクリプトで作っています。

  1. AppleColorPickerを開いて結果(RGB値)を取得してフィールドに記入する
  2. 入力フィールドの値がどのタイプか( Hex、RGB、HSB)を判断する
  3. 値を変換する
  4. 色サンプルを作成する

AppleColorPickerを開いて結果を取得してフィールドに記入する

AppleScriptを使ってAppleのカラーピッカーを開きます。

set selectedColor to choose color default color {<カラー初期値>}

これでいいんですね。カラー初期値は最大が 65535 65535 65535 の値で、これなんですの?16bit?わかりませんが 256 256 256 ではないので注意です。

カラーピッカーで OK すれば値が取得できるので、8bit の最大 256 に変換します。

set r8 to round ((item 1 of selectedColor) / 257) rounding as taught in school

難しいので AI 先生に尋ねたところ、このようなコードを教えられました。教えられても難しいですね。RGBそれぞれを item 1 of selectedColorで受け取るとか、256 に変換するのに 257 で割るとか。そうですね。さらに謎の rounding as taught in school というのがありますが、何の学校ですかと思ったら四捨五入を丸めているようです。こんなの分かるわけないわ。

次に計算結果の数値からカンマ区切り文字列を作成して変数にセットします。この変数をあとでFileMaker に渡すのです。

FileMakerに渡すこと

AppleScript の結果を FileMaker のフィールドに渡すことができます。これもずっと知らなくて、長い間 set the clipboad か、do shell script なら pbcopy しか使ってこなかったんです。フィールドに送るなんて難易度高いだろと思い込んでいました。

tell application "FileMaker Pro"
	activate
	set cell "<保存フィールド>" of current record to rgbString
end tell

// rgbString は文字列の変数です

 

これを丸覚えすれば良いと分かりました。ようやくクリップボード経由の煩わしさから解放されます。<保存フィールド> にはフィールド名を。テーブルが異なるならフルの table::field と書きます。そのフィールドがカレントウインドウのレイアウト上に配置されている必要があります。

そんなこんなでまとめると、AppleScript のテンプレートはこうなりました。

try
	-- 1. カラーピッカーを開く rgb 65535 = 白
	set selectedColor to choose color default color {<カラー初期値>}
	
	-- 2. 計算: 16bit -> 8bit
	set r8 to round ((item 1 of selectedColor) / 257) rounding as taught in school
	set g8 to round ((item 2 of selectedColor) / 257) rounding as taught in school
	set b8 to round ((item 3 of selectedColor) / 257) rounding as taught in school
	
	-- 3. 文字列作成
	set rgbString to (r8 as string) & ", " & (g8 as string) & ", " & (b8 as string)
	
	-- 4. FileMaker Pro の '<保存フィールド>' フィールドに値(rgbString)を格納
	tell application "FileMaker Pro"
		activate
		set cell "<保存フィールド>" of current record to rgbString
	end tell
	
	-- 5. 一応成功の合図をFileMakerに返す
	return "OK"
	
on error number errNum
	-- キャンセルされた場合
	if errNum is -128 then
		-- FileMaker Pro のフィールドに Cancel を格納
		tell application "FileMaker Pro"
			activate
			set cell "<保存フィールド>" of current record to "Cancel"
		end tell

		return "Cancel"
	end if
end try

これはあくまでテンプレートで、あとで<カラー初期値>や<保存フィールド>を実際の値で置換します。

このテンプレートを「テキストを挿入」で変数に格納し、次のステップで実際のフィールド名に Substitue で置換します。あとは「AppleScriptを実行」ステップで走らせれば完了。

タイプを判定

値フィールドに FFFFFF とか 128,62,90 とか値が入ると、それが Hex なのか RGB なのか HSB なのかを判定して「Type」フィールドに格納します。

  • 区切りがなくて「#」を除いた文字数が6文字なら Hex 確定
  • 区切りがあって 1個目が 256 を越える値なら HSB確定
  • 区切りがあって 2個目または3個目が100を越える値ならRGB確定

1個目が256以下で2個目と3個目が100以下なら HSB か RGB かどっちか分からないからユーザーに指定させます。

変換

入力された値のタイプが判明したら、カスタム関数に仕込んでおいた変換の関数で Hex, RGB, HSB の値をそれぞれフィールドに格納します。

サンプルを作成

サンプルの四角は、実はテキストの ■ です。フォントサイズを巨大化させ、RGBで色を指定しただけです。

Let ( [

~rgb = Substitute ( $RGB ; [ ", " ; ¶ ];[ " " ; ¶ ];[ "," ; ¶ ] ) ;

~r = GetValue ( ~rgb ; 1 );
~g = GetValue ( ~rgb ; 2 );
~b = GetValue ( ~rgb ; 3 )

]; 

TextSize ( TextColor ( "██" ; RGB ( ~r ; ~g ; ~b ) ) ; 60 )

)

←こんな感じで。それだけのことでした。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください