0
2

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-12

#1.はじめに

不透明部分からのマスクの作成を行いました。
GIMP 2.10で動作確認をしています。

#2.実行結果

透明で塗りつぶしたレイヤーに緑円と青円を描画し、不透明部分(緑円+青円)からマスクを作成し、赤円を描画しています。その結果、赤円は緑円と青円と重なる部分のみ描画されます。

20191212.PNG

#3.メイン部分説明

gimp_image_select_item()にADD_SELECTION_MASKを指定して不透明部分を選択しています。
gimp_layer_create_mask()とgimp_layer_set_edit_mask()でマスクの作成とレイヤーへの追加を行っています。
gimp_layer_set_edit_mask()にFALSEを指定して、マスクでなく通常部分を編集するようにしています。

    # 緑円
    set_color(0, 255, 0, 1.0)
    make_path_relative2(image, 320, 300, points, 3, TRUE)
    # 青円
    set_color(0, 0, 255, 1.0)
    make_path_relative2(image, 480, 300, points, 3, TRUE)
    #
    # 不透明部分(緑円+青円)を選択する
    pdb.gimp_image_select_item(image, 0, transparent_layer)
    # 選択範囲からマスクを作成する
    mask = pdb.gimp_layer_create_mask(transparent_layer, ADD_SELECTION_MASK)
    # マスクをレイヤーに追加する
    pdb.gimp_layer_add_mask(transparent_layer, mask)
    # マスク編集を無効にする(マスクでない部分を編集する)
    pdb.gimp_layer_set_edit_mask(transparent_layer, FALSE)
    set_color(255, 0, 0, 1.0)
    # 赤円
    make_path_relative2(image, 400, 230, points, 3, TRUE)

#4.スクリプト全体

# 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

def add_layer_transparent(image, name):
  # レイヤーの作成に必要なパラメータ
  width   = image.width
  height  = image.height
  type    = RGBA_IMAGE
  opacity = 100
  mode    = NORMAL_MODE
  #
  # パラメータをもとにレイヤーを作成
  layer = gimp.Layer(image, name, width, height, type, opacity, mode)
  #
  # レイヤーを透明色で塗りつぶす
  layer.fill(TRANSPARENT_FILL)
  #
  # 画像データの 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)
    background_layer = add_layer(image, "背景")
    transparent_layer = add_layer_transparent(image, "透明")
    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),
        ]
    # 緑円
    set_color(0, 255, 0, 1.0)
    make_path_relative2(image, 320, 300, points, 3, TRUE)
    # 青円
    set_color(0, 0, 255, 1.0)
    make_path_relative2(image, 480, 300, points, 3, TRUE)
    #
    # 不透明部分(緑円+青円)を選択する
    pdb.gimp_image_select_item(image, 0, transparent_layer)
    # 選択範囲からマスクを作成する
    mask = pdb.gimp_layer_create_mask(transparent_layer, ADD_SELECTION_MASK)
    # マスクをレイヤーに追加する
    pdb.gimp_layer_add_mask(transparent_layer, mask)
    # マスク編集を無効にする(マスクでない部分を編集する)
    pdb.gimp_layer_set_edit_mask(transparent_layer, FALSE)
    set_color(255, 0, 0, 1.0)
    # 赤円
    make_path_relative2(image, 400, 230, points, 3, TRUE)
    #
    display_image(image)

main()

#5.参考

python-fu 自動操作おさらい - Qiita
Gimp Automating Image Processing with Python Fu

#6.その他

マスクの削除も行いました。
GIMP Python-Fuでマスクを削除する - Qiita

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?