モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

Kritaのpythonプラグインについてメモ・ManagedColor編 (追記あり)

最近PythonによるKritaのプラグインづくりにハマっているのですが、 これが中々面白い。

Scriptorという即スクリプトを試せる環境もあって、これが実に心強いのです。

だがしかしドキュメント的にはあまり整備されていない点が多いようです そこで一応ネットの片隅にこうして放出しておこうかと…

そんなわけで今回はManagedColor編です。 これには本当に苦しめられました。

  • ManagedColorとはKrita内での色を表現し、やり取りするためのオブジェクト。
  • Kritaの使用しているフレームワークのQtには色を示すQColorがありますが、それとは完全に別物。
  • カラープロファイルなどでの変化等にも対応できる(らしい)
  • components()で色成分を取得でき、setComponents()で色成分を設定できる。
  • ViewオブジェクトのsetForeGroundColor()に与えるManagedColorオブジェクトでブラシ色を設定、foregroundColor()で得られるManagedColorで色を取得

…と、基本的にはこうなのですが問題はcomponents() / setComponents()なのであります。

ぶっちゃけこのcomponentsはRGBAの各成分を0.0〜1.0に正規化した、4要素のシーケンス*1なのですが…

r,g,b,a の並びの時もあれば、b,g,r,aの並びの時もある

のですな。これが。調べた結果、ManagedColorのcolorDepth()メソッドで文字列として取得できる色要素の精度が

8ビット符号なし整数の'U8' (←これがKritaデフォルトらしい) もしくは 'U16' の場合は、 b, g, r, a

32ビット浮動小数点の'F32' もしくは 'F16' の場合は、 r, g, b, a

となるようです。 このため、色を取得して設定しようとすると全然違う色になったりして、????という感じだったのですが

将来変わったりしないことを願っております(^^; ってまぁ自作プラグインというのはそういう時にイジれるのも醍醐味だったりして…

ではでは!


追記

ManagedColorを簡単にかつ正しくQColorに変換する方法がありました(^^;

まずViewからcanvas()でキャンバスを取得、そしてManagedColorオブジェクトでcolorForCanvas()を使ってQColorオブジェクトを取得します。これならば簡単確実!

ki = Krita.instance()
win = ki.activeWindow()
view = win.activeView()
cvs = view.canvas()

mcol = view.foregroundColor() # ManagedColorオブジェクト取得
qcol = mcol.colorForCanvas(cvs) # QColorオブジェクト取得!

ただし、残念ながら、QColorをManagedColorに安全に変換する方法が見つかりません。

とりあえず、ManagedColor("RGBA", "U8", "") で作られたオブジェクトであれば、setComponents( (qcol.blueF(), qcol.greenF(), qcol.redF(), 1.0) )で良いようです。今の所ですが…

これの重要な所はcolorModelが'U8'であることです。U16その他であると、setComponents() で設定された色成分は、setForeGroundColor() した時に微妙に色褪せていたり、逆に蛍光っぽかったり、違う色となって反映されます。

ManagedColor.fromXML() にXML文字列を突っ込めば出来ないかな?と思いましたが、これが何故かtoXML()メソッドで得たXMLでも通用しません。

mcol.setComponents((0.0, 1.0, 0.0, 1.0)) # colorModel()が何れにせよ、緑色的な何かになっているはず
xml = mcol.toXML() # -> xmlは<Color>タグ、<RGB>タグの入った文字列として正しく出力されている
print(xml) 

newcol = ManagedColor('RGBA', mcol.colorDepth(), mcol.colorProfile())
newcol.fromXML(xml) # <- 通用しない、RGB = 0,0,0のまま
print(newcol.toXML()) # <-ご覧の有様だよ!

といった感じです。

*1:colorModelが'RGBA'の場合であり、他の場合はcomponentsは当然RGBAではないのだが、割愛