読者です 読者をやめる 読者になる 読者になる

dothikoのカクカクワールド2D REBOOT

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか色々。

結局gimp 2.8.14をubuntu 14.04に入れた件 & ダイナミクスの効いたパスストロークについて

結局入れてしまいましたね。

ppaは12.04でもお世話になったotto-kesselgulaschさんのところで

sudo add-apt-repository ppa:otto-kesselgulasch/gimp
sudo apt-get update

この後にgimpを入れてあればapt-get upgradeで2.8.14になります。なければapt-get install gimp…って、書くまでもないかw

さて話は変わりますが、かねてより入り・抜きの付いたパスストロークを描画したかったのです。

へっぽこなお絵かきの技術をデジタルで克服したい、という祈りにも似た気持ちというかなんと申しますか。

このためにinkscapeで楕円を沿わせる技法やらいろいろやってみましたが、なんといっても本命は次期inkscape 0.91のPowerStrokeでしょう。

しかし当分出そうにもないので他の代替案を考えますと、たとえば

  • gimpでパスを作り「パスに沿わせる」で定規のようにして手でペンタブを操作して電流イライラ棒的に描画
  • mypaintでシフトキーを押しながらマウス描画して入り抜き付き曲線描画
  • AzDrawing / AzPainterで入り抜き設定でベジェ曲線を描く
  • 前述のinkscape沿わせ技法

どれもそれなりに使えるものです。というか、特にAzDrawingは少し使ってみただけでありますがかなりの可能性を感じました。しかし操作感が若干独特ですし、パスの再編集ということができません。 今後、さらに使い込んで行きたく思っております。

時に、実はgimpでもパスを入り抜き付きで描画できることはできるのです。 それが

f:id:dothiko:20140831174348j:plain

パスダイアログで対象のパスを右クリック→「パスの境界線を描画」→「描画ツールを使用」→「インクで描画」を選択→「描画の動的特性をエミュレートする」にチェック→描画(S) なのです。

たとえば、こういうパスがあったとします。

f:id:dothiko:20140831175135j:plain

これに上記の操作を適用すると…

f:id:dothiko:20140831174352j:plain

このように描けます。

しかし残念ながらこれが若干使いづらい。

そこはもうちょっとなんというか、パッパと作業していきたいところなのです。できればキーコンビネーション一発で、現在のコンテキストに関係なく、予め決められたインクサイズでビシッと描画されちゃってほしい。

そんな訳でpython-fuスクリプトから実行しようとしても、pdbには「描画の動的特性をエミュレートする」設定がどうも無いようなのですよ。 pdb.gimp_context_set_dynamics()は、gimp-paintbrushなどでは有効なのですが、gimp-inkでは無視されます。

f:id:dothiko:20140831174343j:plain

それがこの状態。動的特性にチェックを入れない状態と同じです。

だからpython-fuでは今の所、インクでやろうとすると常にぶっとい線で描画されるっぽいです。 美しく描くにはダイアログを表示しなければなりません。

まぁ要するにmypaintかAzDrawing使えよで終わる話なのですが、gimp 2.8.14で何かの間違いで修正されてないかな〜と思ってやってみたんですが、当たり前ながらそんなことはなく。

やはり、MLに英語で報告しないとダメすかね…ものすごい敷居高いな…

そこで、なんとか他の方法でできないかをいろいろやってみた所、発想の転換でちょっといい感じなモノが出来たので書いておきます。

そう、もうインクはやめてgimp-paintbrushでなんとかしよう、と。

まず用意するのが新規作成したダイナミクス「dothiko_dynamics」とブラシ「dothiko_path_brush」です。 dothiko_dynamicsは、「フェード」に

  • サイズ
  • 硬さ
  • 割合

を設定します。

そしてdothiko_path_brushは丸形状で新規作成して、硬さを0.98程度、間隔を1.0に。

(まぁ名前はなんでもいいんですが、当然ながらこの後のスクリプトの中身を変更する必要があります)

しかる後に、次のスクリプトを作成。名前はstroke_and_delete.pyとして、~/.gimp-2.8/plug-ins/に放り込んでおきました。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

from gimpfu import *


BRUSH_NAME='dothiko_path_brush'

def my_stroke(img,layer,path,size,do_delete_path):
    """
    Drawing assigned path into a layer with dynamics.

    Arguments:
        img -- gimp image which contains the layer.
        layer -- destination layer,which to be drawn path
        path -- the path to be drawn
        size -- brush size,in pixel.
                if None,current size of paintbrush should be used.
        do_delete_path -- delete the path or not,boolean.
    """

    # start of groping undoable operations
    pdb.gimp_image_undo_group_start(img)
    try:

        old_dyn=pdb.gimp_context_get_dynamics()
        old_method=pdb.gimp_context_get_paint_method()
        old_brush=pdb.gimp_context_get_brush()
        pdb.gimp_context_set_dynamics("dothiko_dynamics")
        pdb.gimp_context_set_paint_method("gimp-paintbrush")
        pdb.gimp_context_set_brush(BRUSH_NAME)
        if size:
            old_size=pdb.gimp_context_get_brush_size()
            pdb.gimp_context_set_brush_size(size)

        pdb.gimp_edit_stroke_vectors(layer,path)

        if do_delete_path:
            pdb.gimp_image_remove_vectors(img,path)

        if size:
            pdb.gimp_context_set_brush_size(old_size)


        pdb.gimp_context_set_paint_method(old_method)
        pdb.gimp_context_set_dynamics(old_dyn)
        pdb.gimp_context_set_brush(old_brush)

    finally:
        # end of grouping undoable operations
        pdb.gimp_image_undo_group_end(img)
        gimp.displays_flush()


def python_fu_path_stroke_and_delete(a_img,a_drawable,sample_arg=True):

    cp=pdb.gimp_image_get_active_vectors(a_img)
    if cp:
        stroke_base.my_stroke(a_img,a_img.active_layer,cp,None,True)

def python_fu_path_stroke_and_delete_thick(a_img,a_drawable,sample_arg=True):

    cp=pdb.gimp_image_get_active_vectors(a_img)
    if cp:
        stroke_base.my_stroke(a_img,a_img.active_layer,cp,8,True)

def python_fu_path_stroke_and_delete_normal(a_img,a_drawable,sample_arg=True):

    cp=pdb.gimp_image_get_active_vectors(a_img)
    if cp:
        stroke_base.my_stroke(a_img,a_img.active_layer,cp,4,True)

def python_fu_path_stroke_and_delete_thin(a_img,a_drawable,sample_arg=True):

    cp=pdb.gimp_image_get_active_vectors(a_img)
    if cp:
        stroke_base.my_stroke(a_img,a_img.active_layer,cp,2,True)

def do_register(desc,func):
    if desc!="":
        menu="-%s" % desc
        desc="_%s" % desc
    else:
        menu=""

    register(
            "python_fu_path_stroke_and_delete%s" % desc,
            "path auto stroke-deletor",
            "stroke path once and delete it automatically",
            "dothiko",
            "kakukaku world",
            "aug 2014", 
            "<Image>/Python-Fu/path/stroke/stroke-and-delete%s" % menu, 
            "*",
            [
            ],
            [],
            func)

do_register("",python_fu_path_stroke_and_delete)
do_register("thick",python_fu_path_stroke_and_delete_thick)
do_register("normal",python_fu_path_stroke_and_delete_normal)
do_register("thin",python_fu_path_stroke_and_delete_thin)

main()

これで、このように描けます。

f:id:dothiko:20140831174357j:plain

まぁ、手動で設定していっても同じものが描けるわけなのですが、

  • 普段使っているダイナミクスと専用のダイナミクスを切り替え
  • 普段使っているブラシと専用のブラシを切り替え
  • サイズも調整し
  • ダイアログからブラシを指定して描画し
  • ダイナミクスとブラシとサイズを戻す

なんてやってたら日が暮れてしまいます。一発簡単オートにするにはpython-fuが一番便利です。

スクリプト自体も若干いい加減ですが、とりあえず… のちのち「可視状態のパス全部を描画」とか「パスを消さない」などのいろいろなバリエーションを作りたいため、若干回りくどいというか荒削りな状況です。

これでメニューから予め設定したthick/normal/thinの3パターンの太さで描画できます。何かSHIFT+CTRL+で一発で描けるようにしても面白そう。

ただ見てお分かりいただけるように、残念ながら「入り」だけで「抜き」がないんですが、まぁ全く使えないということはないかと…

まぁ線画クリンナップなら結局AzDrawingがベストかな〜現時点では、的な。

しかし、線画のクリーンナップとかならそうかもですが、微修正でgimpと行き来ってのも迂遠な話でして。無いよりはマシ、というか。しばらくは自分で使ってみて考えます。