コードを細かく構造化できた。
成果物
使い方
git clone https://github.com/ytyaru/Python.Gimp.Save.Xcf.Class.20191218122716 cd Python.Gimp.Save.Xcf.Class.20191218122716/src ./run.sh
コード
run.sh
Run() { IsExistCmd() { type "$1" > /dev/null 2>&1; } Install() { ! IsExistCmd "$1" && sudo apt -y install "$1"; } IsExistPkg() { dpkg -l | grep "$1" > /dev/null 2>&1; } InstallPkg() { ! IsExistPkg "$1" && sudo apt -y install "$1"; } RunBatch() { gimp --no-interface --console-messages --no-data --no-splash --batch-interpreter python-fu-eval --batch - < "$1"; } Install gimp InstallPkg gimp-python RunBatch "$(cd $(dirname $0); pwd)/save_xcf.py" } Run "$@"
save_xcf.py
#!/usr/bin/env python # -*- coding: utf-8 -*- from gimpfu import * import os,sys class Image(object): def __init__(self): self.image = None self.layer = None def __create_image(self, width=512, height=512, _type=RGB): self.image = gimp.Image(width, height, _type) # type=RGB,GRAY,INDEXED def __create_layer(self, name="layer01", width=512, height=512, _type=RGBA_IMAGE, opacity=100, mode=NORMAL_MODE): self.layer = gimp.Layer(self.image, name, width, height, _type, 100, mode) self.layer.fill(TRANSPARENT_FILL) def __add_layer(self): self.image.add_layer(self.layer, 0) def create(self, width=512, height=512): self.__create_image(width=width, height=height) self.__create_layer(width=width, height=height) self.__add_layer() class Drawer(object): def __init__(self, layer): self.layer = layer def draw(self): self.__draw_rectangle() self.__to_argb() def __draw_rectangle(self, r=1.0, g=0.0, b=0.0, x=128, y=128, w=256, h=256): import cairo self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.layer.width, self.layer.height) ctx = cairo.Context(self.surface) ctx.set_source_rgb(r, g, b) ctx.rectangle(x, y, w, h) ctx.fill() def __get_rgba_str(self, src): import struct rgba_buf = "" l = len(src) for i in range(l / 4): i0 = i * 4 i1 = i0 + 4 bgra = struct.unpack('@L', src[i0 : i1])[0] a = (bgra >> 24) & 0x0ff r = (bgra >> 16) & 0x0ff g = (bgra >> 8) & 0x0ff b = bgra & 0x0ff rgba = struct.pack('4B', r, g, b, a) rgba_buf += rgba return rgba_buf def __to_argb(self): src = self.surface.get_data() dst = self.__get_rgba_str(src) w = self.layer.width h = self.layer.height rgn = self.layer.get_pixel_rgn(0, 0, w, h, True, True) rgn[0:w, 0:h] = str(dst) self.layer.flush() self.layer.merge_shadow() self.layer.update(0, 0, w, h) class Xcf(object): def __init__(self): pass def save(self, image, path=""): save_path = self.__path() pdb.gimp_xcf_save(0,image,image.layers[0],save_path,save_path) gimp.message("Python " + sys.version) gimp.message("ファイル保存しました。: " + save_path) def __path(self, path=""): dir_path = path if "" == dir_path: dir_path = "/tmp/work/" try: os.makedirs(dir_path) except: pass #import traceback #traceback.print_exc() from datetime import datetime timestamp = datetime.now().strftime("%Y%m%d%H%M%S") save_path = os.path.join(dir_path, timestamp + ".xcf") return save_path i = Image() i.create() d = Drawer(i.layer) d.draw() x = Xcf() x.save(i.image) pdb.gimp_quit(1)
API
gimp.Layer
gimp.Layer(img, name, width, height, type, opacity, mode)
type, mode にはどんな値が入りうるのか不明。
GIMP メニュー ヘルプ
→プロシージャーブラウザ
で調べてみた。layer
で検索。
gimp-layer-new
がそれっぽい。
type
は以下。
The layer type { RGB-IMAGE (0), RGBA-IMAGE (1), GRAY-IMAGE (2), GRAYA-IMAGE (3), INDEXED-IMAGE (4), INDEXEDA-IMAGE (5) }
mode
は以下。
The layer combination mode { LAYER-MODE-NORMAL-LEGACY (0), LAYER-MODE-DISSOLVE (1), LAYER-MODE-BEHIND-LEGACY (2), LAYER-MODE-MULTIPLY-LEGACY (3), LAYER-MODE-SCREEN-LEGACY (4), LAYER-MODE-OVERLAY-LEGACY (5), LAYER-MODE-DIFFERENCE-LEGACY (6), LAYER-MODE-ADDITION-LEGACY (7), LAYER-MODE-SUBTRACT-LEGACY (8), LAYER-MODE-DARKEN-ONLY-LEGACY (9), LAYER-MODE-LIGHTEN-ONLY-LEGACY (10), LAYER-MODE-HSV-HUE-LEGACY (11), LAYER-MODE-HSV-SATURATION-LEGACY (12), LAYER-MODE-HSL-COLOR-LEGACY (13), LAYER-MODE-HSV-VALUE-LEGACY (14), LAYER-MODE-DIVIDE-LEGACY (15), LAYER-MODE-DODGE-LEGACY (16), LAYER-MODE-BURN-LEGACY (17), LAYER-MODE-HARDLIGHT-LEGACY (18), LAYER-MODE-SOFTLIGHT-LEGACY (19), LAYER-MODE-GRAIN-EXTRACT-LEGACY (20), LAYER-MODE-GRAIN-MERGE-LEGACY (21), LAYER-MODE-COLOR-ERASE-LEGACY (22), LAYER-MODE-OVERLAY (23), LAYER-MODE-LCH-HUE (24), LAYER-MODE-LCH-CHROMA (25), LAYER-MODE-LCH-COLOR (26), LAYER-MODE-LCH-LIGHTNESS (27), LAYER-MODE-NORMAL (28), LAYER-MODE-BEHIND (29), LAYER-MODE-MULTIPLY (30), LAYER-MODE-SCREEN (31), LAYER-MODE-DIFFERENCE (32), LAYER-MODE-ADDITION (33), LAYER-MODE-SUBTRACT (34), LAYER-MODE-DARKEN-ONLY (35), LAYER-MODE-LIGHTEN-ONLY (36), LAYER-MODE-HSV-HUE (37), LAYER-MODE-HSV-SATURATION (38), LAYER-MODE-HSL-COLOR (39), LAYER-MODE-HSV-VALUE (40), LAYER-MODE-DIVIDE (41), LAYER-MODE-DODGE (42), LAYER-MODE-BURN (43), LAYER-MODE-HARDLIGHT (44), LAYER-MODE-SOFTLIGHT (45), LAYER-MODE-GRAIN-EXTRACT (46), LAYER-MODE-GRAIN-MERGE (47), LAYER-MODE-VIVID-LIGHT (48), LAYER-MODE-PIN-LIGHT (49), LAYER-MODE-LINEAR-LIGHT (50), LAYER-MODE-HARD-MIX (51), LAYER-MODE-EXCLUSION (52), LAYER-MODE-LINEAR-BURN (53), LAYER-MODE-LUMA-DARKEN-ONLY (54), LAYER-MODE-LUMA-LIGHTEN-ONLY (55), LAYER-MODE-LUMINANCE (56), LAYER-MODE-COLOR-ERASE (57), LAYER-MODE-ERASE (58), LAYER-MODE-MERGE (59), LAYER-MODE-SPLIT (60), LAYER-MODE-PASS-THROUGH (61), LAYER-MODE-REPLACE (62), LAYER-MODE-ANTI-ERASE (63) }
これはscript-fu(scheme言語)上の定義名。python-fuでは別名になっている。たとえは今回使った値との対応表は以下だと思われる。
python-fu | script-fu | int値 |
---|---|---|
RGBA_IMAGE |
RGBA-IMAGE |
1 |
NORMAL_MODE |
LAYER-MODE-NORMAL |
28 |
こういう定義名もどこかにまとめてほしいのだが。
所感
これでpython2でもclass化できることが確認できた。
えらい苦労した。Pythonのコードは汚くみえる。def
,self
が多すぎて。何よりカプセル化できないのが致命的。
対象環境
- Raspbierry pi 4 Model B
- Raspbian buster 10.0 2019-09-26 ※
- bash 5.0.3(1)-release
- GIMP 2.10.8
$ uname -a Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l GNU/Linux