1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GIMP Python-Fuでグラデーションを描画する

Last updated at Posted at 2019-12-07

#1.はじめに

GIMP Python-Fuでグラデーションを描画しました。

GIMP 2.10で動作確認をしています。

#2.実行結果

円を描く正確な方法はまだ分かっていないので、曲線描画でほぼ円にしています。

追記:「鉛筆で描画」を選択していてブラシは「1. Pixel」の場合の実行結果です。「ブラシで描画」や他のブラシの場合には若干結果が変わります。

20191207-10.png

#3.グラデーション関連スクリプト

背景色設定です。
グラデーションでFG_BG_RGB_MODE(前景色から背景色までRGBでグラデーション)を使用するため、追加しています。

def set_bg_color(r, g, b, a):
  color = (r, g, b, a)
  pdb.gimp_context_set_background(color)

以下、メイン関数の中です。
円っぽいものを描画しています。アンチエイリアスありです。

    # ほぼ円
    points = [
        (+100,    0,   0, -50,   0, +50),
        (-100, +100, +50,   0, -50,   0),
        (-100, -100,   0, +50,   0, -50),
        (+100, -100, -50,   0, +50,   0),
        ]
    make_path_relative2(image, 400, 300, points, 2, TRUE)

ファジー選択で円の内側を選択しています。しきい値は150にしています。

    pdb.gimp_fuzzy_select(layer, 400, 300, 150, 2, TRUE, 0, 0, 0)

グラデーション描画です。分かる範囲で記載します。

引数 引数名 内容 指定した値
1 drawable_ID drawable レイヤーを指定しています
2 blend_mode FG_BG_RGB_MODE(前景色から背景色までRGBでグラデーション)
3 paint_mode NORMAL_MODE 色々選べるようですが未確認。GUIでも選べます
4 gradient_type 形状 GRADIENT_LINEAR(線形)
5 opacity 不透明度 100
6 offset オフセット 0
7 repeat リピート形状を選べるようです REPEAT_NONE
8 reverse 反転 FALSE
9 supersample Do adaptive supersampling. FALSE
10 max_depth Maximum recursion levels for supersampling. 0
11 threshold Supersampling threshold. 0
12 dither Use dithering to reduce banding. TRUE
13 x1 開始X座標 400
14 y1 開始Y座標 250
15 x2 終了X座標 400
16 y2 終了Y座標 350
    set_color(255, 255, 0, 1.0)     # 黄色
    set_bg_color(0, 255, 255, 1.0)  # シアン
    pdb.gimp_edit_blend(layer, FG_BG_RGB_MODE, NORMAL_MODE, GRADIENT_LINEAR, 100, 0, REPEAT_NONE, FALSE, FALSE, 0, 0, TRUE, 400, 250, 400, 350)

ファジー選択していた分を解除します。

    pdb.gimp_selection_clear(image)

#4.スクリプト全体

長くなっていますが、曲線描画等のためで、グラデーション部分は前出の通りわずかです。

関数はGIMP Python-Fuでパスを使用して直線・曲線を描く時に、最後を閉じないと線の欠けが発生する - Qiitaと同じですが、set_bg_color()を追加しています。

今回も下記関数は、5 分で始める GIMP Python-Fu - Qiitaのものを使用させて頂いています。
create_image()
add_layer()
set_color()
set_line_width()
display_image()

# Python-Fu のサンプル・スクリプト
# GIMP の Python-Fu コンソールにコピペして実行してください

# 画像データの作成
## 指定したサイズで画像データを作成する
### width : 画像データの幅 (px)
### height : 画像データの高さ (px)
def create_image(width, height):
  # 画像データを生成
  return gimp.Image(width, height, RGB)

# レイヤーの追加
## 指定した名前のレイヤーを新規に作成し、画像データに挿入する
### image : レイヤーを追加する画像データ
### name : 新規に作成するレイヤーの名前(文字列)
def add_layer(image, name):
  # レイヤーの作成に必要なパラメータ
  width   = image.width
  height  = image.height
  type    = RGB_IMAGE
  opacity = 100
  mode    = NORMAL_MODE
  #
  # パラメータをもとにレイヤーを作成
  layer = gimp.Layer(image, name, width, height, type, opacity, mode)
  #
  # レイヤーを背景色で塗りつぶす(GIMP のデフォルトの挙動に合わせています)
  layer.fill(1)
  #
  # 画像データの 0 番目の位置にレイヤーを挿入する
  position = 0
  image.add_layer(layer, position)
  #
  return layer

# 描画する色を変更する
## パレットの前景色を変更して描画色を設定する
### r : 赤要素 (0-255)
### g : 緑要素 (0-255)
### b : 青要素 (0-255)
### a : 透明度 (0-1.0)
def set_color(r, g, b, a):
  color = (r, g, b, a)
  pdb.gimp_context_set_foreground(color)

def set_bg_color(r, g, b, a):
  color = (r, g, b, a)
  pdb.gimp_context_set_background(color)

# 描画する線の太さを変える
## ブラシのサイズを変更して線の太さを設定する
### width : 線の太さ
def set_line_width(width):
  pdb.gimp_context_set_brush_size(width)

# アンチエイリアスを設定する
## アンチエイリアスを設定する
### antialias : TRUE:有効、FALSE:無効
def set_antialias(antialias):
  pdb.gimp_context_set_antialias(antialias)

# 画像の表示
## 新しいウィンドウを作成し、画像データを表示する
### image : 表示する画像データ
def display_image(image):
  gimp.Display(image)

# パス作成
## パスを作成
### image : レイヤーを追加する画像データ
### points : パス座標
### mode : 0:描画しない、1:閉じないストローク(初期値)、2:閉じるストローク、3:塗りつぶし
### delete_path : TRUE:パスを削除する(初期値)、FALSE:パスを残す
def make_path(
    image,
    points,
    mode=1,
    delete_path=TRUE,
    ):
    """ パスを作成する。 """
    #
    # フラグ設定
    #
    is_draw   = FALSE
    is_closed = FALSE
    is_fill   = FALSE
    is_stroke = FALSE
    if mode == 1:           # 閉じないストローク
        is_draw   = TRUE
        is_closed = FALSE
        is_fill   = FALSE
        is_stroke = FALSE
    elif mode == 2:         # 閉じるストローク
        is_draw   = TRUE
        is_closed = TRUE
        is_fill   = FALSE
        is_stroke = FALSE
    elif mode == 3:         # 塗りつぶし
        is_draw   = TRUE
        is_closed = TRUE        # TRUE/FALSEどちらでも変わらない
        is_fill   = TRUE
        is_stroke = FALSE
    elif mode == 4:         # 閉じないストローク(アンチエイリアスが効かない)
        is_draw   = TRUE
        is_closed = FALSE       # 効かない
        is_fill   = FALSE
        is_stroke = TRUE
    elif mode == 5:         # 閉じるストローク(アンチエイリアスが効かない)
        is_draw   = TRUE
        is_closed = TRUE
        is_fill   = FALSE
        is_stroke = TRUE
    #
    vectors = pdb.gimp_vectors_new(image, 'path')  # パス新規作成
    pdb.gimp_image_add_vectors(image, vectors, 0)  # パスを画像に追加
    #
    # パスとしてストロークを追加
    #
    stroke_id = pdb.gimp_vectors_stroke_new_from_points(vectors, 0,
            len(points), points, is_closed)
    #
    # パスを表示
    #
    pdb.gimp_vectors_set_visible(vectors, TRUE)
    #
    # 描画するよう指定されてたら、パスから選択範囲を作って描画する。
    #
    if is_draw:
        #
        # 選択範囲解除
        #
        pdb.gimp_selection_none(image)
        #
        # パスから選択範囲作成
        #
        pdb.gimp_vectors_to_selection(
            vectors,
            CHANNEL_OP_REPLACE,
            TRUE,
            FALSE,
            0,
            0,
            )
        #
        # 前景色で描画
        #
        drawable = pdb.gimp_image_active_drawable(image)
        if is_fill:
            pdb.gimp_edit_fill(drawable, FOREGROUND_FILL)
        elif is_stroke:
            pdb.gimp_edit_stroke(drawable)
        else:
            pdb.gimp_drawable_edit_stroke_item(drawable, vectors)
        #
        # 選択範囲解除
        #
        pdb.gimp_selection_none(image)
    #
    # パス削除が指定されていたらパスを削除する。
    #
    if delete_path:
        # パス削除
        #
        pdb.gimp_image_remove_vectors(image, vectors)
    #
    return

def get_absolute_point(list):
    """ """ 
    rlist = []
    for pos in list:
        if len(pos) == 6:
            (x, y, rx1, ry1, rx2, ry2) = pos
            x1 = x + rx1
            y1 = y + ry1
            x2 = x + rx2
            y2 = y + ry2
        else:
            (x, y) = pos
            x1 = x
            y1 = y
            x2 = x
            y2 = y
        rlist.extend([
            x1,
            y1,
            x,
            y,
            x2,
            y2,
            ])
    return rlist

# 絶対座標取得
def get_absolute_point2(x, y, list):
    """ """
    rlist = []
    bx = x
    by = y
    for pos in list:
        if len(pos) == 6:
            (rx0, ry0, rx1, ry1, rx2, ry2) = pos
            bx = bx + rx0
            by = by + ry0
            x1 = bx + rx1
            y1 = by + ry1
            x2 = bx + rx2
            y2 = by + ry2
        else:
            (rx0, ry0) = pos
            bx = bx + rx0
            by = by + ry0
            x1 = bx
            y1 = by
            x2 = bx
            y2 = by
        rlist.extend([
            x1,
            y1,
            bx,
            by,
            x2,
            y2,
            ])
    return rlist

# パス作成(相対座標指定)
## パスを作成
### image : レイヤーを追加する画像データ
### points : パス座標
### mode : 0:描画しない、1:最後を閉じないストローク(初期値)、2:最後を閉じるストローク、3:塗りつぶし
### delete_path : TRUE:パスを削除する(初期値)、FALSE:パスを残す
def make_path_relative(
    image,
    points,
    mode=1,
    delete_path=TRUE,
    ):
    """ パスを作成する。 """
    new_points = get_absolute_point(points)
    make_path(image, new_points, mode, delete_path)

# パス作成(座標・アンカー・制御点相対座標指定)
## パスを作成
### image : レイヤーを追加する画像データ
### x : 開始X座標
### y : 開始Y座標
### points : パス座標
### mode : 0:描画しない、1:最後を閉じないストローク(初期値)、2:最後を閉じるストローク、3:塗りつぶし
### delete_path : TRUE:パスを削除する(初期値)、FALSE:パスを残す
def make_path_relative2(
    image,
    x,
    y,
    points,
    mode=1,
    delete_path=TRUE,
    ):
    """ パスを作成する。 """
    new_points = get_absolute_point2(x, y, points)
    make_path(image, new_points, mode, delete_path)

# メイン
def main():
    set_bg_color(255, 255, 255, 1.0)
    image = create_image(800, 600)
    layer = add_layer(image, "背景")
    #layer = add_layer(image, "テスト")
    set_color(0, 0, 0, 1.0)
    set_line_width(10)
    set_antialias(TRUE)
    # 値は(アンカーX, Y[, 制御開始点増分X, Y, 制御終了点増分X, Y])
    #
    # ほぼ円
    points = [
        (+100,    0,   0, -50,   0, +50),
        (-100, +100, +50,   0, -50,   0),
        (-100, -100,   0, +50,   0, -50),
        (+100, -100, -50,   0, +50,   0),
        ]
    make_path_relative2(image, 400, 300, points, 2, TRUE)
    #
    pdb.gimp_fuzzy_select(layer, 400, 300, 150, 2, TRUE, 0, 0, 0)
    set_color(255, 255, 0, 1.0)     # 黄色
    set_bg_color(0, 255, 255, 1.0)  # シアン
    pdb.gimp_edit_blend(layer, FG_BG_RGB_MODE, NORMAL_MODE, GRADIENT_LINEAR, 100, 0, REPEAT_NONE, FALSE, FALSE, 0, 0, TRUE, 400, 250, 400, 350)
    pdb.gimp_selection_clear(image)
    #
    display_image(image)

main()
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?